From a684cf76aed6e706aa39dc14378f9f7afe282f75 Mon Sep 17 00:00:00 2001 From: dawe Date: Thu, 15 Feb 2024 20:56:14 +0100 Subject: [PATCH 01/26] First stab at adding a version of TryGetRecentCheckResultsForFile that takes a snapshot instead of project options --- src/Compiler/Facilities/AsyncMemoize.fs | 11 +++++ src/Compiler/Facilities/AsyncMemoize.fsi | 4 ++ src/Compiler/Service/BackgroundCompiler.fs | 23 +++++++++++ src/Compiler/Service/BackgroundCompiler.fsi | 4 ++ src/Compiler/Service/TransparentCompiler.fs | 40 ++++++++++++++++++- src/Compiler/Service/TransparentCompiler.fsi | 6 +++ src/Compiler/Service/service.fs | 4 ++ src/Compiler/Service/service.fsi | 5 +++ ...ervice.SurfaceArea.netstandard20.debug.bsl | 1 + ...vice.SurfaceArea.netstandard20.release.bsl | 1 + 10 files changed, 98 insertions(+), 1 deletion(-) diff --git a/src/Compiler/Facilities/AsyncMemoize.fs b/src/Compiler/Facilities/AsyncMemoize.fs index b780d91ca74..cc9e01b3726 100644 --- a/src/Compiler/Facilities/AsyncMemoize.fs +++ b/src/Compiler/Facilities/AsyncMemoize.fs @@ -534,6 +534,17 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T } + member _.TryGet(key) = + let x = cache.TryGet(key) + + match x with + | Some(Completed(value, _)) -> Some value + | _ -> None + + member _.Set(key, value) = + let v = Job.Completed(value, []) + cache.Set(key, v) + member _.Clear() = cache.Clear() member _.Clear predicate = cache.Clear predicate diff --git a/src/Compiler/Facilities/AsyncMemoize.fsi b/src/Compiler/Facilities/AsyncMemoize.fsi index a34588e7af8..640d114bdea 100644 --- a/src/Compiler/Facilities/AsyncMemoize.fsi +++ b/src/Compiler/Facilities/AsyncMemoize.fsi @@ -69,6 +69,10 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T member Get': key: 'TKey * computation: NodeCode<'TValue> -> NodeCode<'TValue> + member TryGet: key: 'TKey -> 'TValue option + + member Set: key: 'TKey * value: 'TValue -> unit + member Event: IEvent member OnEvent: ((JobEvent * (string * 'TKey * 'TVersion) -> unit) -> unit) diff --git a/src/Compiler/Service/BackgroundCompiler.fs b/src/Compiler/Service/BackgroundCompiler.fs index f9f952dde70..eb1f650c296 100644 --- a/src/Compiler/Service/BackgroundCompiler.fs +++ b/src/Compiler/Service/BackgroundCompiler.fs @@ -163,6 +163,10 @@ type internal IBackgroundCompiler = fileName: string * options: FSharpProjectOptions * sourceText: ISourceText option * userOpName: string -> (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option + abstract member TryGetRecentCheckResultsForFile: + fileName: string * projectSnapshot: FSharpProjectSnapshot * sourceText: ISourceText option * userOpName: string -> + (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option + abstract member BeforeBackgroundFileCheck: IEvent abstract member FileChecked: IEvent @@ -1158,6 +1162,16 @@ type internal BackgroundCompiler | None -> None | None -> None + member _.TryGetRecentCheckResultsForFile + ( + fileName: string, + projectSnapshot: FSharpProjectSnapshot, + sourceText: ISourceText option, + userOpName: string + ) = + let options = projectSnapshot.ToOptions() + self.TryGetRecentCheckResultsForFile(fileName, options, sourceText, userOpName) + /// Parse and typecheck the whole project (the implementation, called recursively as project graph is evaluated) member private _.ParseAndCheckProjectImpl(options, userOpName) = node { @@ -1678,3 +1692,12 @@ type internal BackgroundCompiler userOpName: string ) : (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option = self.TryGetRecentCheckResultsForFile(fileName, options, sourceText, userOpName) + + member _.TryGetRecentCheckResultsForFile + ( + fileName: string, + projectSnapshot: FSharpProjectSnapshot, + sourceText: ISourceText option, + userOpName: string + ) : (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option = + self.TryGetRecentCheckResultsForFile(fileName, projectSnapshot, sourceText, userOpName) diff --git a/src/Compiler/Service/BackgroundCompiler.fsi b/src/Compiler/Service/BackgroundCompiler.fsi index f3bf3c96ccc..d87498407cf 100644 --- a/src/Compiler/Service/BackgroundCompiler.fsi +++ b/src/Compiler/Service/BackgroundCompiler.fsi @@ -153,6 +153,10 @@ type internal IBackgroundCompiler = fileName: string * options: FSharpProjectOptions * sourceText: ISourceText option * userOpName: string -> (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option + abstract TryGetRecentCheckResultsForFile: + fileName: string * projectSnapshot: FSharpProjectSnapshot * sourceText: ISourceText option * userOpName: string -> + (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option + abstract BeforeBackgroundFileCheck: IEvent abstract FileChecked: IEvent diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index b117fef1bf6..948919c9043 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -272,6 +272,8 @@ type internal CompilerCaches(sizeFactor: int) = member val ParseAndCheckProject = AsyncMemoize(sf, 2 * sf, name = "ParseAndCheckProject") + member val RecentCheckFileResults = AsyncMemoize(sf, 2 * sf, name = "RecentCheckFileResults") + member val FrameworkImports = AsyncMemoize(sf, 2 * sf, name = "FrameworkImports") member val BootstrapInfoStatic = AsyncMemoize(sf, 2 * sf, name = "BootstrapInfoStatic") @@ -306,7 +308,8 @@ type internal CompilerCaches(sizeFactor: int) = this.AssemblyData.Clear(shouldClear) this.SemanticClassification.Clear(snd >> shouldClear) this.ItemKeyStore.Clear(snd >> shouldClear) - this.ScriptClosure.Clear(snd >> shouldClear) // Todo check if correct predicate + this.ScriptClosure.Clear(snd >> shouldClear) + this.RecentCheckFileResults.Clear(fun (_, _, i) -> shouldClear i) type internal TransparentCompiler ( @@ -1549,6 +1552,14 @@ type internal TransparentCompiler tcOpenDeclarations ) + let recentCheckFileKey = + (fileName, file.Source.GetHashCode() |> int64, projectSnapshot.Identifier) + + let recentCheckFileValue = + (parseResults, typedResults, file.Source.GetHashCode() |> int64) + + caches.RecentCheckFileResults.Set(recentCheckFileKey, recentCheckFileValue) + return (parseResults, FSharpCheckFileAnswer.Succeeded typedResults) } ) @@ -1575,6 +1586,24 @@ type internal TransparentCompiler } ) + let TryGetRecentCheckResultsForFile + ( + fileName: string, + projectSnapshot: FSharpProjectSnapshot, + sourceText: ISourceText option, + userOpName: string + ) : (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option = + ignore userOpName + + match sourceText with + | None -> None + | Some t -> + let key = + (fileName, t.GetHashCode() |> int64, projectSnapshot.ProjectSnapshot.Identifier) + + let v = caches.RecentCheckFileResults.TryGet(key) + v + let ComputeProjectExtras (bootstrapInfo: BootstrapInfo) (projectSnapshot: ProjectSnapshotWithSources) = caches.ProjectExtras.Get( projectSnapshot.SignatureKey, @@ -2201,3 +2230,12 @@ type internal TransparentCompiler userOpName: string ) : (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option = backgroundCompiler.TryGetRecentCheckResultsForFile(fileName, options, sourceText, userOpName) + + member this.TryGetRecentCheckResultsForFile + ( + fileName: string, + projectSnapshot: FSharpProjectSnapshot, + sourceText: ISourceText option, + userOpName: string + ) : (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option = + TryGetRecentCheckResultsForFile(fileName, projectSnapshot, sourceText, userOpName) diff --git a/src/Compiler/Service/TransparentCompiler.fsi b/src/Compiler/Service/TransparentCompiler.fsi index 9aa5929566c..39564063646 100644 --- a/src/Compiler/Service/TransparentCompiler.fsi +++ b/src/Compiler/Service/TransparentCompiler.fsi @@ -5,6 +5,7 @@ open Internal.Utilities.Collections open FSharp.Compiler.AbstractIL.ILBinaryReader open FSharp.Compiler.BuildGraph open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.CodeAnalysis.ProjectSnapshot open FSharp.Compiler.CompilerConfig open FSharp.Compiler.CompilerImports open FSharp.Compiler.CheckBasics @@ -122,6 +123,11 @@ type internal CompilerCaches = member ParseAndCheckProject: AsyncMemoize<(string * string), string, FSharpCheckProjectResults> + member RecentCheckFileResults: + AsyncMemoize + member ParseFile: AsyncMemoize<((string * string) * string), (string * string * bool), ProjectSnapshot.FSharpParsedFile> diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs index 803755ab13f..af954024bcf 100644 --- a/src/Compiler/Service/service.fs +++ b/src/Compiler/Service/service.fs @@ -338,6 +338,10 @@ type FSharpChecker let userOpName = defaultArg userOpName "Unknown" backgroundCompiler.TryGetRecentCheckResultsForFile(fileName, options, sourceText, userOpName) + member _.TryGetRecentCheckResultsForFile(fileName: string, projectSnapshot: FSharpProjectSnapshot, ?sourceText, ?userOpName: string) = + let userOpName = defaultArg userOpName "Unknown" + backgroundCompiler.TryGetRecentCheckResultsForFile(fileName, projectSnapshot, sourceText, userOpName) + member _.Compile(argv: string[], ?userOpName: string) = let _userOpName = defaultArg userOpName "Unknown" use _ = Activity.start "FSharpChecker.Compile" [| Activity.Tags.userOpName, _userOpName |] diff --git a/src/Compiler/Service/service.fsi b/src/Compiler/Service/service.fsi index e74249cd604..e84a2ad04a2 100644 --- a/src/Compiler/Service/service.fsi +++ b/src/Compiler/Service/service.fsi @@ -393,6 +393,11 @@ type public FSharpChecker = fileName: string * options: FSharpProjectOptions * ?sourceText: ISourceText * ?userOpName: string -> (FSharpParseFileResults * FSharpCheckFileResults (* hash *) * int64) option + [] + member TryGetRecentCheckResultsForFile: + fileName: string * projectSnapshot: FSharpProjectSnapshot * ?sourceText: ISourceText * ?userOpName: string -> + (FSharpParseFileResults * FSharpCheckFileResults (* hash *) * int64) option + /// This function is called when the entire environment is known to have changed for reasons not encoded in the ProjectOptions of any project/compilation. member InvalidateAll: unit -> unit diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl index da61adbe19b..1447c8aaada 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl @@ -2077,6 +2077,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Mi FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Microsoft.FSharp.Control.FSharpHandler`1[System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]],System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]] get_FileChecked() FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Microsoft.FSharp.Control.FSharpHandler`1[System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]],System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]] get_FileParsed() FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults,System.Int64]] TryGetRecentCheckResultsForFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.ISourceText], Microsoft.FSharp.Core.FSharpOption`1[System.String]) +FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults,System.Int64]] TryGetRecentCheckResultsForFile(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.ISourceText], Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParsingOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]] GetParsingOptionsFromCommandLineArgs(Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParsingOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]] GetParsingOptionsFromCommandLineArgs(Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParsingOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]] GetParsingOptionsFromProjectOptions(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions) diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl index da61adbe19b..1447c8aaada 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl @@ -2077,6 +2077,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Mi FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Microsoft.FSharp.Control.FSharpHandler`1[System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]],System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]] get_FileChecked() FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Microsoft.FSharp.Control.FSharpHandler`1[System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]],System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]] get_FileParsed() FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults,System.Int64]] TryGetRecentCheckResultsForFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.ISourceText], Microsoft.FSharp.Core.FSharpOption`1[System.String]) +FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults,System.Int64]] TryGetRecentCheckResultsForFile(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.ISourceText], Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParsingOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]] GetParsingOptionsFromCommandLineArgs(Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParsingOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]] GetParsingOptionsFromCommandLineArgs(Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParsingOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]] GetParsingOptionsFromProjectOptions(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions) From d7c9258323f72410a6c4d0903d6bcd57a2143001 Mon Sep 17 00:00:00 2001 From: dawe Date: Fri, 16 Feb 2024 09:09:47 +0100 Subject: [PATCH 02/26] use version type without defaultof<_> = null --- src/Compiler/Service/TransparentCompiler.fs | 2 +- src/Compiler/Service/TransparentCompiler.fsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index 948919c9043..de37cad6770 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -272,7 +272,7 @@ type internal CompilerCaches(sizeFactor: int) = member val ParseAndCheckProject = AsyncMemoize(sf, 2 * sf, name = "ParseAndCheckProject") - member val RecentCheckFileResults = AsyncMemoize(sf, 2 * sf, name = "RecentCheckFileResults") + member val RecentCheckFileResults: AsyncMemoize<_, int, _> = AsyncMemoize(sf, 2 * sf, name = "RecentCheckFileResults") member val FrameworkImports = AsyncMemoize(sf, 2 * sf, name = "FrameworkImports") diff --git a/src/Compiler/Service/TransparentCompiler.fsi b/src/Compiler/Service/TransparentCompiler.fsi index 39564063646..cf321f07f0f 100644 --- a/src/Compiler/Service/TransparentCompiler.fsi +++ b/src/Compiler/Service/TransparentCompiler.fsi @@ -124,7 +124,7 @@ type internal CompilerCaches = member ParseAndCheckProject: AsyncMemoize<(string * string), string, FSharpCheckProjectResults> member RecentCheckFileResults: - AsyncMemoize From cdcff87d393583fdb9d15ac9658f5f27dae460ea Mon Sep 17 00:00:00 2001 From: dawe Date: Fri, 16 Feb 2024 09:50:34 +0100 Subject: [PATCH 03/26] take sourcetext out of project snapshot, kind of forces us to an async return but let's see if this is acceptable --- src/Compiler/Service/BackgroundCompiler.fs | 22 +++++++++------ src/Compiler/Service/BackgroundCompiler.fsi | 4 +-- src/Compiler/Service/TransparentCompiler.fs | 27 +++++++++---------- src/Compiler/Service/service.fs | 4 +-- src/Compiler/Service/service.fsi | 4 +-- ...ervice.SurfaceArea.netstandard20.debug.bsl | 2 +- ...vice.SurfaceArea.netstandard20.release.bsl | 2 +- 7 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/Compiler/Service/BackgroundCompiler.fs b/src/Compiler/Service/BackgroundCompiler.fs index eb1f650c296..bac01f344a9 100644 --- a/src/Compiler/Service/BackgroundCompiler.fs +++ b/src/Compiler/Service/BackgroundCompiler.fs @@ -164,8 +164,8 @@ type internal IBackgroundCompiler = (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option abstract member TryGetRecentCheckResultsForFile: - fileName: string * projectSnapshot: FSharpProjectSnapshot * sourceText: ISourceText option * userOpName: string -> - (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option + fileName: string * projectSnapshot: FSharpProjectSnapshot * userOpName: string -> + Async<(FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option> abstract member BeforeBackgroundFileCheck: IEvent @@ -1166,11 +1166,18 @@ type internal BackgroundCompiler ( fileName: string, projectSnapshot: FSharpProjectSnapshot, - sourceText: ISourceText option, userOpName: string ) = - let options = projectSnapshot.ToOptions() - self.TryGetRecentCheckResultsForFile(fileName, options, sourceText, userOpName) + let file = + projectSnapshot.ProjectSnapshot.SourceFiles |> List.tryFind(fun f -> f.FileName = fileName) + match file with + | Some f -> + async { + let options = projectSnapshot.ToOptions() + let! sourceText = f.GetSource() |> Async.AwaitTask + return self.TryGetRecentCheckResultsForFile(fileName, options, Some sourceText, userOpName) + } + | None -> async.Return None /// Parse and typecheck the whole project (the implementation, called recursively as project graph is evaluated) member private _.ParseAndCheckProjectImpl(options, userOpName) = @@ -1697,7 +1704,6 @@ type internal BackgroundCompiler ( fileName: string, projectSnapshot: FSharpProjectSnapshot, - sourceText: ISourceText option, userOpName: string - ) : (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option = - self.TryGetRecentCheckResultsForFile(fileName, projectSnapshot, sourceText, userOpName) + ) : Async<(FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option> = + self.TryGetRecentCheckResultsForFile(fileName, projectSnapshot, userOpName) diff --git a/src/Compiler/Service/BackgroundCompiler.fsi b/src/Compiler/Service/BackgroundCompiler.fsi index d87498407cf..fea62f16797 100644 --- a/src/Compiler/Service/BackgroundCompiler.fsi +++ b/src/Compiler/Service/BackgroundCompiler.fsi @@ -154,8 +154,8 @@ type internal IBackgroundCompiler = (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option abstract TryGetRecentCheckResultsForFile: - fileName: string * projectSnapshot: FSharpProjectSnapshot * sourceText: ISourceText option * userOpName: string -> - (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option + fileName: string * projectSnapshot: FSharpProjectSnapshot * userOpName: string -> + Async<(FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option> abstract BeforeBackgroundFileCheck: IEvent diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index de37cad6770..0582e1f2bd6 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -1590,19 +1590,19 @@ type internal TransparentCompiler ( fileName: string, projectSnapshot: FSharpProjectSnapshot, - sourceText: ISourceText option, userOpName: string - ) : (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option = + ) : Async<(FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option> = ignore userOpName - - match sourceText with - | None -> None - | Some t -> - let key = - (fileName, t.GetHashCode() |> int64, projectSnapshot.ProjectSnapshot.Identifier) - - let v = caches.RecentCheckFileResults.TryGet(key) - v + let file = projectSnapshot.ProjectSnapshot.SourceFiles |> List.tryFind(fun f -> f.FileName = fileName) + match file with + | Some f -> + async { + let! sourceText = f.GetSource() |> Async.AwaitTask + let key = (fileName, sourceText.GetHashCode() |> int64, projectSnapshot.ProjectSnapshot.Identifier) + let v = caches.RecentCheckFileResults.TryGet(key) + return v + } + | None -> async.Return None let ComputeProjectExtras (bootstrapInfo: BootstrapInfo) (projectSnapshot: ProjectSnapshotWithSources) = caches.ProjectExtras.Get( @@ -2235,7 +2235,6 @@ type internal TransparentCompiler ( fileName: string, projectSnapshot: FSharpProjectSnapshot, - sourceText: ISourceText option, userOpName: string - ) : (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option = - TryGetRecentCheckResultsForFile(fileName, projectSnapshot, sourceText, userOpName) + ) : Async<(FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option> = + TryGetRecentCheckResultsForFile(fileName, projectSnapshot, userOpName) diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs index af954024bcf..ecbf500a9bb 100644 --- a/src/Compiler/Service/service.fs +++ b/src/Compiler/Service/service.fs @@ -338,9 +338,9 @@ type FSharpChecker let userOpName = defaultArg userOpName "Unknown" backgroundCompiler.TryGetRecentCheckResultsForFile(fileName, options, sourceText, userOpName) - member _.TryGetRecentCheckResultsForFile(fileName: string, projectSnapshot: FSharpProjectSnapshot, ?sourceText, ?userOpName: string) = + member _.TryGetRecentCheckResultsForFile(fileName: string, projectSnapshot: FSharpProjectSnapshot, ?userOpName: string) = let userOpName = defaultArg userOpName "Unknown" - backgroundCompiler.TryGetRecentCheckResultsForFile(fileName, projectSnapshot, sourceText, userOpName) + backgroundCompiler.TryGetRecentCheckResultsForFile(fileName, projectSnapshot, userOpName) member _.Compile(argv: string[], ?userOpName: string) = let _userOpName = defaultArg userOpName "Unknown" diff --git a/src/Compiler/Service/service.fsi b/src/Compiler/Service/service.fsi index e84a2ad04a2..dbd1fe8067a 100644 --- a/src/Compiler/Service/service.fsi +++ b/src/Compiler/Service/service.fsi @@ -395,8 +395,8 @@ type public FSharpChecker = [] member TryGetRecentCheckResultsForFile: - fileName: string * projectSnapshot: FSharpProjectSnapshot * ?sourceText: ISourceText * ?userOpName: string -> - (FSharpParseFileResults * FSharpCheckFileResults (* hash *) * int64) option + fileName: string * projectSnapshot: FSharpProjectSnapshot * ?userOpName: string -> + Async<(FSharpParseFileResults * FSharpCheckFileResults (* hash *) * int64) option> /// This function is called when the entire environment is known to have changed for reasons not encoded in the ProjectOptions of any project/compilation. member InvalidateAll: unit -> unit diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl index 1447c8aaada..64628ca7254 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl @@ -2057,6 +2057,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer]] CheckFileInProjectAllowingStaleCachedResults(FSharp.Compiler.CodeAnalysis.FSharpParseFileResults, System.String, Int32, System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.EditorServices.SemanticClassificationView]] GetBackgroundSemanticClassificationForFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.EditorServices.SemanticClassificationView]] GetBackgroundSemanticClassificationForFile(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) +FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults,System.Int64]]] TryGetRecentCheckResultsForFile(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit] NotifyFileChanged(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit] NotifyProjectCleaned(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Collections.Generic.IEnumerable`1[FSharp.Compiler.Text.Range]] FindBackgroundReferencesInFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, FSharp.Compiler.Symbols.FSharpSymbol, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String]) @@ -2077,7 +2078,6 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Mi FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Microsoft.FSharp.Control.FSharpHandler`1[System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]],System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]] get_FileChecked() FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Microsoft.FSharp.Control.FSharpHandler`1[System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]],System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]] get_FileParsed() FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults,System.Int64]] TryGetRecentCheckResultsForFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.ISourceText], Microsoft.FSharp.Core.FSharpOption`1[System.String]) -FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults,System.Int64]] TryGetRecentCheckResultsForFile(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.ISourceText], Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParsingOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]] GetParsingOptionsFromCommandLineArgs(Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParsingOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]] GetParsingOptionsFromCommandLineArgs(Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParsingOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]] GetParsingOptionsFromProjectOptions(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions) diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl index 1447c8aaada..64628ca7254 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl @@ -2057,6 +2057,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer]] CheckFileInProjectAllowingStaleCachedResults(FSharp.Compiler.CodeAnalysis.FSharpParseFileResults, System.String, Int32, System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.EditorServices.SemanticClassificationView]] GetBackgroundSemanticClassificationForFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.EditorServices.SemanticClassificationView]] GetBackgroundSemanticClassificationForFile(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) +FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults,System.Int64]]] TryGetRecentCheckResultsForFile(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit] NotifyFileChanged(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit] NotifyProjectCleaned(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Collections.Generic.IEnumerable`1[FSharp.Compiler.Text.Range]] FindBackgroundReferencesInFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, FSharp.Compiler.Symbols.FSharpSymbol, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String]) @@ -2077,7 +2078,6 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Mi FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Microsoft.FSharp.Control.FSharpHandler`1[System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]],System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]] get_FileChecked() FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Microsoft.FSharp.Control.FSharpHandler`1[System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]],System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]] get_FileParsed() FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults,System.Int64]] TryGetRecentCheckResultsForFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.ISourceText], Microsoft.FSharp.Core.FSharpOption`1[System.String]) -FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults,System.Int64]] TryGetRecentCheckResultsForFile(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.ISourceText], Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParsingOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]] GetParsingOptionsFromCommandLineArgs(Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParsingOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]] GetParsingOptionsFromCommandLineArgs(Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParsingOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]] GetParsingOptionsFromProjectOptions(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions) From 0672b64c061d9a1322bcd24cdc37d4a442e64ebc Mon Sep 17 00:00:00 2001 From: dawe Date: Fri, 16 Feb 2024 09:59:12 +0100 Subject: [PATCH 04/26] format --- src/Compiler/Service/BackgroundCompiler.fs | 29 +++++++++------------ src/Compiler/Service/TransparentCompiler.fs | 24 ++++++++++------- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/src/Compiler/Service/BackgroundCompiler.fs b/src/Compiler/Service/BackgroundCompiler.fs index bac01f344a9..0db634d7f8c 100644 --- a/src/Compiler/Service/BackgroundCompiler.fs +++ b/src/Compiler/Service/BackgroundCompiler.fs @@ -1162,22 +1162,19 @@ type internal BackgroundCompiler | None -> None | None -> None - member _.TryGetRecentCheckResultsForFile - ( - fileName: string, - projectSnapshot: FSharpProjectSnapshot, - userOpName: string - ) = - let file = - projectSnapshot.ProjectSnapshot.SourceFiles |> List.tryFind(fun f -> f.FileName = fileName) - match file with - | Some f -> - async { - let options = projectSnapshot.ToOptions() - let! sourceText = f.GetSource() |> Async.AwaitTask - return self.TryGetRecentCheckResultsForFile(fileName, options, Some sourceText, userOpName) - } - | None -> async.Return None + member _.TryGetRecentCheckResultsForFile(fileName: string, projectSnapshot: FSharpProjectSnapshot, userOpName: string) = + let file = + projectSnapshot.ProjectSnapshot.SourceFiles + |> List.tryFind (fun f -> f.FileName = fileName) + + match file with + | Some f -> + async { + let options = projectSnapshot.ToOptions() + let! sourceText = f.GetSource() |> Async.AwaitTask + return self.TryGetRecentCheckResultsForFile(fileName, options, Some sourceText, userOpName) + } + | None -> async.Return None /// Parse and typecheck the whole project (the implementation, called recursively as project graph is evaluated) member private _.ParseAndCheckProjectImpl(options, userOpName) = diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index 0582e1f2bd6..f9cb0c929a7 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -1593,16 +1593,22 @@ type internal TransparentCompiler userOpName: string ) : Async<(FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option> = ignore userOpName - let file = projectSnapshot.ProjectSnapshot.SourceFiles |> List.tryFind(fun f -> f.FileName = fileName) + + let file = + projectSnapshot.ProjectSnapshot.SourceFiles + |> List.tryFind (fun f -> f.FileName = fileName) + match file with - | Some f -> - async { - let! sourceText = f.GetSource() |> Async.AwaitTask - let key = (fileName, sourceText.GetHashCode() |> int64, projectSnapshot.ProjectSnapshot.Identifier) - let v = caches.RecentCheckFileResults.TryGet(key) - return v - } - | None -> async.Return None + | Some f -> + async { + let! sourceText = f.GetSource() |> Async.AwaitTask + + let key = + (fileName, sourceText.GetHashCode() |> int64, projectSnapshot.ProjectSnapshot.Identifier) + + return caches.RecentCheckFileResults.TryGet(key) + } + | None -> async.Return None let ComputeProjectExtras (bootstrapInfo: BootstrapInfo) (projectSnapshot: ProjectSnapshotWithSources) = caches.ProjectExtras.Get( From 0a13fa55190ccdfbd5e71d5b1f30a6f3e1dd07e9 Mon Sep 17 00:00:00 2001 From: dawe Date: Sat, 17 Feb 2024 09:23:26 +0100 Subject: [PATCH 05/26] - reuse ParseAndCheckFileInProject cache for TryGetRecentCheckResultsForFile - extend version of ParseAndCheckFileInProject cache with the check sum of the source code - add test --- src/Compiler/Facilities/AsyncMemoize.fs | 18 +- src/Compiler/Facilities/AsyncMemoize.fsi | 4 +- src/Compiler/Service/TransparentCompiler.fs | 269 +++++++++++-------- src/Compiler/Service/TransparentCompiler.fsi | 8 +- tests/service/ProjectAnalysisTests.fs | 62 +++++ 5 files changed, 224 insertions(+), 137 deletions(-) diff --git a/src/Compiler/Facilities/AsyncMemoize.fs b/src/Compiler/Facilities/AsyncMemoize.fs index cc9e01b3726..835f824762e 100644 --- a/src/Compiler/Facilities/AsyncMemoize.fs +++ b/src/Compiler/Facilities/AsyncMemoize.fs @@ -534,16 +534,14 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T } - member _.TryGet(key) = - let x = cache.TryGet(key) - - match x with - | Some(Completed(value, _)) -> Some value - | _ -> None - - member _.Set(key, value) = - let v = Job.Completed(value, []) - cache.Set(key, v) + member _.TryGet(key: 'TKey, dummyVersion: 'TVersion, predicate: 'TVersion -> bool) : 'TValue option = + let _, versionsAndJobs = cache.GetAll(key, dummyVersion) + + versionsAndJobs + |> Seq.tryPick (fun (version, job) -> + match predicate version, job with + | true, Completed(completed, _) -> Some completed + | _ -> None) member _.Clear() = cache.Clear() diff --git a/src/Compiler/Facilities/AsyncMemoize.fsi b/src/Compiler/Facilities/AsyncMemoize.fsi index 640d114bdea..ff57328eb88 100644 --- a/src/Compiler/Facilities/AsyncMemoize.fsi +++ b/src/Compiler/Facilities/AsyncMemoize.fsi @@ -69,9 +69,7 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T member Get': key: 'TKey * computation: NodeCode<'TValue> -> NodeCode<'TValue> - member TryGet: key: 'TKey -> 'TValue option - - member Set: key: 'TKey * value: 'TValue -> unit + member TryGet: key: 'TKey * dummyVersion: 'TVersion * predicate: ('TVersion -> bool) -> 'TValue option member Event: IEvent diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index f9cb0c929a7..ea28b97ddbe 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -272,8 +272,6 @@ type internal CompilerCaches(sizeFactor: int) = member val ParseAndCheckProject = AsyncMemoize(sf, 2 * sf, name = "ParseAndCheckProject") - member val RecentCheckFileResults: AsyncMemoize<_, int, _> = AsyncMemoize(sf, 2 * sf, name = "RecentCheckFileResults") - member val FrameworkImports = AsyncMemoize(sf, 2 * sf, name = "FrameworkImports") member val BootstrapInfoStatic = AsyncMemoize(sf, 2 * sf, name = "BootstrapInfoStatic") @@ -309,7 +307,6 @@ type internal CompilerCaches(sizeFactor: int) = this.SemanticClassification.Clear(snd >> shouldClear) this.ItemKeyStore.Clear(snd >> shouldClear) this.ScriptClosure.Clear(snd >> shouldClear) - this.RecentCheckFileResults.Clear(fun (_, _, i) -> shouldClear i) type internal TransparentCompiler ( @@ -1446,123 +1443,141 @@ type internal TransparentCompiler FSharpParseFileResults(diagnostics, parseTree, true, [||]) let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: ProjectSnapshot) = - caches.ParseAndCheckFileInProject.Get( - projectSnapshot.FileKey fileName, - node { - - use _ = - Activity.start "ComputeParseAndCheckFileInProject" [| Activity.Tags.fileName, fileName |> Path.GetFileName |] - - match! ComputeBootstrapInfo projectSnapshot with - | None, creationDiags -> return emptyParseResult fileName creationDiags, FSharpCheckFileAnswer.Aborted - - | Some bootstrapInfo, creationDiags -> - - let priorSnapshot = projectSnapshot.UpTo fileName - let! snapshotWithSources = LoadSources bootstrapInfo priorSnapshot - let file = snapshotWithSources.SourceFiles |> List.last - - let! parseResults = getParseResult projectSnapshot Seq.empty file bootstrapInfo.TcConfig - - let! result, tcInfo = ComputeTcLastFile bootstrapInfo snapshotWithSources - - let (tcEnv, _topAttribs, checkedImplFileOpt, ccuSigForFile) = result - - let tcState = tcInfo.tcState - - let sink = tcInfo.sink.Head // TODO: don't use head - - let tcResolutions = sink.GetResolutions() - let tcSymbolUses = sink.GetSymbolUses() - let tcOpenDeclarations = sink.GetOpenDeclarations() - - // TODO: Apparently creating diagnostics can produce further diagnostics. So let's capture those too. Hopefully there is a more elegant solution... - // Probably diagnostics need to be evaluated during typecheck anyway for proper formatting, which might take care of this too. - let extraLogger = CapturingDiagnosticsLogger("DiagnosticsWhileCreatingDiagnostics") - use _ = new CompilationGlobalsScope(extraLogger, BuildPhase.TypeCheck) - - // Apply nowarns to tcConfig (may generate errors, so ensure diagnosticsLogger is installed) - let tcConfig = - ApplyNoWarnsToTcConfig(bootstrapInfo.TcConfig, parseResults.ParseTree, Path.GetDirectoryName fileName) - - let diagnosticsOptions = tcConfig.diagnosticsOptions - - let symbolEnv = - SymbolEnv(bootstrapInfo.TcGlobals, tcState.Ccu, Some tcState.CcuSig, bootstrapInfo.TcImports) - - let tcDiagnostics = - DiagnosticHelpers.CreateDiagnostics( - diagnosticsOptions, - false, - fileName, - tcInfo.TcDiagnostics, - suggestNamesForErrors, - bootstrapInfo.TcConfig.flatErrors, - Some symbolEnv - ) + node { + let fileKey = projectSnapshot.FileKey fileName - let extraDiagnostics = - DiagnosticHelpers.CreateDiagnostics( - diagnosticsOptions, - false, - fileName, - extraLogger.Diagnostics, - suggestNamesForErrors, - bootstrapInfo.TcConfig.flatErrors, - Some symbolEnv - ) + let file = + projectSnapshot.SourceFiles |> List.tryFind (fun f -> f.FileName = fileName) - let tcDiagnostics = [| yield! extraDiagnostics; yield! tcDiagnostics |] - - let! loadClosure = - ComputeScriptClosure - fileName - file.Source - tcConfig.fsharpBinariesDir - tcConfig.useSimpleResolution - (Some tcConfig.useFsiAuxLib) - (Some tcConfig.useSdkRefs) - tcConfig.sdkDirOverride - (Some tcConfig.assumeDotNetFramework) - projectSnapshot - - let typedResults = - FSharpCheckFileResults.Make( - fileName, - projectSnapshot.ProjectFileName, - bootstrapInfo.TcConfig, - bootstrapInfo.TcGlobals, - projectSnapshot.IsIncompleteTypeCheckEnvironment, - None, - projectSnapshot.ToOptions(), - Array.ofList tcInfo.tcDependencyFiles, - creationDiags, - parseResults.Diagnostics, - tcDiagnostics, - keepAssemblyContents, - ccuSigForFile, - tcState.Ccu, - bootstrapInfo.TcImports, - tcEnv.AccessRights, - tcResolutions, - tcSymbolUses, - tcEnv.NameEnv, - Some loadClosure, - checkedImplFileOpt, - tcOpenDeclarations - ) + match file with + | None -> return emptyParseResult fileName [||], FSharpCheckFileAnswer.Aborted + | Some f -> + let! source = f.GetSource() |> NodeCode.AwaitTask - let recentCheckFileKey = - (fileName, file.Source.GetHashCode() |> int64, projectSnapshot.Identifier) + let cacheKey = + { new ICacheKey<_, _> with + member _.GetLabel() = $"{fileName} ({projectSnapshot.Label})" - let recentCheckFileValue = - (parseResults, typedResults, file.Source.GetHashCode() |> int64) + member _.GetKey() = + fileName, projectSnapshot.ProjectCore.Identifier - caches.RecentCheckFileResults.Set(recentCheckFileKey, recentCheckFileValue) + member _.GetVersion() = + fileKey.GetVersion(), source.GetHashCode() |> int64 + } - return (parseResults, FSharpCheckFileAnswer.Succeeded typedResults) - } - ) + return! + caches.ParseAndCheckFileInProject.Get( + cacheKey, + node { + + use _ = + Activity.start + "ComputeParseAndCheckFileInProject" + [| Activity.Tags.fileName, fileName |> Path.GetFileName |] + + match! ComputeBootstrapInfo projectSnapshot with + | None, creationDiags -> return emptyParseResult fileName creationDiags, FSharpCheckFileAnswer.Aborted + + | Some bootstrapInfo, creationDiags -> + + let priorSnapshot = projectSnapshot.UpTo fileName + let! snapshotWithSources = LoadSources bootstrapInfo priorSnapshot + let file = snapshotWithSources.SourceFiles |> List.last + + let! parseResults = getParseResult projectSnapshot Seq.empty file bootstrapInfo.TcConfig + + let! result, tcInfo = ComputeTcLastFile bootstrapInfo snapshotWithSources + + let (tcEnv, _topAttribs, checkedImplFileOpt, ccuSigForFile) = result + + let tcState = tcInfo.tcState + + let sink = tcInfo.sink.Head // TODO: don't use head + + let tcResolutions = sink.GetResolutions() + let tcSymbolUses = sink.GetSymbolUses() + let tcOpenDeclarations = sink.GetOpenDeclarations() + + // TODO: Apparently creating diagnostics can produce further diagnostics. So let's capture those too. Hopefully there is a more elegant solution... + // Probably diagnostics need to be evaluated during typecheck anyway for proper formatting, which might take care of this too. + let extraLogger = CapturingDiagnosticsLogger("DiagnosticsWhileCreatingDiagnostics") + use _ = new CompilationGlobalsScope(extraLogger, BuildPhase.TypeCheck) + + // Apply nowarns to tcConfig (may generate errors, so ensure diagnosticsLogger is installed) + let tcConfig = + ApplyNoWarnsToTcConfig(bootstrapInfo.TcConfig, parseResults.ParseTree, Path.GetDirectoryName fileName) + + let diagnosticsOptions = tcConfig.diagnosticsOptions + + let symbolEnv = + SymbolEnv(bootstrapInfo.TcGlobals, tcState.Ccu, Some tcState.CcuSig, bootstrapInfo.TcImports) + + let tcDiagnostics = + DiagnosticHelpers.CreateDiagnostics( + diagnosticsOptions, + false, + fileName, + tcInfo.TcDiagnostics, + suggestNamesForErrors, + bootstrapInfo.TcConfig.flatErrors, + Some symbolEnv + ) + + let extraDiagnostics = + DiagnosticHelpers.CreateDiagnostics( + diagnosticsOptions, + false, + fileName, + extraLogger.Diagnostics, + suggestNamesForErrors, + bootstrapInfo.TcConfig.flatErrors, + Some symbolEnv + ) + + let tcDiagnostics = [| yield! extraDiagnostics; yield! tcDiagnostics |] + + let! loadClosure = + ComputeScriptClosure + fileName + file.Source + tcConfig.fsharpBinariesDir + tcConfig.useSimpleResolution + (Some tcConfig.useFsiAuxLib) + (Some tcConfig.useSdkRefs) + tcConfig.sdkDirOverride + (Some tcConfig.assumeDotNetFramework) + projectSnapshot + + let typedResults = + FSharpCheckFileResults.Make( + fileName, + projectSnapshot.ProjectFileName, + bootstrapInfo.TcConfig, + bootstrapInfo.TcGlobals, + projectSnapshot.IsIncompleteTypeCheckEnvironment, + None, + projectSnapshot.ToOptions(), + Array.ofList tcInfo.tcDependencyFiles, + creationDiags, + parseResults.Diagnostics, + tcDiagnostics, + keepAssemblyContents, + ccuSigForFile, + tcState.Ccu, + bootstrapInfo.TcImports, + tcEnv.AccessRights, + tcResolutions, + tcSymbolUses, + tcEnv.NameEnv, + Some loadClosure, + checkedImplFileOpt, + tcOpenDeclarations + ) + + return (parseResults, FSharpCheckFileAnswer.Succeeded typedResults) + } + ) + } let ComputeParseAndCheckAllFilesInProject (bootstrapInfo: BootstrapInfo) (projectSnapshot: ProjectSnapshotWithSources) = caches.ParseAndCheckAllFilesInProject.Get( @@ -1601,12 +1616,30 @@ type internal TransparentCompiler match file with | Some f -> async { - let! sourceText = f.GetSource() |> Async.AwaitTask + let! source = f.GetSource() |> Async.AwaitTask + let fileKey = projectSnapshot.ProjectSnapshot.FileKey fileName + let sourceHash = source.GetHashCode() |> int64 + + let cacheKey = + { new ICacheKey<_, _> with + member _.GetLabel() = $"{fileName} ({projectSnapshot.Label})" + + member _.GetKey() = + fileName, projectSnapshot.ProjectSnapshot.ProjectCore.Identifier + + member _.GetVersion() = + fileKey.GetVersion(), sourceHash + } - let key = - (fileName, sourceText.GetHashCode() |> int64, projectSnapshot.ProjectSnapshot.Identifier) + let parseFileResultsAndcheckFileAnswer = + let version = cacheKey.GetVersion() + let _, _ba = version + caches.ParseAndCheckFileInProject.TryGet(cacheKey.GetKey(), ("", 0L), (fun v -> v = version)) - return caches.RecentCheckFileResults.TryGet(key) + match parseFileResultsAndcheckFileAnswer with + | Some(parseFileResults, FSharpCheckFileAnswer.Succeeded checkFileResults) -> + return Some(parseFileResults, checkFileResults, sourceHash) + | _ -> return None } | None -> async.Return None diff --git a/src/Compiler/Service/TransparentCompiler.fsi b/src/Compiler/Service/TransparentCompiler.fsi index cf321f07f0f..ce6fd1c344f 100644 --- a/src/Compiler/Service/TransparentCompiler.fsi +++ b/src/Compiler/Service/TransparentCompiler.fsi @@ -119,15 +119,11 @@ type internal CompilerCaches = member ParseAndCheckAllFilesInProject: AsyncMemoizeDisabled member ParseAndCheckFileInProject: - AsyncMemoize<(string * (string * string)), string, (FSharpParseFileResults * FSharpCheckFileAnswer)> + AsyncMemoize<(string * (string * string)), (string * SourceTextHash), (FSharpParseFileResults * + FSharpCheckFileAnswer)> member ParseAndCheckProject: AsyncMemoize<(string * string), string, FSharpCheckProjectResults> - member RecentCheckFileResults: - AsyncMemoize - member ParseFile: AsyncMemoize<((string * string) * string), (string * string * bool), ProjectSnapshot.FSharpParsedFile> diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs index 8a643c9a7bc..aa3c207ef88 100644 --- a/tests/service/ProjectAnalysisTests.fs +++ b/tests/service/ProjectAnalysisTests.fs @@ -7,6 +7,8 @@ module Tests.Service.ProjectAnalysisTests #endif +#nowarn "57" + let runningOnMono = try System.Type.GetType("Mono.Runtime") <> null with e -> false open NUnit.Framework @@ -5460,6 +5462,66 @@ type A(i:int) = | Some decl -> failwithf "unexpected declaration %A" decl | None -> failwith "declaration list is empty" +[] +[] +[] +let ``TryGetRecentCheckResultsForFile called with snapshot returns cached result after ParseAndCheckFile`` useTransparentCompiler = + let fileName1 = Path.ChangeExtension(tryCreateTemporaryFileName (), ".fs") + let base2 = tryCreateTemporaryFileName () + let dllName = Path.ChangeExtension(base2, ".dll") + let projFileName = Path.ChangeExtension(base2, ".fsproj") + let fileSource1Text = """ +type A(i:int) = + member x.Value = i +""" + let fileSource1 = SourceText.ofString fileSource1Text + FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1Text) + + let fileNames = [|fileName1|] + let args = mkProjectCommandLineArgs (dllName, []) + let checker = FSharpChecker.Create(useTransparentCompiler=useTransparentCompiler) + let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } + let snapshot = FSharpProjectSnapshot.FromOptions(options, DocumentSource.FileSystem) |> Async.RunImmediate + + let rbefore = checker.TryGetRecentCheckResultsForFile(fileName1, snapshot) |> Async.RunImmediate + match rbefore with + | Some(fileResults, checkFileResults, int64) -> failwith "cached results before ParseAndCheckFileInProject was called" + | None -> () + + checker.ParseAndCheckFileInProject(fileName1, snapshot) |> Async.RunImmediate + |> function + | _, FSharpCheckFileAnswer.Succeeded(res) -> () + | _ -> failwithf "Parsing aborted unexpectedly..." + + let rafterCheckResults = checker.TryGetRecentCheckResultsForFile(fileName1, snapshot) |> Async.RunImmediate + match rafterCheckResults with + | Some(fileResults, checkFileResults, hash) -> + Assert.AreEqual(fileSource1Text.GetHashCode() |> int64, hash) + | None -> failwith "no results from TryGetRecentCheckResultsForFile" + + let fileSource1TextEdited = """ +type A(i:int) = + member x.Value = i + member x.Value2 = 23 +""" + let fileSource1Edited = SourceText.ofString fileSource1TextEdited + FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1TextEdited) + + let rafterEditBefore2ndCheckResults = checker.TryGetRecentCheckResultsForFile(fileName1, snapshot) |> Async.RunImmediate + match rafterEditBefore2ndCheckResults with + | Some(fileResults, checkFileResults, hash) -> failwith "stale cache results from TryGetRecentCheckResultsForFile after edit" + | None -> () + + checker.ParseAndCheckFileInProject(fileName1, snapshot) |> Async.RunImmediate + |> function + | _, FSharpCheckFileAnswer.Succeeded(res) -> () + | _ -> failwithf "Parsing aborted unexpectedly..." + + let rafterEditAfter2ndCheckResults = checker.TryGetRecentCheckResultsForFile(fileName1, snapshot) |> Async.RunImmediate + match rafterEditAfter2ndCheckResults with + | Some(fileResults, checkFileResults, hash) -> + Assert.AreEqual(fileSource1TextEdited.GetHashCode() |> int64, hash) + | None -> failwith "no results from TryGetRecentCheckResultsForFile" [] [] From fa6cfd445ea93c7ce9544dea8636fc3d25e8b5ab Mon Sep 17 00:00:00 2001 From: dawe Date: Sat, 17 Feb 2024 17:19:56 +0100 Subject: [PATCH 06/26] format --- src/Compiler/Service/TransparentCompiler.fs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index ea28b97ddbe..25617b7f579 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -1627,8 +1627,7 @@ type internal TransparentCompiler member _.GetKey() = fileName, projectSnapshot.ProjectSnapshot.ProjectCore.Identifier - member _.GetVersion() = - fileKey.GetVersion(), sourceHash + member _.GetVersion() = fileKey.GetVersion(), sourceHash } let parseFileResultsAndcheckFileAnswer = From d98542ec8a40ade8575617e4f71f529f5ead0179 Mon Sep 17 00:00:00 2001 From: dawe Date: Sat, 17 Feb 2024 17:48:50 +0100 Subject: [PATCH 07/26] cleanup --- src/Compiler/Service/TransparentCompiler.fsi | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Compiler/Service/TransparentCompiler.fsi b/src/Compiler/Service/TransparentCompiler.fsi index ce6fd1c344f..d05beb6420f 100644 --- a/src/Compiler/Service/TransparentCompiler.fsi +++ b/src/Compiler/Service/TransparentCompiler.fsi @@ -5,7 +5,6 @@ open Internal.Utilities.Collections open FSharp.Compiler.AbstractIL.ILBinaryReader open FSharp.Compiler.BuildGraph open FSharp.Compiler.CodeAnalysis -open FSharp.Compiler.CodeAnalysis.ProjectSnapshot open FSharp.Compiler.CompilerConfig open FSharp.Compiler.CompilerImports open FSharp.Compiler.CheckBasics From 516ab7c8aff0302d0ebba2293bb2405a9c6258b1 Mon Sep 17 00:00:00 2001 From: dawe Date: Mon, 19 Feb 2024 11:40:47 +0100 Subject: [PATCH 08/26] use a new LruCache member GetAll to get rid of the dummy version --- src/Compiler/Facilities/AsyncMemoize.fs | 4 ++-- src/Compiler/Facilities/AsyncMemoize.fsi | 2 +- src/Compiler/Service/TransparentCompiler.fs | 2 +- src/Compiler/Utilities/LruCache.fs | 11 ++++++++--- src/Compiler/Utilities/LruCache.fsi | 3 +++ 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/Compiler/Facilities/AsyncMemoize.fs b/src/Compiler/Facilities/AsyncMemoize.fs index 835f824762e..d6ae83ada6e 100644 --- a/src/Compiler/Facilities/AsyncMemoize.fs +++ b/src/Compiler/Facilities/AsyncMemoize.fs @@ -534,8 +534,8 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T } - member _.TryGet(key: 'TKey, dummyVersion: 'TVersion, predicate: 'TVersion -> bool) : 'TValue option = - let _, versionsAndJobs = cache.GetAll(key, dummyVersion) + member _.TryGet(key: 'TKey, predicate: 'TVersion -> bool) : 'TValue option = + let versionsAndJobs = cache.GetAll(key) versionsAndJobs |> Seq.tryPick (fun (version, job) -> diff --git a/src/Compiler/Facilities/AsyncMemoize.fsi b/src/Compiler/Facilities/AsyncMemoize.fsi index ff57328eb88..1cce68cf999 100644 --- a/src/Compiler/Facilities/AsyncMemoize.fsi +++ b/src/Compiler/Facilities/AsyncMemoize.fsi @@ -69,7 +69,7 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T member Get': key: 'TKey * computation: NodeCode<'TValue> -> NodeCode<'TValue> - member TryGet: key: 'TKey * dummyVersion: 'TVersion * predicate: ('TVersion -> bool) -> 'TValue option + member TryGet: key: 'TKey * predicate: ('TVersion -> bool) -> 'TValue option member Event: IEvent diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index 412ee87cc11..318a0923c74 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -1633,7 +1633,7 @@ type internal TransparentCompiler let parseFileResultsAndcheckFileAnswer = let version = cacheKey.GetVersion() let _, _ba = version - caches.ParseAndCheckFileInProject.TryGet(cacheKey.GetKey(), ("", 0L), (fun v -> v = version)) + caches.ParseAndCheckFileInProject.TryGet(cacheKey.GetKey(), (fun v -> v = version)) match parseFileResultsAndcheckFileAnswer with | Some(parseFileResults, FSharpCheckFileAnswer.Succeeded checkFileResults) -> diff --git a/src/Compiler/Utilities/LruCache.fs b/src/Compiler/Utilities/LruCache.fs index c75ed1d88cf..bbe1cea7ec5 100644 --- a/src/Compiler/Utilities/LruCache.fs +++ b/src/Compiler/Utilities/LruCache.fs @@ -198,14 +198,19 @@ type internal LruCache<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'TVers /// Returns an option of a value for given key and version, and also a list of all other versions for given key member this.GetAll(key, version) = - this.TryGet(key, version), + let others = this.GetAll(key) |> List.filter (fun (ver, _val) -> ver <> version) + this.TryGet(key, version), others + /// Returns a list of version * value pairs for a given key. The strongly held value is first in the list. + member _.GetAll(key: 'TKey) : ('TVersion * 'TValue) list = match dictionary.TryGetValue key with | false, _ -> [] | true, versionDict -> versionDict.Values - |> Seq.map (fun node -> node.Value) - |> Seq.filter (p24 >> ((<>) version)) + |> Seq.map (_.Value) + |> Seq.sortBy (function + | _, _, _, Strong _ -> 0 + | _ -> 1) |> Seq.choose (function | _, ver, _, Strong v -> Some(ver, v) | _, ver, _, Weak r -> diff --git a/src/Compiler/Utilities/LruCache.fsi b/src/Compiler/Utilities/LruCache.fsi index d9aefd2a240..5ba4f4371e4 100644 --- a/src/Compiler/Utilities/LruCache.fsi +++ b/src/Compiler/Utilities/LruCache.fsi @@ -33,6 +33,9 @@ type internal LruCache<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'TVers /// Returns an option of a value for given key and version, and also a list of all other versions for given key member GetAll: key: 'TKey * version: 'TVersion -> 'TValue option * ('TVersion * 'TValue) list + /// Returns a list of version * value pairs for a given key. The strongly held value is first in the list. + member GetAll: key: 'TKey -> ('TVersion * 'TValue) list + member GetValues: unit -> (string * 'TVersion * 'TValue) seq member Remove: key: 'TKey -> unit From 9d735a42cfdf6b241d3994c6b68776c2dfd399fe Mon Sep 17 00:00:00 2001 From: dawe Date: Mon, 19 Feb 2024 12:09:12 +0100 Subject: [PATCH 09/26] cleanup --- src/Compiler/Service/TransparentCompiler.fs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index 318a0923c74..93918cde862 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -1632,7 +1632,6 @@ type internal TransparentCompiler let parseFileResultsAndcheckFileAnswer = let version = cacheKey.GetVersion() - let _, _ba = version caches.ParseAndCheckFileInProject.TryGet(cacheKey.GetKey(), (fun v -> v = version)) match parseFileResultsAndcheckFileAnswer with From 7d6a64301bc3c212cac4c11d708e101bb1133529 Mon Sep 17 00:00:00 2001 From: dawe Date: Mon, 19 Feb 2024 16:13:58 +0100 Subject: [PATCH 10/26] Update src/Compiler/Service/TransparentCompiler.fs Co-authored-by: Petr Pokorny --- src/Compiler/Service/TransparentCompiler.fs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index 93918cde862..0bd18dafb43 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -1631,8 +1631,7 @@ type internal TransparentCompiler } let parseFileResultsAndcheckFileAnswer = - let version = cacheKey.GetVersion() - caches.ParseAndCheckFileInProject.TryGet(cacheKey.GetKey(), (fun v -> v = version)) + caches.ParseAndCheckFileInProject.TryGet(cacheKey.GetKey(), (fun (_, hash) -> hash = sourceHash)) match parseFileResultsAndcheckFileAnswer with | Some(parseFileResults, FSharpCheckFileAnswer.Succeeded checkFileResults) -> From c7cc1b2f21f79a38b52de31cbf6bc671306d5c6d Mon Sep 17 00:00:00 2001 From: dawe Date: Mon, 19 Feb 2024 16:53:51 +0100 Subject: [PATCH 11/26] unify key creation --- src/Compiler/Service/TransparentCompiler.fs | 37 +++++++++------------ 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index 0bd18dafb43..0f4195aa76a 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -1442,10 +1442,21 @@ type internal TransparentCompiler let parseTree = EmptyParsedInput(fileName, (false, false)) FSharpParseFileResults(diagnostics, parseTree, true, [||]) + let keyForParseAndCheckFileInProject (fileName: string) (source: ISourceTextNew) (projectSnapshot: ProjectSnapshot) = + let fileKey = projectSnapshot.FileKey fileName + let sourceHash = source.GetHashCode() |> int64 + + { new ICacheKey<_, _> with + member _.GetLabel() = $"{fileName} ({projectSnapshot.Label})" + + member _.GetKey() = + fileName, projectSnapshot.ProjectCore.Identifier + + member _.GetVersion() = fileKey.GetVersion(), sourceHash + } + let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: ProjectSnapshot) = node { - let fileKey = projectSnapshot.FileKey fileName - let file = projectSnapshot.SourceFiles |> List.tryFind (fun f -> f.FileName = fileName) @@ -1453,17 +1464,7 @@ type internal TransparentCompiler | None -> return emptyParseResult fileName [||], FSharpCheckFileAnswer.Aborted | Some f -> let! source = f.GetSource() |> NodeCode.AwaitTask - - let cacheKey = - { new ICacheKey<_, _> with - member _.GetLabel() = $"{fileName} ({projectSnapshot.Label})" - - member _.GetKey() = - fileName, projectSnapshot.ProjectCore.Identifier - - member _.GetVersion() = - fileKey.GetVersion(), source.GetHashCode() |> int64 - } + let cacheKey = keyForParseAndCheckFileInProject fileName source projectSnapshot return! caches.ParseAndCheckFileInProject.Get( @@ -1617,18 +1618,10 @@ type internal TransparentCompiler | Some f -> async { let! source = f.GetSource() |> Async.AwaitTask - let fileKey = projectSnapshot.ProjectSnapshot.FileKey fileName let sourceHash = source.GetHashCode() |> int64 let cacheKey = - { new ICacheKey<_, _> with - member _.GetLabel() = $"{fileName} ({projectSnapshot.Label})" - - member _.GetKey() = - fileName, projectSnapshot.ProjectSnapshot.ProjectCore.Identifier - - member _.GetVersion() = fileKey.GetVersion(), sourceHash - } + keyForParseAndCheckFileInProject fileName source projectSnapshot.ProjectSnapshot let parseFileResultsAndcheckFileAnswer = caches.ParseAndCheckFileInProject.TryGet(cacheKey.GetKey(), (fun (_, hash) -> hash = sourceHash)) From 52bd57aec6e57d3b50ad2021192b63932082ee98 Mon Sep 17 00:00:00 2001 From: dawe Date: Mon, 19 Feb 2024 18:08:52 +0100 Subject: [PATCH 12/26] just use ProjectSnapShot.FileKey --- src/Compiler/Service/TransparentCompiler.fs | 243 +++++++++---------- src/Compiler/Service/TransparentCompiler.fsi | 3 +- tests/service/ProjectAnalysisTests.fs | 7 +- 3 files changed, 114 insertions(+), 139 deletions(-) diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index 0f4195aa76a..4af33770c09 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -1442,143 +1442,115 @@ type internal TransparentCompiler let parseTree = EmptyParsedInput(fileName, (false, false)) FSharpParseFileResults(diagnostics, parseTree, true, [||]) - let keyForParseAndCheckFileInProject (fileName: string) (source: ISourceTextNew) (projectSnapshot: ProjectSnapshot) = - let fileKey = projectSnapshot.FileKey fileName - let sourceHash = source.GetHashCode() |> int64 + let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: ProjectSnapshot) = + caches.ParseAndCheckFileInProject.Get( + projectSnapshot.FileKey fileName, + node { + use _ = + Activity.start "ComputeParseAndCheckFileInProject" [| Activity.Tags.fileName, fileName |> Path.GetFileName |] - { new ICacheKey<_, _> with - member _.GetLabel() = $"{fileName} ({projectSnapshot.Label})" + match! ComputeBootstrapInfo projectSnapshot with + | None, creationDiags -> return emptyParseResult fileName creationDiags, FSharpCheckFileAnswer.Aborted - member _.GetKey() = - fileName, projectSnapshot.ProjectCore.Identifier + | Some bootstrapInfo, creationDiags -> - member _.GetVersion() = fileKey.GetVersion(), sourceHash - } + let priorSnapshot = projectSnapshot.UpTo fileName + let! snapshotWithSources = LoadSources bootstrapInfo priorSnapshot + let file = snapshotWithSources.SourceFiles |> List.last - let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: ProjectSnapshot) = - node { - let file = - projectSnapshot.SourceFiles |> List.tryFind (fun f -> f.FileName = fileName) + let! parseResults = getParseResult projectSnapshot Seq.empty file bootstrapInfo.TcConfig - match file with - | None -> return emptyParseResult fileName [||], FSharpCheckFileAnswer.Aborted - | Some f -> - let! source = f.GetSource() |> NodeCode.AwaitTask - let cacheKey = keyForParseAndCheckFileInProject fileName source projectSnapshot + let! result, tcInfo = ComputeTcLastFile bootstrapInfo snapshotWithSources - return! - caches.ParseAndCheckFileInProject.Get( - cacheKey, - node { - - use _ = - Activity.start - "ComputeParseAndCheckFileInProject" - [| Activity.Tags.fileName, fileName |> Path.GetFileName |] - - match! ComputeBootstrapInfo projectSnapshot with - | None, creationDiags -> return emptyParseResult fileName creationDiags, FSharpCheckFileAnswer.Aborted - - | Some bootstrapInfo, creationDiags -> - - let priorSnapshot = projectSnapshot.UpTo fileName - let! snapshotWithSources = LoadSources bootstrapInfo priorSnapshot - let file = snapshotWithSources.SourceFiles |> List.last - - let! parseResults = getParseResult projectSnapshot Seq.empty file bootstrapInfo.TcConfig - - let! result, tcInfo = ComputeTcLastFile bootstrapInfo snapshotWithSources - - let (tcEnv, _topAttribs, checkedImplFileOpt, ccuSigForFile) = result - - let tcState = tcInfo.tcState - - let sink = tcInfo.sink.Head // TODO: don't use head - - let tcResolutions = sink.GetResolutions() - let tcSymbolUses = sink.GetSymbolUses() - let tcOpenDeclarations = sink.GetOpenDeclarations() - - // TODO: Apparently creating diagnostics can produce further diagnostics. So let's capture those too. Hopefully there is a more elegant solution... - // Probably diagnostics need to be evaluated during typecheck anyway for proper formatting, which might take care of this too. - let extraLogger = CapturingDiagnosticsLogger("DiagnosticsWhileCreatingDiagnostics") - use _ = new CompilationGlobalsScope(extraLogger, BuildPhase.TypeCheck) - - // Apply nowarns to tcConfig (may generate errors, so ensure diagnosticsLogger is installed) - let tcConfig = - ApplyNoWarnsToTcConfig(bootstrapInfo.TcConfig, parseResults.ParseTree, Path.GetDirectoryName fileName) - - let diagnosticsOptions = tcConfig.diagnosticsOptions - - let symbolEnv = - SymbolEnv(bootstrapInfo.TcGlobals, tcState.Ccu, Some tcState.CcuSig, bootstrapInfo.TcImports) - - let tcDiagnostics = - DiagnosticHelpers.CreateDiagnostics( - diagnosticsOptions, - false, - fileName, - tcInfo.TcDiagnostics, - suggestNamesForErrors, - bootstrapInfo.TcConfig.flatErrors, - Some symbolEnv - ) - - let extraDiagnostics = - DiagnosticHelpers.CreateDiagnostics( - diagnosticsOptions, - false, - fileName, - extraLogger.Diagnostics, - suggestNamesForErrors, - bootstrapInfo.TcConfig.flatErrors, - Some symbolEnv - ) - - let tcDiagnostics = [| yield! extraDiagnostics; yield! tcDiagnostics |] - - let! loadClosure = - ComputeScriptClosure - fileName - file.Source - tcConfig.fsharpBinariesDir - tcConfig.useSimpleResolution - (Some tcConfig.useFsiAuxLib) - (Some tcConfig.useSdkRefs) - tcConfig.sdkDirOverride - (Some tcConfig.assumeDotNetFramework) - projectSnapshot - - let typedResults = - FSharpCheckFileResults.Make( - fileName, - projectSnapshot.ProjectFileName, - bootstrapInfo.TcConfig, - bootstrapInfo.TcGlobals, - projectSnapshot.IsIncompleteTypeCheckEnvironment, - None, - projectSnapshot.ToOptions(), - Array.ofList tcInfo.tcDependencyFiles, - creationDiags, - parseResults.Diagnostics, - tcDiagnostics, - keepAssemblyContents, - ccuSigForFile, - tcState.Ccu, - bootstrapInfo.TcImports, - tcEnv.AccessRights, - tcResolutions, - tcSymbolUses, - tcEnv.NameEnv, - Some loadClosure, - checkedImplFileOpt, - tcOpenDeclarations - ) - - return (parseResults, FSharpCheckFileAnswer.Succeeded typedResults) - } - ) - } + let (tcEnv, _topAttribs, checkedImplFileOpt, ccuSigForFile) = result + + let tcState = tcInfo.tcState + + let sink = tcInfo.sink.Head // TODO: don't use head + + let tcResolutions = sink.GetResolutions() + let tcSymbolUses = sink.GetSymbolUses() + let tcOpenDeclarations = sink.GetOpenDeclarations() + + // TODO: Apparently creating diagnostics can produce further diagnostics. So let's capture those too. Hopefully there is a more elegant solution... + // Probably diagnostics need to be evaluated during typecheck anyway for proper formatting, which might take care of this too. + let extraLogger = CapturingDiagnosticsLogger("DiagnosticsWhileCreatingDiagnostics") + use _ = new CompilationGlobalsScope(extraLogger, BuildPhase.TypeCheck) + + // Apply nowarns to tcConfig (may generate errors, so ensure diagnosticsLogger is installed) + let tcConfig = + ApplyNoWarnsToTcConfig(bootstrapInfo.TcConfig, parseResults.ParseTree, Path.GetDirectoryName fileName) + + let diagnosticsOptions = tcConfig.diagnosticsOptions + + let symbolEnv = + SymbolEnv(bootstrapInfo.TcGlobals, tcState.Ccu, Some tcState.CcuSig, bootstrapInfo.TcImports) + + let tcDiagnostics = + DiagnosticHelpers.CreateDiagnostics( + diagnosticsOptions, + false, + fileName, + tcInfo.TcDiagnostics, + suggestNamesForErrors, + bootstrapInfo.TcConfig.flatErrors, + Some symbolEnv + ) + + let extraDiagnostics = + DiagnosticHelpers.CreateDiagnostics( + diagnosticsOptions, + false, + fileName, + extraLogger.Diagnostics, + suggestNamesForErrors, + bootstrapInfo.TcConfig.flatErrors, + Some symbolEnv + ) + + let tcDiagnostics = [| yield! extraDiagnostics; yield! tcDiagnostics |] + + let! loadClosure = + ComputeScriptClosure + fileName + file.Source + tcConfig.fsharpBinariesDir + tcConfig.useSimpleResolution + (Some tcConfig.useFsiAuxLib) + (Some tcConfig.useSdkRefs) + tcConfig.sdkDirOverride + (Some tcConfig.assumeDotNetFramework) + projectSnapshot + + let typedResults = + FSharpCheckFileResults.Make( + fileName, + projectSnapshot.ProjectFileName, + bootstrapInfo.TcConfig, + bootstrapInfo.TcGlobals, + projectSnapshot.IsIncompleteTypeCheckEnvironment, + None, + projectSnapshot.ToOptions(), + Array.ofList tcInfo.tcDependencyFiles, + creationDiags, + parseResults.Diagnostics, + tcDiagnostics, + keepAssemblyContents, + ccuSigForFile, + tcState.Ccu, + bootstrapInfo.TcImports, + tcEnv.AccessRights, + tcResolutions, + tcSymbolUses, + tcEnv.NameEnv, + Some loadClosure, + checkedImplFileOpt, + tcOpenDeclarations + ) + + return (parseResults, FSharpCheckFileAnswer.Succeeded typedResults) + } + ) let ComputeParseAndCheckAllFilesInProject (bootstrapInfo: BootstrapInfo) (projectSnapshot: ProjectSnapshotWithSources) = caches.ParseAndCheckAllFilesInProject.Get( @@ -1620,11 +1592,14 @@ type internal TransparentCompiler let! source = f.GetSource() |> Async.AwaitTask let sourceHash = source.GetHashCode() |> int64 - let cacheKey = - keyForParseAndCheckFileInProject fileName source projectSnapshot.ProjectSnapshot + let cacheKey = projectSnapshot.ProjectSnapshot.FileKey fileName + let version = cacheKey.GetVersion() let parseFileResultsAndcheckFileAnswer = - caches.ParseAndCheckFileInProject.TryGet(cacheKey.GetKey(), (fun (_, hash) -> hash = sourceHash)) + caches.ParseAndCheckFileInProject.TryGet( + cacheKey.GetKey(), + (fun (fileSnapshotVersion) -> fileSnapshotVersion = version) + ) match parseFileResultsAndcheckFileAnswer with | Some(parseFileResults, FSharpCheckFileAnswer.Succeeded checkFileResults) -> diff --git a/src/Compiler/Service/TransparentCompiler.fsi b/src/Compiler/Service/TransparentCompiler.fsi index d05beb6420f..9aa5929566c 100644 --- a/src/Compiler/Service/TransparentCompiler.fsi +++ b/src/Compiler/Service/TransparentCompiler.fsi @@ -118,8 +118,7 @@ type internal CompilerCaches = member ParseAndCheckAllFilesInProject: AsyncMemoizeDisabled member ParseAndCheckFileInProject: - AsyncMemoize<(string * (string * string)), (string * SourceTextHash), (FSharpParseFileResults * - FSharpCheckFileAnswer)> + AsyncMemoize<(string * (string * string)), string, (FSharpParseFileResults * FSharpCheckFileAnswer)> member ParseAndCheckProject: AsyncMemoize<(string * string), string, FSharpCheckProjectResults> diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs index 7987ef9df48..bf7b47a26cf 100644 --- a/tests/service/ProjectAnalysisTests.fs +++ b/tests/service/ProjectAnalysisTests.fs @@ -5506,18 +5506,19 @@ type A(i:int) = """ let fileSource1Edited = SourceText.ofString fileSource1TextEdited FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1TextEdited) + let snapshotAfterFileEdit = FSharpProjectSnapshot.FromOptions(options, DocumentSource.FileSystem) |> Async.RunImmediate - let rafterEditBefore2ndCheckResults = checker.TryGetRecentCheckResultsForFile(fileName1, snapshot) |> Async.RunImmediate + let rafterEditBefore2ndCheckResults = checker.TryGetRecentCheckResultsForFile(fileName1, snapshotAfterFileEdit) |> Async.RunImmediate match rafterEditBefore2ndCheckResults with | Some(fileResults, checkFileResults, hash) -> failwith "stale cache results from TryGetRecentCheckResultsForFile after edit" | None -> () - checker.ParseAndCheckFileInProject(fileName1, snapshot) |> Async.RunImmediate + checker.ParseAndCheckFileInProject(fileName1, snapshotAfterFileEdit) |> Async.RunImmediate |> function | _, FSharpCheckFileAnswer.Succeeded(res) -> () | _ -> failwithf "Parsing aborted unexpectedly..." - let rafterEditAfter2ndCheckResults = checker.TryGetRecentCheckResultsForFile(fileName1, snapshot) |> Async.RunImmediate + let rafterEditAfter2ndCheckResults = checker.TryGetRecentCheckResultsForFile(fileName1, snapshotAfterFileEdit) |> Async.RunImmediate match rafterEditAfter2ndCheckResults with | Some(fileResults, checkFileResults, hash) -> Assert.AreEqual(fileSource1TextEdited.GetHashCode() |> int64, hash) From 60a2a832ea8c7fe422acc61b19fe2bd4ffd883d5 Mon Sep 17 00:00:00 2001 From: dawe Date: Tue, 20 Feb 2024 18:18:38 +0100 Subject: [PATCH 13/26] to have it on record, push a version with "f.Version |> Md5Hasher.toString" as the second part of lastFileKey.Version --- src/Compiler/Service/FSharpProjectSnapshot.fs | 2 +- src/Compiler/Service/TransparentCompiler.fs | 22 ++++- src/Compiler/Service/TransparentCompiler.fsi | 10 +- .../FSharpChecker/TransparentCompiler.fs | 98 ++++++++++++++++++- tests/service/ProjectAnalysisTests.fs | 4 +- 5 files changed, 124 insertions(+), 12 deletions(-) diff --git a/src/Compiler/Service/FSharpProjectSnapshot.fs b/src/Compiler/Service/FSharpProjectSnapshot.fs index a5ae2447db6..871d330a264 100644 --- a/src/Compiler/Service/FSharpProjectSnapshot.fs +++ b/src/Compiler/Service/FSharpProjectSnapshot.fs @@ -235,7 +235,7 @@ type internal ProjectSnapshotBase<'T when 'T :> IFileSnapshot>(projectCore: Proj { new ICacheKey<_, _> with member _.GetLabel() = $"{f.FileName} ({projectCore.Label})" member _.GetKey() = f.FileName, projectCore.Identifier - member _.GetVersion() = hash |> Md5Hasher.toString + member _.GetVersion() = hash |> Md5Hasher.toString, f.Version |> Md5Hasher.toString }) let sourceFileNames = lazy (sourceFiles |> List.map (fun x -> x.FileName)) diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index 4af33770c09..6f81647d95f 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -1442,9 +1442,25 @@ type internal TransparentCompiler let parseTree = EmptyParsedInput(fileName, (false, false)) FSharpParseFileResults(diagnostics, parseTree, true, [||]) + + // let keyForParseAndCheckFileInProject (fileName: string) (projectSnapshot: ProjectSnapshot) = + // let fileKey = projectSnapshot.FileKey fileName + // let fileSnapshot = projectSnapshot.SourceFiles |> Seq.find(fun f -> f.FileName = fileName) + // + // { new ICacheKey<_, _> with + // member _.GetLabel() = $"{fileName} ({projectSnapshot.Label})" + // + // member _.GetKey() = + // fileName, projectSnapshot.ProjectCore.Identifier + // + // member _.GetVersion() = fileKey.GetVersion(), fileSnapshot.Version + // } + let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: ProjectSnapshot) = + let key = projectSnapshot.FileKey fileName // keyForParseAndCheckFileInProject fileName projectSnapshot + caches.ParseAndCheckFileInProject.Get( - projectSnapshot.FileKey fileName, + key, node { use _ = Activity.start "ComputeParseAndCheckFileInProject" [| Activity.Tags.fileName, fileName |> Path.GetFileName |] @@ -1592,13 +1608,13 @@ type internal TransparentCompiler let! source = f.GetSource() |> Async.AwaitTask let sourceHash = source.GetHashCode() |> int64 - let cacheKey = projectSnapshot.ProjectSnapshot.FileKey fileName + let cacheKey = projectSnapshot.ProjectSnapshot.FileKey fileName // keyForParseAndCheckFileInProject fileName projectSnapshot.ProjectSnapshot let version = cacheKey.GetVersion() let parseFileResultsAndcheckFileAnswer = caches.ParseAndCheckFileInProject.TryGet( cacheKey.GetKey(), - (fun (fileSnapshotVersion) -> fileSnapshotVersion = version) + (fun cachedVersion -> cachedVersion = version) ) match parseFileResultsAndcheckFileAnswer with diff --git a/src/Compiler/Service/TransparentCompiler.fsi b/src/Compiler/Service/TransparentCompiler.fsi index 9aa5929566c..65f5a35879d 100644 --- a/src/Compiler/Service/TransparentCompiler.fsi +++ b/src/Compiler/Service/TransparentCompiler.fsi @@ -113,12 +113,12 @@ type internal CompilerCaches = member FrameworkImports: AsyncMemoize - member ItemKeyStore: AsyncMemoize<(string * (string * string)), string, ItemKeyStore option> + member ItemKeyStore: AsyncMemoize<(string * (string * string)), string * string, ItemKeyStore option> member ParseAndCheckAllFilesInProject: AsyncMemoizeDisabled member ParseAndCheckFileInProject: - AsyncMemoize<(string * (string * string)), string, (FSharpParseFileResults * FSharpCheckFileAnswer)> + AsyncMemoize<(string * (string * string)), string * string, (FSharpParseFileResults * FSharpCheckFileAnswer)> member ParseAndCheckProject: AsyncMemoize<(string * string), string, FSharpCheckProjectResults> @@ -127,13 +127,13 @@ type internal CompilerCaches = member ProjectExtras: AsyncMemoizeDisabled - member SemanticClassification: AsyncMemoize<(string * (string * string)), string, SemanticClassificationView option> + member SemanticClassification: AsyncMemoize<(string * (string * string)), string * string, SemanticClassificationView option> member SizeFactor: int - member TcIntermediate: AsyncMemoize<(string * (string * string)), (string * int), TcIntermediate> + member TcIntermediate: AsyncMemoize<(string * (string * string)), ((string * string) * int), TcIntermediate> - member ScriptClosure: AsyncMemoize<(string * (string * string)), string, LoadClosure> + member ScriptClosure: AsyncMemoize<(string * (string * string)), string * string, LoadClosure> member TcLastFile: AsyncMemoizeDisabled diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs index cbc8e7690fe..041ba86dba5 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs @@ -3,6 +3,7 @@ open System.Collections.Concurrent open System.Diagnostics open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.Text open Internal.Utilities.Collections open FSharp.Compiler.CodeAnalysis.TransparentCompiler open Internal.Utilities.Library.Extras @@ -894,4 +895,99 @@ let ``LoadClosure for script is recomputed after changes`` () = |> Seq.map (fun (k, g) -> k, g |> Seq.map fst |> Seq.toList) |> Map - Assert.Equal([Weakened; Requested; Started; Finished; Weakened; Requested; Started; Finished], closureComputations["FileFirst.fs"]) \ No newline at end of file + Assert.Equal([Weakened; Requested; Started; Finished; Weakened; Requested; Started; Finished], closureComputations["FileFirst.fs"]) + +[] +let ``TryGetRecentCheckResultsForFile returns None before first call to ParseAndCheckFileInProject`` () = + let project = SyntheticProject.Create( + sourceFile "First" []) + + let getSource f = f |> getSourceText project :> ISourceText |> Some |> async.Return + + ProjectWorkflowBuilder(project, useTransparentCompiler = true) { + withProject( fun project checker -> + async { + let projectOptions = project.GetProjectOptions(checker) + let projectSnapshot = FSharpProjectSnapshot.FromOptions(projectOptions, DocumentSource.Custom getSource) |> Async.RunSynchronously + let r = checker.TryGetRecentCheckResultsForFile(project.SourceFilePaths[0], projectSnapshot) |> Async.RunSynchronously + Assert.True(Option.isNone r) + } + ) + } |> ignore + +[] +let ``TryGetRecentCheckResultsForFile returns result after first call to ParseAndCheckFileInProject`` () = + let project = SyntheticProject.Create( + sourceFile "First" [] ) + + let getSource f = f |> getSourceText project :> ISourceText |> Some |> async.Return + + ProjectWorkflowBuilder(project, useTransparentCompiler = true) { + + withProject( fun project checker -> + async { + let projectOptions = project.GetProjectOptions(checker) + let! projectSnapshot = FSharpProjectSnapshot.FromOptions(projectOptions, DocumentSource.Custom getSource) + do! checker.ParseAndCheckFileInProject (project.SourceFilePaths[0], projectSnapshot) |> Async.Ignore + let! r = checker.TryGetRecentCheckResultsForFile(project.SourceFilePaths[0], projectSnapshot) + Assert.True(Option.isSome r) + } + ) + } |> ignore + +[] +let ``TryGetRecentCheckResultsForFile returns no result after edit`` () = + let project = SyntheticProject.Create( + sourceFile "First" []) + + let getSource f = f |> getSourceText project :> ISourceText |> Some |> async.Return + + ProjectWorkflowBuilder(project, useTransparentCompiler = true) { + + withProject( fun project checker -> + async { + let projectOptions = project.GetProjectOptions(checker) + let! projectSnapshot = FSharpProjectSnapshot.FromOptions(projectOptions, DocumentSource.Custom getSource) + do! checker.ParseAndCheckFileInProject (project.SourceFilePaths[0], projectSnapshot) |> Async.Ignore + let! rBeforeEdit = checker.TryGetRecentCheckResultsForFile(project.SourceFilePaths[0], projectSnapshot) + Assert.True(Option.isSome rBeforeEdit) + + // update file + let projectAfterEdit = ProjectOperations.updateFile "First" updateInternal project + let projectOptionsAfterEdit = projectAfterEdit.GetProjectOptions(checker) + let! projectSnapshotAfterEdit = FSharpProjectSnapshot.FromOptions(projectOptionsAfterEdit, DocumentSource.Custom getSource) + let! rAfterEdit = checker.TryGetRecentCheckResultsForFile(project.SourceFilePaths[0], projectSnapshotAfterEdit) + Assert.True(Option.isNone rAfterEdit) + } + ) + } |> ignore + +[] +let ``TryGetRecentCheckResultsForFile returns result after edit of other file`` () = + let project = SyntheticProject.Create( + sourceFile "First" [], + sourceFile "Second" []) + + let getSource f = f |> getSourceText project :> ISourceText |> Some |> async.Return + + ProjectWorkflowBuilder(project, useTransparentCompiler = true) { + + withProject( fun project checker -> + async { + let projectOptions = project.GetProjectOptions(checker) + let! projectSnapshot = FSharpProjectSnapshot.FromOptions(projectOptions, DocumentSource.Custom getSource) + do! checker.ParseAndCheckFileInProject (project.SourceFilePaths[0], projectSnapshot) |> Async.Ignore + do! checker.ParseAndCheckFileInProject (project.SourceFilePaths[1], projectSnapshot) |> Async.Ignore + let! rBeforeEdit = checker.TryGetRecentCheckResultsForFile(project.SourceFilePaths[0], projectSnapshot) + Assert.True(Option.isSome rBeforeEdit) + + // update other file + let projectAfterEdit = ProjectOperations.updateFile "Second" updateInternal project + let! newFileSnapShot = getFileSnapshot projectAfterEdit projectOptions projectSnapshot.SourceFiles[1].FileName + let projectSnapshotAfterEdit = projectSnapshot.Replace([newFileSnapShot]) + + let! rAfterEdit = checker.TryGetRecentCheckResultsForFile(project.SourceFilePaths[0], projectSnapshotAfterEdit) + Assert.True(Option.isSome rAfterEdit) + } + ) + } |> ignore diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs index bf7b47a26cf..87027eeb79b 100644 --- a/tests/service/ProjectAnalysisTests.fs +++ b/tests/service/ProjectAnalysisTests.fs @@ -5496,7 +5496,7 @@ type A(i:int) = let rafterCheckResults = checker.TryGetRecentCheckResultsForFile(fileName1, snapshot) |> Async.RunImmediate match rafterCheckResults with | Some(fileResults, checkFileResults, hash) -> - Assert.AreEqual(fileSource1Text.GetHashCode() |> int64, hash) + Assert.AreEqual(fileSource1.GetHashCode() |> int64, hash) | None -> failwith "no results from TryGetRecentCheckResultsForFile" let fileSource1TextEdited = """ @@ -5521,7 +5521,7 @@ type A(i:int) = let rafterEditAfter2ndCheckResults = checker.TryGetRecentCheckResultsForFile(fileName1, snapshotAfterFileEdit) |> Async.RunImmediate match rafterEditAfter2ndCheckResults with | Some(fileResults, checkFileResults, hash) -> - Assert.AreEqual(fileSource1TextEdited.GetHashCode() |> int64, hash) + Assert.AreEqual(fileSource1Edited.GetHashCode() |> int64, hash) | None -> failwith "no results from TryGetRecentCheckResultsForFile" [] From aadb0be63288dbe39768d7b2fa46253e37a1bfab Mon Sep 17 00:00:00 2001 From: dawe Date: Tue, 20 Feb 2024 18:33:32 +0100 Subject: [PATCH 14/26] use FileKeyWithExtraFileSnapshotVersion for the ParseAndCheckFileInProject cache --- src/Compiler/Service/FSharpProjectSnapshot.fs | 15 ++++++++++- src/Compiler/Service/TransparentCompiler.fs | 27 ++++--------------- src/Compiler/Service/TransparentCompiler.fsi | 8 +++--- 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/Compiler/Service/FSharpProjectSnapshot.fs b/src/Compiler/Service/FSharpProjectSnapshot.fs index 871d330a264..306347d8d23 100644 --- a/src/Compiler/Service/FSharpProjectSnapshot.fs +++ b/src/Compiler/Service/FSharpProjectSnapshot.fs @@ -235,7 +235,7 @@ type internal ProjectSnapshotBase<'T when 'T :> IFileSnapshot>(projectCore: Proj { new ICacheKey<_, _> with member _.GetLabel() = $"{f.FileName} ({projectCore.Label})" member _.GetKey() = f.FileName, projectCore.Identifier - member _.GetVersion() = hash |> Md5Hasher.toString, f.Version |> Md5Hasher.toString + member _.GetVersion() = hash |> Md5Hasher.toString }) let sourceFileNames = lazy (sourceFiles |> List.map (fun x -> x.FileName)) @@ -345,6 +345,19 @@ type internal ProjectSnapshotBase<'T when 'T :> IFileSnapshot>(projectCore: Proj member this.FileKey(fileName: string) = this.UpTo(fileName).LastFileKey member this.FileKey(index: FileIndex) = this.UpTo(index).LastFileKey + member this.FileKeyWithExtraFileSnapshotVersion(fileName: string) = + let fileKey = this.FileKey fileName + let fileSnapshot = this.SourceFiles |> Seq.find (fun f -> f.FileName = fileName) + + { new ICacheKey<_, _> with + member _.GetLabel() = $"{fileName} ({this.Label})" + + member _.GetKey() = fileName, this.ProjectCore.Identifier + + member _.GetVersion() = + fileKey.GetVersion(), fileSnapshot.Version |> Md5Hasher.toString + } + /// Project snapshot with filenames and versions given as initial input and internal ProjectSnapshot = ProjectSnapshotBase diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index 6f81647d95f..0d599b26f5c 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -1442,25 +1442,9 @@ type internal TransparentCompiler let parseTree = EmptyParsedInput(fileName, (false, false)) FSharpParseFileResults(diagnostics, parseTree, true, [||]) - - // let keyForParseAndCheckFileInProject (fileName: string) (projectSnapshot: ProjectSnapshot) = - // let fileKey = projectSnapshot.FileKey fileName - // let fileSnapshot = projectSnapshot.SourceFiles |> Seq.find(fun f -> f.FileName = fileName) - // - // { new ICacheKey<_, _> with - // member _.GetLabel() = $"{fileName} ({projectSnapshot.Label})" - // - // member _.GetKey() = - // fileName, projectSnapshot.ProjectCore.Identifier - // - // member _.GetVersion() = fileKey.GetVersion(), fileSnapshot.Version - // } - let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: ProjectSnapshot) = - let key = projectSnapshot.FileKey fileName // keyForParseAndCheckFileInProject fileName projectSnapshot - caches.ParseAndCheckFileInProject.Get( - key, + projectSnapshot.FileKeyWithExtraFileSnapshotVersion fileName, node { use _ = Activity.start "ComputeParseAndCheckFileInProject" [| Activity.Tags.fileName, fileName |> Path.GetFileName |] @@ -1608,14 +1592,13 @@ type internal TransparentCompiler let! source = f.GetSource() |> Async.AwaitTask let sourceHash = source.GetHashCode() |> int64 - let cacheKey = projectSnapshot.ProjectSnapshot.FileKey fileName // keyForParseAndCheckFileInProject fileName projectSnapshot.ProjectSnapshot + let cacheKey = + projectSnapshot.ProjectSnapshot.FileKeyWithExtraFileSnapshotVersion fileName + let version = cacheKey.GetVersion() let parseFileResultsAndcheckFileAnswer = - caches.ParseAndCheckFileInProject.TryGet( - cacheKey.GetKey(), - (fun cachedVersion -> cachedVersion = version) - ) + caches.ParseAndCheckFileInProject.TryGet(cacheKey.GetKey(), (fun cachedVersion -> cachedVersion = version)) match parseFileResultsAndcheckFileAnswer with | Some(parseFileResults, FSharpCheckFileAnswer.Succeeded checkFileResults) -> diff --git a/src/Compiler/Service/TransparentCompiler.fsi b/src/Compiler/Service/TransparentCompiler.fsi index 65f5a35879d..8e581872d84 100644 --- a/src/Compiler/Service/TransparentCompiler.fsi +++ b/src/Compiler/Service/TransparentCompiler.fsi @@ -113,7 +113,7 @@ type internal CompilerCaches = member FrameworkImports: AsyncMemoize - member ItemKeyStore: AsyncMemoize<(string * (string * string)), string * string, ItemKeyStore option> + member ItemKeyStore: AsyncMemoize<(string * (string * string)), string, ItemKeyStore option> member ParseAndCheckAllFilesInProject: AsyncMemoizeDisabled @@ -127,13 +127,13 @@ type internal CompilerCaches = member ProjectExtras: AsyncMemoizeDisabled - member SemanticClassification: AsyncMemoize<(string * (string * string)), string * string, SemanticClassificationView option> + member SemanticClassification: AsyncMemoize<(string * (string * string)), string, SemanticClassificationView option> member SizeFactor: int - member TcIntermediate: AsyncMemoize<(string * (string * string)), ((string * string) * int), TcIntermediate> + member TcIntermediate: AsyncMemoize<(string * (string * string)), (string * int), TcIntermediate> - member ScriptClosure: AsyncMemoize<(string * (string * string)), string * string, LoadClosure> + member ScriptClosure: AsyncMemoize<(string * (string * string)), string, LoadClosure> member TcLastFile: AsyncMemoizeDisabled From c85b5f07a4459ff405dd516c91ac9c0f5a98e725 Mon Sep 17 00:00:00 2001 From: dawe Date: Wed, 21 Feb 2024 08:36:45 +0100 Subject: [PATCH 15/26] replace FileSnapShot after edit in Test --- .../FSharpChecker/TransparentCompiler.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs index 041ba86dba5..9ea5e96ed71 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs @@ -954,8 +954,8 @@ let ``TryGetRecentCheckResultsForFile returns no result after edit`` () = // update file let projectAfterEdit = ProjectOperations.updateFile "First" updateInternal project - let projectOptionsAfterEdit = projectAfterEdit.GetProjectOptions(checker) - let! projectSnapshotAfterEdit = FSharpProjectSnapshot.FromOptions(projectOptionsAfterEdit, DocumentSource.Custom getSource) + let! newFileSnapShot = getFileSnapshot projectAfterEdit projectOptions projectSnapshot.SourceFiles[0].FileName + let projectSnapshotAfterEdit = projectSnapshot.Replace([newFileSnapShot]) let! rAfterEdit = checker.TryGetRecentCheckResultsForFile(project.SourceFilePaths[0], projectSnapshotAfterEdit) Assert.True(Option.isNone rAfterEdit) } From 1d29a2da3cd2b95aa86d738c81f1a25ff0f20b66 Mon Sep 17 00:00:00 2001 From: dawe Date: Wed, 21 Feb 2024 11:40:12 +0100 Subject: [PATCH 16/26] add CustomOperation tryGetRecentCheckResults for tests --- .../FSharpChecker/TransparentCompiler.fs | 76 ++++--------------- .../ProjectGeneration.fs | 33 ++++++++ 2 files changed, 46 insertions(+), 63 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs index 9ea5e96ed71..3d1a6bdd63a 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs @@ -902,17 +902,8 @@ let ``TryGetRecentCheckResultsForFile returns None before first call to ParseAnd let project = SyntheticProject.Create( sourceFile "First" []) - let getSource f = f |> getSourceText project :> ISourceText |> Some |> async.Return - - ProjectWorkflowBuilder(project, useTransparentCompiler = true) { - withProject( fun project checker -> - async { - let projectOptions = project.GetProjectOptions(checker) - let projectSnapshot = FSharpProjectSnapshot.FromOptions(projectOptions, DocumentSource.Custom getSource) |> Async.RunSynchronously - let r = checker.TryGetRecentCheckResultsForFile(project.SourceFilePaths[0], projectSnapshot) |> Async.RunSynchronously - Assert.True(Option.isNone r) - } - ) + ProjectWorkflowBuilder(project, autoStart = false, useTransparentCompiler = true) { + tryGetRecentCheckResults "First" (TryGetRecentCheckExpects.ExpectNone expectNone) } |> ignore [] @@ -920,19 +911,8 @@ let ``TryGetRecentCheckResultsForFile returns result after first call to ParseAn let project = SyntheticProject.Create( sourceFile "First" [] ) - let getSource f = f |> getSourceText project :> ISourceText |> Some |> async.Return - ProjectWorkflowBuilder(project, useTransparentCompiler = true) { - - withProject( fun project checker -> - async { - let projectOptions = project.GetProjectOptions(checker) - let! projectSnapshot = FSharpProjectSnapshot.FromOptions(projectOptions, DocumentSource.Custom getSource) - do! checker.ParseAndCheckFileInProject (project.SourceFilePaths[0], projectSnapshot) |> Async.Ignore - let! r = checker.TryGetRecentCheckResultsForFile(project.SourceFilePaths[0], projectSnapshot) - Assert.True(Option.isSome r) - } - ) + tryGetRecentCheckResults "First" (TryGetRecentCheckExpects.ExpectSome expectRecentCheck) } |> ignore [] @@ -940,26 +920,12 @@ let ``TryGetRecentCheckResultsForFile returns no result after edit`` () = let project = SyntheticProject.Create( sourceFile "First" []) - let getSource f = f |> getSourceText project :> ISourceText |> Some |> async.Return - ProjectWorkflowBuilder(project, useTransparentCompiler = true) { - - withProject( fun project checker -> - async { - let projectOptions = project.GetProjectOptions(checker) - let! projectSnapshot = FSharpProjectSnapshot.FromOptions(projectOptions, DocumentSource.Custom getSource) - do! checker.ParseAndCheckFileInProject (project.SourceFilePaths[0], projectSnapshot) |> Async.Ignore - let! rBeforeEdit = checker.TryGetRecentCheckResultsForFile(project.SourceFilePaths[0], projectSnapshot) - Assert.True(Option.isSome rBeforeEdit) - - // update file - let projectAfterEdit = ProjectOperations.updateFile "First" updateInternal project - let! newFileSnapShot = getFileSnapshot projectAfterEdit projectOptions projectSnapshot.SourceFiles[0].FileName - let projectSnapshotAfterEdit = projectSnapshot.Replace([newFileSnapShot]) - let! rAfterEdit = checker.TryGetRecentCheckResultsForFile(project.SourceFilePaths[0], projectSnapshotAfterEdit) - Assert.True(Option.isNone rAfterEdit) - } - ) + tryGetRecentCheckResults "First" (TryGetRecentCheckExpects.ExpectSome expectRecentCheck) + updateFile "First" updateInternal + tryGetRecentCheckResults "First" (TryGetRecentCheckExpects.ExpectNone expectNone) + checkFile "First" expectOk + tryGetRecentCheckResults "First" (TryGetRecentCheckExpects.ExpectSome expectRecentCheck) } |> ignore [] @@ -968,26 +934,10 @@ let ``TryGetRecentCheckResultsForFile returns result after edit of other file`` sourceFile "First" [], sourceFile "Second" []) - let getSource f = f |> getSourceText project :> ISourceText |> Some |> async.Return - ProjectWorkflowBuilder(project, useTransparentCompiler = true) { - - withProject( fun project checker -> - async { - let projectOptions = project.GetProjectOptions(checker) - let! projectSnapshot = FSharpProjectSnapshot.FromOptions(projectOptions, DocumentSource.Custom getSource) - do! checker.ParseAndCheckFileInProject (project.SourceFilePaths[0], projectSnapshot) |> Async.Ignore - do! checker.ParseAndCheckFileInProject (project.SourceFilePaths[1], projectSnapshot) |> Async.Ignore - let! rBeforeEdit = checker.TryGetRecentCheckResultsForFile(project.SourceFilePaths[0], projectSnapshot) - Assert.True(Option.isSome rBeforeEdit) - - // update other file - let projectAfterEdit = ProjectOperations.updateFile "Second" updateInternal project - let! newFileSnapShot = getFileSnapshot projectAfterEdit projectOptions projectSnapshot.SourceFiles[1].FileName - let projectSnapshotAfterEdit = projectSnapshot.Replace([newFileSnapShot]) - - let! rAfterEdit = checker.TryGetRecentCheckResultsForFile(project.SourceFilePaths[0], projectSnapshotAfterEdit) - Assert.True(Option.isSome rAfterEdit) - } - ) + tryGetRecentCheckResults "First" (TryGetRecentCheckExpects.ExpectSome expectRecentCheck) + tryGetRecentCheckResults "Second" (TryGetRecentCheckExpects.ExpectSome expectRecentCheck) + updateFile "Second" updateInternal + tryGetRecentCheckResults "First" (TryGetRecentCheckExpects.ExpectSome expectRecentCheck) + tryGetRecentCheckResults "Second" (TryGetRecentCheckExpects.ExpectNone expectNone) } |> ignore diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs index 2157d8fb7fe..a5861193f9d 100644 --- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs +++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs @@ -754,6 +754,19 @@ module ProjectOperations = |> Seq.toArray Assert.Equal<(string * int * int * int)[]>(expected |> Seq.sort |> Seq.toArray, actual) + + let expectNone x = + if Option.isSome x then failwith "expected None, but was Some" + + let expectRecentCheck (results: (FSharpParseFileResults * FSharpCheckFileResults * int64) option) expectedHash = + match results with + | Some (_parseFileResults, _checkFileResults, hash) -> Assert.Equal(expectedHash, hash) + | _ -> failwith "expected Some, but was None" + + [] + type TryGetRecentCheckExpects = + | ExpectNone of ((FSharpParseFileResults * FSharpCheckFileResults * int64) option -> unit) + | ExpectSome of ((FSharpParseFileResults * FSharpCheckFileResults * int64) option -> int64 -> unit) let rec saveProject (p: SyntheticProject) generateSignatureFiles checker = async { @@ -1346,6 +1359,26 @@ type ProjectWorkflowBuilder exn $"Compilation failed with exit code {exitCode}" |> raise return ctx } + + [] + member this.TryGetRecentCheckResults(workflow: Async, fileId: string, expected: TryGetRecentCheckExpects) = //((FSharpParseFileResults * FSharpCheckFileResults * int64) option -> unit) + async { + let! ctx = workflow + let project, file = ctx.Project.FindInAllProjects fileId + let fileName = project.ProjectDir ++ file.FileName + let options = project.GetProjectOptions checker + let! snapshot = FSharpProjectSnapshot.FromOptions(options, getFileSnapshot ctx.Project) + let! r = checker.TryGetRecentCheckResultsForFile(fileName, snapshot) + match expected with + | TryGetRecentCheckExpects.ExpectNone e -> e r + | TryGetRecentCheckExpects.ExpectSome tupleOptionFunc -> + let fileSnapshot = snapshot.SourceFiles |> List.find (fun f -> f.FileName = fileName) + let! source = fileSnapshot.GetSource() |> Async.AwaitTask + let hash = source.GetHashCode() + tupleOptionFunc r hash + + return ctx + } /// Execute a set of operations on a given synthetic project. /// The project is saved to disk and type checked at the start. From 846e07a63ba91d45a77bb544430cd51a46a09231 Mon Sep 17 00:00:00 2001 From: dawe Date: Wed, 21 Feb 2024 17:11:23 +0100 Subject: [PATCH 17/26] - Make API non-async and don't return hash - let tests run for background compiler, too --- src/Compiler/Service/BackgroundCompiler.fs | 22 +++++-------- src/Compiler/Service/BackgroundCompiler.fsi | 2 +- src/Compiler/Service/FSharpProjectSnapshot.fs | 8 ++++- src/Compiler/Service/TransparentCompiler.fs | 33 ++++++------------- src/Compiler/Service/service.fsi | 2 +- .../FSharpChecker/TransparentCompiler.fs | 27 +++++++-------- ...ervice.SurfaceArea.netstandard20.debug.bsl | 2 +- ...vice.SurfaceArea.netstandard20.release.bsl | 2 +- .../ProjectGeneration.fs | 25 ++++---------- tests/service/ProjectAnalysisTests.fs | 18 +++++----- 10 files changed, 58 insertions(+), 83 deletions(-) diff --git a/src/Compiler/Service/BackgroundCompiler.fs b/src/Compiler/Service/BackgroundCompiler.fs index 427d1f7d132..de883185806 100644 --- a/src/Compiler/Service/BackgroundCompiler.fs +++ b/src/Compiler/Service/BackgroundCompiler.fs @@ -167,7 +167,7 @@ type internal IBackgroundCompiler = abstract member TryGetRecentCheckResultsForFile: fileName: string * projectSnapshot: FSharpProjectSnapshot * userOpName: string -> - Async<(FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option> + (FSharpParseFileResults * FSharpCheckFileResults) option abstract member BeforeBackgroundFileCheck: IEvent @@ -1165,18 +1165,14 @@ type internal BackgroundCompiler | None -> None member _.TryGetRecentCheckResultsForFile(fileName: string, projectSnapshot: FSharpProjectSnapshot, userOpName: string) = - let file = - projectSnapshot.ProjectSnapshot.SourceFiles - |> List.tryFind (fun f -> f.FileName = fileName) + projectSnapshot.ProjectSnapshot.SourceFiles + |> List.tryFind (fun f -> f.FileName = fileName) + |> Option.bind (fun (f: FSharpFileSnapshot) -> + let options = projectSnapshot.ToOptions() + let sourceText = f.GetSource() |> Async.AwaitTask |> Async.RunSynchronously - match file with - | Some f -> - async { - let options = projectSnapshot.ToOptions() - let! sourceText = f.GetSource() |> Async.AwaitTask - return self.TryGetRecentCheckResultsForFile(fileName, options, Some sourceText, userOpName) - } - | None -> async.Return None + self.TryGetRecentCheckResultsForFile(fileName, options, Some sourceText, userOpName) + |> Option.map (fun (parseFileResults, checkFileResults, _hash) -> (parseFileResults, checkFileResults))) /// Parse and typecheck the whole project (the implementation, called recursively as project graph is evaluated) member private _.ParseAndCheckProjectImpl(options, userOpName) = @@ -1708,5 +1704,5 @@ type internal BackgroundCompiler fileName: string, projectSnapshot: FSharpProjectSnapshot, userOpName: string - ) : Async<(FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option> = + ) : (FSharpParseFileResults * FSharpCheckFileResults) option = self.TryGetRecentCheckResultsForFile(fileName, projectSnapshot, userOpName) diff --git a/src/Compiler/Service/BackgroundCompiler.fsi b/src/Compiler/Service/BackgroundCompiler.fsi index 7f6b77f0511..ba1e9399b3f 100644 --- a/src/Compiler/Service/BackgroundCompiler.fsi +++ b/src/Compiler/Service/BackgroundCompiler.fsi @@ -157,7 +157,7 @@ type internal IBackgroundCompiler = abstract TryGetRecentCheckResultsForFile: fileName: string * projectSnapshot: FSharpProjectSnapshot * userOpName: string -> - Async<(FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option> + (FSharpParseFileResults * FSharpCheckFileResults) option abstract BeforeBackgroundFileCheck: IEvent diff --git a/src/Compiler/Service/FSharpProjectSnapshot.fs b/src/Compiler/Service/FSharpProjectSnapshot.fs index 306347d8d23..0e5e75a59a6 100644 --- a/src/Compiler/Service/FSharpProjectSnapshot.fs +++ b/src/Compiler/Service/FSharpProjectSnapshot.fs @@ -681,11 +681,17 @@ and [] FSha FSharpProjectSnapshot.FromOptions(options, getFileSnapshot) let rec internal snapshotToOptions (projectSnapshot: ProjectSnapshotBase<_>) = + let referencesOnDisk, otherOptions = // making sure we always produce the same order of flags and -r references + projectSnapshot.CommandLineOptions + |> List.partition (fun x -> x.StartsWith("-r:")) + + let commandLineOptions = List.append otherOptions referencesOnDisk |> List.toArray + { ProjectFileName = projectSnapshot.ProjectFileName ProjectId = projectSnapshot.ProjectId SourceFiles = projectSnapshot.SourceFiles |> Seq.map (fun x -> x.FileName) |> Seq.toArray - OtherOptions = projectSnapshot.CommandLineOptions |> List.toArray + OtherOptions = commandLineOptions ReferencedProjects = projectSnapshot.ReferencedProjects |> Seq.map (function diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index 0d599b26f5c..2b1a5ea787e 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -1579,33 +1579,20 @@ type internal TransparentCompiler fileName: string, projectSnapshot: FSharpProjectSnapshot, userOpName: string - ) : Async<(FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option> = + ) : (FSharpParseFileResults * FSharpCheckFileResults) option = ignore userOpName - let file = - projectSnapshot.ProjectSnapshot.SourceFiles - |> List.tryFind (fun f -> f.FileName = fileName) + let cacheKey = + projectSnapshot.ProjectSnapshot.FileKeyWithExtraFileSnapshotVersion fileName - match file with - | Some f -> - async { - let! source = f.GetSource() |> Async.AwaitTask - let sourceHash = source.GetHashCode() |> int64 + let version = cacheKey.GetVersion() - let cacheKey = - projectSnapshot.ProjectSnapshot.FileKeyWithExtraFileSnapshotVersion fileName + let parseFileResultsAndcheckFileAnswer = + caches.ParseAndCheckFileInProject.TryGet(cacheKey.GetKey(), (fun cachedVersion -> cachedVersion = version)) - let version = cacheKey.GetVersion() - - let parseFileResultsAndcheckFileAnswer = - caches.ParseAndCheckFileInProject.TryGet(cacheKey.GetKey(), (fun cachedVersion -> cachedVersion = version)) - - match parseFileResultsAndcheckFileAnswer with - | Some(parseFileResults, FSharpCheckFileAnswer.Succeeded checkFileResults) -> - return Some(parseFileResults, checkFileResults, sourceHash) - | _ -> return None - } - | None -> async.Return None + match parseFileResultsAndcheckFileAnswer with + | Some(parseFileResults, FSharpCheckFileAnswer.Succeeded checkFileResults) -> Some(parseFileResults, checkFileResults) + | _ -> None let ComputeProjectExtras (bootstrapInfo: BootstrapInfo) (projectSnapshot: ProjectSnapshotWithSources) = caches.ProjectExtras.Get( @@ -2245,5 +2232,5 @@ type internal TransparentCompiler fileName: string, projectSnapshot: FSharpProjectSnapshot, userOpName: string - ) : Async<(FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option> = + ) : (FSharpParseFileResults * FSharpCheckFileResults) option = TryGetRecentCheckResultsForFile(fileName, projectSnapshot, userOpName) diff --git a/src/Compiler/Service/service.fsi b/src/Compiler/Service/service.fsi index 38659633855..63b9d25937f 100644 --- a/src/Compiler/Service/service.fsi +++ b/src/Compiler/Service/service.fsi @@ -397,7 +397,7 @@ type public FSharpChecker = [] member TryGetRecentCheckResultsForFile: fileName: string * projectSnapshot: FSharpProjectSnapshot * ?userOpName: string -> - Async<(FSharpParseFileResults * FSharpCheckFileResults (* hash *) * int64) option> + (FSharpParseFileResults * FSharpCheckFileResults) option /// This function is called when the entire environment is known to have changed for reasons not encoded in the ProjectOptions of any project/compilation. member InvalidateAll: unit -> unit diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs index 3d1a6bdd63a..27c5ddef210 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs @@ -902,8 +902,9 @@ let ``TryGetRecentCheckResultsForFile returns None before first call to ParseAnd let project = SyntheticProject.Create( sourceFile "First" []) - ProjectWorkflowBuilder(project, autoStart = false, useTransparentCompiler = true) { - tryGetRecentCheckResults "First" (TryGetRecentCheckExpects.ExpectNone expectNone) + ProjectWorkflowBuilder(project) { + clearCache + tryGetRecentCheckResults "First" expectNone } |> ignore [] @@ -911,8 +912,8 @@ let ``TryGetRecentCheckResultsForFile returns result after first call to ParseAn let project = SyntheticProject.Create( sourceFile "First" [] ) - ProjectWorkflowBuilder(project, useTransparentCompiler = true) { - tryGetRecentCheckResults "First" (TryGetRecentCheckExpects.ExpectSome expectRecentCheck) + ProjectWorkflowBuilder(project) { + tryGetRecentCheckResults "First" expectSome } |> ignore [] @@ -920,12 +921,12 @@ let ``TryGetRecentCheckResultsForFile returns no result after edit`` () = let project = SyntheticProject.Create( sourceFile "First" []) - ProjectWorkflowBuilder(project, useTransparentCompiler = true) { - tryGetRecentCheckResults "First" (TryGetRecentCheckExpects.ExpectSome expectRecentCheck) + ProjectWorkflowBuilder(project) { + tryGetRecentCheckResults "First" expectSome updateFile "First" updateInternal - tryGetRecentCheckResults "First" (TryGetRecentCheckExpects.ExpectNone expectNone) + tryGetRecentCheckResults "First" expectNone checkFile "First" expectOk - tryGetRecentCheckResults "First" (TryGetRecentCheckExpects.ExpectSome expectRecentCheck) + tryGetRecentCheckResults "First" expectSome } |> ignore [] @@ -934,10 +935,10 @@ let ``TryGetRecentCheckResultsForFile returns result after edit of other file`` sourceFile "First" [], sourceFile "Second" []) - ProjectWorkflowBuilder(project, useTransparentCompiler = true) { - tryGetRecentCheckResults "First" (TryGetRecentCheckExpects.ExpectSome expectRecentCheck) - tryGetRecentCheckResults "Second" (TryGetRecentCheckExpects.ExpectSome expectRecentCheck) + ProjectWorkflowBuilder(project) { + tryGetRecentCheckResults "First" expectSome + tryGetRecentCheckResults "Second" expectSome updateFile "Second" updateInternal - tryGetRecentCheckResults "First" (TryGetRecentCheckExpects.ExpectSome expectRecentCheck) - tryGetRecentCheckResults "Second" (TryGetRecentCheckExpects.ExpectNone expectNone) + tryGetRecentCheckResults "First" expectSome + tryGetRecentCheckResults "Second" expectNone } |> ignore diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl index 81dc02b4d51..baec9d2734f 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl @@ -2059,7 +2059,6 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer]] CheckFileInProjectAllowingStaleCachedResults(FSharp.Compiler.CodeAnalysis.FSharpParseFileResults, System.String, Int32, System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.EditorServices.SemanticClassificationView]] GetBackgroundSemanticClassificationForFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.EditorServices.SemanticClassificationView]] GetBackgroundSemanticClassificationForFile(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) -FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults,System.Int64]]] TryGetRecentCheckResultsForFile(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit] NotifyFileChanged(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit] NotifyProjectCleaned(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Collections.Generic.IEnumerable`1[FSharp.Compiler.Text.Range]] FindBackgroundReferencesInFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, FSharp.Compiler.Symbols.FSharpSymbol, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String]) @@ -2079,6 +2078,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Mi FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Microsoft.FSharp.Control.FSharpHandler`1[System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]],System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]] get_BeforeBackgroundFileCheck() FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Microsoft.FSharp.Control.FSharpHandler`1[System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]],System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]] get_FileChecked() FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Microsoft.FSharp.Control.FSharpHandler`1[System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]],System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]] get_FileParsed() +FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults]] TryGetRecentCheckResultsForFile(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults,System.Int64]] TryGetRecentCheckResultsForFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.ISourceText], Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParsingOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]] GetParsingOptionsFromCommandLineArgs(Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParsingOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]] GetParsingOptionsFromCommandLineArgs(Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl index 81dc02b4d51..baec9d2734f 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl @@ -2059,7 +2059,6 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer]] CheckFileInProjectAllowingStaleCachedResults(FSharp.Compiler.CodeAnalysis.FSharpParseFileResults, System.String, Int32, System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.EditorServices.SemanticClassificationView]] GetBackgroundSemanticClassificationForFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.EditorServices.SemanticClassificationView]] GetBackgroundSemanticClassificationForFile(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) -FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults,System.Int64]]] TryGetRecentCheckResultsForFile(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit] NotifyFileChanged(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit] NotifyProjectCleaned(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Collections.Generic.IEnumerable`1[FSharp.Compiler.Text.Range]] FindBackgroundReferencesInFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, FSharp.Compiler.Symbols.FSharpSymbol, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String]) @@ -2079,6 +2078,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Mi FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Microsoft.FSharp.Control.FSharpHandler`1[System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]],System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]] get_BeforeBackgroundFileCheck() FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Microsoft.FSharp.Control.FSharpHandler`1[System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]],System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]] get_FileChecked() FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Microsoft.FSharp.Control.FSharpHandler`1[System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]],System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions]] get_FileParsed() +FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults]] TryGetRecentCheckResultsForFile(System.String, FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults,System.Int64]] TryGetRecentCheckResultsForFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.ISourceText], Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParsingOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]] GetParsingOptionsFromCommandLineArgs(Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) FSharp.Compiler.CodeAnalysis.FSharpChecker: System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParsingOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]] GetParsingOptionsFromCommandLineArgs(Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs index a5861193f9d..f10443339bd 100644 --- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs +++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs @@ -757,17 +757,10 @@ module ProjectOperations = let expectNone x = if Option.isSome x then failwith "expected None, but was Some" + + let expectSome x = + if Option.isNone x then failwith "expected Some, but was None" - let expectRecentCheck (results: (FSharpParseFileResults * FSharpCheckFileResults * int64) option) expectedHash = - match results with - | Some (_parseFileResults, _checkFileResults, hash) -> Assert.Equal(expectedHash, hash) - | _ -> failwith "expected Some, but was None" - - [] - type TryGetRecentCheckExpects = - | ExpectNone of ((FSharpParseFileResults * FSharpCheckFileResults * int64) option -> unit) - | ExpectSome of ((FSharpParseFileResults * FSharpCheckFileResults * int64) option -> int64 -> unit) - let rec saveProject (p: SyntheticProject) generateSignatureFiles checker = async { Directory.CreateDirectory(p.ProjectDir) |> ignore @@ -1361,21 +1354,15 @@ type ProjectWorkflowBuilder } [] - member this.TryGetRecentCheckResults(workflow: Async, fileId: string, expected: TryGetRecentCheckExpects) = //((FSharpParseFileResults * FSharpCheckFileResults * int64) option -> unit) + member this.TryGetRecentCheckResults(workflow: Async, fileId: string, expected) = async { let! ctx = workflow let project, file = ctx.Project.FindInAllProjects fileId let fileName = project.ProjectDir ++ file.FileName let options = project.GetProjectOptions checker let! snapshot = FSharpProjectSnapshot.FromOptions(options, getFileSnapshot ctx.Project) - let! r = checker.TryGetRecentCheckResultsForFile(fileName, snapshot) - match expected with - | TryGetRecentCheckExpects.ExpectNone e -> e r - | TryGetRecentCheckExpects.ExpectSome tupleOptionFunc -> - let fileSnapshot = snapshot.SourceFiles |> List.find (fun f -> f.FileName = fileName) - let! source = fileSnapshot.GetSource() |> Async.AwaitTask - let hash = source.GetHashCode() - tupleOptionFunc r hash + let r = checker.TryGetRecentCheckResultsForFile(fileName, snapshot) + expected r return ctx } diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs index 87027eeb79b..0336edf78bc 100644 --- a/tests/service/ProjectAnalysisTests.fs +++ b/tests/service/ProjectAnalysisTests.fs @@ -5483,9 +5483,9 @@ type A(i:int) = let options = { checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames } let snapshot = FSharpProjectSnapshot.FromOptions(options, DocumentSource.FileSystem) |> Async.RunImmediate - let rbefore = checker.TryGetRecentCheckResultsForFile(fileName1, snapshot) |> Async.RunImmediate + let rbefore = checker.TryGetRecentCheckResultsForFile(fileName1, snapshot) match rbefore with - | Some(fileResults, checkFileResults, int64) -> failwith "cached results before ParseAndCheckFileInProject was called" + | Some(fileResults, checkFileResults) -> failwith "cached results before ParseAndCheckFileInProject was called" | None -> () checker.ParseAndCheckFileInProject(fileName1, snapshot) |> Async.RunImmediate @@ -5493,10 +5493,9 @@ type A(i:int) = | _, FSharpCheckFileAnswer.Succeeded(res) -> () | _ -> failwithf "Parsing aborted unexpectedly..." - let rafterCheckResults = checker.TryGetRecentCheckResultsForFile(fileName1, snapshot) |> Async.RunImmediate + let rafterCheckResults = checker.TryGetRecentCheckResultsForFile(fileName1, snapshot) match rafterCheckResults with - | Some(fileResults, checkFileResults, hash) -> - Assert.AreEqual(fileSource1.GetHashCode() |> int64, hash) + | Some(fileResults, checkFileResults) -> () | None -> failwith "no results from TryGetRecentCheckResultsForFile" let fileSource1TextEdited = """ @@ -5508,9 +5507,9 @@ type A(i:int) = FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1TextEdited) let snapshotAfterFileEdit = FSharpProjectSnapshot.FromOptions(options, DocumentSource.FileSystem) |> Async.RunImmediate - let rafterEditBefore2ndCheckResults = checker.TryGetRecentCheckResultsForFile(fileName1, snapshotAfterFileEdit) |> Async.RunImmediate + let rafterEditBefore2ndCheckResults = checker.TryGetRecentCheckResultsForFile(fileName1, snapshotAfterFileEdit) match rafterEditBefore2ndCheckResults with - | Some(fileResults, checkFileResults, hash) -> failwith "stale cache results from TryGetRecentCheckResultsForFile after edit" + | Some(fileResults, checkFileResults) -> failwith "stale cache results from TryGetRecentCheckResultsForFile after edit" | None -> () checker.ParseAndCheckFileInProject(fileName1, snapshotAfterFileEdit) |> Async.RunImmediate @@ -5518,10 +5517,9 @@ type A(i:int) = | _, FSharpCheckFileAnswer.Succeeded(res) -> () | _ -> failwithf "Parsing aborted unexpectedly..." - let rafterEditAfter2ndCheckResults = checker.TryGetRecentCheckResultsForFile(fileName1, snapshotAfterFileEdit) |> Async.RunImmediate + let rafterEditAfter2ndCheckResults = checker.TryGetRecentCheckResultsForFile(fileName1, snapshotAfterFileEdit) match rafterEditAfter2ndCheckResults with - | Some(fileResults, checkFileResults, hash) -> - Assert.AreEqual(fileSource1Edited.GetHashCode() |> int64, hash) + | Some(fileResults, checkFileResults) -> () | None -> failwith "no results from TryGetRecentCheckResultsForFile" [] From fa3844faaa83671fa30d00b155de65e67955a68b Mon Sep 17 00:00:00 2001 From: dawe Date: Wed, 21 Feb 2024 17:30:51 +0100 Subject: [PATCH 18/26] better fix for commandLineOptions order --- src/Compiler/Service/FSharpProjectSnapshot.fs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/Compiler/Service/FSharpProjectSnapshot.fs b/src/Compiler/Service/FSharpProjectSnapshot.fs index 0e5e75a59a6..6acfe9dea00 100644 --- a/src/Compiler/Service/FSharpProjectSnapshot.fs +++ b/src/Compiler/Service/FSharpProjectSnapshot.fs @@ -407,10 +407,10 @@ and internal ProjectCore let commandLineOptions = lazy (seq { + yield! OtherOptions + for r in ReferencesOnDisk do $"-r:{r.Path}" - - yield! OtherOptions } |> Seq.toList) @@ -681,17 +681,11 @@ and [] FSha FSharpProjectSnapshot.FromOptions(options, getFileSnapshot) let rec internal snapshotToOptions (projectSnapshot: ProjectSnapshotBase<_>) = - let referencesOnDisk, otherOptions = // making sure we always produce the same order of flags and -r references - projectSnapshot.CommandLineOptions - |> List.partition (fun x -> x.StartsWith("-r:")) - - let commandLineOptions = List.append otherOptions referencesOnDisk |> List.toArray - { ProjectFileName = projectSnapshot.ProjectFileName ProjectId = projectSnapshot.ProjectId SourceFiles = projectSnapshot.SourceFiles |> Seq.map (fun x -> x.FileName) |> Seq.toArray - OtherOptions = commandLineOptions + OtherOptions = projectSnapshot.CommandLineOptions |> List.toArray ReferencedProjects = projectSnapshot.ReferencedProjects |> Seq.map (function From ec883105940ae0555db3694ac2b0ef2fc9e3cf46 Mon Sep 17 00:00:00 2001 From: dawe Date: Wed, 21 Feb 2024 17:43:12 +0100 Subject: [PATCH 19/26] Update src/Compiler/Service/FSharpProjectSnapshot.fs Co-authored-by: Petr Pokorny --- src/Compiler/Service/FSharpProjectSnapshot.fs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/Compiler/Service/FSharpProjectSnapshot.fs b/src/Compiler/Service/FSharpProjectSnapshot.fs index 6acfe9dea00..c15892a9e6a 100644 --- a/src/Compiler/Service/FSharpProjectSnapshot.fs +++ b/src/Compiler/Service/FSharpProjectSnapshot.fs @@ -349,14 +349,7 @@ type internal ProjectSnapshotBase<'T when 'T :> IFileSnapshot>(projectCore: Proj let fileKey = this.FileKey fileName let fileSnapshot = this.SourceFiles |> Seq.find (fun f -> f.FileName = fileName) - { new ICacheKey<_, _> with - member _.GetLabel() = $"{fileName} ({this.Label})" - - member _.GetKey() = fileName, this.ProjectCore.Identifier - - member _.GetVersion() = - fileKey.GetVersion(), fileSnapshot.Version |> Md5Hasher.toString - } + fileKey.WithExtraVersion(fileSnapshot.Version |> Md5Hasher.toString) /// Project snapshot with filenames and versions given as initial input and internal ProjectSnapshot = ProjectSnapshotBase From 96c43b2917e1708392d4289f1f70155587123554 Mon Sep 17 00:00:00 2001 From: dawe Date: Thu, 22 Feb 2024 00:16:06 +0100 Subject: [PATCH 20/26] Update tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs Co-authored-by: Petr Pokorny --- .../FSharpChecker/TransparentCompiler.fs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs index 27c5ddef210..04d7b64ad10 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs @@ -938,7 +938,7 @@ let ``TryGetRecentCheckResultsForFile returns result after edit of other file`` ProjectWorkflowBuilder(project) { tryGetRecentCheckResults "First" expectSome tryGetRecentCheckResults "Second" expectSome - updateFile "Second" updateInternal - tryGetRecentCheckResults "First" expectSome - tryGetRecentCheckResults "Second" expectNone + updateFile "First" updateInternal + tryGetRecentCheckResults "First" expectNone + tryGetRecentCheckResults "Second" expectSome // file didn't change so we still want to get the recent result } |> ignore From fafa8461006922275632b7904352fca47de094dd Mon Sep 17 00:00:00 2001 From: dawe Date: Thu, 22 Feb 2024 00:16:18 +0100 Subject: [PATCH 21/26] Update tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs Co-authored-by: Petr Pokorny --- .../FSharpChecker/TransparentCompiler.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs index 04d7b64ad10..b786f745f1f 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs @@ -933,7 +933,7 @@ let ``TryGetRecentCheckResultsForFile returns no result after edit`` () = let ``TryGetRecentCheckResultsForFile returns result after edit of other file`` () = let project = SyntheticProject.Create( sourceFile "First" [], - sourceFile "Second" []) + sourceFile "Second" ["First"]) ProjectWorkflowBuilder(project) { tryGetRecentCheckResults "First" expectSome From c4e8ccf2a11ed6f8ebabfeb8c2e93cb259c9096c Mon Sep 17 00:00:00 2001 From: dawe Date: Thu, 22 Feb 2024 00:19:57 +0100 Subject: [PATCH 22/26] fix version predicate --- src/Compiler/Service/TransparentCompiler.fs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index 2b1a5ea787e..7a56f6c15fe 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -1588,7 +1588,10 @@ type internal TransparentCompiler let version = cacheKey.GetVersion() let parseFileResultsAndcheckFileAnswer = - caches.ParseAndCheckFileInProject.TryGet(cacheKey.GetKey(), (fun cachedVersion -> cachedVersion = version)) + caches.ParseAndCheckFileInProject.TryGet( + cacheKey.GetKey(), + (fun (_fullVersion, fileContentVersion) -> fileContentVersion = (snd version)) + ) match parseFileResultsAndcheckFileAnswer with | Some(parseFileResults, FSharpCheckFileAnswer.Succeeded checkFileResults) -> Some(parseFileResults, checkFileResults) From acb7bf2969048e3b20bb08f6789796be3b8ae5bf Mon Sep 17 00:00:00 2001 From: dawe Date: Thu, 22 Feb 2024 11:20:09 +0100 Subject: [PATCH 23/26] let LruCache.GetAll(key: 'TKey) return a seq instead of a list --- src/Compiler/Utilities/LruCache.fs | 7 ++++--- src/Compiler/Utilities/LruCache.fsi | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Compiler/Utilities/LruCache.fs b/src/Compiler/Utilities/LruCache.fs index bbe1cea7ec5..7b06292c2e2 100644 --- a/src/Compiler/Utilities/LruCache.fs +++ b/src/Compiler/Utilities/LruCache.fs @@ -198,11 +198,13 @@ type internal LruCache<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'TVers /// Returns an option of a value for given key and version, and also a list of all other versions for given key member this.GetAll(key, version) = - let others = this.GetAll(key) |> List.filter (fun (ver, _val) -> ver <> version) + let others = + this.GetAll(key) |> Seq.filter (fun (ver, _val) -> ver <> version) |> Seq.toList + this.TryGet(key, version), others /// Returns a list of version * value pairs for a given key. The strongly held value is first in the list. - member _.GetAll(key: 'TKey) : ('TVersion * 'TValue) list = + member _.GetAll(key: 'TKey) : ('TVersion * 'TValue) seq = match dictionary.TryGetValue key with | false, _ -> [] | true, versionDict -> @@ -217,7 +219,6 @@ type internal LruCache<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'TVers match r.TryGetTarget() with | true, x -> Some(ver, x) | _ -> None) - |> Seq.toList member _.Remove(key, version) = match dictionary.TryGetValue key with diff --git a/src/Compiler/Utilities/LruCache.fsi b/src/Compiler/Utilities/LruCache.fsi index 5ba4f4371e4..eb2880047d7 100644 --- a/src/Compiler/Utilities/LruCache.fsi +++ b/src/Compiler/Utilities/LruCache.fsi @@ -34,7 +34,7 @@ type internal LruCache<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'TVers member GetAll: key: 'TKey * version: 'TVersion -> 'TValue option * ('TVersion * 'TValue) list /// Returns a list of version * value pairs for a given key. The strongly held value is first in the list. - member GetAll: key: 'TKey -> ('TVersion * 'TValue) list + member GetAll: key: 'TKey -> ('TVersion * 'TValue) seq member GetValues: unit -> (string * 'TVersion * 'TValue) seq From 9f6e7fa6f622a6552656059125211f0105915447 Mon Sep 17 00:00:00 2001 From: dawe Date: Fri, 23 Feb 2024 13:47:27 +0100 Subject: [PATCH 24/26] compare signatures in CustomOperation tryGetRecentCheckResults to tighten the tests --- .../FSharpChecker/TransparentCompiler.fs | 4 ++-- tests/FSharp.Test.Utilities/ProjectGeneration.fs | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs index b786f745f1f..4ee017ba8c5 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs @@ -923,7 +923,7 @@ let ``TryGetRecentCheckResultsForFile returns no result after edit`` () = ProjectWorkflowBuilder(project) { tryGetRecentCheckResults "First" expectSome - updateFile "First" updateInternal + updateFile "First" updatePublicSurface tryGetRecentCheckResults "First" expectNone checkFile "First" expectOk tryGetRecentCheckResults "First" expectSome @@ -938,7 +938,7 @@ let ``TryGetRecentCheckResultsForFile returns result after edit of other file`` ProjectWorkflowBuilder(project) { tryGetRecentCheckResults "First" expectSome tryGetRecentCheckResults "Second" expectSome - updateFile "First" updateInternal + updateFile "First" updatePublicSurface tryGetRecentCheckResults "First" expectNone tryGetRecentCheckResults "Second" expectSome // file didn't change so we still want to get the recent result } |> ignore diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs index f10443339bd..998f2bd201d 100644 --- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs +++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs @@ -1362,7 +1362,15 @@ type ProjectWorkflowBuilder let options = project.GetProjectOptions checker let! snapshot = FSharpProjectSnapshot.FromOptions(options, getFileSnapshot ctx.Project) let r = checker.TryGetRecentCheckResultsForFile(fileName, snapshot) - expected r + expected r + + match r with + | Some(parseFileResults, checkFileResults) -> + let signature = getSignature(parseFileResults, FSharpCheckFileAnswer.Succeeded(checkFileResults)) + match ctx.Signatures.TryFind(fileId) with + | Some priorSignature -> Assert.Equal(priorSignature, signature) + | None -> () + | None -> () return ctx } From c72df2bc328469fd3ab5ec31cf6d584d46359ae0 Mon Sep 17 00:00:00 2001 From: dawe Date: Fri, 23 Feb 2024 19:00:26 +0100 Subject: [PATCH 25/26] kick the CI --- tests/service/ProjectAnalysisTests.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs index 0336edf78bc..c545d884b64 100644 --- a/tests/service/ProjectAnalysisTests.fs +++ b/tests/service/ProjectAnalysisTests.fs @@ -5498,6 +5498,7 @@ type A(i:int) = | Some(fileResults, checkFileResults) -> () | None -> failwith "no results from TryGetRecentCheckResultsForFile" + let fileSource1TextEdited = """ type A(i:int) = member x.Value = i From 23e17043a0661f6d95d54359718ed86c3bccf02a Mon Sep 17 00:00:00 2001 From: dawe Date: Fri, 23 Feb 2024 19:00:57 +0100 Subject: [PATCH 26/26] Revert "kick the CI" This reverts commit c72df2bc328469fd3ab5ec31cf6d584d46359ae0. --- tests/service/ProjectAnalysisTests.fs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs index c545d884b64..0336edf78bc 100644 --- a/tests/service/ProjectAnalysisTests.fs +++ b/tests/service/ProjectAnalysisTests.fs @@ -5498,7 +5498,6 @@ type A(i:int) = | Some(fileResults, checkFileResults) -> () | None -> failwith "no results from TryGetRecentCheckResultsForFile" - let fileSource1TextEdited = """ type A(i:int) = member x.Value = i