Skip to content

Ignore --pathmap in the IDE's F# project options - #20470

Open
xperiandri wants to merge 4 commits into
dotnet:mainfrom
xperiandri:fix/ignore-pathmap-in-ide
Open

Ignore --pathmap in the IDE's F# project options#20470
xperiandri wants to merge 4 commits into
dotnet:mainfrom
xperiandri:fix/ignore-pathmap-in-ide

Conversation

@xperiandri

@xperiandri xperiandri commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Description

In a solution whose Directory.Build.props sets <PathMap>$(MSBuildThisFileDirectory)=.\</PathMap> (or DeterministicSourcePaths), Go To Definition from an F# file to a symbol declared in another F# project of the solution opens the generated signature (the "F# Metadata" document) instead of the source. Reproduced with the in-box tools too.

Measured in the debugger: for a symbol imported from a sibling project, FindDeclResult.DeclFound carried .\backend\Use cases\Circulars\GraphQL\.\backend\Use cases\Circulars\GraphQL\Types\Circular.fs while the workspace document is D:\Boardwise\core\backend\Use cases\Circulars\GraphQL\Types\Circular.fs. The project system passes the build's --pathmap: into the IDE's compilation options; FCS applies tcGlobals.pathMap when it pickles the ranges of the in-memory referenced-assembly data (TypedTreePickle.fs), and ComputeMakePathAbsolute then prepends the equally mapped implicit include directory. No lookup by path can find such a file.

The map also leaks between projects. TcGlobals carries pathMap, and FCS caches TcGlobals together with the framework imports (FrameworkImportsCache, IncrementalBuild.fs), keyed by the framework assemblies, the primary assembly, the target framework directories, the compiler binaries and the import-reuse key — not by the path map. A project that reuses the cached entry only refreshes langVersion, realsig and compilationMode on it, so every project of one framework set pickles its ranges with the map of whichever project built the imports first: one project with a --pathmap: is enough to break navigation into any sibling, and a project with a map whose sibling came first is checked without it. Dropping the option in the IDE makes the cached pathMap empty for all of them; the FCS cache itself is unchanged here.

Fix: FSharpProjectOptionsManager drops --pathmap: from the options it takes from the project site, next to the -r: options it already discards. The map only describes what the build should write into its output; nothing in the IDE needs it.

Tests: PathMapNavigationTests builds a library and an application referencing it, both with --pathmap:<root>=. as a Directory.Build.props would set it (with the map on the library alone the outcome depends on which project fills the framework cache first), and checks that the computed options have no --pathmap: and that Go To Definition from the application lands on the library's source file. Both fail without the fix.

Checklist

  • Test cases added

  • Performance benchmarks added in case of performance changes

  • Release notes entry updated:

    Please make sure to add an entry with short succinct description of the change as well as link to this pull request to the respective release notes file, if applicable.

    Release notes files:

    • If anything under src/Compiler has been changed, please make sure to make an entry in docs/release-notes/.FSharp.Compiler.Service/<version>.md, where <version> is usually "highest" one, e.g. 42.8.200
    • If language feature was added (i.e. LanguageFeatures.fsi was changed), please add it to docs/release-notes/.Language/preview.md
    • If a change to FSharp.Core was made, please make sure to edit docs/release-notes/.FSharp.Core/<version>.md where version is "highest" one, e.g. 8.0.200.

    Information about the release notes entries format can be found in the documentation.
    Example:

    If you believe that release notes are not necessary for this PR, please add NO_RELEASE_NOTES label to the pull request.

🤖 Generated with Claude Code

xperiandri and others added 3 commits September 7, 2026 03:59
…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>
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

❗ Release notes required

You can open this PR in browser to add release notes: open in github.dev


✅ Found changes and release notes in following paths:

Change path Release notes path Description
`vsintegration/src` docs/release-notes/.VisualStudio/18.vNext.md

@T-Gro T-Gro left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖🕵️ LGTM & approved, but CI is red.

@github-project-automation github-project-automation Bot moved this from New to In Progress in F# Compiler and Tooling Sep 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI-Tooling-Check-Scanned-Clean Tooling check: diff analyzed, no interesting infrastructure files

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

2 participants