Let FSharpProjectSnapshot.FromOptions take reference stamps from the host - #20459
xperiandri wants to merge 3 commits into
Conversation
✅ Release notes checked
|
268d203 to
c75a5bd
Compare
FSharpProjectSnapshot.FromOptions take reference stamps from the host
c75a5bd to
dab34ee
Compare
|
|
||
| static member FromOptions(options: FSharpProjectOptions, getFileSnapshot, ?snapshotAccumulator) = | ||
| static member FromOptions | ||
| (options: FSharpProjectOptions, getFileSnapshot, ?snapshotAccumulator, ?getReferenceStamp: string -> DateTime) |
There was a problem hiding this comment.
🤖🕵️ Keep the existing public FromOptions CLR method. Put shared logic in a private implementation and expose a distinctly named internal host entry point for the editor.
There was a problem hiding this comment.
@xperiandri TODO - I think this hasnt been addressed
There was a problem hiding this comment.
I wonder if this really required, if added parameter is optional
There was a problem hiding this comment.
I wonder if this really required, if added parameter is optional
There was a problem hiding this comment.
Addressed now, in ab9604d250. You were right and my "the arguments are optional" was not: an optional parameter is part of the CLR signature, so adding one replaced the existing FromOptions instead of extending it, and a consumer built against the old one would have hit a MissingMethodException.
The shape is the one you asked for — a private SnapshotOfOptions does the work, the three FromOptions overloads are byte-for-byte what main has, and the host entry point is the separately named FromOptionsWithReferenceStamps(options, getFileSnapshot, getReferenceStamp, ?snapshotAccumulator).
It is public rather than internal: FSharp.Compiler.Service grants InternalsVisibleTo to fsc, fsi, VisualFSharp.Salsa, VisualFSharp.UnitTests and the two test projects, and not to FSharp.Editor, which is the host that would pass the stamps. Happy to make it internal and add that IVT instead if you prefer to keep it off the public surface.
dab34ee to
6a1f447
Compare
This comment has been minimized.
This comment has been minimized.
|
🔍 Tooling Safety Check — Affects-Design-Time
|
FSharpProjectSnapshot.FromOptions stats every -r: reference each time a snapshot is built from options; under the transparent compiler in Visual Studio that is every from-scratch snapshot after an options recompute. A host that already tracks the last-write times of its references can pass getReferenceStamp instead; the default stays FileSystem.GetLastWriteTimeShim. The callback is threaded through the recursive call for referenced F# projects. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
6a1f447 to
b61c671
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Preserve the existing FromOptions overload to avoid breaking already-built consumers.
Review effort: Lite
Findings: 1
What changed in this PR
Adds host-provided reference timestamp callbacks to FSharpProjectSnapshot.FromOptions, including recursive referenced projects.
Changes:
- Adds callback-based reference stamping with filesystem fallback.
- Adds tests for project and referenced-project stamps.
- Updates the API baseline and release notes.
| File | Summary |
|---|---|
src/Compiler/Service/FSharpProjectSnapshot.fs |
Implements callback-based stamping; retain the existing 3-argument overload for binary compatibility. |
tests/FSharp.Compiler.ComponentTests/FSharpChecker/ProjectSnapshot.fs |
Tests callback propagation. |
tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl |
Updates the public API baseline. |
docs/release-notes/.FSharp.Compiler.Service/11.0.100.md |
Documents the API enhancement. |
| static member FromOptions | ||
| (options: FSharpProjectOptions, getFileSnapshot, ?snapshotAccumulator, ?getReferenceStamp: string -> DateTime) | ||
| = |
There was a problem hiding this comment.
Both of you are right, and my "but the argument is optional" was wrong: F# compiles an optional parameter into the CLR signature, so the 3-argument method was replaced rather than extended, and a consumer built against it would have found no such method.
Fixed in ab9604d250, the way @T-Gro asked for it: the work moved to a private SnapshotOfOptions, the three FromOptions overloads are back exactly as they were on main, and a host that already tracks its references calls the new FromOptionsWithReferenceStamps(options, getFileSnapshot, getReferenceStamp, ?snapshotAccumulator).
One deviation from your wording, @T-Gro: the new entry point is public rather than internal. FSharp.Compiler.Service has InternalsVisibleTo for fsc, fsi, VisualFSharp.Salsa, VisualFSharp.UnitTests and the two test projects, but not for FSharp.Editor, which is the host meant to pass the stamps — internal would need a new IVT entry for it. Say the word if you would rather have the IVT than a public name.
The surface-area baseline now has the three original lines untouched plus one for the new member (regenerated with TEST_UPDATE_BSL=1, and the test passes on a re-run). The component test calls the new name and passes.
`main` opened 11.0.200 for SDK 11.0.200; 11.0.100 has shipped. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
An optional parameter is part of the CLR signature, so adding one replaced `FromOptions` rather than extending it: an already-built consumer would have found no such method. The three overloads are back as they were, the work moved to a private implementation, and a host that tracks its references calls `FromOptionsWithReferenceStamps`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Description
FSharpProjectSnapshot.FromOptionsstats every-r:reference (FileSystem.GetLastWriteTimeShim) each time a snapshot is built from options. Under the transparent compiler in Visual Studio that is the from-scratch path for every new RoslynProjectinstance whose options are not reusable — after every options recompute, sinceFSharpProjectOptions.AreSameForCheckingcompares only theStamp— so a project with a few hundred references pays a few hundred stats per typecheck request.This adds an optional
getReferenceStamp: string -> DateTimetoFromOptions. A host that already tracks the last-write times of its references (#20457 keeps them behind anIVsAsyncFileChangeEx2watcher) supplies them; everyone else gets the sameFileSystem.GetLastWriteTimeShimas before. The callback is threaded through the recursive call forFSharpReferencedProject.FSharpReference, so referenced projects' snapshots use it too.No behaviour change for existing callers; the surface-area baseline gains the new optional parameter on the existing overload.
Checklist
FSharpChecker/ProjectSnapshot.fs: the stamps of both the project and its referenced F# project come from the callback.docs/release-notes/.FSharp.Compiler.Service/11.0.100.md.