From c8a3c03a017ddcc9b981f0edb5330a3f3d10cba2 Mon Sep 17 00:00:00 2001 From: nojaf Date: Mon, 12 Feb 2024 15:22:52 +0100 Subject: [PATCH 1/4] WIP --- src/Compiler/Service/TransparentCompiler.fs | 10 ++++++---- src/Compiler/Service/TransparentCompiler.fsi | 3 ++- .../FSharpChecker/TransparentCompiler.fs | 19 +++++++++++++++++-- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index 124be183fd9..1e8e93f6e9e 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -115,6 +115,7 @@ type internal BootstrapInfo = LoadClosure: LoadClosure option LastFileName: string + ImportsInvalidatedByTypeProvider: Event } type internal TcIntermediateResult = TcInfo * TcResultsSinkImpl * CheckedImplFile option * string @@ -742,9 +743,10 @@ type internal TransparentCompiler /// Bootstrap info that does not depend source files let ComputeBootstrapInfoStatic (projectSnapshot: ProjectCore, tcConfig: TcConfig, assemblyName: string, loadClosureOpt) = + let cacheKey = projectSnapshot.CacheKeyWith("BootstrapInfoStatic", assemblyName) caches.BootstrapInfoStatic.Get( - projectSnapshot.CacheKeyWith("BootstrapInfoStatic", assemblyName), + cacheKey, node { use _ = Activity.start @@ -815,6 +817,7 @@ type internal TransparentCompiler ) let bootstrapId = Interlocked.Increment &BootstrapInfoIdCounter + importsInvalidatedByTypeProvider.Publish.Add(fun () -> caches.BootstrapInfoStatic.Clear(fun kv -> kv = cacheKey.GetKey())) return bootstrapId, tcImports, tcGlobals, initialTcInfo, importsInvalidatedByTypeProvider } @@ -865,7 +868,7 @@ type internal TransparentCompiler let tcConfig = TcConfig.Create(tcConfigB, validate = true) let outFile, _, assemblyName = tcConfigB.DecideNames sourceFiles - let! bootstrapId, tcImports, tcGlobals, initialTcInfo, _importsInvalidatedByTypeProvider = + let! bootstrapId, tcImports, tcGlobals, initialTcInfo, importsInvalidatedByTypeProvider = ComputeBootstrapInfoStatic(projectSnapshot.ProjectCore, tcConfig, assemblyName, loadClosureOpt) // Check for the existence of loaded sources and prepend them to the sources list if present. @@ -889,7 +892,7 @@ type internal TransparentCompiler LoadedSources = loadedSources LoadClosure = loadClosureOpt LastFileName = sourceFiles |> List.tryLast |> Option.defaultValue "" - //ImportsInvalidatedByTypeProvider = importsInvalidatedByTypeProvider + ImportsInvalidatedByTypeProvider = importsInvalidatedByTypeProvider } } @@ -1732,7 +1735,6 @@ type internal TransparentCompiler | None, creationDiags -> return FSharpCheckProjectResults(projectSnapshot.ProjectFileName, None, keepAssemblyContents, creationDiags, None) | Some bootstrapInfo, creationDiags -> - let! snapshotWithSources = LoadSources bootstrapInfo projectSnapshot let! tcInfo, ilAssemRef, assemblyDataResult, checkedImplFiles = ComputeProjectExtras bootstrapInfo snapshotWithSources diff --git a/src/Compiler/Service/TransparentCompiler.fsi b/src/Compiler/Service/TransparentCompiler.fsi index 14562f34f15..9aa5929566c 100644 --- a/src/Compiler/Service/TransparentCompiler.fsi +++ b/src/Compiler/Service/TransparentCompiler.fsi @@ -75,7 +75,8 @@ type internal BootstrapInfo = InitialTcInfo: TcInfo LoadedSources: (range * ProjectSnapshot.FSharpFileSnapshot) list LoadClosure: LoadClosure option - LastFileName: string } + LastFileName: string + ImportsInvalidatedByTypeProvider: Event } type internal TcIntermediateResult = TcInfo * TcResultsSinkImpl * CheckedImplFile option * string diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs index cbc8e7690fe..c87222f2c66 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs @@ -805,7 +805,8 @@ module Stuff = /// References projects are expected to have been built. let localResponseFiles = [| - @"C:\Projects\fantomas\src\Fantomas.Core.Tests\Fantomas.Core.Tests.rsp" + // @"C:\Projects\fantomas\src\Fantomas.Core.Tests\Fantomas.Core.Tests.rsp" + @"C:\Users\nojaf\Projects\TypeProviderSample\TypeProviderSample.rsp" |] |> Array.collect (fun f -> [| @@ -815,7 +816,7 @@ let localResponseFiles = ) // Uncomment this attribute if you want run this test against local response files. -// [] +[] [] let ``TypeCheck last file in project with transparent compiler`` useTransparentCompiler responseFile = let responseFile = FileInfo responseFile @@ -837,9 +838,23 @@ let ``TypeCheck last file in project with transparent compiler`` useTransparentC | None -> failwithf "Last file of project could not be found" | Some lastFile -> + let updatedSource = " +open FSharp.Data + +type Simple = JsonProvider<\"\"\" { \"name\":\"John\", \"level\": \"s\" } \"\"\"> +let simple = Simple.Parse(\"\"\" { \"name\":\"Tomas\", \"level\": \"a\" } \"\"\") + +ignore (simple.Level, simple.Name) + +// For more information see https://aka.ms/fsharp-console-apps +printfn \"Hello from F#\" +" + workflow { clearCache checkFile lastFile expectOk + updateFile lastFile (fun sf -> { sf with Source = updatedSource}) + checkFile lastFile expectOk } [] From 3ff895b42e867819af1d0dfab64c7f4b32930a6f Mon Sep 17 00:00:00 2001 From: nojaf Date: Mon, 12 Feb 2024 16:27:23 +0100 Subject: [PATCH 2/4] Clear all caches of projectSnapshot --- src/Compiler/Service/TransparentCompiler.fs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index 1e8e93f6e9e..6fab3eb72ee 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -817,7 +817,14 @@ type internal TransparentCompiler ) let bootstrapId = Interlocked.Increment &BootstrapInfoIdCounter - importsInvalidatedByTypeProvider.Publish.Add(fun () -> caches.BootstrapInfoStatic.Clear(fun kv -> kv = cacheKey.GetKey())) + + importsInvalidatedByTypeProvider.Publish.Add(fun () -> + // caches.BootstrapInfoStatic.Clear() + // caches.BootstrapInfo.Clear() + caches.Clear(Set.singleton projectSnapshot.Identifier) + // TODO: Should we clear more caches? + // caches.BootstrapInfoStatic.Clear(fun kv -> kv = cacheKey.GetKey()) + ) return bootstrapId, tcImports, tcGlobals, initialTcInfo, importsInvalidatedByTypeProvider } From 98bae430045c742a1cc9c1643ddeab77edaa13a5 Mon Sep 17 00:00:00 2001 From: nojaf Date: Tue, 13 Feb 2024 14:16:26 +0100 Subject: [PATCH 3/4] Revert local test --- src/Compiler/Service/TransparentCompiler.fs | 8 +------- .../FSharpChecker/TransparentCompiler.fs | 19 ++----------------- 2 files changed, 3 insertions(+), 24 deletions(-) diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index 6fab3eb72ee..424247cc9d2 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -818,13 +818,7 @@ type internal TransparentCompiler let bootstrapId = Interlocked.Increment &BootstrapInfoIdCounter - importsInvalidatedByTypeProvider.Publish.Add(fun () -> - // caches.BootstrapInfoStatic.Clear() - // caches.BootstrapInfo.Clear() - caches.Clear(Set.singleton projectSnapshot.Identifier) - // TODO: Should we clear more caches? - // caches.BootstrapInfoStatic.Clear(fun kv -> kv = cacheKey.GetKey()) - ) + importsInvalidatedByTypeProvider.Publish.Add(fun () -> caches.Clear(Set.singleton projectSnapshot.Identifier)) return bootstrapId, tcImports, tcGlobals, initialTcInfo, importsInvalidatedByTypeProvider } diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs index c87222f2c66..cbc8e7690fe 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs @@ -805,8 +805,7 @@ module Stuff = /// References projects are expected to have been built. let localResponseFiles = [| - // @"C:\Projects\fantomas\src\Fantomas.Core.Tests\Fantomas.Core.Tests.rsp" - @"C:\Users\nojaf\Projects\TypeProviderSample\TypeProviderSample.rsp" + @"C:\Projects\fantomas\src\Fantomas.Core.Tests\Fantomas.Core.Tests.rsp" |] |> Array.collect (fun f -> [| @@ -816,7 +815,7 @@ let localResponseFiles = ) // Uncomment this attribute if you want run this test against local response files. -[] +// [] [] let ``TypeCheck last file in project with transparent compiler`` useTransparentCompiler responseFile = let responseFile = FileInfo responseFile @@ -838,23 +837,9 @@ let ``TypeCheck last file in project with transparent compiler`` useTransparentC | None -> failwithf "Last file of project could not be found" | Some lastFile -> - let updatedSource = " -open FSharp.Data - -type Simple = JsonProvider<\"\"\" { \"name\":\"John\", \"level\": \"s\" } \"\"\"> -let simple = Simple.Parse(\"\"\" { \"name\":\"Tomas\", \"level\": \"a\" } \"\"\") - -ignore (simple.Level, simple.Name) - -// For more information see https://aka.ms/fsharp-console-apps -printfn \"Hello from F#\" -" - workflow { clearCache checkFile lastFile expectOk - updateFile lastFile (fun sf -> { sf with Source = updatedSource}) - checkFile lastFile expectOk } [] From dbea2104fe72f7835b2767420058d8a91d0c953b Mon Sep 17 00:00:00 2001 From: nojaf Date: Tue, 13 Feb 2024 15:34:33 +0100 Subject: [PATCH 4/4] Add todo about future plan. --- src/Compiler/Service/TransparentCompiler.fs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index 424247cc9d2..01f539c4f44 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -818,6 +818,9 @@ type internal TransparentCompiler let bootstrapId = Interlocked.Increment &BootstrapInfoIdCounter + // TODO: In the future it might make sense to expose the event on the ProjectSnapshot and let the consumer deal with this. + // We could include a timestamp as part of the ProjectSnapshot key that represents the last time since the TypeProvider assembly was invalidated. + // When the event trigger, the consumer could then create a new snapshot based on the updated time. importsInvalidatedByTypeProvider.Publish.Add(fun () -> caches.Clear(Set.singleton projectSnapshot.Identifier)) return bootstrapId, tcImports, tcGlobals, initialTcInfo, importsInvalidatedByTypeProvider