Match a path-mapped file name against the solution, not the current directory - #20519
Open
xperiandri wants to merge 7 commits into
Open
Match a path-mapped file name against the solution, not the current directory#20519xperiandri wants to merge 7 commits into
xperiandri wants to merge 7 commits into
Conversation
…r tests Test helpers so far put every synthetic file into one Roslyn project. CreateMultiProjectSolution creates one project per synthetic project with project references, the way VS wires project-to-project references; CreateMultiTargetSolution creates one project per target instance sharing the project path and the document paths, the way VS loads a multi-targeted project. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A project built with DeterministicSourcePaths or an explicit PathMap hands the IDE a `--pathmap:` option. FCS applies the map when it pickles the ranges of the in-memory reference other projects check against, so every symbol imported from such a project names a mapped, relative file that no workspace document has, and Go To Definition ends in the generated signature instead of the source. The map is a property of the build output; the IDE now drops it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
An assembly built with a path map names its source files relative to a root it never records. Resolving such a name with Path.GetFullPath resolved it against the process's current directory, which is not that root and is not even the solution's - it is wherever the last component to set it left it - so the answer differed between sessions and named a file that does not exist. Navigation then took the symbol for an external one and opened generated metadata instead of its source. A name that arrives relative is now matched by its tail against the paths the solution already holds, anchored on a separator so that it matches whole directories rather than the tail of one. A rooted name still goes through the workspace's index, so nothing changes for a build without a map. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
❗ Release notes requiredYou can open this PR in browser to add release notes: open in github.dev
|
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
|
🔍 Tooling Safety Check — Affects-Design-Time
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Go To Definition, Find All References and Rename on a symbol whose assembly was built with a path map
—
DeterministicSourcePaths, or a<PathMap>set inDirectory.Build.props— open generatedmetadata instead of the symbol's source.
Why
A path-mapped assembly names each source file relative to the map's root, and does not record the
root.
TryGetDocumentIdFromFSharpRangeandFSharpSymbolUse.GetSymbolScoperesolved that name withPath.GetFullPath, that is, againstEnvironment.CurrentDirectory. The current directory belongs tothe process, not to the solution, and holds whatever the last component to set it left there; the
path it produced named a file that does not exist, no document matched, and the symbol was taken for
an external one.
This is the editor half of the path-map fix. #20518 stops the compiler naming the directory twice in
GetDeclarationLocation, which is what reaches the editor in the first place; #20470 keeps the map outof the options the IDE builds, which covers references between projects held in memory. A referenced
assembly on disk was built by MSBuild with the map, and still carries the mapped names.
The change
Solution.GetDocumentIdsWithFSharpFileNameanswers which documents a compiler range's file namedenotes:
a map;
anchored on a separator so that it matches whole directories and never the tail of one. The rule is
isTheFileAt, which also accepts the doubled separator the compiler writes when the map'sreplacement ends in one (
.\+\src\…).TryGetDocumentIdFromFSharpRange— Go To Definition, and the declaration document Find AllReferences starts from, through
TryGetDocumentFromFSharpRange— andGetSymbolScope, which decidesthe projects Find All References and Rename search, now go through it.
The scan over the solution's documents runs only for a relative name, which means only for a symbol
declared in a path-mapped assembly, and once per navigation: the ranges of the references found are
the solution's own and rooted. Paths are compared case-insensitively; they are not identifiers.
Tests: the rule, including that a name inside a segment matches nothing; and a range whose name a map
left relative finding its document. On the branch this was developed on, running them without the
change fails the second with
no document is named by .\Library_…\FileLibrary.fs. On this branchPathMapNavigationTestspass (9), as do the Go To Definition (3) and Find References (7) tests.Two lookups in other pending work resolve the same kind of name and need the same rule:
GetSolutionDocumentsWithFilePathin #20462, and the comparisonFindSymbolDeclarationInDocumentmakes in #20492. Whichever of those merges after this will route through the helper.
Base
Stacked on #20470, which adds
PathMapNavigationTests.fs; the diff shrinks to its own commit oncethat merges.
🤖 Generated with Claude Code