Skip to content

[VS] Go To Definition into C#/VB projects of the solution, F12 picks the overload - #2170

Merged
RobertvanderHulst merged 7 commits into
X-Sharp:devfrom
hpetriffer:feature/goto-definition-into-csharp
Nov 11, 2026
Merged

RobertvanderHulst merged 7 commits into
X-Sharp:devfrom
hpetriffer:feature/goto-definition-into-csharp

Conversation

@hpetriffer

Copy link
Copy Markdown
Contributor

Summary

Go To Definition (F12), Peek Definition (Alt+F12) and Go To Base (Alt+Home) on a type or member that comes from a C# or VB project of the same solution now open the real source file at the declaration, the way C# does for project references. Until now X# only knew such symbols from the project's output DLL and showed a generated, read-only X# header.

LOCAL c := Crate{1} AS Crate      F12 on Crate  -> Lib\Crate.cs, "public class Crate"
c:Open("x")                       F12 on Open   -> Lib\Crate.cs, "public void Open(string key)"
v:Hello()                         F12 on Hello  -> VbLib\Greeter.vb
"a":ToUpper()                     F12           -> generated header (framework type, unchanged)
  • How: the symbol's assembly is mapped to the C#/VB project that produces it (the X# code model already keeps the output DLL of every referenced foreign project). That project's Compilation comes from VS's own Roslyn workspace (VisualStudioWorkspace via MEF), and the symbol is found by its XML doc ID, which the code model already builds for the documentation lookup.
  • Fallbacks: when the doc ID does not resolve (generics), the member name and parameter count decide; a member without source (implicit constructor) goes to its type. Nested types in metadata spelling (Outer/Inner) are handled.
  • Partial classes: several declarations are listed in the Find All References window, as Go To Implementation does.
  • Never worse than before: any failure (project unloaded, symbol renamed since the last build, workspace busy for more than 3 s, Roslyn not loadable in an older VS) falls back silently to the generated header. Locations in source-generated files (virtual paths) are skipped.
  • Overloads: at a call site F12 now jumps straight to the overload that takes the arguments (count, then the argument types that are known), using the same OverloadFilter as Find All References and Go To Implementation. When the arguments do not decide, the "X# Goto Definition Results" list appears as before. This applies to X# methods as well.
LanguageService/ForeignSource/
├── ForeignSymbolResolver.cs   # pure Roslyn: doc ID -> source locations, fallbacks, dedupe (multi-targeting)
├── ForeignProjects.cs         # output DLL -> C#/VB project file (X# projects excluded)
├── ForeignNavigator.cs        # VS glue: workspace, compilations (3 s timeout), open / list
├── ForeignSymbolKey.cs        # what to look for, built from an X# PE symbol
└── ForeignLocation.cs
  • XProject.ProjectOutputs (code model) exposes the stored project → output DLL map.
  • References: Microsoft.VisualStudio.LanguageServices compile-only (ExcludeAssets="runtime"): 4.8.0 for VS 2022, 3.9.0 for VS 2019. At runtime VS's own Roslyn is used; the VSIX contains no Roslyn assembly (checked for the 2022 VSIX).

Notes

  • Symbols that were added to the C# project but not built yet are still unknown to X# (same as IntelliSense today): build first, then jump.
  • The very first F12 right after loading a solution can still show the header when the C# compilation takes longer than 3 s; the next one jumps into the source.
  • The VS 2019 manifest allows [15.0,17.0); Roslyn 3.9 needs VS 16.9. Below that F12 keeps showing the header (no error).

Test plan

  • LanguageService.Tests: 538/538 pass (26 new: resolver against real Roslyn compilations incl. partial, nested, generic fallback, implicit constructor, generated files, multi-target dedupe; DLL → project mapping; overload pick)
  • Both LanguageService projects compile (VS 2022 and VS 2019)
  • VS 2022 Exp instance with a solution of an X# project referencing a multi-targeted C# project (net48;net8.0) and a VB project: F12 on class, constructor call, property, nested class, interface, enum, generic method, overloads, partial class (list), VB class and method; Peek on a property; Go To Base from an X# class to its C# base; renamed-but-not-built member lands on its type; System.Text.StringBuilder still opens the generated header
  • Not checked: VS 2019 VSIX build and run

🤖 Generated with Claude Code

hpetriffer and others added 7 commits November 11, 2026 11:13
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…header

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@RobertvanderHulst
RobertvanderHulst merged commit a34ad88 into X-Sharp:dev Nov 11, 2026
1 check passed
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.

2 participants