Skip to content

Go To Definition: Automatically navigate to user code when multiple locations include generated code#80669

Merged
CyrusNajmabadi merged 9 commits intomainfrom
copilot/fix-go-to-definition-tool-window
Oct 13, 2025
Merged

Go To Definition: Automatically navigate to user code when multiple locations include generated code#80669
CyrusNajmabadi merged 9 commits intomainfrom
copilot/fix-go-to-definition-tool-window

Conversation

Copy link
Contributor

Copilot AI commented Oct 12, 2025

Plan: Improve Go To Definition to prefer user code over generated code

  • Explore repository structure and understand current implementation
  • Modify GetStreamingLocationAsync in IStreamingFindReferencesPresenter.cs to:
    • Check if there are multiple definition items
    • Filter items to find the first non-generated code location
    • Navigate to that location while still showing all results in the window
  • Add logic to check if a Document is generated code using IGeneratedCodeRecognitionService
  • Build and test the changes
  • Add/update tests to validate the new behavior
  • Address code review feedback - use IsGeneratedCodeAsync extension method
  • Remove redundant inline comments
  • Inline local variable and remove unused using directive
  • Add WorkItem attribute to test
  • Manual testing to verify UI behavior (pending reviewer validation)

Fixes #77895

Original prompt

This section details on the original issue you should resolve

<issue_title>Go To Definition should not require tool window to decide between user code and generated code</issue_title>
<issue_description>## Summary

When the Go To Definition command encounters a type reference whose type declaration is split across multiple locations, but only one location lies within user code, jump to that location without prompting the user.

Background and Motivation

With the proliferation of source generators, which dictate partial types, Go To Definition on a reference to a user type no longer jumps to the user's definition of the type, but rather opens a tool window that shows the user's one file and one or more source generated code files. The user then has to choose their user code file before the IDE will jump to their type declaration.

This is a pain, since 99-100% of the time I want to jump to my own code declaration, as the source generated code is largely invisible and irrelevant to my work. I don't want a tool window to interact with. Just jump to my definition!

Proposed Feature

When Go To Definition has multiple locations it might navigate to, only ask the user which one they want if there are multiple non-source generated files that are candidate targets.

Alternative Designs

Craft a new attribute (with [Conditional(false)] and AllowMultiple=true on it, that source generators can emit on partial declarations that can act as a clue to GTD to indicate that users are unlikely to care about it.
Maybe some source generators emit partials that are more often interesting for users to look at. Allowing the source generators to indicate (with an attribute) the likelihood of this happening can help the GTD command prompt when the user would likely see value there, and skip the prompt otherwise.</issue_description>

<agent_instructions>This one is tricky, but doable. What we likely want here is to augment GetStreamingLocationAsync such that if it finds multiple locations, it continues to show the window with all the results, but it also navigates to the first item that comes from a Document for whom IsGeneratedCodeAsync is false.

THis way the user can see all the results and navigate between them. But they get taken to the likely location they want. </agent_instructions>

Comments on the Issue (you are @copilot in this section)

Fixes #77895


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Copilot AI and others added 2 commits October 12, 2025 13:34
Modified GetStreamingLocationAsync to automatically navigate to the first non-generated
code location when multiple definition locations exist, while still showing all results
in the tool window. This improves the user experience when dealing with partial types
that have both user code and source-generated code.

Co-authored-by: CyrusNajmabadi <4564579+CyrusNajmabadi@users.noreply.github.com>
Co-authored-by: CyrusNajmabadi <4564579+CyrusNajmabadi@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix Go To Definition to jump directly to user code Go To Definition: Automatically navigate to user code when multiple locations include generated code Oct 12, 2025
Copilot AI requested a review from CyrusNajmabadi October 12, 2025 13:45
var document = sourceSpan.Document;

// Check if this document is generated code
var generatedCodeService = document.GetLanguageService<IGeneratedCodeRecognitionService>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot use the existing IsGeneratedCodeAsync extension. You don't need to directly access this service. You will also not need any sort of null check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to use the IsGeneratedCodeAsync extension method and removed the unnecessary service access and null check. Commit: HEAD

Co-authored-by: CyrusNajmabadi <4564579+CyrusNajmabadi@users.noreply.github.com>
ArrayBuilder<(DefinitionItem item, INavigableLocation location)> builder,
CancellationToken cancellationToken)
{
// Look through all definition items to find the first one that comes from a non-generated document
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot remove all the comments inside this method. they're very redundant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed all inline comments from the method. Commit: HEAD

// Check each source span in the definition item
foreach (var sourceSpan in item.SourceSpans)
{
var document = sourceSpan.Document;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot inline this local variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inlined the local variable. Commit: HEAD

{
// Found a non-generated location, return it
return location;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot remove these braces.

Assert.Equal(HelloWorldGenerator.GeneratedFolderClassName, await TestServices.Editor.GetSelectedTextAsync(HangMitigatingCancellationToken));
}

[IdeFact]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot add WorkItem attribute here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added WorkItem attribute for issue #77895. Commit: HEAD

// See the LICENSE file in the project root for more information.

using System.Collections.Immutable;
using System.Linq;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot was this using directive needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it was not needed. SelectAsArray is from PooledObjects, not System.Linq. Removed. Commit: HEAD

…nAsync

Co-authored-by: CyrusNajmabadi <4564579+CyrusNajmabadi@users.noreply.github.com>
@CyrusNajmabadi CyrusNajmabadi marked this pull request as ready for review October 12, 2025 14:16
@CyrusNajmabadi CyrusNajmabadi requested a review from a team as a code owner October 12, 2025 14:16
Copilot AI requested a review from CyrusNajmabadi October 12, 2025 14:16
…dd WorkItem

Co-authored-by: CyrusNajmabadi <4564579+CyrusNajmabadi@users.noreply.github.com>
@CyrusNajmabadi CyrusNajmabadi merged commit 3a0fb03 into main Oct 13, 2025
25 checks passed
@CyrusNajmabadi CyrusNajmabadi deleted the copilot/fix-go-to-definition-tool-window branch October 13, 2025 17:10
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Oct 13, 2025
@davidwengier davidwengier modified the milestones: Next, 18.3 Jan 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Go To Definition should not require tool window to decide between user code and generated code

4 participants