From 6339b2ee946f4241a4b63796c606a94e61a54d98 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Wed, 5 Apr 2023 13:47:51 +0200
Subject: [PATCH 001/222] AsyncMemoize v1
---
 src/Compiler/FSharp.Compiler.Service.fsproj   |   1 +
 src/Compiler/Facilities/AsyncMemoize.fs       | 130 ++++++++++++++++++
 src/Compiler/Facilities/BuildGraph.fsi        |   2 +
 .../CompilerService/AsyncMemoize.fs           | 115 ++++++++++++++++
 .../FSharp.Compiler.ComponentTests.fsproj     |  12 +-
 5 files changed, 254 insertions(+), 6 deletions(-)
 create mode 100644 src/Compiler/Facilities/AsyncMemoize.fs
 create mode 100644 tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj
index 537636de072..56c023a3a46 100644
--- a/src/Compiler/FSharp.Compiler.Service.fsproj
+++ b/src/Compiler/FSharp.Compiler.Service.fsproj
@@ -153,6 +153,7 @@
     
     
     
+    
     
       --unicode --lexlib Internal.Utilities.Text.Lexing
       AbstractIL\illex.fsl
diff --git a/src/Compiler/Facilities/AsyncMemoize.fs b/src/Compiler/Facilities/AsyncMemoize.fs
new file mode 100644
index 00000000000..d7f17f2352c
--- /dev/null
+++ b/src/Compiler/Facilities/AsyncMemoize.fs
@@ -0,0 +1,130 @@
+namespace Internal.Utilities.Collections
+
+open FSharp.Compiler.BuildGraph
+open System.Threading
+open System.Collections.Generic
+
+type internal Action<'TKey, 'TValue> =
+    | GetOrCompute of ('TKey -> NodeCode<'TValue>) * CancellationToken
+    | CancelRequest
+    | JobCompleted
+
+type MemoizeRequest<'TKey, 'TValue> = 'TKey * Action<'TKey, 'TValue> * AsyncReplyChannel>
+
+type internal Job<'TValue> =
+    | Running of NodeCode<'TValue> * CancellationTokenSource
+    | Completed of NodeCode<'TValue>
+
+type internal JobEvent<'TKey> =
+    | Started of 'TKey
+    | Finished of 'TKey
+    | Canceled of 'TKey
+
+    member this.Key =
+        match this with
+        | Started key -> key
+        | Finished key -> key
+        | Canceled key -> key
+
+type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?eventLog: ResizeArray>) =
+
+    let tok = obj ()
+
+    let cache =
+        MruCache<_, 'TKey, Job<'TValue>>(keepStrongly = 10, areSame = (fun (x, y) -> x = y))
+
+    let requestCounts = Dictionary<'TKey, int>()
+
+    let incrRequestCount key =
+        requestCounts.[key] <-
+            if requestCounts.ContainsKey key then
+                requestCounts.[key] + 1
+            else
+                1
+
+    let sendAsync (inbox: MailboxProcessor<_>) key msg =
+        inbox.PostAndAsyncReply(fun rc -> key, msg, rc) |> Async.Ignore |> Async.Start
+
+    let log event =
+        eventLog |> Option.iter (fun log -> log.Add event)
+
+    let agent =
+        MailboxProcessor.Start(fun (inbox: MailboxProcessor>) ->
+
+            let post = sendAsync inbox
+
+            async {
+                while true do
+
+                    let! key, action, replyChannel = inbox.Receive()
+
+                    match action, cache.TryGet(tok, key) with
+                    | GetOrCompute _, Some (Completed job) -> replyChannel.Reply job
+                    | GetOrCompute (_, ct), Some (Running (job, _)) ->
+
+                        incrRequestCount key
+                        replyChannel.Reply job
+                        ct.Register(fun _ -> post key CancelRequest) |> ignore
+
+                    | GetOrCompute (computation, ct), None ->
+
+                        let cts = new CancellationTokenSource()
+
+                        let startedComputation =
+                            Async.StartAsTask(
+                                Async.AwaitNodeCode(
+                                    node {
+                                        let! result = computation key
+                                        post key JobCompleted
+                                        return result
+                                    }
+                                ),
+                                cancellationToken = cts.Token
+                            )
+
+                        log (Started key)
+
+                        let job = NodeCode.AwaitTask startedComputation
+
+                        cache.Set(tok, key, (Running(job, cts)))
+
+                        incrRequestCount key
+
+                        ct.Register(fun _ -> post key CancelRequest) |> ignore
+
+                        replyChannel.Reply job
+
+                    | CancelRequest, Some (Running (_, cts)) ->
+                        let requestCount = requestCounts.TryGetValue key |> snd
+
+                        if requestCount > 1 then
+                            requestCounts.[key] <- requestCount - 1
+
+                        else
+                            cts.Cancel()
+                            cache.RemoveAnySimilar(tok, key)
+                            requestCounts.Remove key |> ignore
+                            log (Canceled key)
+
+                    | CancelRequest, None
+                    | CancelRequest, Some (Completed _) -> ()
+
+                    | JobCompleted, Some (Running (job, _)) ->
+                        cache.Set(tok, key, (Completed job))
+                        requestCounts.Remove key |> ignore
+                        log (Finished key)
+
+                    | JobCompleted, _ -> failwith "If this happens there's a bug"
+
+            })
+
+    member _.Get(key, computation) =
+        node {
+            let! ct = NodeCode.CancellationToken
+
+            let! job =
+                agent.PostAndAsyncReply(fun rc -> key, (GetOrCompute(computation, ct)), rc)
+                |> NodeCode.AwaitAsync
+
+            return! job
+        }
diff --git a/src/Compiler/Facilities/BuildGraph.fsi b/src/Compiler/Facilities/BuildGraph.fsi
index 1bfa2f30cac..afbf9d2898b 100644
--- a/src/Compiler/Facilities/BuildGraph.fsi
+++ b/src/Compiler/Facilities/BuildGraph.fsi
@@ -70,6 +70,8 @@ type NodeCode =
 
     static member Parallel: computations: (NodeCode<'T> seq) -> NodeCode<'T[]>
 
+    static member AwaitAsync: computation: Async<'T> -> NodeCode<'T>
+
     static member AwaitTask: task: Task<'T> -> NodeCode<'T>
 
     static member AwaitTask: task: Task -> NodeCode
diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
new file mode 100644
index 00000000000..78123ef4efd
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
@@ -0,0 +1,115 @@
+module FSharp.Compiler.ComponentTests.CompilerService.AsyncMemoize
+
+open System
+open System.Threading
+open Xunit
+open FSharp.Test
+open FSharp.Compiler.BuildGraph
+open Internal.Utilities.Collections
+open System.Threading.Tasks
+
+[]
+let ``Basics``() =
+
+    let computation key = node {
+        do! Async.Sleep 1 |> NodeCode.AwaitAsync
+        return key * 2
+    }
+
+    let eventLog = ResizeArray()
+
+    let memoize = AsyncMemoize(eventLog)
+
+    let task =
+        NodeCode.Parallel(seq {
+            memoize.Get(5, computation)
+            memoize.Get(5, computation)
+            memoize.Get(2, computation)
+            memoize.Get(5, computation)
+            memoize.Get(3, computation)
+            memoize.Get(2, computation)
+        }) |> NodeCode.StartAsTask_ForTesting
+
+    let result = task.Result
+    let expected = [| 10; 10; 4; 10; 6; 4|]
+
+    Assert.Equal(expected, result)
+
+    let groups = eventLog |> Seq.groupBy (fun e -> e.Key) |> Seq.toList
+    Assert.Equal(3, groups.Length)
+    for key, events in groups do
+        Assert.Equal array>([| Started key; Finished key |], events |> Seq.toArray)
+
+[]
+let ``We can cancel a job`` () =
+
+    let computation key = node {
+        do! Async.Sleep 1000 |> NodeCode.AwaitAsync
+        failwith "Should be canceled before it gets here"
+        return key * 2
+    }
+
+    let eventLog = ResizeArray()
+    let memoize = AsyncMemoize(eventLog)
+
+    use cts1 = new CancellationTokenSource()
+    use cts2 = new CancellationTokenSource()
+    use cts3 = new CancellationTokenSource()
+
+    let key = 1
+
+    let _task1 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation), cts1.Token)
+    let _task2 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation), cts2.Token)
+    let _task3 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation), cts3.Token)
+
+    Thread.Sleep 10
+
+    Assert.Equal array>([| Started key |], eventLog |> Seq.toArray )
+
+    cts1.Cancel()
+    cts2.Cancel()
+
+    Assert.Equal array>([| Started key |], eventLog |> Seq.toArray )
+
+    cts3.Cancel()
+
+    Thread.Sleep 10
+
+    Assert.Equal array>([| Started key; Canceled key |], eventLog |> Seq.toArray )
+
+    try
+        Task.WaitAll(_task1, _task2, _task3)
+    with :? AggregateException as ex ->
+        Assert.Equal(3, ex.InnerExceptions.Count)
+        Assert.True(ex.InnerExceptions |> Seq.forall (fun e -> e :? TaskCanceledException))
+
+[]
+let ``Job keeps running even if first requestor cancels`` () =
+    let computation key = node {
+        do! Async.Sleep 100 |> NodeCode.AwaitAsync
+        return key * 2
+    }
+
+    let eventLog = ResizeArray()
+    let memoize = AsyncMemoize(eventLog)
+
+    use cts1 = new CancellationTokenSource()
+    use cts2 = new CancellationTokenSource()
+    use cts3 = new CancellationTokenSource()
+
+    let key = 1
+
+    let _task1 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation), cts1.Token)
+    let _task2 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation), cts2.Token)
+    let _task3 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation), cts3.Token)
+
+    Thread.Sleep 10
+
+    cts1.Cancel()
+    cts3.Cancel()
+
+    let result = _task2.Result
+    Assert.Equal(2, result)
+
+    Assert.Equal array>([| Started key; Finished key |], eventLog |> Seq.toArray )
+
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
index f3f67a4020a..2447e2a0906 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
+++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
@@ -221,7 +221,11 @@
     
     
 	
-    
+	  
+	  
+    
+      %(RelativeDir)TestSource\%(Filename)%(Extension)
+    
     
     
     
@@ -247,11 +251,7 @@
     
   
 
-  
-    
-      %(RelativeDir)TestSource\%(Filename)%(Extension)
-    
-  
+  
 
   
     
From 1059824f747c89f92c140e786a232b6ee926a959 Mon Sep 17 00:00:00 2001
From: Petr Pokorny 
Date: Wed, 5 Apr 2023 16:31:03 +0200
Subject: [PATCH 002/222] IBackgroundCompiler
---
 src/Compiler/FSharp.Compiler.Service.fsproj |    4 +-
 src/Compiler/Service/BackgroundCompiler.fs  | 1523 +++++++++++++++++++
 src/Compiler/Service/TransparentCompiler.fs |   54 +
 src/Compiler/Service/service.fs             | 1136 +-------------
 4 files changed, 1581 insertions(+), 1136 deletions(-)
 create mode 100644 src/Compiler/Service/BackgroundCompiler.fs
 create mode 100644 src/Compiler/Service/TransparentCompiler.fs
diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj
index 56c023a3a46..d6e391936db 100644
--- a/src/Compiler/FSharp.Compiler.Service.fsproj
+++ b/src/Compiler/FSharp.Compiler.Service.fsproj
@@ -464,7 +464,9 @@
     
     
     
-    
+	  
+	  
+	  
     
     
     
diff --git a/src/Compiler/Service/BackgroundCompiler.fs b/src/Compiler/Service/BackgroundCompiler.fs
new file mode 100644
index 00000000000..3882e06bc8d
--- /dev/null
+++ b/src/Compiler/Service/BackgroundCompiler.fs
@@ -0,0 +1,1523 @@
+namespace FSharp.Compiler.CodeAnalysis
+
+open FSharp.Compiler.Text
+open FSharp.Compiler.BuildGraph
+
+open System
+open System.Diagnostics
+open System.IO
+open System.Reflection
+open System.Reflection.Emit
+open System.Threading
+open Internal.Utilities.Collections
+open Internal.Utilities.Library
+open Internal.Utilities.Library.Extras
+open FSharp.Compiler
+open FSharp.Compiler.AbstractIL
+open FSharp.Compiler.AbstractIL.IL
+open FSharp.Compiler.AbstractIL.ILBinaryReader
+open FSharp.Compiler.AbstractIL.ILDynamicAssemblyWriter
+open FSharp.Compiler.CodeAnalysis
+open FSharp.Compiler.CompilerConfig
+open FSharp.Compiler.CompilerDiagnostics
+open FSharp.Compiler.CompilerImports
+open FSharp.Compiler.CompilerOptions
+open FSharp.Compiler.DependencyManager
+open FSharp.Compiler.Diagnostics
+open FSharp.Compiler.Driver
+open FSharp.Compiler.DiagnosticsLogger
+open FSharp.Compiler.IO
+open FSharp.Compiler.ParseAndCheckInputs
+open FSharp.Compiler.ScriptClosure
+open FSharp.Compiler.Symbols
+open FSharp.Compiler.Syntax
+open FSharp.Compiler.Tokenization
+open FSharp.Compiler.Text
+open FSharp.Compiler.Text.Range
+open FSharp.Compiler.TcGlobals
+open FSharp.Compiler.BuildGraph
+
+type SourceTextHash = int64
+type CacheStamp = int64
+type FileName = string
+type FilePath = string
+type ProjectPath = string
+type FileVersion = int
+
+type internal IBackgroundCompiler =
+
+    /// Type-check the result obtained by parsing. Force the evaluation of the antecedent type checking context if needed.
+    abstract member CheckFileInProject:
+        parseResults: FSharpParseFileResults *
+        fileName: string *
+        fileVersion: int *
+        sourceText: ISourceText *
+        options: FSharpProjectOptions *
+        userOpName: string ->
+            NodeCode
+
+    /// Type-check the result obtained by parsing, but only if the antecedent type checking context is available.
+    abstract member CheckFileInProjectAllowingStaleCachedResults:
+        parseResults: FSharpParseFileResults *
+        fileName: string *
+        fileVersion: int *
+        sourceText: ISourceText *
+        options: FSharpProjectOptions *
+        userOpName: string ->
+            NodeCode
+
+    abstract member ClearCache: options: seq * userOpName: string -> unit
+
+    abstract member ClearCaches: unit -> unit
+
+    abstract member DownsizeCaches: unit -> unit
+
+    abstract member FindReferencesInFile:
+        fileName: string *
+        options: FSharpProjectOptions *
+        symbol: FSharp.Compiler.Symbols.FSharpSymbol *
+        canInvalidateProject: bool *
+        userOpName: string ->
+            NodeCode>
+
+    abstract member GetAssemblyData:
+        options: FSharpProjectOptions * userOpName: string -> NodeCode
+
+    /// Fetch the check information from the background compiler (which checks w.r.t. the FileSystem API)
+    abstract member GetBackgroundCheckResultsForFileInProject:
+        fileName: string * options: FSharpProjectOptions * userOpName: string -> NodeCode
+
+    /// Fetch the parse information from the background compiler (which checks w.r.t. the FileSystem API)
+    abstract member GetBackgroundParseResultsForFileInProject:
+        fileName: string * options: FSharpProjectOptions * userOpName: string -> NodeCode
+
+    abstract member GetCachedCheckFileResult:
+        builder: IncrementalBuilder * fileName: string * sourceText: ISourceText * options: FSharpProjectOptions ->
+            NodeCode<(FSharpParseFileResults * FSharpCheckFileResults) option>
+
+    abstract member GetProjectOptionsFromScript:
+        fileName: string *
+        sourceText: ISourceText *
+        previewEnabled: bool option *
+        loadedTimeStamp: System.DateTime option *
+        otherFlags: string array option *
+        useFsiAuxLib: bool option *
+        useSdkRefs: bool option *
+        sdkDirOverride: string option *
+        assumeDotNetFramework: bool option *
+        optionsStamp: int64 option *
+        userOpName: string ->
+            Async
+
+    abstract member GetSemanticClassificationForFile:
+        fileName: string * options: FSharpProjectOptions * userOpName: string ->
+            NodeCode
+
+    abstract member InvalidateConfiguration: options: FSharpProjectOptions * userOpName: string -> unit
+
+    abstract member NotifyFileChanged: fileName: string * options: FSharpProjectOptions * userOpName: string -> NodeCode
+
+    abstract member NotifyProjectCleaned: options: FSharpProjectOptions * userOpName: string -> Async
+
+    /// Parses and checks the source file and returns untyped AST and check results.
+    abstract member ParseAndCheckFileInProject:
+        fileName: string * fileVersion: int * sourceText: ISourceText * options: FSharpProjectOptions * userOpName: string ->
+            NodeCode
+
+    /// Parse and typecheck the whole project.
+    abstract member ParseAndCheckProject: options: FSharpProjectOptions * userOpName: string -> NodeCode
+
+    abstract member ParseFile:
+        fileName: string * sourceText: ISourceText * options: FSharpParsingOptions * cache: bool * userOpName: string ->
+            Async
+
+    /// Try to get recent approximate type check results for a file.
+    abstract member TryGetRecentCheckResultsForFile:
+        fileName: string * options: FSharpProjectOptions * sourceText: ISourceText option * userOpName: string ->
+            (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option
+
+    abstract member BeforeBackgroundFileCheck: IEvent
+
+    abstract member FileChecked: IEvent
+
+    abstract member FileParsed: IEvent
+
+    abstract member FrameworkImportsCache: FrameworkImportsCache
+
+    abstract member ProjectChecked: IEvent
+
+type ParseCacheLockToken() =
+    interface LockToken
+
+type ScriptClosureCacheToken() =
+    interface LockToken
+
+type CheckFileCacheKey = FileName * SourceTextHash * FSharpProjectOptions
+type CheckFileCacheValue = FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash * DateTime
+
+[]
+module EnvMisc =
+    let braceMatchCacheSize = GetEnvInteger "FCS_BraceMatchCacheSize" 5
+    let parseFileCacheSize = GetEnvInteger "FCS_ParseFileCacheSize" 2
+    let checkFileInProjectCacheSize = GetEnvInteger "FCS_CheckFileInProjectCacheSize" 10
+
+    let projectCacheSizeDefault = GetEnvInteger "FCS_ProjectCacheSizeDefault" 3
+
+    let frameworkTcImportsCacheStrongSize =
+        GetEnvInteger "FCS_frameworkTcImportsCacheStrongSizeDefault" 8
+
+[]
+module Helpers =
+
+    /// Determine whether two (fileName,options) keys are identical w.r.t. affect on checking
+    let AreSameForChecking2 ((fileName1: string, options1: FSharpProjectOptions), (fileName2, options2)) =
+        (fileName1 = fileName2)
+        && FSharpProjectOptions.AreSameForChecking(options1, options2)
+
+    /// Determine whether two (fileName,options) keys should be identical w.r.t. resource usage
+    let AreSubsumable2 ((fileName1: string, o1: FSharpProjectOptions), (fileName2: string, o2: FSharpProjectOptions)) =
+        (fileName1 = fileName2) && FSharpProjectOptions.UseSameProject(o1, o2)
+
+    /// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. parsing
+    let AreSameForParsing ((fileName1: string, source1Hash: int64, options1), (fileName2, source2Hash, options2)) =
+        fileName1 = fileName2 && options1 = options2 && source1Hash = source2Hash
+
+    let AreSimilarForParsing ((fileName1, _, _), (fileName2, _, _)) = fileName1 = fileName2
+
+    /// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. checking
+    let AreSameForChecking3 ((fileName1: string, source1Hash: int64, options1: FSharpProjectOptions), (fileName2, source2Hash, options2)) =
+        (fileName1 = fileName2)
+        && FSharpProjectOptions.AreSameForChecking(options1, options2)
+        && source1Hash = source2Hash
+
+    /// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. resource usage
+    let AreSubsumable3 ((fileName1: string, _, o1: FSharpProjectOptions), (fileName2: string, _, o2: FSharpProjectOptions)) =
+        (fileName1 = fileName2) && FSharpProjectOptions.UseSameProject(o1, o2)
+
+    /// If a symbol is an attribute check if given set of names contains its name without the Attribute suffix
+    let rec NamesContainAttribute (symbol: FSharpSymbol) names =
+        match symbol with
+        | :? FSharpMemberOrFunctionOrValue as mofov ->
+            mofov.DeclaringEntity
+            |> Option.map (fun entity -> NamesContainAttribute entity names)
+            |> Option.defaultValue false
+        | :? FSharpEntity as entity when entity.IsAttributeType && symbol.DisplayNameCore.EndsWithOrdinal "Attribute" ->
+            let nameWithoutAttribute = String.dropSuffix symbol.DisplayNameCore "Attribute"
+            names |> Set.contains nameWithoutAttribute
+        | _ -> false
+
+// There is only one instance of this type, held in FSharpChecker
+type internal BackgroundCompiler
+    (
+        legacyReferenceResolver,
+        projectCacheSize,
+        keepAssemblyContents,
+        keepAllBackgroundResolutions,
+        tryGetMetadataSnapshot,
+        suggestNamesForErrors,
+        keepAllBackgroundSymbolUses,
+        enableBackgroundItemKeyStoreAndSemanticClassification,
+        enablePartialTypeChecking,
+        parallelReferenceResolution,
+        captureIdentifiersWhenParsing,
+        getSource: (string -> ISourceText option) option,
+        useChangeNotifications,
+        useSyntaxTreeCache
+    ) as self =
+
+    let beforeFileChecked = Event()
+    let fileParsed = Event()
+    let fileChecked = Event()
+    let projectChecked = Event()
+
+    // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.backgroundCompiler.scriptClosureCache
+    /// Information about the derived script closure.
+    let scriptClosureCache =
+        MruCache(
+            projectCacheSize,
+            areSame = FSharpProjectOptions.AreSameForChecking,
+            areSimilar = FSharpProjectOptions.UseSameProject
+        )
+
+    let frameworkTcImportsCache =
+        FrameworkImportsCache(frameworkTcImportsCacheStrongSize)
+
+    // We currently share one global dependency provider for all scripts for the FSharpChecker.
+    // For projects, one is used per project.
+    //
+    // Sharing one for all scripts is necessary for good performance from GetProjectOptionsFromScript,
+    // which requires a dependency provider to process through the project options prior to working out
+    // if the cached incremental builder can be used for the project.
+    let dependencyProviderForScripts = new DependencyProvider()
+
+    let getProjectReferences (options: FSharpProjectOptions) userOpName =
+        [
+            for r in options.ReferencedProjects do
+
+                match r with
+                | FSharpReferencedProject.FSharpReference (nm, opts) ->
+                    // Don't use cross-project references for FSharp.Core, since various bits of code
+                    // require a concrete FSharp.Core to exist on-disk. The only solutions that have
+                    // these cross-project references to FSharp.Core are VisualFSharp.sln and FSharp.sln. The ramification
+                    // of this is that you need to build FSharp.Core to get intellisense in those projects.
+
+                    if
+                        (try
+                            Path.GetFileNameWithoutExtension(nm)
+                         with _ ->
+                             "")
+                        <> GetFSharpCoreLibraryName()
+                    then
+                        { new IProjectReference with
+                            member x.EvaluateRawContents() =
+                                node {
+                                    Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "GetAssemblyData", nm)
+                                    return! self.GetAssemblyData(opts, userOpName + ".CheckReferencedProject(" + nm + ")")
+                                }
+
+                            member x.TryGetLogicalTimeStamp(cache) =
+                                self.TryGetLogicalTimeStampForProject(cache, opts)
+
+                            member x.FileName = nm
+                        }
+
+                | FSharpReferencedProject.PEReference (nm, getStamp, delayedReader) ->
+                    { new IProjectReference with
+                        member x.EvaluateRawContents() =
+                            node {
+                                let! ilReaderOpt = delayedReader.TryGetILModuleReader() |> NodeCode.FromCancellable
+
+                                match ilReaderOpt with
+                                | Some ilReader ->
+                                    let ilModuleDef, ilAsmRefs = ilReader.ILModuleDef, ilReader.ILAssemblyRefs
+                                    let data = RawFSharpAssemblyData(ilModuleDef, ilAsmRefs) :> IRawFSharpAssemblyData
+                                    return ProjectAssemblyDataResult.Available data
+                                | _ ->
+                                    // Note 'false' - if a PEReference doesn't find an ILModuleReader then we don't
+                                    // continue to try to use an on-disk DLL
+                                    return ProjectAssemblyDataResult.Unavailable false
+                            }
+
+                        member x.TryGetLogicalTimeStamp _ = getStamp () |> Some
+                        member x.FileName = nm
+                    }
+
+                | FSharpReferencedProject.ILModuleReference (nm, getStamp, getReader) ->
+                    { new IProjectReference with
+                        member x.EvaluateRawContents() =
+                            node {
+                                let ilReader = getReader ()
+                                let ilModuleDef, ilAsmRefs = ilReader.ILModuleDef, ilReader.ILAssemblyRefs
+                                let data = RawFSharpAssemblyData(ilModuleDef, ilAsmRefs) :> IRawFSharpAssemblyData
+                                return ProjectAssemblyDataResult.Available data
+                            }
+
+                        member x.TryGetLogicalTimeStamp _ = getStamp () |> Some
+                        member x.FileName = nm
+                    }
+        ]
+
+    /// CreateOneIncrementalBuilder (for background type checking). Note that fsc.fs also
+    /// creates an incremental builder used by the command line compiler.
+    let CreateOneIncrementalBuilder (options: FSharpProjectOptions, userOpName) =
+        node {
+            use _ =
+                Activity.start "BackgroundCompiler.CreateOneIncrementalBuilder" [| Activity.Tags.project, options.ProjectFileName |]
+
+            Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "CreateOneIncrementalBuilder", options.ProjectFileName)
+            let projectReferences = getProjectReferences options userOpName
+
+            let loadClosure = scriptClosureCache.TryGet(AnyCallerThread, options)
+
+            let dependencyProvider =
+                if options.UseScriptResolutionRules then
+                    Some dependencyProviderForScripts
+                else
+                    None
+
+            let! builderOpt, diagnostics =
+                IncrementalBuilder.TryCreateIncrementalBuilderForProjectOptions(
+                    legacyReferenceResolver,
+                    FSharpCheckerResultsSettings.defaultFSharpBinariesDir,
+                    frameworkTcImportsCache,
+                    loadClosure,
+                    Array.toList options.SourceFiles,
+                    Array.toList options.OtherOptions,
+                    projectReferences,
+                    options.ProjectDirectory,
+                    options.UseScriptResolutionRules,
+                    keepAssemblyContents,
+                    keepAllBackgroundResolutions,
+                    tryGetMetadataSnapshot,
+                    suggestNamesForErrors,
+                    keepAllBackgroundSymbolUses,
+                    enableBackgroundItemKeyStoreAndSemanticClassification,
+                    enablePartialTypeChecking,
+                    dependencyProvider,
+                    parallelReferenceResolution,
+                    captureIdentifiersWhenParsing,
+                    getSource,
+                    useChangeNotifications,
+                    useSyntaxTreeCache
+                )
+
+            match builderOpt with
+            | None -> ()
+            | Some builder ->
+
+#if !NO_TYPEPROVIDERS
+                // Register the behaviour that responds to CCUs being invalidated because of type
+                // provider Invalidate events. This invalidates the configuration in the build.
+                builder.ImportsInvalidatedByTypeProvider.Add(fun () -> self.InvalidateConfiguration(options, userOpName))
+#endif
+
+                // Register the callback called just before a file is typechecked by the background builder (without recording
+                // errors or intellisense information).
+                //
+                // This indicates to the UI that the file type check state is dirty. If the file is open and visible then
+                // the UI will sooner or later request a typecheck of the file, recording errors and intellisense information.
+                builder.BeforeFileChecked.Add(fun file -> beforeFileChecked.Trigger(file, options))
+                builder.FileParsed.Add(fun file -> fileParsed.Trigger(file, options))
+                builder.FileChecked.Add(fun file -> fileChecked.Trigger(file, options))
+                builder.ProjectChecked.Add(fun () -> projectChecked.Trigger options)
+
+            return (builderOpt, diagnostics)
+        }
+
+    let parseCacheLock = Lock()
+
+    // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.parseFileInProjectCache. Most recently used cache for parsing files.
+    let parseFileCache =
+        MruCache(
+            parseFileCacheSize,
+            areSimilar = AreSimilarForParsing,
+            areSame = AreSameForParsing
+        )
+
+    // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.checkFileInProjectCache
+    //
+    /// Cache which holds recently seen type-checks.
+    /// This cache may hold out-of-date entries, in two senses
+    ///    - there may be a more recent antecedent state available because the background build has made it available
+    ///    - the source for the file may have changed
+
+    // Also keyed on source. This can only be out of date if the antecedent is out of date
+    let checkFileInProjectCache =
+        MruCache>(
+            keepStrongly = checkFileInProjectCacheSize,
+            areSame = AreSameForChecking3,
+            areSimilar = AreSubsumable3
+        )
+
+    // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.backgroundCompiler.incrementalBuildersCache. This root typically holds more
+    // live information than anything else in the F# Language Service, since it holds up to 3 (projectCacheStrongSize) background project builds
+    // strongly.
+    //
+    /// Cache of builds keyed by options.
+    let gate = obj ()
+
+    let incrementalBuildersCache =
+        MruCache>(
+            keepStrongly = projectCacheSize,
+            keepMax = projectCacheSize,
+            areSame = FSharpProjectOptions.AreSameForChecking,
+            areSimilar = FSharpProjectOptions.UseSameProject
+        )
+
+    let tryGetBuilderNode options =
+        incrementalBuildersCache.TryGet(AnyCallerThread, options)
+
+    let tryGetBuilder options : NodeCode option =
+        tryGetBuilderNode options |> Option.map (fun x -> x.GetOrComputeValue())
+
+    let tryGetSimilarBuilder options : NodeCode option =
+        incrementalBuildersCache.TryGetSimilar(AnyCallerThread, options)
+        |> Option.map (fun x -> x.GetOrComputeValue())
+
+    let tryGetAnyBuilder options : NodeCode option =
+        incrementalBuildersCache.TryGetAny(AnyCallerThread, options)
+        |> Option.map (fun x -> x.GetOrComputeValue())
+
+    let createBuilderNode (options, userOpName, ct: CancellationToken) =
+        lock gate (fun () ->
+            if ct.IsCancellationRequested then
+                GraphNode.FromResult(None, [||])
+            else
+                let getBuilderNode = GraphNode(CreateOneIncrementalBuilder(options, userOpName))
+                incrementalBuildersCache.Set(AnyCallerThread, options, getBuilderNode)
+                getBuilderNode)
+
+    let createAndGetBuilder (options, userOpName) =
+        node {
+            let! ct = NodeCode.CancellationToken
+            let getBuilderNode = createBuilderNode (options, userOpName, ct)
+            return! getBuilderNode.GetOrComputeValue()
+        }
+
+    let getOrCreateBuilder (options, userOpName) : NodeCode =
+        match tryGetBuilder options with
+        | Some getBuilder ->
+            node {
+                match! getBuilder with
+                | builderOpt, creationDiags when builderOpt.IsNone || not builderOpt.Value.IsReferencesInvalidated ->
+                    return builderOpt, creationDiags
+                | _ ->
+                    // The builder could be re-created,
+                    //    clear the check file caches that are associated with it.
+                    //    We must do this in order to not return stale results when references
+                    //    in the project get changed/added/removed.
+                    parseCacheLock.AcquireLock(fun ltok ->
+                        options.SourceFiles
+                        |> Array.iter (fun sourceFile ->
+                            let key = (sourceFile, 0L, options)
+                            checkFileInProjectCache.RemoveAnySimilar(ltok, key)))
+
+                    return! createAndGetBuilder (options, userOpName)
+            }
+        | _ -> createAndGetBuilder (options, userOpName)
+
+    let getSimilarOrCreateBuilder (options, userOpName) =
+        match tryGetSimilarBuilder options with
+        | Some res -> res
+        // The builder does not exist at all. Create it.
+        | None -> getOrCreateBuilder (options, userOpName)
+
+    let getOrCreateBuilderWithInvalidationFlag (options, canInvalidateProject, userOpName) =
+        if canInvalidateProject then
+            getOrCreateBuilder (options, userOpName)
+        else
+            getSimilarOrCreateBuilder (options, userOpName)
+
+    let getAnyBuilder (options, userOpName) =
+        match tryGetAnyBuilder options with
+        | Some getBuilder -> getBuilder
+        | _ -> getOrCreateBuilder (options, userOpName)
+
+    static let mutable actualParseFileCount = 0
+
+    static let mutable actualCheckFileCount = 0
+
+    /// Should be a fast operation. Ensures that we have only one async lazy object per file and its hash.
+    let getCheckFileNode (parseResults, sourceText, fileName, options, _fileVersion, builder, tcPrior, tcInfo, creationDiags) =
+
+        // Here we lock for the creation of the node, not its execution
+        parseCacheLock.AcquireLock(fun ltok ->
+            let key = (fileName, sourceText.GetHashCode() |> int64, options)
+
+            match checkFileInProjectCache.TryGet(ltok, key) with
+            | Some res -> res
+            | _ ->
+                let res =
+                    GraphNode(
+                        node {
+                            let! res =
+                                self.CheckOneFileImplAux(
+                                    parseResults,
+                                    sourceText,
+                                    fileName,
+                                    options,
+                                    builder,
+                                    tcPrior,
+                                    tcInfo,
+                                    creationDiags
+                                )
+
+                            Interlocked.Increment(&actualCheckFileCount) |> ignore
+                            return res
+                        }
+                    )
+
+                checkFileInProjectCache.Set(ltok, key, res)
+                res)
+
+    member _.ParseFile(fileName: string, sourceText: ISourceText, options: FSharpParsingOptions, cache: bool, userOpName: string) =
+        async {
+            use _ =
+                Activity.start
+                    "BackgroundCompiler.ParseFile"
+                    [|
+                        Activity.Tags.fileName, fileName
+                        Activity.Tags.userOpName, userOpName
+                        Activity.Tags.cache, cache.ToString()
+                    |]
+
+            if cache then
+                let hash = sourceText.GetHashCode() |> int64
+
+                match parseCacheLock.AcquireLock(fun ltok -> parseFileCache.TryGet(ltok, (fileName, hash, options))) with
+                | Some res -> return res
+                | None ->
+                    Interlocked.Increment(&actualParseFileCount) |> ignore
+
+                    let parseDiagnostics, parseTree, anyErrors =
+                        ParseAndCheckFile.parseFile (
+                            sourceText,
+                            fileName,
+                            options,
+                            userOpName,
+                            suggestNamesForErrors,
+                            captureIdentifiersWhenParsing
+                        )
+
+                    let res =
+                        FSharpParseFileResults(parseDiagnostics, parseTree, anyErrors, options.SourceFiles)
+
+                    parseCacheLock.AcquireLock(fun ltok -> parseFileCache.Set(ltok, (fileName, hash, options), res))
+                    return res
+            else
+                let parseDiagnostics, parseTree, anyErrors =
+                    ParseAndCheckFile.parseFile (sourceText, fileName, options, userOpName, false, captureIdentifiersWhenParsing)
+
+                return FSharpParseFileResults(parseDiagnostics, parseTree, anyErrors, options.SourceFiles)
+        }
+
+    /// Fetch the parse information from the background compiler (which checks w.r.t. the FileSystem API)
+    member _.GetBackgroundParseResultsForFileInProject(fileName, options, userOpName) =
+        node {
+            use _ =
+                Activity.start
+                    "BackgroundCompiler.GetBackgroundParseResultsForFileInProject"
+                    [| Activity.Tags.fileName, fileName; Activity.Tags.userOpName, userOpName |]
+
+            let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName)
+
+            match builderOpt with
+            | None ->
+                let parseTree = EmptyParsedInput(fileName, (false, false))
+                return FSharpParseFileResults(creationDiags, parseTree, true, [||])
+            | Some builder ->
+                let parseTree, _, _, parseDiagnostics = builder.GetParseResultsForFile fileName
+
+                let parseDiagnostics =
+                    DiagnosticHelpers.CreateDiagnostics(
+                        builder.TcConfig.diagnosticsOptions,
+                        false,
+                        fileName,
+                        parseDiagnostics,
+                        suggestNamesForErrors
+                    )
+
+                let diagnostics = [| yield! creationDiags; yield! parseDiagnostics |]
+
+                let parseResults =
+                    FSharpParseFileResults(
+                        diagnostics = diagnostics,
+                        input = parseTree,
+                        parseHadErrors = false,
+                        dependencyFiles = builder.AllDependenciesDeprecated
+                    )
+
+                return parseResults
+        }
+
+    member _.GetCachedCheckFileResult(builder: IncrementalBuilder, fileName, sourceText: ISourceText, options) =
+        node {
+            use _ =
+                Activity.start "BackgroundCompiler.GetCachedCheckFileResult" [| Activity.Tags.fileName, fileName |]
+
+            let hash = sourceText.GetHashCode() |> int64
+            let key = (fileName, hash, options)
+
+            let cachedResultsOpt =
+                parseCacheLock.AcquireLock(fun ltok -> checkFileInProjectCache.TryGet(ltok, key))
+
+            match cachedResultsOpt with
+            | Some cachedResults ->
+                match! cachedResults.GetOrComputeValue() with
+                | parseResults, checkResults, _, priorTimeStamp when
+                    (match builder.GetCheckResultsBeforeFileInProjectEvenIfStale fileName with
+                     | None -> false
+                     | Some (tcPrior) ->
+                         tcPrior.ProjectTimeStamp = priorTimeStamp
+                         && builder.AreCheckResultsBeforeFileInProjectReady(fileName))
+                    ->
+                    return Some(parseResults, checkResults)
+                | _ ->
+                    parseCacheLock.AcquireLock(fun ltok -> checkFileInProjectCache.RemoveAnySimilar(ltok, key))
+                    return None
+            | _ -> return None
+        }
+
+    member private _.CheckOneFileImplAux
+        (
+            parseResults: FSharpParseFileResults,
+            sourceText: ISourceText,
+            fileName: string,
+            options: FSharpProjectOptions,
+            builder: IncrementalBuilder,
+            tcPrior: PartialCheckResults,
+            tcInfo: TcInfo,
+            creationDiags: FSharpDiagnostic[]
+        ) : NodeCode =
+
+        node {
+            // Get additional script #load closure information if applicable.
+            // For scripts, this will have been recorded by GetProjectOptionsFromScript.
+            let tcConfig = tcPrior.TcConfig
+            let loadClosure = scriptClosureCache.TryGet(AnyCallerThread, options)
+
+            let! checkAnswer =
+                FSharpCheckFileResults.CheckOneFile(
+                    parseResults,
+                    sourceText,
+                    fileName,
+                    options.ProjectFileName,
+                    tcConfig,
+                    tcPrior.TcGlobals,
+                    tcPrior.TcImports,
+                    tcInfo.tcState,
+                    tcInfo.moduleNamesDict,
+                    loadClosure,
+                    tcInfo.TcDiagnostics,
+                    options.IsIncompleteTypeCheckEnvironment,
+                    options,
+                    builder,
+                    Array.ofList tcInfo.tcDependencyFiles,
+                    creationDiags,
+                    parseResults.Diagnostics,
+                    keepAssemblyContents,
+                    suggestNamesForErrors
+                )
+                |> NodeCode.FromCancellable
+
+            GraphNode.SetPreferredUILang tcConfig.preferredUiLang
+            return (parseResults, checkAnswer, sourceText.GetHashCode() |> int64, tcPrior.ProjectTimeStamp)
+        }
+
+    member private bc.CheckOneFileImpl
+        (
+            parseResults: FSharpParseFileResults,
+            sourceText: ISourceText,
+            fileName: string,
+            options: FSharpProjectOptions,
+            fileVersion: int,
+            builder: IncrementalBuilder,
+            tcPrior: PartialCheckResults,
+            tcInfo: TcInfo,
+            creationDiags: FSharpDiagnostic[]
+        ) =
+
+        node {
+            match! bc.GetCachedCheckFileResult(builder, fileName, sourceText, options) with
+            | Some (_, results) -> return FSharpCheckFileAnswer.Succeeded results
+            | _ ->
+                let lazyCheckFile =
+                    getCheckFileNode (parseResults, sourceText, fileName, options, fileVersion, builder, tcPrior, tcInfo, creationDiags)
+
+                let! _, results, _, _ = lazyCheckFile.GetOrComputeValue()
+                return FSharpCheckFileAnswer.Succeeded results
+        }
+
+    /// Type-check the result obtained by parsing, but only if the antecedent type checking context is available.
+    member bc.CheckFileInProjectAllowingStaleCachedResults
+        (
+            parseResults: FSharpParseFileResults,
+            fileName,
+            fileVersion,
+            sourceText: ISourceText,
+            options,
+            userOpName
+        ) =
+        node {
+            use _ =
+                Activity.start
+                    "BackgroundCompiler.CheckFileInProjectAllowingStaleCachedResults"
+                    [|
+                        Activity.Tags.project, options.ProjectFileName
+                        Activity.Tags.fileName, fileName
+                        Activity.Tags.userOpName, userOpName
+                    |]
+
+            let! cachedResults =
+                node {
+                    let! builderOpt, creationDiags = getAnyBuilder (options, userOpName)
+
+                    match builderOpt with
+                    | Some builder ->
+                        match! bc.GetCachedCheckFileResult(builder, fileName, sourceText, options) with
+                        | Some (_, checkResults) -> return Some(builder, creationDiags, Some(FSharpCheckFileAnswer.Succeeded checkResults))
+                        | _ -> return Some(builder, creationDiags, None)
+                    | _ -> return None // the builder wasn't ready
+                }
+
+            match cachedResults with
+            | None -> return None
+            | Some (_, _, Some x) -> return Some x
+            | Some (builder, creationDiags, None) ->
+                Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "CheckFileInProjectAllowingStaleCachedResults.CacheMiss", fileName)
+
+                match builder.GetCheckResultsBeforeFileInProjectEvenIfStale fileName with
+                | Some tcPrior ->
+                    match tcPrior.TryPeekTcInfo() with
+                    | Some tcInfo ->
+                        let! checkResults =
+                            bc.CheckOneFileImpl(
+                                parseResults,
+                                sourceText,
+                                fileName,
+                                options,
+                                fileVersion,
+                                builder,
+                                tcPrior,
+                                tcInfo,
+                                creationDiags
+                            )
+
+                        return Some checkResults
+                    | None -> return None
+                | None -> return None // the incremental builder was not up to date
+        }
+
+    /// Type-check the result obtained by parsing. Force the evaluation of the antecedent type checking context if needed.
+    member bc.CheckFileInProject
+        (
+            parseResults: FSharpParseFileResults,
+            fileName,
+            fileVersion,
+            sourceText: ISourceText,
+            options,
+            userOpName
+        ) =
+        node {
+            use _ =
+                Activity.start
+                    "BackgroundCompiler.CheckFileInProject"
+                    [|
+                        Activity.Tags.project, options.ProjectFileName
+                        Activity.Tags.fileName, fileName
+                        Activity.Tags.userOpName, userOpName
+                    |]
+
+            let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName)
+
+            match builderOpt with
+            | None ->
+                return FSharpCheckFileAnswer.Succeeded(FSharpCheckFileResults.MakeEmpty(fileName, creationDiags, keepAssemblyContents))
+            | Some builder ->
+                // Check the cache. We can only use cached results when there is no work to do to bring the background builder up-to-date
+                let! cachedResults = bc.GetCachedCheckFileResult(builder, fileName, sourceText, options)
+
+                match cachedResults with
+                | Some (_, checkResults) -> return FSharpCheckFileAnswer.Succeeded checkResults
+                | _ ->
+                    let! tcPrior = builder.GetCheckResultsBeforeFileInProject fileName
+                    let! tcInfo = tcPrior.GetOrComputeTcInfo()
+
+                    return!
+                        bc.CheckOneFileImpl(
+                            parseResults,
+                            sourceText,
+                            fileName,
+                            options,
+                            fileVersion,
+                            builder,
+                            tcPrior,
+                            tcInfo,
+                            creationDiags
+                        )
+        }
+
+    /// Parses and checks the source file and returns untyped AST and check results.
+    member bc.ParseAndCheckFileInProject
+        (
+            fileName: string,
+            fileVersion,
+            sourceText: ISourceText,
+            options: FSharpProjectOptions,
+            userOpName
+        ) =
+        node {
+            use _ =
+                Activity.start
+                    "BackgroundCompiler.ParseAndCheckFileInProject"
+                    [|
+                        Activity.Tags.project, options.ProjectFileName
+                        Activity.Tags.fileName, fileName
+                        Activity.Tags.userOpName, userOpName
+                    |]
+
+            let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName)
+
+            match builderOpt with
+            | None ->
+                let parseTree = EmptyParsedInput(fileName, (false, false))
+                let parseResults = FSharpParseFileResults(creationDiags, parseTree, true, [||])
+                return (parseResults, FSharpCheckFileAnswer.Aborted)
+
+            | Some builder ->
+                let! cachedResults = bc.GetCachedCheckFileResult(builder, fileName, sourceText, options)
+
+                match cachedResults with
+                | Some (parseResults, checkResults) -> return (parseResults, FSharpCheckFileAnswer.Succeeded checkResults)
+                | _ ->
+                    let! tcPrior = builder.GetCheckResultsBeforeFileInProject fileName
+                    let! tcInfo = tcPrior.GetOrComputeTcInfo()
+                    // Do the parsing.
+                    let parsingOptions =
+                        FSharpParsingOptions.FromTcConfig(
+                            builder.TcConfig,
+                            Array.ofList builder.SourceFiles,
+                            options.UseScriptResolutionRules
+                        )
+
+                    GraphNode.SetPreferredUILang tcPrior.TcConfig.preferredUiLang
+
+                    let parseDiagnostics, parseTree, anyErrors =
+                        ParseAndCheckFile.parseFile (
+                            sourceText,
+                            fileName,
+                            parsingOptions,
+                            userOpName,
+                            suggestNamesForErrors,
+                            captureIdentifiersWhenParsing
+                        )
+
+                    let parseResults =
+                        FSharpParseFileResults(parseDiagnostics, parseTree, anyErrors, builder.AllDependenciesDeprecated)
+
+                    let! checkResults =
+                        bc.CheckOneFileImpl(
+                            parseResults,
+                            sourceText,
+                            fileName,
+                            options,
+                            fileVersion,
+                            builder,
+                            tcPrior,
+                            tcInfo,
+                            creationDiags
+                        )
+
+                    return (parseResults, checkResults)
+        }
+
+    member _.NotifyFileChanged(fileName, options, userOpName) =
+        node {
+            use _ =
+                Activity.start
+                    "BackgroundCompiler.NotifyFileChanged"
+                    [|
+                        Activity.Tags.project, options.ProjectFileName
+                        Activity.Tags.fileName, fileName
+                        Activity.Tags.userOpName, userOpName
+                    |]
+
+            let! builderOpt, _ = getOrCreateBuilder (options, userOpName)
+
+            match builderOpt with
+            | None -> return ()
+            | Some builder -> do! builder.NotifyFileChanged(fileName, DateTime.UtcNow)
+        }
+
+    /// Fetch the check information from the background compiler (which checks w.r.t. the FileSystem API)
+    member _.GetBackgroundCheckResultsForFileInProject(fileName, options, userOpName) =
+        node {
+            use _ =
+                Activity.start
+                    "BackgroundCompiler.ParseAndCheckFileInProject"
+                    [|
+                        Activity.Tags.project, options.ProjectFileName
+                        Activity.Tags.fileName, fileName
+                        Activity.Tags.userOpName, userOpName
+                    |]
+
+            let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName)
+
+            match builderOpt with
+            | None ->
+                let parseTree = EmptyParsedInput(fileName, (false, false))
+                let parseResults = FSharpParseFileResults(creationDiags, parseTree, true, [||])
+                let typedResults = FSharpCheckFileResults.MakeEmpty(fileName, creationDiags, true)
+                return (parseResults, typedResults)
+            | Some builder ->
+                let parseTree, _, _, parseDiagnostics = builder.GetParseResultsForFile fileName
+                let! tcProj = builder.GetFullCheckResultsAfterFileInProject fileName
+
+                let! tcInfo, tcInfoExtras = tcProj.GetOrComputeTcInfoWithExtras()
+
+                let tcResolutions = tcInfoExtras.tcResolutions
+                let tcSymbolUses = tcInfoExtras.tcSymbolUses
+                let tcOpenDeclarations = tcInfoExtras.tcOpenDeclarations
+                let latestCcuSigForFile = tcInfo.latestCcuSigForFile
+                let tcState = tcInfo.tcState
+                let tcEnvAtEnd = tcInfo.tcEnvAtEndOfFile
+                let latestImplementationFile = tcInfoExtras.latestImplFile
+                let tcDependencyFiles = tcInfo.tcDependencyFiles
+                let tcDiagnostics = tcInfo.TcDiagnostics
+                let diagnosticsOptions = builder.TcConfig.diagnosticsOptions
+
+                let parseDiagnostics =
+                    DiagnosticHelpers.CreateDiagnostics(diagnosticsOptions, false, fileName, parseDiagnostics, suggestNamesForErrors)
+
+                let parseDiagnostics = [| yield! creationDiags; yield! parseDiagnostics |]
+
+                let tcDiagnostics =
+                    DiagnosticHelpers.CreateDiagnostics(diagnosticsOptions, false, fileName, tcDiagnostics, suggestNamesForErrors)
+
+                let tcDiagnostics = [| yield! creationDiags; yield! tcDiagnostics |]
+
+                let parseResults =
+                    FSharpParseFileResults(
+                        diagnostics = parseDiagnostics,
+                        input = parseTree,
+                        parseHadErrors = false,
+                        dependencyFiles = builder.AllDependenciesDeprecated
+                    )
+
+                let loadClosure = scriptClosureCache.TryGet(AnyCallerThread, options)
+
+                let typedResults =
+                    FSharpCheckFileResults.Make(
+                        fileName,
+                        options.ProjectFileName,
+                        tcProj.TcConfig,
+                        tcProj.TcGlobals,
+                        options.IsIncompleteTypeCheckEnvironment,
+                        builder,
+                        options,
+                        Array.ofList tcDependencyFiles,
+                        creationDiags,
+                        parseResults.Diagnostics,
+                        tcDiagnostics,
+                        keepAssemblyContents,
+                        Option.get latestCcuSigForFile,
+                        tcState.Ccu,
+                        tcProj.TcImports,
+                        tcEnvAtEnd.AccessRights,
+                        tcResolutions,
+                        tcSymbolUses,
+                        tcEnvAtEnd.NameEnv,
+                        loadClosure,
+                        latestImplementationFile,
+                        tcOpenDeclarations
+                    )
+
+                return (parseResults, typedResults)
+        }
+
+    member _.FindReferencesInFile
+        (
+            fileName: string,
+            options: FSharpProjectOptions,
+            symbol: FSharpSymbol,
+            canInvalidateProject: bool,
+            userOpName: string
+        ) =
+        node {
+            use _ =
+                Activity.start
+                    "BackgroundCompiler.FindReferencesInFile"
+                    [|
+                        Activity.Tags.project, options.ProjectFileName
+                        Activity.Tags.fileName, fileName
+                        Activity.Tags.userOpName, userOpName
+                        "symbol", symbol.FullName
+                    |]
+
+            let! builderOpt, _ = getOrCreateBuilderWithInvalidationFlag (options, canInvalidateProject, userOpName)
+
+            match builderOpt with
+            | None -> return Seq.empty
+            | Some builder ->
+                if builder.ContainsFile fileName then
+                    let! checkResults = builder.GetFullCheckResultsAfterFileInProject fileName
+                    let! keyStoreOpt = checkResults.GetOrComputeItemKeyStoreIfEnabled()
+
+                    match keyStoreOpt with
+                    | None -> return Seq.empty
+                    | Some reader -> return reader.FindAll symbol.Item
+                else
+                    return Seq.empty
+        }
+
+    member _.GetSemanticClassificationForFile(fileName: string, options: FSharpProjectOptions, userOpName: string) =
+        node {
+            use _ =
+                Activity.start
+                    "BackgroundCompiler.GetSemanticClassificationForFile"
+                    [|
+                        Activity.Tags.project, options.ProjectFileName
+                        Activity.Tags.fileName, fileName
+                        Activity.Tags.userOpName, userOpName
+                    |]
+
+            let! builderOpt, _ = getOrCreateBuilder (options, userOpName)
+
+            match builderOpt with
+            | None -> return None
+            | Some builder ->
+                let! checkResults = builder.GetFullCheckResultsAfterFileInProject fileName
+                let! scopt = checkResults.GetOrComputeSemanticClassificationIfEnabled()
+
+                match scopt with
+                | None -> return None
+                | Some sc -> return Some(sc.GetView())
+        }
+
+    /// Try to get recent approximate type check results for a file.
+    member _.TryGetRecentCheckResultsForFile
+        (
+            fileName: string,
+            options: FSharpProjectOptions,
+            sourceText: ISourceText option,
+            _userOpName: string
+        ) =
+        use _ =
+            Activity.start
+                "BackgroundCompiler.GetSemanticClassificationForFile"
+                [|
+                    Activity.Tags.project, options.ProjectFileName
+                    Activity.Tags.fileName, fileName
+                    Activity.Tags.userOpName, _userOpName
+                |]
+
+        match sourceText with
+        | Some sourceText ->
+            let hash = sourceText.GetHashCode() |> int64
+
+            let resOpt =
+                parseCacheLock.AcquireLock(fun ltok -> checkFileInProjectCache.TryGet(ltok, (fileName, hash, options)))
+
+            match resOpt with
+            | Some res ->
+                match res.TryPeekValue() with
+                | ValueSome (a, b, c, _) -> Some(a, b, c)
+                | ValueNone -> None
+            | None -> None
+        | None -> None
+
+    /// Parse and typecheck the whole project (the implementation, called recursively as project graph is evaluated)
+    member private _.ParseAndCheckProjectImpl(options, userOpName) =
+        node {
+            let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName)
+
+            match builderOpt with
+            | None ->
+                let emptyResults =
+                    FSharpCheckProjectResults(options.ProjectFileName, None, keepAssemblyContents, creationDiags, None)
+
+                return emptyResults
+            | Some builder ->
+                let! tcProj, ilAssemRef, tcAssemblyDataOpt, tcAssemblyExprOpt = builder.GetFullCheckResultsAndImplementationsForProject()
+                let diagnosticsOptions = tcProj.TcConfig.diagnosticsOptions
+                let fileName = DummyFileNameForRangesWithoutASpecificLocation
+
+                // Although we do not use 'tcInfoExtras', computing it will make sure we get an extra info.
+                let! tcInfo, _tcInfoExtras = tcProj.GetOrComputeTcInfoWithExtras()
+
+                let topAttribs = tcInfo.topAttribs
+                let tcState = tcInfo.tcState
+                let tcEnvAtEnd = tcInfo.tcEnvAtEndOfFile
+                let tcDiagnostics = tcInfo.TcDiagnostics
+                let tcDependencyFiles = tcInfo.tcDependencyFiles
+
+                let tcDiagnostics =
+                    DiagnosticHelpers.CreateDiagnostics(diagnosticsOptions, true, fileName, tcDiagnostics, suggestNamesForErrors)
+
+                let diagnostics = [| yield! creationDiags; yield! tcDiagnostics |]
+
+                let getAssemblyData () =
+                    match tcAssemblyDataOpt with
+                    | ProjectAssemblyDataResult.Available data -> Some data
+                    | _ -> None
+
+                let details =
+                    (tcProj.TcGlobals,
+                     tcProj.TcImports,
+                     tcState.Ccu,
+                     tcState.CcuSig,
+                     Choice1Of2 builder,
+                     topAttribs,
+                     getAssemblyData,
+                     ilAssemRef,
+                     tcEnvAtEnd.AccessRights,
+                     tcAssemblyExprOpt,
+                     Array.ofList tcDependencyFiles,
+                     options)
+
+                let results =
+                    FSharpCheckProjectResults(
+                        options.ProjectFileName,
+                        Some tcProj.TcConfig,
+                        keepAssemblyContents,
+                        diagnostics,
+                        Some details
+                    )
+
+                return results
+        }
+
+    member _.GetAssemblyData(options, userOpName) =
+        node {
+            use _ =
+                Activity.start
+                    "BackgroundCompiler.GetAssemblyData"
+                    [|
+                        Activity.Tags.project, options.ProjectFileName
+                        Activity.Tags.userOpName, userOpName
+                    |]
+
+            let! builderOpt, _ = getOrCreateBuilder (options, userOpName)
+
+            match builderOpt with
+            | None -> return ProjectAssemblyDataResult.Unavailable true
+            | Some builder ->
+                let! _, _, tcAssemblyDataOpt, _ = builder.GetCheckResultsAndImplementationsForProject()
+                return tcAssemblyDataOpt
+        }
+
+    /// Get the timestamp that would be on the output if fully built immediately
+    member private _.TryGetLogicalTimeStampForProject(cache, options) =
+        match tryGetBuilderNode options with
+        | Some lazyWork ->
+            match lazyWork.TryPeekValue() with
+            | ValueSome (Some builder, _) -> Some(builder.GetLogicalTimeStampForProject(cache))
+            | _ -> None
+        | _ -> None
+
+    /// Parse and typecheck the whole project.
+    member bc.ParseAndCheckProject(options, userOpName) =
+        use _ =
+            Activity.start
+                "BackgroundCompiler.ParseAndCheckProject"
+                [|
+                    Activity.Tags.project, options.ProjectFileName
+                    Activity.Tags.userOpName, userOpName
+                |]
+
+        bc.ParseAndCheckProjectImpl(options, userOpName)
+
+    member _.GetProjectOptionsFromScript
+        (
+            fileName,
+            sourceText,
+            previewEnabled,
+            loadedTimeStamp,
+            otherFlags,
+            useFsiAuxLib: bool option,
+            useSdkRefs: bool option,
+            sdkDirOverride: string option,
+            assumeDotNetFramework: bool option,
+            optionsStamp: int64 option,
+            _userOpName
+        ) =
+        use _ =
+            Activity.start
+                "BackgroundCompiler.GetProjectOptionsFromScript"
+                [| Activity.Tags.fileName, fileName; Activity.Tags.userOpName, _userOpName |]
+
+        cancellable {
+            use diagnostics = new DiagnosticsScope()
+
+            // Do we add a reference to FSharp.Compiler.Interactive.Settings by default?
+            let useFsiAuxLib = defaultArg useFsiAuxLib true
+            let useSdkRefs = defaultArg useSdkRefs true
+            let reduceMemoryUsage = ReduceMemoryFlag.Yes
+            let previewEnabled = defaultArg previewEnabled false
+
+            // Do we assume .NET Framework references for scripts?
+            let assumeDotNetFramework = defaultArg assumeDotNetFramework true
+
+            let extraFlags =
+                if previewEnabled then
+                    [| "--langversion:preview" |]
+                else
+                    [||]
+
+            let otherFlags = defaultArg otherFlags extraFlags
+
+            let useSimpleResolution =
+                otherFlags |> Array.exists (fun x -> x = "--simpleresolution")
+
+            let loadedTimeStamp = defaultArg loadedTimeStamp DateTime.MaxValue // Not 'now', we don't want to force reloading
+
+            let applyCompilerOptions tcConfigB =
+                let fsiCompilerOptions = GetCoreFsiCompilerOptions tcConfigB
+                ParseCompilerOptions(ignore, fsiCompilerOptions, Array.toList otherFlags)
+
+            let loadClosure =
+                LoadClosure.ComputeClosureOfScriptText(
+                    legacyReferenceResolver,
+                    FSharpCheckerResultsSettings.defaultFSharpBinariesDir,
+                    fileName,
+                    sourceText,
+                    CodeContext.Editing,
+                    useSimpleResolution,
+                    useFsiAuxLib,
+                    useSdkRefs,
+                    sdkDirOverride,
+                    Lexhelp.LexResourceManager(),
+                    applyCompilerOptions,
+                    assumeDotNetFramework,
+                    tryGetMetadataSnapshot,
+                    reduceMemoryUsage,
+                    dependencyProviderForScripts
+                )
+
+            let otherFlags =
+                [|
+                    yield "--noframework"
+                    yield "--warn:3"
+                    yield! otherFlags
+                    for r in loadClosure.References do
+                        yield "-r:" + fst r
+                    for code, _ in loadClosure.NoWarns do
+                        yield "--nowarn:" + code
+                |]
+
+            let options =
+                {
+                    ProjectFileName = fileName + ".fsproj" // Make a name that is unique in this directory.
+                    ProjectId = None
+                    SourceFiles = loadClosure.SourceFiles |> List.map fst |> List.toArray
+                    OtherOptions = otherFlags
+                    ReferencedProjects = [||]
+                    IsIncompleteTypeCheckEnvironment = false
+                    UseScriptResolutionRules = true
+                    LoadTime = loadedTimeStamp
+                    UnresolvedReferences = Some(FSharpUnresolvedReferencesSet(loadClosure.UnresolvedReferences))
+                    OriginalLoadReferences = loadClosure.OriginalLoadReferences
+                    Stamp = optionsStamp
+                }
+
+            scriptClosureCache.Set(AnyCallerThread, options, loadClosure) // Save the full load closure for later correlation.
+
+            let diags =
+                loadClosure.LoadClosureRootFileDiagnostics
+                |> List.map (fun (exn, isError) -> FSharpDiagnostic.CreateFromException(exn, isError, range.Zero, false))
+
+            return options, (diags @ diagnostics.Diagnostics)
+        }
+        |> Cancellable.toAsync
+
+    member bc.InvalidateConfiguration(options: FSharpProjectOptions, userOpName) =
+        use _ =
+            Activity.start
+                "BackgroundCompiler.InvalidateConfiguration"
+                [|
+                    Activity.Tags.project, options.ProjectFileName
+                    Activity.Tags.userOpName, userOpName
+                |]
+
+        if incrementalBuildersCache.ContainsSimilarKey(AnyCallerThread, options) then
+            parseCacheLock.AcquireLock(fun ltok ->
+                for sourceFile in options.SourceFiles do
+                    checkFileInProjectCache.RemoveAnySimilar(ltok, (sourceFile, 0L, options)))
+
+            let _ = createBuilderNode (options, userOpName, CancellationToken.None)
+            ()
+
+    member bc.ClearCache(options: seq, _userOpName) =
+        use _ =
+            Activity.start "BackgroundCompiler.ClearCache" [| Activity.Tags.userOpName, _userOpName |]
+
+        lock gate (fun () ->
+            options
+            |> Seq.iter (fun options -> incrementalBuildersCache.RemoveAnySimilar(AnyCallerThread, options)))
+
+    member _.NotifyProjectCleaned(options: FSharpProjectOptions, userOpName) =
+        use _ =
+            Activity.start
+                "BackgroundCompiler.NotifyProjectCleaned"
+                [|
+                    Activity.Tags.project, options.ProjectFileName
+                    Activity.Tags.userOpName, userOpName
+                |]
+
+        async {
+            let! ct = Async.CancellationToken
+            // If there was a similar entry (as there normally will have been) then re-establish an empty builder .  This
+            // is a somewhat arbitrary choice - it will have the effect of releasing memory associated with the previous
+            // builder, but costs some time.
+            if incrementalBuildersCache.ContainsSimilarKey(AnyCallerThread, options) then
+                let _ = createBuilderNode (options, userOpName, ct)
+                ()
+        }
+
+    member _.BeforeBackgroundFileCheck = beforeFileChecked.Publish
+
+    member _.FileParsed = fileParsed.Publish
+
+    member _.FileChecked = fileChecked.Publish
+
+    member _.ProjectChecked = projectChecked.Publish
+
+    member _.ClearCaches() =
+        use _ = Activity.startNoTags "BackgroundCompiler.ClearCaches"
+
+        lock gate (fun () ->
+            parseCacheLock.AcquireLock(fun ltok ->
+                checkFileInProjectCache.Clear(ltok)
+                parseFileCache.Clear(ltok))
+
+            incrementalBuildersCache.Clear(AnyCallerThread)
+            frameworkTcImportsCache.Clear()
+            scriptClosureCache.Clear AnyCallerThread)
+
+    member _.DownsizeCaches() =
+        use _ = Activity.startNoTags "BackgroundCompiler.DownsizeCaches"
+
+        lock gate (fun () ->
+            parseCacheLock.AcquireLock(fun ltok ->
+                checkFileInProjectCache.Resize(ltok, newKeepStrongly = 1)
+                parseFileCache.Resize(ltok, newKeepStrongly = 1))
+
+            incrementalBuildersCache.Resize(AnyCallerThread, newKeepStrongly = 1, newKeepMax = 1)
+            frameworkTcImportsCache.Downsize()
+            scriptClosureCache.Resize(AnyCallerThread, newKeepStrongly = 1, newKeepMax = 1))
+
+    member _.FrameworkImportsCache = frameworkTcImportsCache
+
+    static member ActualParseFileCount = actualParseFileCount
+
+    static member ActualCheckFileCount = actualCheckFileCount
+
+    interface IBackgroundCompiler with
+        member _.BeforeBackgroundFileCheck = self.BeforeBackgroundFileCheck
+
+        member _.CheckFileInProject
+            (
+                parseResults: FSharpParseFileResults,
+                fileName: string,
+                fileVersion: int,
+                sourceText: ISourceText,
+                options: FSharpProjectOptions,
+                userOpName: string
+            ) : NodeCode =
+            self.CheckFileInProject(parseResults, fileName, fileVersion, sourceText, options, userOpName)
+
+        member _.CheckFileInProjectAllowingStaleCachedResults
+            (
+                parseResults: FSharpParseFileResults,
+                fileName: string,
+                fileVersion: int,
+                sourceText: ISourceText,
+                options: FSharpProjectOptions,
+                userOpName: string
+            ) : NodeCode =
+            self.CheckFileInProjectAllowingStaleCachedResults(parseResults, fileName, fileVersion, sourceText, options, userOpName)
+
+        member _.ClearCache(options: seq, userOpName: string) : unit = self.ClearCache(options, userOpName)
+        member _.ClearCaches() : unit = self.ClearCaches()
+        member _.DownsizeCaches() : unit = self.DownsizeCaches()
+        member _.FileChecked: IEvent = self.FileChecked
+        member _.FileParsed: IEvent = self.FileParsed
+
+        member _.FindReferencesInFile
+            (
+                fileName: string,
+                options: FSharpProjectOptions,
+                symbol: FSharpSymbol,
+                canInvalidateProject: bool,
+                userOpName: string
+            ) : NodeCode> =
+            self.FindReferencesInFile(fileName, options, symbol, canInvalidateProject, userOpName)
+
+        member _.FrameworkImportsCache: FrameworkImportsCache = self.FrameworkImportsCache
+
+        member _.GetAssemblyData(options: FSharpProjectOptions, userOpName: string) : NodeCode =
+            self.GetAssemblyData(options, userOpName)
+
+        member _.GetBackgroundCheckResultsForFileInProject
+            (
+                fileName: string,
+                options: FSharpProjectOptions,
+                userOpName: string
+            ) : NodeCode =
+            self.GetBackgroundCheckResultsForFileInProject(fileName, options, userOpName)
+
+        member _.GetBackgroundParseResultsForFileInProject
+            (
+                fileName: string,
+                options: FSharpProjectOptions,
+                userOpName: string
+            ) : NodeCode =
+            self.GetBackgroundParseResultsForFileInProject(fileName, options, userOpName)
+
+        member _.GetCachedCheckFileResult
+            (
+                builder: IncrementalBuilder,
+                fileName: string,
+                sourceText: ISourceText,
+                options: FSharpProjectOptions
+            ) : NodeCode<(FSharpParseFileResults * FSharpCheckFileResults) option> =
+            self.GetCachedCheckFileResult(builder, fileName, sourceText, options)
+
+        member _.GetProjectOptionsFromScript
+            (
+                fileName: string,
+                sourceText: ISourceText,
+                previewEnabled: bool option,
+                loadedTimeStamp: DateTime option,
+                otherFlags: string array option,
+                useFsiAuxLib: bool option,
+                useSdkRefs: bool option,
+                sdkDirOverride: string option,
+                assumeDotNetFramework: bool option,
+                optionsStamp: int64 option,
+                userOpName: string
+            ) : Async =
+            self.GetProjectOptionsFromScript(
+                fileName,
+                sourceText,
+                previewEnabled,
+                loadedTimeStamp,
+                otherFlags,
+                useFsiAuxLib,
+                useSdkRefs,
+                sdkDirOverride,
+                assumeDotNetFramework,
+                optionsStamp,
+                userOpName
+            )
+
+        member _.GetSemanticClassificationForFile
+            (
+                fileName: string,
+                options: FSharpProjectOptions,
+                userOpName: string
+            ) : NodeCode =
+            self.GetSemanticClassificationForFile(fileName, options, userOpName)
+
+        member _.InvalidateConfiguration(options: FSharpProjectOptions, userOpName: string) : unit =
+            self.InvalidateConfiguration(options, userOpName)
+
+        member _.NotifyFileChanged(fileName: string, options: FSharpProjectOptions, userOpName: string) : NodeCode =
+            self.NotifyFileChanged(fileName, options, userOpName)
+
+        member _.NotifyProjectCleaned(options: FSharpProjectOptions, userOpName: string) : Async =
+            self.NotifyProjectCleaned(options, userOpName)
+
+        member _.ParseAndCheckFileInProject
+            (
+                fileName: string,
+                fileVersion: int,
+                sourceText: ISourceText,
+                options: FSharpProjectOptions,
+                userOpName: string
+            ) : NodeCode =
+            self.ParseAndCheckFileInProject(fileName, fileVersion, sourceText, options, userOpName)
+
+        member _.ParseAndCheckProject(options: FSharpProjectOptions, userOpName: string) : NodeCode =
+            self.ParseAndCheckProject(options, userOpName)
+
+        member _.ParseFile
+            (
+                fileName: string,
+                sourceText: ISourceText,
+                options: FSharpParsingOptions,
+                cache: bool,
+                userOpName: string
+            ) : Async =
+            self.ParseFile(fileName, sourceText, options, cache, userOpName)
+
+        member _.ProjectChecked: IEvent = self.ProjectChecked
+
+        member _.TryGetRecentCheckResultsForFile
+            (
+                fileName: string,
+                options: FSharpProjectOptions,
+                sourceText: ISourceText option,
+                userOpName: string
+            ) : (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option =
+            self.TryGetRecentCheckResultsForFile(fileName, options, sourceText, userOpName)
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
new file mode 100644
index 00000000000..28d5996b5b0
--- /dev/null
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -0,0 +1,54 @@
+namespace FSharp.Compiler.CodeAnalysis
+
+
+type internal TransparentCompiler() =
+
+    interface IBackgroundCompiler with
+        member this.BeforeBackgroundFileCheck: IEvent =
+            raise (System.NotImplementedException())
+        member this.CheckFileInProject(parseResults: FSharpParseFileResults, fileName: string, fileVersion: int, sourceText: FSharp.Compiler.Text.ISourceText, options: FSharpProjectOptions, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode =
+            raise (System.NotImplementedException())
+        member this.CheckFileInProjectAllowingStaleCachedResults(parseResults: FSharpParseFileResults, fileName: string, fileVersion: int, sourceText: FSharp.Compiler.Text.ISourceText, options: FSharpProjectOptions, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode =
+            raise (System.NotImplementedException())
+        member this.ClearCache(options: seq, userOpName: string): unit =
+            raise (System.NotImplementedException())
+        member this.ClearCaches(): unit =
+            raise (System.NotImplementedException())
+        member this.DownsizeCaches(): unit =
+            raise (System.NotImplementedException())
+        member this.FileChecked: IEvent =
+            raise (System.NotImplementedException())
+        member this.FileParsed: IEvent =
+            raise (System.NotImplementedException())
+        member this.FindReferencesInFile(fileName: string, options: FSharpProjectOptions, symbol: FSharp.Compiler.Symbols.FSharpSymbol, canInvalidateProject: bool, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode> =
+            raise (System.NotImplementedException())
+        member this.FrameworkImportsCache: FrameworkImportsCache =
+            raise (System.NotImplementedException())
+        member this.GetAssemblyData(options: FSharpProjectOptions, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode =
+            raise (System.NotImplementedException())
+        member this.GetBackgroundCheckResultsForFileInProject(fileName: string, options: FSharpProjectOptions, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode =
+            raise (System.NotImplementedException())
+        member this.GetBackgroundParseResultsForFileInProject(fileName: string, options: FSharpProjectOptions, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode =
+            raise (System.NotImplementedException())
+        member this.GetCachedCheckFileResult(builder: IncrementalBuilder, fileName: string, sourceText: FSharp.Compiler.Text.ISourceText, options: FSharpProjectOptions): FSharp.Compiler.BuildGraph.NodeCode<(FSharpParseFileResults * FSharpCheckFileResults) option> =
+            raise (System.NotImplementedException())
+        member this.GetProjectOptionsFromScript(fileName: string, sourceText: FSharp.Compiler.Text.ISourceText, previewEnabled: bool option, loadedTimeStamp: System.DateTime option, otherFlags: string array option, useFsiAuxLib: bool option, useSdkRefs: bool option, sdkDirOverride: string option, assumeDotNetFramework: bool option, optionsStamp: int64 option, userOpName: string): Async =
+            raise (System.NotImplementedException())
+        member this.GetSemanticClassificationForFile(fileName: string, options: FSharpProjectOptions, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode =
+            raise (System.NotImplementedException())
+        member this.InvalidateConfiguration(options: FSharpProjectOptions, userOpName: string): unit =
+            raise (System.NotImplementedException())
+        member this.NotifyFileChanged(fileName: string, options: FSharpProjectOptions, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode =
+            raise (System.NotImplementedException())
+        member this.NotifyProjectCleaned(options: FSharpProjectOptions, userOpName: string): Async =
+            raise (System.NotImplementedException())
+        member this.ParseAndCheckFileInProject(fileName: string, fileVersion: int, sourceText: FSharp.Compiler.Text.ISourceText, options: FSharpProjectOptions, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode =
+            raise (System.NotImplementedException())
+        member this.ParseAndCheckProject(options: FSharpProjectOptions, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode =
+            raise (System.NotImplementedException())
+        member this.ParseFile(fileName: string, sourceText: FSharp.Compiler.Text.ISourceText, options: FSharpParsingOptions, cache: bool, userOpName: string): Async =
+            raise (System.NotImplementedException())
+        member this.ProjectChecked: IEvent =
+            raise (System.NotImplementedException())
+        member this.TryGetRecentCheckResultsForFile(fileName: string, options: FSharpProjectOptions, sourceText: FSharp.Compiler.Text.ISourceText option, userOpName: string): (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option =
+            raise (System.NotImplementedException())
\ No newline at end of file
diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs
index cf5487e25df..8b6a9c1766a 100644
--- a/src/Compiler/Service/service.fs
+++ b/src/Compiler/Service/service.fs
@@ -36,19 +36,6 @@ open FSharp.Compiler.Text.Range
 open FSharp.Compiler.TcGlobals
 open FSharp.Compiler.BuildGraph
 
-[]
-module EnvMisc =
-    let braceMatchCacheSize = GetEnvInteger "FCS_BraceMatchCacheSize" 5
-    let parseFileCacheSize = GetEnvInteger "FCS_ParseFileCacheSize" 2
-    let checkFileInProjectCacheSize = GetEnvInteger "FCS_CheckFileInProjectCacheSize" 10
-
-    let projectCacheSizeDefault = GetEnvInteger "FCS_ProjectCacheSizeDefault" 3
-    let frameworkTcImportsCacheStrongSize = GetEnvInteger "FCS_frameworkTcImportsCacheStrongSizeDefault" 8
-
-//----------------------------------------------------------------------------
-// BackgroundCompiler
-//
-
 []
 type DocumentSource =
     | FileSystem
@@ -58,46 +45,6 @@ type DocumentSource =
 []
 type IsResultObsolete = IsResultObsolete of (unit -> bool)
 
-[]
-module Helpers =
-
-    /// Determine whether two (fileName,options) keys are identical w.r.t. affect on checking
-    let AreSameForChecking2 ((fileName1: string, options1: FSharpProjectOptions), (fileName2, options2)) =
-        (fileName1 = fileName2)
-        && FSharpProjectOptions.AreSameForChecking(options1, options2)
-
-    /// Determine whether two (fileName,options) keys should be identical w.r.t. resource usage
-    let AreSubsumable2 ((fileName1: string, o1: FSharpProjectOptions), (fileName2: string, o2: FSharpProjectOptions)) =
-        (fileName1 = fileName2) && FSharpProjectOptions.UseSameProject(o1, o2)
-
-    /// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. parsing
-    let AreSameForParsing ((fileName1: string, source1Hash: int64, options1), (fileName2, source2Hash, options2)) =
-        fileName1 = fileName2 && options1 = options2 && source1Hash = source2Hash
-
-    let AreSimilarForParsing ((fileName1, _, _), (fileName2, _, _)) = fileName1 = fileName2
-
-    /// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. checking
-    let AreSameForChecking3 ((fileName1: string, source1Hash: int64, options1: FSharpProjectOptions), (fileName2, source2Hash, options2)) =
-        (fileName1 = fileName2)
-        && FSharpProjectOptions.AreSameForChecking(options1, options2)
-        && source1Hash = source2Hash
-
-    /// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. resource usage
-    let AreSubsumable3 ((fileName1: string, _, o1: FSharpProjectOptions), (fileName2: string, _, o2: FSharpProjectOptions)) =
-        (fileName1 = fileName2) && FSharpProjectOptions.UseSameProject(o1, o2)
-
-    /// If a symbol is an attribute check if given set of names contains its name without the Attribute suffix
-    let rec NamesContainAttribute (symbol: FSharpSymbol) names =
-        match symbol with
-        | :? FSharpMemberOrFunctionOrValue as mofov ->
-            mofov.DeclaringEntity
-            |> Option.map (fun entity -> NamesContainAttribute entity names)
-            |> Option.defaultValue false
-        | :? FSharpEntity as entity when entity.IsAttributeType && symbol.DisplayNameCore.EndsWithOrdinal "Attribute" ->
-            let nameWithoutAttribute = String.dropSuffix symbol.DisplayNameCore "Attribute"
-            names |> Set.contains nameWithoutAttribute
-        | _ -> false
-
 module CompileHelpers =
     let mkCompilationDiagnosticsHandlers () =
         let diagnostics = ResizeArray<_>()
@@ -164,1088 +111,6 @@ module CompileHelpers =
             Console.SetError error
         | None -> ()
 
-type SourceTextHash = int64
-type CacheStamp = int64
-type FileName = string
-type FilePath = string
-type ProjectPath = string
-type FileVersion = int
-
-type ParseCacheLockToken() =
-    interface LockToken
-
-type ScriptClosureCacheToken() =
-    interface LockToken
-
-type CheckFileCacheKey = FileName * SourceTextHash * FSharpProjectOptions
-type CheckFileCacheValue = FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash * DateTime
-
-// There is only one instance of this type, held in FSharpChecker
-type BackgroundCompiler
-    (
-        legacyReferenceResolver,
-        projectCacheSize,
-        keepAssemblyContents,
-        keepAllBackgroundResolutions,
-        tryGetMetadataSnapshot,
-        suggestNamesForErrors,
-        keepAllBackgroundSymbolUses,
-        enableBackgroundItemKeyStoreAndSemanticClassification,
-        enablePartialTypeChecking,
-        parallelReferenceResolution,
-        captureIdentifiersWhenParsing,
-        getSource: (string -> ISourceText option) option,
-        useChangeNotifications,
-        useSyntaxTreeCache
-    ) as self =
-
-    let beforeFileChecked = Event()
-    let fileParsed = Event()
-    let fileChecked = Event()
-    let projectChecked = Event()
-
-    // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.backgroundCompiler.scriptClosureCache
-    /// Information about the derived script closure.
-    let scriptClosureCache =
-        MruCache(
-            projectCacheSize,
-            areSame = FSharpProjectOptions.AreSameForChecking,
-            areSimilar = FSharpProjectOptions.UseSameProject
-        )
-
-    let frameworkTcImportsCache = FrameworkImportsCache(frameworkTcImportsCacheStrongSize)
-
-    // We currently share one global dependency provider for all scripts for the FSharpChecker.
-    // For projects, one is used per project.
-    //
-    // Sharing one for all scripts is necessary for good performance from GetProjectOptionsFromScript,
-    // which requires a dependency provider to process through the project options prior to working out
-    // if the cached incremental builder can be used for the project.
-    let dependencyProviderForScripts = new DependencyProvider()
-
-    let getProjectReferences (options: FSharpProjectOptions) userOpName =
-        [
-            for r in options.ReferencedProjects do
-
-                match r with
-                | FSharpReferencedProject.FSharpReference (nm, opts) ->
-                    // Don't use cross-project references for FSharp.Core, since various bits of code
-                    // require a concrete FSharp.Core to exist on-disk. The only solutions that have
-                    // these cross-project references to FSharp.Core are VisualFSharp.sln and FSharp.sln. The ramification
-                    // of this is that you need to build FSharp.Core to get intellisense in those projects.
-
-                    if
-                        (try
-                            Path.GetFileNameWithoutExtension(nm)
-                         with _ ->
-                             "")
-                        <> GetFSharpCoreLibraryName()
-                    then
-                        { new IProjectReference with
-                            member x.EvaluateRawContents() =
-                                node {
-                                    Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "GetAssemblyData", nm)
-                                    return! self.GetAssemblyData(opts, userOpName + ".CheckReferencedProject(" + nm + ")")
-                                }
-
-                            member x.TryGetLogicalTimeStamp(cache) =
-                                self.TryGetLogicalTimeStampForProject(cache, opts)
-
-                            member x.FileName = nm
-                        }
-
-                | FSharpReferencedProject.PEReference (nm, getStamp, delayedReader) ->
-                    { new IProjectReference with
-                        member x.EvaluateRawContents() =
-                            node {
-                                let! ilReaderOpt = delayedReader.TryGetILModuleReader() |> NodeCode.FromCancellable
-
-                                match ilReaderOpt with
-                                | Some ilReader ->
-                                    let ilModuleDef, ilAsmRefs = ilReader.ILModuleDef, ilReader.ILAssemblyRefs
-                                    let data = RawFSharpAssemblyData(ilModuleDef, ilAsmRefs) :> IRawFSharpAssemblyData
-                                    return ProjectAssemblyDataResult.Available data
-                                | _ ->
-                                    // Note 'false' - if a PEReference doesn't find an ILModuleReader then we don't
-                                    // continue to try to use an on-disk DLL
-                                    return ProjectAssemblyDataResult.Unavailable false
-                            }
-
-                        member x.TryGetLogicalTimeStamp _ = getStamp () |> Some
-                        member x.FileName = nm
-                    }
-
-                | FSharpReferencedProject.ILModuleReference (nm, getStamp, getReader) ->
-                    { new IProjectReference with
-                        member x.EvaluateRawContents() =
-                            node {
-                                let ilReader = getReader ()
-                                let ilModuleDef, ilAsmRefs = ilReader.ILModuleDef, ilReader.ILAssemblyRefs
-                                let data = RawFSharpAssemblyData(ilModuleDef, ilAsmRefs) :> IRawFSharpAssemblyData
-                                return ProjectAssemblyDataResult.Available data
-                            }
-
-                        member x.TryGetLogicalTimeStamp _ = getStamp () |> Some
-                        member x.FileName = nm
-                    }
-        ]
-
-    /// CreateOneIncrementalBuilder (for background type checking). Note that fsc.fs also
-    /// creates an incremental builder used by the command line compiler.
-    let CreateOneIncrementalBuilder (options: FSharpProjectOptions, userOpName) =
-        node {
-            use _ =
-                Activity.start "BackgroundCompiler.CreateOneIncrementalBuilder" [| Activity.Tags.project, options.ProjectFileName |]
-
-            Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "CreateOneIncrementalBuilder", options.ProjectFileName)
-            let projectReferences = getProjectReferences options userOpName
-
-            let loadClosure = scriptClosureCache.TryGet(AnyCallerThread, options)
-
-            let dependencyProvider =
-                if options.UseScriptResolutionRules then
-                    Some dependencyProviderForScripts
-                else
-                    None
-
-            let! builderOpt, diagnostics =
-                IncrementalBuilder.TryCreateIncrementalBuilderForProjectOptions(
-                    legacyReferenceResolver,
-                    FSharpCheckerResultsSettings.defaultFSharpBinariesDir,
-                    frameworkTcImportsCache,
-                    loadClosure,
-                    Array.toList options.SourceFiles,
-                    Array.toList options.OtherOptions,
-                    projectReferences,
-                    options.ProjectDirectory,
-                    options.UseScriptResolutionRules,
-                    keepAssemblyContents,
-                    keepAllBackgroundResolutions,
-                    tryGetMetadataSnapshot,
-                    suggestNamesForErrors,
-                    keepAllBackgroundSymbolUses,
-                    enableBackgroundItemKeyStoreAndSemanticClassification,
-                    enablePartialTypeChecking,
-                    dependencyProvider,
-                    parallelReferenceResolution,
-                    captureIdentifiersWhenParsing,
-                    getSource,
-                    useChangeNotifications,
-                    useSyntaxTreeCache
-                )
-
-            match builderOpt with
-            | None -> ()
-            | Some builder ->
-
-#if !NO_TYPEPROVIDERS
-                // Register the behaviour that responds to CCUs being invalidated because of type
-                // provider Invalidate events. This invalidates the configuration in the build.
-                builder.ImportsInvalidatedByTypeProvider.Add(fun () -> self.InvalidateConfiguration(options, userOpName))
-#endif
-
-                // Register the callback called just before a file is typechecked by the background builder (without recording
-                // errors or intellisense information).
-                //
-                // This indicates to the UI that the file type check state is dirty. If the file is open and visible then
-                // the UI will sooner or later request a typecheck of the file, recording errors and intellisense information.
-                builder.BeforeFileChecked.Add(fun file -> beforeFileChecked.Trigger(file, options))
-                builder.FileParsed.Add(fun file -> fileParsed.Trigger(file, options))
-                builder.FileChecked.Add(fun file -> fileChecked.Trigger(file, options))
-                builder.ProjectChecked.Add(fun () -> projectChecked.Trigger options)
-
-            return (builderOpt, diagnostics)
-        }
-
-    let parseCacheLock = Lock()
-
-    // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.parseFileInProjectCache. Most recently used cache for parsing files.
-    let parseFileCache =
-        MruCache(parseFileCacheSize, areSimilar = AreSimilarForParsing, areSame = AreSameForParsing)
-
-    // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.checkFileInProjectCache
-    //
-    /// Cache which holds recently seen type-checks.
-    /// This cache may hold out-of-date entries, in two senses
-    ///    - there may be a more recent antecedent state available because the background build has made it available
-    ///    - the source for the file may have changed
-
-    // Also keyed on source. This can only be out of date if the antecedent is out of date
-    let checkFileInProjectCache =
-        MruCache>(
-            keepStrongly = checkFileInProjectCacheSize,
-            areSame = AreSameForChecking3,
-            areSimilar = AreSubsumable3
-        )
-
-    // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.backgroundCompiler.incrementalBuildersCache. This root typically holds more
-    // live information than anything else in the F# Language Service, since it holds up to 3 (projectCacheStrongSize) background project builds
-    // strongly.
-    //
-    /// Cache of builds keyed by options.
-    let gate = obj ()
-
-    let incrementalBuildersCache =
-        MruCache>(
-            keepStrongly = projectCacheSize,
-            keepMax = projectCacheSize,
-            areSame = FSharpProjectOptions.AreSameForChecking,
-            areSimilar = FSharpProjectOptions.UseSameProject
-        )
-
-    let tryGetBuilderNode options =
-        incrementalBuildersCache.TryGet(AnyCallerThread, options)
-
-    let tryGetBuilder options : NodeCode option =
-        tryGetBuilderNode options |> Option.map (fun x -> x.GetOrComputeValue())
-
-    let tryGetSimilarBuilder options : NodeCode option =
-        incrementalBuildersCache.TryGetSimilar(AnyCallerThread, options)
-        |> Option.map (fun x -> x.GetOrComputeValue())
-
-    let tryGetAnyBuilder options : NodeCode option =
-        incrementalBuildersCache.TryGetAny(AnyCallerThread, options)
-        |> Option.map (fun x -> x.GetOrComputeValue())
-
-    let createBuilderNode (options, userOpName, ct: CancellationToken) =
-        lock gate (fun () ->
-            if ct.IsCancellationRequested then
-                GraphNode.FromResult(None, [||])
-            else
-                let getBuilderNode = GraphNode(CreateOneIncrementalBuilder(options, userOpName))
-                incrementalBuildersCache.Set(AnyCallerThread, options, getBuilderNode)
-                getBuilderNode)
-
-    let createAndGetBuilder (options, userOpName) =
-        node {
-            let! ct = NodeCode.CancellationToken
-            let getBuilderNode = createBuilderNode (options, userOpName, ct)
-            return! getBuilderNode.GetOrComputeValue()
-        }
-
-    let getOrCreateBuilder (options, userOpName) : NodeCode =
-        match tryGetBuilder options with
-        | Some getBuilder ->
-            node {
-                match! getBuilder with
-                | builderOpt, creationDiags when builderOpt.IsNone || not builderOpt.Value.IsReferencesInvalidated -> return builderOpt, creationDiags
-                | _ ->
-                    // The builder could be re-created,
-                    //    clear the check file caches that are associated with it.
-                    //    We must do this in order to not return stale results when references
-                    //    in the project get changed/added/removed.
-                    parseCacheLock.AcquireLock(fun ltok ->
-                        options.SourceFiles
-                        |> Array.iter (fun sourceFile ->
-                            let key = (sourceFile, 0L, options)
-                            checkFileInProjectCache.RemoveAnySimilar(ltok, key)))
-
-                    return! createAndGetBuilder (options, userOpName)
-            }
-        | _ -> createAndGetBuilder (options, userOpName)
-
-    let getSimilarOrCreateBuilder (options, userOpName) =
-        match tryGetSimilarBuilder options with
-        | Some res -> res
-        // The builder does not exist at all. Create it.
-        | None -> getOrCreateBuilder (options, userOpName)
-
-    let getOrCreateBuilderWithInvalidationFlag (options, canInvalidateProject, userOpName) =
-        if canInvalidateProject then
-            getOrCreateBuilder (options, userOpName)
-        else
-            getSimilarOrCreateBuilder (options, userOpName)
-
-    let getAnyBuilder (options, userOpName) =
-        match tryGetAnyBuilder options with
-        | Some getBuilder -> getBuilder
-        | _ -> getOrCreateBuilder (options, userOpName)
-
-    static let mutable actualParseFileCount = 0
-
-    static let mutable actualCheckFileCount = 0
-
-    /// Should be a fast operation. Ensures that we have only one async lazy object per file and its hash.
-    let getCheckFileNode (parseResults, sourceText, fileName, options, _fileVersion, builder, tcPrior, tcInfo, creationDiags) =
-
-        // Here we lock for the creation of the node, not its execution
-        parseCacheLock.AcquireLock(fun ltok ->
-            let key = (fileName, sourceText.GetHashCode() |> int64, options)
-
-            match checkFileInProjectCache.TryGet(ltok, key) with
-            | Some res -> res
-            | _ ->
-                let res =
-                    GraphNode(
-                        node {
-                            let! res = self.CheckOneFileImplAux(parseResults, sourceText, fileName, options, builder, tcPrior, tcInfo, creationDiags)
-                            Interlocked.Increment(&actualCheckFileCount) |> ignore
-                            return res
-                        }
-                    )
-
-                checkFileInProjectCache.Set(ltok, key, res)
-                res)
-
-    member _.ParseFile(fileName: string, sourceText: ISourceText, options: FSharpParsingOptions, cache: bool, userOpName: string) =
-        async {
-            use _ =
-                Activity.start
-                    "BackgroundCompiler.ParseFile"
-                    [|
-                        Activity.Tags.fileName, fileName
-                        Activity.Tags.userOpName, userOpName
-                        Activity.Tags.cache, cache.ToString()
-                    |]
-
-            if cache then
-                let hash = sourceText.GetHashCode() |> int64
-
-                match parseCacheLock.AcquireLock(fun ltok -> parseFileCache.TryGet(ltok, (fileName, hash, options))) with
-                | Some res -> return res
-                | None ->
-                    Interlocked.Increment(&actualParseFileCount) |> ignore
-
-                    let parseDiagnostics, parseTree, anyErrors =
-                        ParseAndCheckFile.parseFile (sourceText, fileName, options, userOpName, suggestNamesForErrors, captureIdentifiersWhenParsing)
-
-                    let res = FSharpParseFileResults(parseDiagnostics, parseTree, anyErrors, options.SourceFiles)
-                    parseCacheLock.AcquireLock(fun ltok -> parseFileCache.Set(ltok, (fileName, hash, options), res))
-                    return res
-            else
-                let parseDiagnostics, parseTree, anyErrors =
-                    ParseAndCheckFile.parseFile (sourceText, fileName, options, userOpName, false, captureIdentifiersWhenParsing)
-
-                return FSharpParseFileResults(parseDiagnostics, parseTree, anyErrors, options.SourceFiles)
-        }
-
-    /// Fetch the parse information from the background compiler (which checks w.r.t. the FileSystem API)
-    member _.GetBackgroundParseResultsForFileInProject(fileName, options, userOpName) =
-        node {
-            use _ =
-                Activity.start
-                    "BackgroundCompiler.GetBackgroundParseResultsForFileInProject"
-                    [| Activity.Tags.fileName, fileName; Activity.Tags.userOpName, userOpName |]
-
-            let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName)
-
-            match builderOpt with
-            | None ->
-                let parseTree = EmptyParsedInput(fileName, (false, false))
-                return FSharpParseFileResults(creationDiags, parseTree, true, [||])
-            | Some builder ->
-                let parseTree, _, _, parseDiagnostics = builder.GetParseResultsForFile fileName
-
-                let parseDiagnostics =
-                    DiagnosticHelpers.CreateDiagnostics(builder.TcConfig.diagnosticsOptions, false, fileName, parseDiagnostics, suggestNamesForErrors)
-
-                let diagnostics = [| yield! creationDiags; yield! parseDiagnostics |]
-
-                let parseResults =
-                    FSharpParseFileResults(
-                        diagnostics = diagnostics,
-                        input = parseTree,
-                        parseHadErrors = false,
-                        dependencyFiles = builder.AllDependenciesDeprecated
-                    )
-
-                return parseResults
-        }
-
-    member _.GetCachedCheckFileResult(builder: IncrementalBuilder, fileName, sourceText: ISourceText, options) =
-        node {
-            use _ =
-                Activity.start "BackgroundCompiler.GetCachedCheckFileResult" [| Activity.Tags.fileName, fileName |]
-
-            let hash = sourceText.GetHashCode() |> int64
-            let key = (fileName, hash, options)
-            let cachedResultsOpt = parseCacheLock.AcquireLock(fun ltok -> checkFileInProjectCache.TryGet(ltok, key))
-
-            match cachedResultsOpt with
-            | Some cachedResults ->
-                match! cachedResults.GetOrComputeValue() with
-                | parseResults, checkResults, _, priorTimeStamp when
-                    (match builder.GetCheckResultsBeforeFileInProjectEvenIfStale fileName with
-                     | None -> false
-                     | Some (tcPrior) ->
-                         tcPrior.ProjectTimeStamp = priorTimeStamp
-                         && builder.AreCheckResultsBeforeFileInProjectReady(fileName))
-                    ->
-                    return Some(parseResults, checkResults)
-                | _ ->
-                    parseCacheLock.AcquireLock(fun ltok -> checkFileInProjectCache.RemoveAnySimilar(ltok, key))
-                    return None
-            | _ -> return None
-        }
-
-    member private _.CheckOneFileImplAux
-        (
-            parseResults: FSharpParseFileResults,
-            sourceText: ISourceText,
-            fileName: string,
-            options: FSharpProjectOptions,
-            builder: IncrementalBuilder,
-            tcPrior: PartialCheckResults,
-            tcInfo: TcInfo,
-            creationDiags: FSharpDiagnostic[]
-        ) : NodeCode =
-
-        node {
-            // Get additional script #load closure information if applicable.
-            // For scripts, this will have been recorded by GetProjectOptionsFromScript.
-            let tcConfig = tcPrior.TcConfig
-            let loadClosure = scriptClosureCache.TryGet(AnyCallerThread, options)
-
-            let! checkAnswer =
-                FSharpCheckFileResults.CheckOneFile(
-                    parseResults,
-                    sourceText,
-                    fileName,
-                    options.ProjectFileName,
-                    tcConfig,
-                    tcPrior.TcGlobals,
-                    tcPrior.TcImports,
-                    tcInfo.tcState,
-                    tcInfo.moduleNamesDict,
-                    loadClosure,
-                    tcInfo.TcDiagnostics,
-                    options.IsIncompleteTypeCheckEnvironment,
-                    options,
-                    builder,
-                    Array.ofList tcInfo.tcDependencyFiles,
-                    creationDiags,
-                    parseResults.Diagnostics,
-                    keepAssemblyContents,
-                    suggestNamesForErrors
-                )
-                |> NodeCode.FromCancellable
-
-            GraphNode.SetPreferredUILang tcConfig.preferredUiLang
-            return (parseResults, checkAnswer, sourceText.GetHashCode() |> int64, tcPrior.ProjectTimeStamp)
-        }
-
-    member private bc.CheckOneFileImpl
-        (
-            parseResults: FSharpParseFileResults,
-            sourceText: ISourceText,
-            fileName: string,
-            options: FSharpProjectOptions,
-            fileVersion: int,
-            builder: IncrementalBuilder,
-            tcPrior: PartialCheckResults,
-            tcInfo: TcInfo,
-            creationDiags: FSharpDiagnostic[]
-        ) =
-
-        node {
-            match! bc.GetCachedCheckFileResult(builder, fileName, sourceText, options) with
-            | Some (_, results) -> return FSharpCheckFileAnswer.Succeeded results
-            | _ ->
-                let lazyCheckFile =
-                    getCheckFileNode (parseResults, sourceText, fileName, options, fileVersion, builder, tcPrior, tcInfo, creationDiags)
-
-                let! _, results, _, _ = lazyCheckFile.GetOrComputeValue()
-                return FSharpCheckFileAnswer.Succeeded results
-        }
-
-    /// Type-check the result obtained by parsing, but only if the antecedent type checking context is available.
-    member bc.CheckFileInProjectAllowingStaleCachedResults
-        (
-            parseResults: FSharpParseFileResults,
-            fileName,
-            fileVersion,
-            sourceText: ISourceText,
-            options,
-            userOpName
-        ) =
-        node {
-            use _ =
-                Activity.start
-                    "BackgroundCompiler.CheckFileInProjectAllowingStaleCachedResults"
-                    [|
-                        Activity.Tags.project, options.ProjectFileName
-                        Activity.Tags.fileName, fileName
-                        Activity.Tags.userOpName, userOpName
-                    |]
-
-            let! cachedResults =
-                node {
-                    let! builderOpt, creationDiags = getAnyBuilder (options, userOpName)
-
-                    match builderOpt with
-                    | Some builder ->
-                        match! bc.GetCachedCheckFileResult(builder, fileName, sourceText, options) with
-                        | Some (_, checkResults) -> return Some(builder, creationDiags, Some(FSharpCheckFileAnswer.Succeeded checkResults))
-                        | _ -> return Some(builder, creationDiags, None)
-                    | _ -> return None // the builder wasn't ready
-                }
-
-            match cachedResults with
-            | None -> return None
-            | Some (_, _, Some x) -> return Some x
-            | Some (builder, creationDiags, None) ->
-                Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "CheckFileInProjectAllowingStaleCachedResults.CacheMiss", fileName)
-
-                match builder.GetCheckResultsBeforeFileInProjectEvenIfStale fileName with
-                | Some tcPrior ->
-                    match tcPrior.TryPeekTcInfo() with
-                    | Some tcInfo ->
-                        let! checkResults =
-                            bc.CheckOneFileImpl(parseResults, sourceText, fileName, options, fileVersion, builder, tcPrior, tcInfo, creationDiags)
-
-                        return Some checkResults
-                    | None -> return None
-                | None -> return None // the incremental builder was not up to date
-        }
-
-    /// Type-check the result obtained by parsing. Force the evaluation of the antecedent type checking context if needed.
-    member bc.CheckFileInProject(parseResults: FSharpParseFileResults, fileName, fileVersion, sourceText: ISourceText, options, userOpName) =
-        node {
-            use _ =
-                Activity.start
-                    "BackgroundCompiler.CheckFileInProject"
-                    [|
-                        Activity.Tags.project, options.ProjectFileName
-                        Activity.Tags.fileName, fileName
-                        Activity.Tags.userOpName, userOpName
-                    |]
-
-            let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName)
-
-            match builderOpt with
-            | None -> return FSharpCheckFileAnswer.Succeeded(FSharpCheckFileResults.MakeEmpty(fileName, creationDiags, keepAssemblyContents))
-            | Some builder ->
-                // Check the cache. We can only use cached results when there is no work to do to bring the background builder up-to-date
-                let! cachedResults = bc.GetCachedCheckFileResult(builder, fileName, sourceText, options)
-
-                match cachedResults with
-                | Some (_, checkResults) -> return FSharpCheckFileAnswer.Succeeded checkResults
-                | _ ->
-                    let! tcPrior = builder.GetCheckResultsBeforeFileInProject fileName
-                    let! tcInfo = tcPrior.GetOrComputeTcInfo()
-                    return! bc.CheckOneFileImpl(parseResults, sourceText, fileName, options, fileVersion, builder, tcPrior, tcInfo, creationDiags)
-        }
-
-    /// Parses and checks the source file and returns untyped AST and check results.
-    member bc.ParseAndCheckFileInProject(fileName: string, fileVersion, sourceText: ISourceText, options: FSharpProjectOptions, userOpName) =
-        node {
-            use _ =
-                Activity.start
-                    "BackgroundCompiler.ParseAndCheckFileInProject"
-                    [|
-                        Activity.Tags.project, options.ProjectFileName
-                        Activity.Tags.fileName, fileName
-                        Activity.Tags.userOpName, userOpName
-                    |]
-
-            let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName)
-
-            match builderOpt with
-            | None ->
-                let parseTree = EmptyParsedInput(fileName, (false, false))
-                let parseResults = FSharpParseFileResults(creationDiags, parseTree, true, [||])
-                return (parseResults, FSharpCheckFileAnswer.Aborted)
-
-            | Some builder ->
-                let! cachedResults = bc.GetCachedCheckFileResult(builder, fileName, sourceText, options)
-
-                match cachedResults with
-                | Some (parseResults, checkResults) -> return (parseResults, FSharpCheckFileAnswer.Succeeded checkResults)
-                | _ ->
-                    let! tcPrior = builder.GetCheckResultsBeforeFileInProject fileName
-                    let! tcInfo = tcPrior.GetOrComputeTcInfo()
-                    // Do the parsing.
-                    let parsingOptions =
-                        FSharpParsingOptions.FromTcConfig(builder.TcConfig, Array.ofList builder.SourceFiles, options.UseScriptResolutionRules)
-
-                    GraphNode.SetPreferredUILang tcPrior.TcConfig.preferredUiLang
-
-                    let parseDiagnostics, parseTree, anyErrors =
-                        ParseAndCheckFile.parseFile (
-                            sourceText,
-                            fileName,
-                            parsingOptions,
-                            userOpName,
-                            suggestNamesForErrors,
-                            captureIdentifiersWhenParsing
-                        )
-
-                    let parseResults =
-                        FSharpParseFileResults(parseDiagnostics, parseTree, anyErrors, builder.AllDependenciesDeprecated)
-
-                    let! checkResults =
-                        bc.CheckOneFileImpl(parseResults, sourceText, fileName, options, fileVersion, builder, tcPrior, tcInfo, creationDiags)
-
-                    return (parseResults, checkResults)
-        }
-
-    member _.NotifyFileChanged(fileName, options, userOpName) =
-        node {
-            use _ =
-                Activity.start
-                    "BackgroundCompiler.NotifyFileChanged"
-                    [|
-                        Activity.Tags.project, options.ProjectFileName
-                        Activity.Tags.fileName, fileName
-                        Activity.Tags.userOpName, userOpName
-                    |]
-
-            let! builderOpt, _ = getOrCreateBuilder (options, userOpName)
-
-            match builderOpt with
-            | None -> return ()
-            | Some builder -> do! builder.NotifyFileChanged(fileName, DateTime.UtcNow)
-        }
-
-    /// Fetch the check information from the background compiler (which checks w.r.t. the FileSystem API)
-    member _.GetBackgroundCheckResultsForFileInProject(fileName, options, userOpName) =
-        node {
-            use _ =
-                Activity.start
-                    "BackgroundCompiler.ParseAndCheckFileInProject"
-                    [|
-                        Activity.Tags.project, options.ProjectFileName
-                        Activity.Tags.fileName, fileName
-                        Activity.Tags.userOpName, userOpName
-                    |]
-
-            let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName)
-
-            match builderOpt with
-            | None ->
-                let parseTree = EmptyParsedInput(fileName, (false, false))
-                let parseResults = FSharpParseFileResults(creationDiags, parseTree, true, [||])
-                let typedResults = FSharpCheckFileResults.MakeEmpty(fileName, creationDiags, true)
-                return (parseResults, typedResults)
-            | Some builder ->
-                let parseTree, _, _, parseDiagnostics = builder.GetParseResultsForFile fileName
-                let! tcProj = builder.GetFullCheckResultsAfterFileInProject fileName
-
-                let! tcInfo, tcInfoExtras = tcProj.GetOrComputeTcInfoWithExtras()
-
-                let tcResolutions = tcInfoExtras.tcResolutions
-                let tcSymbolUses = tcInfoExtras.tcSymbolUses
-                let tcOpenDeclarations = tcInfoExtras.tcOpenDeclarations
-                let latestCcuSigForFile = tcInfo.latestCcuSigForFile
-                let tcState = tcInfo.tcState
-                let tcEnvAtEnd = tcInfo.tcEnvAtEndOfFile
-                let latestImplementationFile = tcInfoExtras.latestImplFile
-                let tcDependencyFiles = tcInfo.tcDependencyFiles
-                let tcDiagnostics = tcInfo.TcDiagnostics
-                let diagnosticsOptions = builder.TcConfig.diagnosticsOptions
-
-                let parseDiagnostics =
-                    DiagnosticHelpers.CreateDiagnostics(diagnosticsOptions, false, fileName, parseDiagnostics, suggestNamesForErrors)
-
-                let parseDiagnostics = [| yield! creationDiags; yield! parseDiagnostics |]
-
-                let tcDiagnostics =
-                    DiagnosticHelpers.CreateDiagnostics(diagnosticsOptions, false, fileName, tcDiagnostics, suggestNamesForErrors)
-
-                let tcDiagnostics = [| yield! creationDiags; yield! tcDiagnostics |]
-
-                let parseResults =
-                    FSharpParseFileResults(
-                        diagnostics = parseDiagnostics,
-                        input = parseTree,
-                        parseHadErrors = false,
-                        dependencyFiles = builder.AllDependenciesDeprecated
-                    )
-
-                let loadClosure = scriptClosureCache.TryGet(AnyCallerThread, options)
-
-                let typedResults =
-                    FSharpCheckFileResults.Make(
-                        fileName,
-                        options.ProjectFileName,
-                        tcProj.TcConfig,
-                        tcProj.TcGlobals,
-                        options.IsIncompleteTypeCheckEnvironment,
-                        builder,
-                        options,
-                        Array.ofList tcDependencyFiles,
-                        creationDiags,
-                        parseResults.Diagnostics,
-                        tcDiagnostics,
-                        keepAssemblyContents,
-                        Option.get latestCcuSigForFile,
-                        tcState.Ccu,
-                        tcProj.TcImports,
-                        tcEnvAtEnd.AccessRights,
-                        tcResolutions,
-                        tcSymbolUses,
-                        tcEnvAtEnd.NameEnv,
-                        loadClosure,
-                        latestImplementationFile,
-                        tcOpenDeclarations
-                    )
-
-                return (parseResults, typedResults)
-        }
-
-    member _.FindReferencesInFile
-        (
-            fileName: string,
-            options: FSharpProjectOptions,
-            symbol: FSharpSymbol,
-            canInvalidateProject: bool,
-            userOpName: string
-        ) =
-        node {
-            use _ =
-                Activity.start
-                    "BackgroundCompiler.FindReferencesInFile"
-                    [|
-                        Activity.Tags.project, options.ProjectFileName
-                        Activity.Tags.fileName, fileName
-                        Activity.Tags.userOpName, userOpName
-                        "symbol", symbol.FullName
-                    |]
-
-            let! builderOpt, _ = getOrCreateBuilderWithInvalidationFlag (options, canInvalidateProject, userOpName)
-
-            match builderOpt with
-            | None -> return Seq.empty
-            | Some builder ->
-                if builder.ContainsFile fileName then
-                    let! checkResults = builder.GetFullCheckResultsAfterFileInProject fileName
-                    let! keyStoreOpt = checkResults.GetOrComputeItemKeyStoreIfEnabled()
-
-                    match keyStoreOpt with
-                    | None -> return Seq.empty
-                    | Some reader -> return reader.FindAll symbol.Item
-                else
-                    return Seq.empty
-        }
-
-    member _.GetSemanticClassificationForFile(fileName: string, options: FSharpProjectOptions, userOpName: string) =
-        node {
-            use _ =
-                Activity.start
-                    "BackgroundCompiler.GetSemanticClassificationForFile"
-                    [|
-                        Activity.Tags.project, options.ProjectFileName
-                        Activity.Tags.fileName, fileName
-                        Activity.Tags.userOpName, userOpName
-                    |]
-
-            let! builderOpt, _ = getOrCreateBuilder (options, userOpName)
-
-            match builderOpt with
-            | None -> return None
-            | Some builder ->
-                let! checkResults = builder.GetFullCheckResultsAfterFileInProject fileName
-                let! scopt = checkResults.GetOrComputeSemanticClassificationIfEnabled()
-
-                match scopt with
-                | None -> return None
-                | Some sc -> return Some(sc.GetView())
-        }
-
-    /// Try to get recent approximate type check results for a file.
-    member _.TryGetRecentCheckResultsForFile(fileName: string, options: FSharpProjectOptions, sourceText: ISourceText option, _userOpName: string) =
-        use _ =
-            Activity.start
-                "BackgroundCompiler.GetSemanticClassificationForFile"
-                [|
-                    Activity.Tags.project, options.ProjectFileName
-                    Activity.Tags.fileName, fileName
-                    Activity.Tags.userOpName, _userOpName
-                |]
-
-        match sourceText with
-        | Some sourceText ->
-            let hash = sourceText.GetHashCode() |> int64
-
-            let resOpt =
-                parseCacheLock.AcquireLock(fun ltok -> checkFileInProjectCache.TryGet(ltok, (fileName, hash, options)))
-
-            match resOpt with
-            | Some res ->
-                match res.TryPeekValue() with
-                | ValueSome (a, b, c, _) -> Some(a, b, c)
-                | ValueNone -> None
-            | None -> None
-        | None -> None
-
-    /// Parse and typecheck the whole project (the implementation, called recursively as project graph is evaluated)
-    member private _.ParseAndCheckProjectImpl(options, userOpName) =
-        node {
-            let! builderOpt, creationDiags = getOrCreateBuilder (options, userOpName)
-
-            match builderOpt with
-            | None ->
-                let emptyResults =
-                    FSharpCheckProjectResults(options.ProjectFileName, None, keepAssemblyContents, creationDiags, None)
-
-                return emptyResults
-            | Some builder ->
-                let! tcProj, ilAssemRef, tcAssemblyDataOpt, tcAssemblyExprOpt = builder.GetFullCheckResultsAndImplementationsForProject()
-                let diagnosticsOptions = tcProj.TcConfig.diagnosticsOptions
-                let fileName = DummyFileNameForRangesWithoutASpecificLocation
-
-                // Although we do not use 'tcInfoExtras', computing it will make sure we get an extra info.
-                let! tcInfo, _tcInfoExtras = tcProj.GetOrComputeTcInfoWithExtras()
-
-                let topAttribs = tcInfo.topAttribs
-                let tcState = tcInfo.tcState
-                let tcEnvAtEnd = tcInfo.tcEnvAtEndOfFile
-                let tcDiagnostics = tcInfo.TcDiagnostics
-                let tcDependencyFiles = tcInfo.tcDependencyFiles
-
-                let tcDiagnostics =
-                    DiagnosticHelpers.CreateDiagnostics(diagnosticsOptions, true, fileName, tcDiagnostics, suggestNamesForErrors)
-
-                let diagnostics = [| yield! creationDiags; yield! tcDiagnostics |]
-
-                let getAssemblyData () =
-                    match tcAssemblyDataOpt with
-                    | ProjectAssemblyDataResult.Available data -> Some data
-                    | _ -> None
-
-                let details =
-                    (tcProj.TcGlobals,
-                     tcProj.TcImports,
-                     tcState.Ccu,
-                     tcState.CcuSig,
-                     Choice1Of2 builder,
-                     topAttribs,
-                     getAssemblyData,
-                     ilAssemRef,
-                     tcEnvAtEnd.AccessRights,
-                     tcAssemblyExprOpt,
-                     Array.ofList tcDependencyFiles,
-                     options)
-
-                let results =
-                    FSharpCheckProjectResults(options.ProjectFileName, Some tcProj.TcConfig, keepAssemblyContents, diagnostics, Some details)
-
-                return results
-        }
-
-    member _.GetAssemblyData(options, userOpName) =
-        node {
-            use _ =
-                Activity.start
-                    "BackgroundCompiler.GetAssemblyData"
-                    [|
-                        Activity.Tags.project, options.ProjectFileName
-                        Activity.Tags.userOpName, userOpName
-                    |]
-
-            let! builderOpt, _ = getOrCreateBuilder (options, userOpName)
-
-            match builderOpt with
-            | None -> return ProjectAssemblyDataResult.Unavailable true
-            | Some builder ->
-                let! _, _, tcAssemblyDataOpt, _ = builder.GetCheckResultsAndImplementationsForProject()
-                return tcAssemblyDataOpt
-        }
-
-    /// Get the timestamp that would be on the output if fully built immediately
-    member private _.TryGetLogicalTimeStampForProject(cache, options) =
-        match tryGetBuilderNode options with
-        | Some lazyWork ->
-            match lazyWork.TryPeekValue() with
-            | ValueSome (Some builder, _) -> Some(builder.GetLogicalTimeStampForProject(cache))
-            | _ -> None
-        | _ -> None
-
-    /// Parse and typecheck the whole project.
-    member bc.ParseAndCheckProject(options, userOpName) =
-        use _ =
-            Activity.start
-                "BackgroundCompiler.ParseAndCheckProject"
-                [|
-                    Activity.Tags.project, options.ProjectFileName
-                    Activity.Tags.userOpName, userOpName
-                |]
-
-        bc.ParseAndCheckProjectImpl(options, userOpName)
-
-    member _.GetProjectOptionsFromScript
-        (
-            fileName,
-            sourceText,
-            previewEnabled,
-            loadedTimeStamp,
-            otherFlags,
-            useFsiAuxLib: bool option,
-            useSdkRefs: bool option,
-            sdkDirOverride: string option,
-            assumeDotNetFramework: bool option,
-            optionsStamp: int64 option,
-            _userOpName
-        ) =
-        use _ =
-            Activity.start
-                "BackgroundCompiler.GetProjectOptionsFromScript"
-                [| Activity.Tags.fileName, fileName; Activity.Tags.userOpName, _userOpName |]
-
-        cancellable {
-            use diagnostics = new DiagnosticsScope()
-
-            // Do we add a reference to FSharp.Compiler.Interactive.Settings by default?
-            let useFsiAuxLib = defaultArg useFsiAuxLib true
-            let useSdkRefs = defaultArg useSdkRefs true
-            let reduceMemoryUsage = ReduceMemoryFlag.Yes
-            let previewEnabled = defaultArg previewEnabled false
-
-            // Do we assume .NET Framework references for scripts?
-            let assumeDotNetFramework = defaultArg assumeDotNetFramework true
-
-            let extraFlags =
-                if previewEnabled then
-                    [| "--langversion:preview" |]
-                else
-                    [||]
-
-            let otherFlags = defaultArg otherFlags extraFlags
-
-            let useSimpleResolution = otherFlags |> Array.exists (fun x -> x = "--simpleresolution")
-
-            let loadedTimeStamp = defaultArg loadedTimeStamp DateTime.MaxValue // Not 'now', we don't want to force reloading
-
-            let applyCompilerOptions tcConfigB =
-                let fsiCompilerOptions = GetCoreFsiCompilerOptions tcConfigB
-                ParseCompilerOptions(ignore, fsiCompilerOptions, Array.toList otherFlags)
-
-            let loadClosure =
-                LoadClosure.ComputeClosureOfScriptText(
-                    legacyReferenceResolver,
-                    FSharpCheckerResultsSettings.defaultFSharpBinariesDir,
-                    fileName,
-                    sourceText,
-                    CodeContext.Editing,
-                    useSimpleResolution,
-                    useFsiAuxLib,
-                    useSdkRefs,
-                    sdkDirOverride,
-                    Lexhelp.LexResourceManager(),
-                    applyCompilerOptions,
-                    assumeDotNetFramework,
-                    tryGetMetadataSnapshot,
-                    reduceMemoryUsage,
-                    dependencyProviderForScripts
-                )
-
-            let otherFlags =
-                [|
-                    yield "--noframework"
-                    yield "--warn:3"
-                    yield! otherFlags
-                    for r in loadClosure.References do
-                        yield "-r:" + fst r
-                    for code, _ in loadClosure.NoWarns do
-                        yield "--nowarn:" + code
-                |]
-
-            let options =
-                {
-                    ProjectFileName = fileName + ".fsproj" // Make a name that is unique in this directory.
-                    ProjectId = None
-                    SourceFiles = loadClosure.SourceFiles |> List.map fst |> List.toArray
-                    OtherOptions = otherFlags
-                    ReferencedProjects = [||]
-                    IsIncompleteTypeCheckEnvironment = false
-                    UseScriptResolutionRules = true
-                    LoadTime = loadedTimeStamp
-                    UnresolvedReferences = Some(FSharpUnresolvedReferencesSet(loadClosure.UnresolvedReferences))
-                    OriginalLoadReferences = loadClosure.OriginalLoadReferences
-                    Stamp = optionsStamp
-                }
-
-            scriptClosureCache.Set(AnyCallerThread, options, loadClosure) // Save the full load closure for later correlation.
-
-            let diags =
-                loadClosure.LoadClosureRootFileDiagnostics
-                |> List.map (fun (exn, isError) -> FSharpDiagnostic.CreateFromException(exn, isError, range.Zero, false))
-
-            return options, (diags @ diagnostics.Diagnostics)
-        }
-        |> Cancellable.toAsync
-
-    member bc.InvalidateConfiguration(options: FSharpProjectOptions, userOpName) =
-        use _ =
-            Activity.start
-                "BackgroundCompiler.InvalidateConfiguration"
-                [|
-                    Activity.Tags.project, options.ProjectFileName
-                    Activity.Tags.userOpName, userOpName
-                |]
-
-        if incrementalBuildersCache.ContainsSimilarKey(AnyCallerThread, options) then
-            parseCacheLock.AcquireLock(fun ltok ->
-                for sourceFile in options.SourceFiles do
-                    checkFileInProjectCache.RemoveAnySimilar(ltok, (sourceFile, 0L, options)))
-
-            let _ = createBuilderNode (options, userOpName, CancellationToken.None)
-            ()
-
-    member bc.ClearCache(options: seq, _userOpName) =
-        use _ = Activity.start "BackgroundCompiler.ClearCache" [| Activity.Tags.userOpName, _userOpName |]
-
-        lock gate (fun () ->
-            options
-            |> Seq.iter (fun options -> incrementalBuildersCache.RemoveAnySimilar(AnyCallerThread, options)))
-
-    member _.NotifyProjectCleaned(options: FSharpProjectOptions, userOpName) =
-        use _ =
-            Activity.start
-                "BackgroundCompiler.NotifyProjectCleaned"
-                [|
-                    Activity.Tags.project, options.ProjectFileName
-                    Activity.Tags.userOpName, userOpName
-                |]
-
-        async {
-            let! ct = Async.CancellationToken
-            // If there was a similar entry (as there normally will have been) then re-establish an empty builder .  This
-            // is a somewhat arbitrary choice - it will have the effect of releasing memory associated with the previous
-            // builder, but costs some time.
-            if incrementalBuildersCache.ContainsSimilarKey(AnyCallerThread, options) then
-                let _ = createBuilderNode (options, userOpName, ct)
-                ()
-        }
-
-    member _.BeforeBackgroundFileCheck = beforeFileChecked.Publish
-
-    member _.FileParsed = fileParsed.Publish
-
-    member _.FileChecked = fileChecked.Publish
-
-    member _.ProjectChecked = projectChecked.Publish
-
-    member _.ClearCaches() =
-        use _ = Activity.startNoTags "BackgroundCompiler.ClearCaches"
-
-        lock gate (fun () ->
-            parseCacheLock.AcquireLock(fun ltok ->
-                checkFileInProjectCache.Clear(ltok)
-                parseFileCache.Clear(ltok))
-
-            incrementalBuildersCache.Clear(AnyCallerThread)
-            frameworkTcImportsCache.Clear()
-            scriptClosureCache.Clear AnyCallerThread)
-
-    member _.DownsizeCaches() =
-        use _ = Activity.startNoTags "BackgroundCompiler.DownsizeCaches"
-
-        lock gate (fun () ->
-            parseCacheLock.AcquireLock(fun ltok ->
-                checkFileInProjectCache.Resize(ltok, newKeepStrongly = 1)
-                parseFileCache.Resize(ltok, newKeepStrongly = 1))
-
-            incrementalBuildersCache.Resize(AnyCallerThread, newKeepStrongly = 1, newKeepMax = 1)
-            frameworkTcImportsCache.Downsize()
-            scriptClosureCache.Resize(AnyCallerThread, newKeepStrongly = 1, newKeepMax = 1))
-
-    member _.FrameworkImportsCache = frameworkTcImportsCache
-
-    static member ActualParseFileCount = actualParseFileCount
-
-    static member ActualCheckFileCount = actualCheckFileCount
-
 []
 // There is typically only one instance of this type in an IDE process.
 type FSharpChecker
@@ -1283,6 +148,7 @@ type FSharpChecker
             useChangeNotifications,
             useSyntaxTreeCache
         )
+        :> IBackgroundCompiler
 
     static let globalInstance = lazy FSharpChecker.Create()
 
From 55f784abedb0b273eeff66e4c91f1cbb77b0c86a Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Wed, 12 Apr 2023 12:07:11 +0200
Subject: [PATCH 003/222] wip
---
 src/Compiler/Facilities/AsyncMemoize.fs       |   1 +
 src/Compiler/Service/BackgroundCompiler.fs    |   2 +-
 src/Compiler/Service/FSharpCheckerResults.fs  | 129 ++++++-
 src/Compiler/Service/FSharpCheckerResults.fsi | 105 +++++-
 src/Compiler/Service/TransparentCompiler.fs   | 345 +++++++++++++++---
 src/Compiler/Service/service.fs               |  58 ++-
 src/Compiler/Service/service.fsi              |   4 +-
 .../ProjectGeneration.fs                      |   6 +-
 8 files changed, 575 insertions(+), 75 deletions(-)
diff --git a/src/Compiler/Facilities/AsyncMemoize.fs b/src/Compiler/Facilities/AsyncMemoize.fs
index d7f17f2352c..960d2d0eeda 100644
--- a/src/Compiler/Facilities/AsyncMemoize.fs
+++ b/src/Compiler/Facilities/AsyncMemoize.fs
@@ -110,6 +110,7 @@ type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?eventLog: Resiz
                     | CancelRequest, Some (Completed _) -> ()
 
                     | JobCompleted, Some (Running (job, _)) ->
+                        // TODO: should we re-wrap the result?
                         cache.Set(tok, key, (Completed job))
                         requestCounts.Remove key |> ignore
                         log (Finished key)
diff --git a/src/Compiler/Service/BackgroundCompiler.fs b/src/Compiler/Service/BackgroundCompiler.fs
index 3882e06bc8d..227a0b670c5 100644
--- a/src/Compiler/Service/BackgroundCompiler.fs
+++ b/src/Compiler/Service/BackgroundCompiler.fs
@@ -671,7 +671,7 @@ type internal BackgroundCompiler
                     tcInfo.TcDiagnostics,
                     options.IsIncompleteTypeCheckEnvironment,
                     options,
-                    builder,
+                    Some builder,
                     Array.ofList tcInfo.tcDependencyFiles,
                     creationDiags,
                     parseResults.Diagnostics,
diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs
index 7582e109849..a70274d731e 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fs
+++ b/src/Compiler/Service/FSharpCheckerResults.fs
@@ -58,6 +58,7 @@ open FSharp.Compiler.BuildGraph
 open Internal.Utilities
 open Internal.Utilities.Collections
 open FSharp.Compiler.AbstractIL.ILBinaryReader
+open System.Threading.Tasks
 
 type FSharpUnresolvedReferencesSet = FSharpUnresolvedReferencesSet of UnresolvedAssemblyReference list
 
@@ -114,6 +115,130 @@ type internal DelayedILModuleReader =
             }
         | _ -> cancellable.Return(Some this.result)
 
+
+
+type FSharpFileKey = string * string
+
+type FSharpProjectSnapshotKey =
+    {
+        ProjectFileName: string
+        SourceFiles: FSharpFileKey list
+        OtherOptions: string list
+        ReferencedProjects: FSharpProjectSnapshotKey list
+
+        // Do we need these?
+        IsIncompleteTypeCheckEnvironment: bool
+        UseScriptResolutionRules: bool
+    }
+
+[]
+type FSharpFileSnapshot = {
+    FileName: string
+    Version: string
+    GetSource: unit -> Task
+} with
+    member this.Key = this.FileName, this.Version
+    override this.Equals(o) =
+        match o with
+        | :? FSharpFileSnapshot as o -> o.FileName = this.FileName && o.Version = this.Version
+        | _ -> false
+
+    override this.GetHashCode() = this.Key.GetHashCode()
+
+
+
+[]
+type FSharpProjectSnapshot =
+    {
+        ProjectFileName: string
+        ProjectId: string option
+        SourceFiles: FSharpFileSnapshot list
+        OtherOptions: string list
+        ReferencedProjects: FSharpReferencedProjectSnapshot list
+        IsIncompleteTypeCheckEnvironment: bool
+        UseScriptResolutionRules: bool
+        LoadTime: DateTime
+        UnresolvedReferences: FSharpUnresolvedReferencesSet option
+        OriginalLoadReferences: (range * string * string) list
+        Stamp: int64 option
+    }
+    static member UseSameProject(options1, options2) =
+        match options1.ProjectId, options2.ProjectId with
+        | Some (projectId1), Some (projectId2) when
+            not (String.IsNullOrWhiteSpace(projectId1))
+            && not (String.IsNullOrWhiteSpace(projectId2))
+            ->
+            projectId1 = projectId2
+        | Some _, Some _
+        | None, None -> options1.ProjectFileName = options2.ProjectFileName
+        | _ -> false
+
+    static member AreSameForChecking(options1, options2) =
+        match options1.Stamp, options2.Stamp with
+        | Some x, Some y -> (x = y)
+        | _ ->
+            FSharpProjectSnapshot.UseSameProject(options1, options2)
+            && options1.SourceFiles = options2.SourceFiles
+            && options1.OtherOptions = options2.OtherOptions
+            && options1.UnresolvedReferences = options2.UnresolvedReferences
+            && options1.OriginalLoadReferences = options2.OriginalLoadReferences
+            && options1.ReferencedProjects.Length = options2.ReferencedProjects.Length
+            && (options1.ReferencedProjects, options2.ReferencedProjects)
+               ||> List.forall2 (fun r1 r2 ->
+                   match r1, r2 with
+                   | FSharpReferencedProjectSnapshot.FSharpReference (n1, a), FSharpReferencedProjectSnapshot.FSharpReference (n2, b) ->
+                       n1 = n2 && FSharpProjectSnapshot.AreSameForChecking(a, b))
+
+            && options1.LoadTime = options2.LoadTime
+
+    member po.ProjectDirectory = Path.GetDirectoryName(po.ProjectFileName)
+
+    member this.Key = {
+        ProjectFileName = this.ProjectFileName
+        SourceFiles = this.SourceFiles |> List.map (fun x -> x.Key)
+        OtherOptions = this.OtherOptions
+        ReferencedProjects = this.ReferencedProjects |> List.map (function FSharpReference (_, x) -> x.Key)
+        IsIncompleteTypeCheckEnvironment = this.IsIncompleteTypeCheckEnvironment
+        UseScriptResolutionRules = this.UseScriptResolutionRules
+    }
+
+    override this.ToString() =
+        "FSharpProjectSnapshot(" + this.ProjectFileName + ")"
+
+and [] public FSharpReferencedProjectSnapshot =
+    internal
+    | FSharpReference of projectOutputFile: string * options: FSharpProjectSnapshot
+    //| PEReference of projectOutputFile: string * getStamp: (unit -> DateTime) * delayedReader: DelayedILModuleReader
+    //| ILModuleReference of
+    //    projectOutputFile: string *
+    //    getStamp: (unit -> DateTime) *
+    //    getReader: (unit -> ILModuleReader)
+
+    /// 
+    /// The fully qualified path to the output of the referenced project. This should be the same value as the -r
+    /// reference in the project options for this referenced project.
+    /// 
+    member this.OutputFile = match this with FSharpReference (projectOutputFile, _) -> projectOutputFile
+
+    /// 
+    /// Creates a reference for an F# project. The physical data for it is stored/cached inside of the compiler service.
+    /// 
+    /// The fully qualified path to the output of the referenced project. This should be the same value as the -r reference in the project options for this referenced project.
+    /// The Project Options for this F# project
+    static member CreateFSharp(projectOutputFile, options: FSharpProjectSnapshot) = FSharpReference (projectOutputFile, options)
+
+    override this.Equals(o) =
+        match o with
+        | :? FSharpReferencedProjectSnapshot as o ->
+            match this, o with
+            | FSharpReference (projectOutputFile1, options1), FSharpReference (projectOutputFile2, options2) ->
+                projectOutputFile1 = projectOutputFile2 && options1 = options2
+
+        | _ -> false
+
+    override this.GetHashCode() = this.OutputFile.GetHashCode()
+
+
 []
 type FSharpReferencedProject =
     | FSharpReference of projectOutputFile: string * options: FSharpProjectOptions
@@ -2996,7 +3121,7 @@ type FSharpCheckFileResults
             backgroundDiagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity)[],
             isIncompleteTypeCheckEnvironment: bool,
             projectOptions: FSharpProjectOptions,
-            builder: IncrementalBuilder,
+            builder: IncrementalBuilder option,
             dependencyFiles: string[],
             creationErrors: FSharpDiagnostic[],
             parseErrors: FSharpDiagnostic[],
@@ -3025,7 +3150,7 @@ type FSharpCheckFileResults
                 FSharpCheckFileResults.JoinErrors(isIncompleteTypeCheckEnvironment, creationErrors, parseErrors, tcErrors)
 
             let results =
-                FSharpCheckFileResults(mainInputFileName, errors, Some tcFileInfo, dependencyFiles, Some builder, keepAssemblyContents)
+                FSharpCheckFileResults(mainInputFileName, errors, Some tcFileInfo, dependencyFiles, builder, keepAssemblyContents)
 
             return results
         }
diff --git a/src/Compiler/Service/FSharpCheckerResults.fsi b/src/Compiler/Service/FSharpCheckerResults.fsi
index 5b14cdf9bc7..0294123474c 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fsi
+++ b/src/Compiler/Service/FSharpCheckerResults.fsi
@@ -39,6 +39,108 @@ type internal DelayedILModuleReader =
 /// Unused in this API
 type public FSharpUnresolvedReferencesSet = internal FSharpUnresolvedReferencesSet of UnresolvedAssemblyReference list
 
+
+type FSharpFileKey = string * string
+
+type FSharpProjectSnapshotKey =
+    {
+        ProjectFileName: string
+        SourceFiles: FSharpFileKey list
+        OtherOptions: string list
+        ReferencedProjects: FSharpProjectSnapshotKey list
+
+        // Do we need these?
+        IsIncompleteTypeCheckEnvironment: bool
+        UseScriptResolutionRules: bool
+    }
+
+[]
+type FSharpFileSnapshot = {
+    FileName: string
+    Version: string
+    GetSource: unit -> System.Threading.Tasks.Task
+} with member Key: FSharpFileKey
+
+[]
+type FSharpProjectSnapshot =
+    {
+        // Note that this may not reduce to just the project directory, because there may be two projects in the same directory.
+        ProjectFileName: string
+
+        /// This is the unique identifier for the project, it is case sensitive. If it's None, will key off of ProjectFileName in our caching.
+        ProjectId: string option
+
+        /// The files in the project
+        SourceFiles: FSharpFileSnapshot list
+
+        /// Additional command line argument options for the project. These can include additional files and references.
+        OtherOptions: string list
+
+        /// The command line arguments for the other projects referenced by this project, indexed by the
+        /// exact text used in the "-r:" reference in FSharpProjectOptions.
+        ReferencedProjects: FSharpReferencedProjectSnapshot list
+
+        /// When true, the typechecking environment is known a priori to be incomplete, for
+        /// example when a .fs file is opened outside of a project. In this case, the number of error
+        /// messages reported is reduced.
+        IsIncompleteTypeCheckEnvironment: bool
+
+        /// When true, use the reference resolution rules for scripts rather than the rules for compiler.
+        UseScriptResolutionRules: bool
+
+        /// Timestamp of project/script load, used to differentiate between different instances of a project load.
+        /// This ensures that a complete reload of the project or script type checking
+        /// context occurs on project or script unload/reload.
+        LoadTime: DateTime
+
+        /// Unused in this API and should be 'None' when used as user-specified input
+        UnresolvedReferences: FSharpUnresolvedReferencesSet option
+
+        /// Unused in this API and should be '[]' when used as user-specified input
+        OriginalLoadReferences: (range * string * string) list
+
+        /// An optional stamp to uniquely identify this set of options
+        /// If two sets of options both have stamps, then they are considered equal
+        /// if and only if the stamps are equal
+        Stamp: int64 option
+    }
+
+    /// Whether the two parse options refer to the same project.
+    static member internal UseSameProject: options1: FSharpProjectSnapshot * options2: FSharpProjectSnapshot -> bool
+
+    /// Compare two options sets with respect to the parts of the options that are important to building.
+    static member internal AreSameForChecking: options1: FSharpProjectSnapshot * options2: FSharpProjectSnapshot -> bool
+
+    /// Compute the project directory.
+    member internal ProjectDirectory: string
+
+    member Key: FSharpProjectSnapshotKey
+
+
+and [] public FSharpReferencedProjectSnapshot =
+    internal
+    | FSharpReference of projectOutputFile: string * options: FSharpProjectSnapshot
+    //| PEReference of projectOutputFile: string * version: string * delayedReader: DelayedILModuleReader
+    //| ILModuleReference of
+    //    projectOutputFile: string *
+    //    getStamp: (unit -> DateTime) *
+    //    getReader: (unit -> ILModuleReader)
+
+    /// 
+    /// The fully qualified path to the output of the referenced project. This should be the same value as the -r
+    /// reference in the project options for this referenced project.
+    /// 
+    member OutputFile: string
+
+    /// 
+    /// Creates a reference for an F# project. The physical data for it is stored/cached inside of the compiler service.
+    /// 
+    /// The fully qualified path to the output of the referenced project. This should be the same value as the -r reference in the project options for this referenced project.
+    /// The Project Options for this F# project
+    static member CreateFSharp: projectOutputFile: string * options: FSharpProjectSnapshot -> FSharpReferencedProjectSnapshot
+
+
+
 /// A set of information describing a project or script build configuration.
 type public FSharpProjectOptions =
     {
@@ -137,6 +239,7 @@ and [] public FSharpReferencedProject =
         projectOutputFile: string * getStamp: (unit -> DateTime) * getReader: (unit -> ILModuleReader) ->
             FSharpReferencedProject
 
+
 /// Represents the use of an F# symbol from F# source code
 []
 type public FSharpSymbolUse =
@@ -467,7 +570,7 @@ type public FSharpCheckFileResults =
         backgroundDiagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity)[] *
         isIncompleteTypeCheckEnvironment: bool *
         projectOptions: FSharpProjectOptions *
-        builder: IncrementalBuilder *
+        builder: IncrementalBuilder option *
         dependencyFiles: string[] *
         creationErrors: FSharpDiagnostic[] *
         parseErrors: FSharpDiagnostic[] *
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 28d5996b5b0..98c1fd5b8f5 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -1,54 +1,303 @@
 namespace FSharp.Compiler.CodeAnalysis
 
+open FSharp.Compiler.Text
+open FSharp.Compiler.BuildGraph
+open FSharp.Compiler.Symbols
+open FSharp.Compiler.CompilerConfig
+open FSharp.Compiler.Diagnostics
+open System
+open FSharp.Compiler
+open Internal.Utilities.Collections
+open FSharp.Compiler.ParseAndCheckInputs
+
+
+
+type internal FSharpFile = {
+    Range: range
+    Source: FSharpFileSnapshot
+    IsLastCompiland: bool
+    IsExe: bool
+}
+
+/// Things we need to start parsing and checking files for a given project snapshot
+type BootstrapInfo = {
+    TcConfig: TcConfig
+    SourceFiles: FSharpFile list
+}
+
+
+type internal TransparentCompiler
+    (
+        legacyReferenceResolver,
+        projectCacheSize,
+        keepAssemblyContents,
+        keepAllBackgroundResolutions,
+        tryGetMetadataSnapshot,
+        suggestNamesForErrors,
+        keepAllBackgroundSymbolUses,
+        enableBackgroundItemKeyStoreAndSemanticClassification,
+        enablePartialTypeChecking,
+        parallelReferenceResolution,
+        captureIdentifiersWhenParsing,
+        getSource: (string -> ISourceText option) option,
+        useChangeNotifications,
+        useSyntaxTreeCache
+    ) =
+
+    // Is having just one of these ok?
+    let lexResourceManager = Lexhelp.LexResourceManager()
+
+    let ParseFileCache = AsyncMemoize()
+    let ParseAndCheckFileInProjectCache = AsyncMemoize()
+
+
+    // use this to process not-yet-implemented tasks
+    let backgroundCompiler =
+        BackgroundCompiler(
+            legacyReferenceResolver,
+            projectCacheSize,
+            keepAssemblyContents,
+            keepAllBackgroundResolutions,
+            tryGetMetadataSnapshot,
+            suggestNamesForErrors,
+            keepAllBackgroundSymbolUses,
+            enableBackgroundItemKeyStoreAndSemanticClassification,
+            enablePartialTypeChecking,
+            parallelReferenceResolution,
+            captureIdentifiersWhenParsing,
+            getSource,
+            useChangeNotifications,
+            useSyntaxTreeCache
+        )
+        :> IBackgroundCompiler
+
+
+    let ComputeParseFile (file: FSharpFile) (projectSnapshot: FSharpProjectSnapshot) userOpName _key = node {
+
+        return ()
+
+    }
+
+
+    let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: FSharpProjectSnapshot) _key =
+        node {
+
+            let! bootstrapInfoOpt, creationDiags = getBootstrapInfo projectSnapshot // probably cache
+
+            match bootstrapInfoOpt with
+            | None ->
+                let parseTree = EmptyParsedInput(fileName, (false, false))
+                let parseResults = FSharpParseFileResults(creationDiags, parseTree, true, [||])
+                return (parseResults, FSharpCheckFileAnswer.Aborted)
+
+            | Some bootstrapInfo ->
+
+
+                
+
+                // Do the parsing.
+                let parsingOptions =
+                    FSharpParsingOptions.FromTcConfig(
+                        bootstrapInfo.TcConfig,
+                        projectSnapshot.SourceFiles |> Seq.map (fun f -> f.FileName) |> Array.ofSeq,
+                        projectSnapshot.UseScriptResolutionRules
+                    )
+
+                // TODO: what is this?
+                // GraphNode.SetPreferredUILang tcPrior.TcConfig.preferredUiLang
+
+                let parseDiagnostics, parseTree, anyErrors =
+                    ParseAndCheckFile.parseFile (
+                        sourceText,
+                        fileName,
+                        parsingOptions,
+                        userOpName,
+                        suggestNamesForErrors,
+                        captureIdentifiersWhenParsing
+                    )
+
+                // TODO: check if we need this in parse results
+                let dependencyFiles = [||]
+
+                let parseResults =
+                    FSharpParseFileResults(parseDiagnostics, parseTree, anyErrors, dependencyFiles)
+
+                let! checkResults =
+                    bc.CheckOneFileImpl(
+                        parseResults,
+                        sourceText,
+                        fileName,
+                        options,
+                        fileVersion,
+                        builder,
+                        tcPrior,
+                        tcInfo,
+                        creationDiags
+                    )
+
+                return (parseResults, checkResults)
+        }
+
+    member _.ParseAndCheckFileInProject
+        (
+            fileName: string,
+            projectSnapshot: FSharpProjectSnapshot,
+            userOpName: string
+        ) : NodeCode = node {
+            ignore userOpName // TODO
+            let key = fileName, projectSnapshot.Key
+            return! ParseAndCheckFileInProjectCache.Get(key, ComputeParseAndCheckFileInProject fileName projectSnapshot)
+        }
 
-type internal TransparentCompiler() =
 
     interface IBackgroundCompiler with
         member this.BeforeBackgroundFileCheck: IEvent =
-            raise (System.NotImplementedException())
-        member this.CheckFileInProject(parseResults: FSharpParseFileResults, fileName: string, fileVersion: int, sourceText: FSharp.Compiler.Text.ISourceText, options: FSharpProjectOptions, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode =
-            raise (System.NotImplementedException())
-        member this.CheckFileInProjectAllowingStaleCachedResults(parseResults: FSharpParseFileResults, fileName: string, fileVersion: int, sourceText: FSharp.Compiler.Text.ISourceText, options: FSharpProjectOptions, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode =
-            raise (System.NotImplementedException())
-        member this.ClearCache(options: seq, userOpName: string): unit =
-            raise (System.NotImplementedException())
-        member this.ClearCaches(): unit =
-            raise (System.NotImplementedException())
-        member this.DownsizeCaches(): unit =
-            raise (System.NotImplementedException())
-        member this.FileChecked: IEvent =
-            raise (System.NotImplementedException())
-        member this.FileParsed: IEvent =
-            raise (System.NotImplementedException())
-        member this.FindReferencesInFile(fileName: string, options: FSharpProjectOptions, symbol: FSharp.Compiler.Symbols.FSharpSymbol, canInvalidateProject: bool, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode> =
-            raise (System.NotImplementedException())
-        member this.FrameworkImportsCache: FrameworkImportsCache =
-            raise (System.NotImplementedException())
-        member this.GetAssemblyData(options: FSharpProjectOptions, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode =
-            raise (System.NotImplementedException())
-        member this.GetBackgroundCheckResultsForFileInProject(fileName: string, options: FSharpProjectOptions, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode =
-            raise (System.NotImplementedException())
-        member this.GetBackgroundParseResultsForFileInProject(fileName: string, options: FSharpProjectOptions, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode =
-            raise (System.NotImplementedException())
-        member this.GetCachedCheckFileResult(builder: IncrementalBuilder, fileName: string, sourceText: FSharp.Compiler.Text.ISourceText, options: FSharpProjectOptions): FSharp.Compiler.BuildGraph.NodeCode<(FSharpParseFileResults * FSharpCheckFileResults) option> =
-            raise (System.NotImplementedException())
-        member this.GetProjectOptionsFromScript(fileName: string, sourceText: FSharp.Compiler.Text.ISourceText, previewEnabled: bool option, loadedTimeStamp: System.DateTime option, otherFlags: string array option, useFsiAuxLib: bool option, useSdkRefs: bool option, sdkDirOverride: string option, assumeDotNetFramework: bool option, optionsStamp: int64 option, userOpName: string): Async =
-            raise (System.NotImplementedException())
-        member this.GetSemanticClassificationForFile(fileName: string, options: FSharpProjectOptions, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode =
-            raise (System.NotImplementedException())
-        member this.InvalidateConfiguration(options: FSharpProjectOptions, userOpName: string): unit =
-            raise (System.NotImplementedException())
-        member this.NotifyFileChanged(fileName: string, options: FSharpProjectOptions, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode =
-            raise (System.NotImplementedException())
-        member this.NotifyProjectCleaned(options: FSharpProjectOptions, userOpName: string): Async =
-            raise (System.NotImplementedException())
-        member this.ParseAndCheckFileInProject(fileName: string, fileVersion: int, sourceText: FSharp.Compiler.Text.ISourceText, options: FSharpProjectOptions, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode =
-            raise (System.NotImplementedException())
-        member this.ParseAndCheckProject(options: FSharpProjectOptions, userOpName: string): FSharp.Compiler.BuildGraph.NodeCode =
-            raise (System.NotImplementedException())
-        member this.ParseFile(fileName: string, sourceText: FSharp.Compiler.Text.ISourceText, options: FSharpParsingOptions, cache: bool, userOpName: string): Async =
-            raise (System.NotImplementedException())
-        member this.ProjectChecked: IEvent =
-            raise (System.NotImplementedException())
-        member this.TryGetRecentCheckResultsForFile(fileName: string, options: FSharpProjectOptions, sourceText: FSharp.Compiler.Text.ISourceText option, userOpName: string): (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option =
-            raise (System.NotImplementedException())
\ No newline at end of file
+            backgroundCompiler.BeforeBackgroundFileCheck
+
+        member _.CheckFileInProject
+            (
+                parseResults: FSharpParseFileResults,
+                fileName: string,
+                fileVersion: int,
+                sourceText: ISourceText,
+                options: FSharpProjectOptions,
+                userOpName: string
+            ) : NodeCode =
+            backgroundCompiler.CheckFileInProject(parseResults, fileName, fileVersion, sourceText, options, userOpName)
+
+        member _.CheckFileInProjectAllowingStaleCachedResults
+            (
+                parseResults: FSharpParseFileResults,
+                fileName: string,
+                fileVersion: int,
+                sourceText: ISourceText,
+                options: FSharpProjectOptions,
+                userOpName: string
+            ) : NodeCode =
+            backgroundCompiler.CheckFileInProjectAllowingStaleCachedResults(parseResults, fileName, fileVersion, sourceText, options, userOpName)
+
+        member _.ClearCache(options: seq, userOpName: string) : unit = backgroundCompiler.ClearCache(options, userOpName)
+        member _.ClearCaches() : unit = backgroundCompiler.ClearCaches()
+        member _.DownsizeCaches() : unit = backgroundCompiler.DownsizeCaches()
+        member _.FileChecked: IEvent = backgroundCompiler.FileChecked
+        member _.FileParsed: IEvent = backgroundCompiler.FileParsed
+
+        member _.FindReferencesInFile
+            (
+                fileName: string,
+                options: FSharpProjectOptions,
+                symbol: FSharpSymbol,
+                canInvalidateProject: bool,
+                userOpName: string
+            ) : NodeCode> =
+            backgroundCompiler.FindReferencesInFile(fileName, options, symbol, canInvalidateProject, userOpName)
+
+        member _.FrameworkImportsCache: FrameworkImportsCache = backgroundCompiler.FrameworkImportsCache
+
+        member _.GetAssemblyData(options: FSharpProjectOptions, userOpName: string) : NodeCode =
+            backgroundCompiler.GetAssemblyData(options, userOpName)
+
+        member _.GetBackgroundCheckResultsForFileInProject
+            (
+                fileName: string,
+                options: FSharpProjectOptions,
+                userOpName: string
+            ) : NodeCode =
+            backgroundCompiler.GetBackgroundCheckResultsForFileInProject(fileName, options, userOpName)
+
+        member _.GetBackgroundParseResultsForFileInProject
+            (
+                fileName: string,
+                options: FSharpProjectOptions,
+                userOpName: string
+            ) : NodeCode =
+            backgroundCompiler.GetBackgroundParseResultsForFileInProject(fileName, options, userOpName)
+
+        member _.GetCachedCheckFileResult
+            (
+                builder: IncrementalBuilder,
+                fileName: string,
+                sourceText: ISourceText,
+                options: FSharpProjectOptions
+            ) : NodeCode<(FSharpParseFileResults * FSharpCheckFileResults) option> =
+            backgroundCompiler.GetCachedCheckFileResult(builder, fileName, sourceText, options)
+
+        member _.GetProjectOptionsFromScript
+            (
+                fileName: string,
+                sourceText: ISourceText,
+                previewEnabled: bool option,
+                loadedTimeStamp: DateTime option,
+                otherFlags: string array option,
+                useFsiAuxLib: bool option,
+                useSdkRefs: bool option,
+                sdkDirOverride: string option,
+                assumeDotNetFramework: bool option,
+                optionsStamp: int64 option,
+                userOpName: string
+            ) : Async =
+            backgroundCompiler.GetProjectOptionsFromScript(
+                fileName,
+                sourceText,
+                previewEnabled,
+                loadedTimeStamp,
+                otherFlags,
+                useFsiAuxLib,
+                useSdkRefs,
+                sdkDirOverride,
+                assumeDotNetFramework,
+                optionsStamp,
+                userOpName
+            )
+
+        member _.GetSemanticClassificationForFile
+            (
+                fileName: string,
+                options: FSharpProjectOptions,
+                userOpName: string
+            ) : NodeCode =
+            backgroundCompiler.GetSemanticClassificationForFile(fileName, options, userOpName)
+
+        member _.InvalidateConfiguration(options: FSharpProjectOptions, userOpName: string) : unit =
+            backgroundCompiler.InvalidateConfiguration(options, userOpName)
+
+        member _.NotifyFileChanged(fileName: string, options: FSharpProjectOptions, userOpName: string) : NodeCode =
+            backgroundCompiler.NotifyFileChanged(fileName, options, userOpName)
+
+        member _.NotifyProjectCleaned(options: FSharpProjectOptions, userOpName: string) : Async =
+            backgroundCompiler.NotifyProjectCleaned(options, userOpName)
+
+        member _.ParseAndCheckFileInProject
+            (
+                fileName: string,
+                fileVersion: int,
+                sourceText: ISourceText,
+                options: FSharpProjectOptions,
+                userOpName: string
+            ) : NodeCode =
+
+            backgroundCompiler.ParseAndCheckFileInProject(fileName, fileVersion, sourceText, options, userOpName)
+
+        member _.ParseAndCheckProject(options: FSharpProjectOptions, userOpName: string) : NodeCode =
+            backgroundCompiler.ParseAndCheckProject(options, userOpName)
+
+        member _.ParseFile
+            (
+                fileName: string,
+                sourceText: ISourceText,
+                options: FSharpParsingOptions,
+                cache: bool,
+                userOpName: string
+            ) : Async =
+            backgroundCompiler.ParseFile(fileName, sourceText, options, cache, userOpName)
+
+        member _.ProjectChecked: IEvent = backgroundCompiler.ProjectChecked
+
+        member _.TryGetRecentCheckResultsForFile
+            (
+                fileName: string,
+                options: FSharpProjectOptions,
+                sourceText: ISourceText option,
+                userOpName: string
+            ) : (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option =
+            backgroundCompiler.TryGetRecentCheckResultsForFile(fileName, options, sourceText, userOpName)
diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs
index 8b6a9c1766a..bd7501463d1 100644
--- a/src/Compiler/Service/service.fs
+++ b/src/Compiler/Service/service.fs
@@ -128,27 +128,43 @@ type FSharpChecker
         captureIdentifiersWhenParsing,
         getSource,
         useChangeNotifications,
-        useSyntaxTreeCache
+        useSyntaxTreeCache,
+        useTransparentCompiler
     ) =
 
     let backgroundCompiler =
-        BackgroundCompiler(
-            legacyReferenceResolver,
-            projectCacheSize,
-            keepAssemblyContents,
-            keepAllBackgroundResolutions,
-            tryGetMetadataSnapshot,
-            suggestNamesForErrors,
-            keepAllBackgroundSymbolUses,
-            enableBackgroundItemKeyStoreAndSemanticClassification,
-            enablePartialTypeChecking,
-            parallelReferenceResolution,
-            captureIdentifiersWhenParsing,
-            getSource,
-            useChangeNotifications,
-            useSyntaxTreeCache
-        )
-        :> IBackgroundCompiler
+        if useTransparentCompiler = Some true then
+            TransparentCompiler(
+                legacyReferenceResolver,
+                projectCacheSize,
+                keepAssemblyContents,
+                keepAllBackgroundResolutions,
+                tryGetMetadataSnapshot,
+                suggestNamesForErrors,
+                keepAllBackgroundSymbolUses,
+                enableBackgroundItemKeyStoreAndSemanticClassification,
+                enablePartialTypeChecking,
+                parallelReferenceResolution,
+                captureIdentifiersWhenParsing,
+                getSource,
+                useChangeNotifications,
+                useSyntaxTreeCache) :> IBackgroundCompiler
+        else
+            BackgroundCompiler(
+                legacyReferenceResolver,
+                projectCacheSize,
+                keepAssemblyContents,
+                keepAllBackgroundResolutions,
+                tryGetMetadataSnapshot,
+                suggestNamesForErrors,
+                keepAllBackgroundSymbolUses,
+                enableBackgroundItemKeyStoreAndSemanticClassification,
+                enablePartialTypeChecking,
+                parallelReferenceResolution,
+                captureIdentifiersWhenParsing,
+                getSource,
+                useChangeNotifications,
+                useSyntaxTreeCache) :> IBackgroundCompiler
 
     static let globalInstance = lazy FSharpChecker.Create()
 
@@ -192,7 +208,8 @@ type FSharpChecker
             ?parallelReferenceResolution: bool,
             ?captureIdentifiersWhenParsing: bool,
             ?documentSource: DocumentSource,
-            ?useSyntaxTreeCache: bool
+            ?useSyntaxTreeCache: bool,
+            ?useTransparentCompiler: bool
         ) =
 
         use _ = Activity.startNoTags "FSharpChecker.Create"
@@ -243,7 +260,8 @@ type FSharpChecker
              | Some (DocumentSource.Custom f) -> Some f
              | _ -> None),
             useChangeNotifications,
-            useSyntaxTreeCache
+            useSyntaxTreeCache,
+            useTransparentCompiler
         )
 
     member _.ReferenceResolver = legacyReferenceResolver
diff --git a/src/Compiler/Service/service.fsi b/src/Compiler/Service/service.fsi
index 5d482b3cbed..497baf4d347 100644
--- a/src/Compiler/Service/service.fsi
+++ b/src/Compiler/Service/service.fsi
@@ -42,6 +42,7 @@ type public FSharpChecker =
     /// When set to true we create a set of all identifiers for each parsed file which can be used to speed up finding references.
     /// Default: FileSystem. You can use Custom source to provide a function that will return the source for a given file path instead of reading it from the file system. Note that with this option the FSharpChecker will also not monitor the file system for file changes. It will expect to be notified of changes via the NotifyFileChanged method.
     /// Default: true. Indicates whether to keep parsing results in a cache.
+    /// Default: false. Indicates whether we use a new experimental background compiler.
     static member Create:
         ?projectCacheSize: int *
         ?keepAssemblyContents: bool *
@@ -55,7 +56,8 @@ type public FSharpChecker =
         ?parallelReferenceResolution: bool *
         ?captureIdentifiersWhenParsing: bool *
         [] ?documentSource: DocumentSource *
-        [] ?useSyntaxTreeCache: bool ->
+        [] ?useSyntaxTreeCache: bool *
+        [] ?useTransparentCompiler: bool ->
             FSharpChecker
 
     /// 
diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
index 578a39aa17d..3f14fa601a1 100644
--- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs
+++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
@@ -468,7 +468,8 @@ module Helpers =
             enableBackgroundItemKeyStoreAndSemanticClassification = true,
             enablePartialTypeChecking = true,
             captureIdentifiersWhenParsing = true,
-            documentSource = DocumentSource.Custom getSource)
+            documentSource = DocumentSource.Custom getSource,
+            useTransparentCompiler = true)
 
         let options =
             let baseOptions, _ =
@@ -564,7 +565,8 @@ type ProjectWorkflowBuilder
                 enablePartialTypeChecking = true,
                 captureIdentifiersWhenParsing = true,
                 documentSource = (if useGetSource then DocumentSource.Custom getSource else DocumentSource.FileSystem),
-                useSyntaxTreeCache = defaultArg useSyntaxTreeCache false
+                useSyntaxTreeCache = defaultArg useSyntaxTreeCache false,
+                useTransparentCompiler = true
             ))
 
     let mapProjectAsync f workflow =
From 9fe9e221f7a860e028ed57fa5dc43ae1f2887dbd Mon Sep 17 00:00:00 2001
From: Petr Pokorny 
Date: Fri, 14 Apr 2023 12:30:38 +0200
Subject: [PATCH 004/222] wip
---
 src/Compiler/Service/FSharpCheckerResults.fs  |  17 +
 src/Compiler/Service/FSharpCheckerResults.fsi |   5 +
 src/Compiler/Service/TransparentCompiler.fs   | 325 ++++++++++++++++--
 3 files changed, 318 insertions(+), 29 deletions(-)
diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs
index a70274d731e..63b9e1893d0 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fs
+++ b/src/Compiler/Service/FSharpCheckerResults.fs
@@ -202,6 +202,8 @@ type FSharpProjectSnapshot =
         UseScriptResolutionRules = this.UseScriptResolutionRules
     }
 
+    member this.SourceFileNames = this.SourceFiles |> List.map (fun x -> x.FileName)
+
     override this.ToString() =
         "FSharpProjectSnapshot(" + this.ProjectFileName + ")"
 
@@ -327,6 +329,21 @@ and FSharpProjectOptions =
     override this.ToString() =
         "FSharpProjectOptions(" + this.ProjectFileName + ")"
 
+type FSharpProjectSnapshot with
+    member this.ToOptions (): FSharpProjectOptions = {
+        ProjectFileName = this.ProjectFileName
+        ProjectId = this.ProjectId
+        SourceFiles = this.SourceFiles |> Seq.map (fun x -> x.FileName) |> Seq.toArray
+        OtherOptions = this.OtherOptions |> List.toArray
+        ReferencedProjects = this.ReferencedProjects |> Seq.map (function FSharpReference (name, opts) -> FSharpReferencedProject.FSharpReference (name, opts.ToOptions())) |> Seq.toArray
+        IsIncompleteTypeCheckEnvironment = this.IsIncompleteTypeCheckEnvironment
+        UseScriptResolutionRules = this.UseScriptResolutionRules
+        LoadTime = this.LoadTime
+        UnresolvedReferences = this.UnresolvedReferences
+        OriginalLoadReferences = this.OriginalLoadReferences
+        Stamp = this.Stamp
+    }
+
 []
 module internal FSharpCheckerResultsSettings =
 
diff --git a/src/Compiler/Service/FSharpCheckerResults.fsi b/src/Compiler/Service/FSharpCheckerResults.fsi
index 0294123474c..6dfe65ca2b5 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fsi
+++ b/src/Compiler/Service/FSharpCheckerResults.fsi
@@ -114,6 +114,8 @@ type FSharpProjectSnapshot =
     /// Compute the project directory.
     member internal ProjectDirectory: string
 
+    member SourceFileNames: string list
+
     member Key: FSharpProjectSnapshotKey
 
 
@@ -239,6 +241,9 @@ and [] public FSharpReferencedProject =
         projectOutputFile: string * getStamp: (unit -> DateTime) * getReader: (unit -> ILModuleReader) ->
             FSharpReferencedProject
 
+type FSharpProjectSnapshot with
+    member ToOptions: unit -> FSharpProjectOptions
+
 
 /// Represents the use of an F# symbol from F# source code
 []
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 98c1fd5b8f5..01cc8bfaccb 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -9,6 +9,16 @@ open System
 open FSharp.Compiler
 open Internal.Utilities.Collections
 open FSharp.Compiler.ParseAndCheckInputs
+open FSharp.Compiler.ScriptClosure
+open FSharp.Compiler.AbstractIL.ILBinaryReader
+open FSharp.Compiler.Text.Range
+open FSharp.Compiler.AbstractIL.IL
+open FSharp.Compiler.ConstraintSolver
+open System.Diagnostics
+open System.IO
+open FSharp.Compiler.CompilerOptions
+open FSharp.Compiler.Xml
+open FSharp.Compiler.CompilerImports
 
 
 
@@ -49,7 +59,7 @@ type internal TransparentCompiler
 
     let ParseFileCache = AsyncMemoize()
     let ParseAndCheckFileInProjectCache = AsyncMemoize()
-
+    let FrameworkImportsCache = AsyncMemoize()
 
     // use this to process not-yet-implemented tasks
     let backgroundCompiler =
@@ -71,18 +81,296 @@ type internal TransparentCompiler
         )
         :> IBackgroundCompiler
 
+    let getProjectReferences (project: FSharpProjectSnapshot) userOpName =
+        [
+            for r in project.ReferencedProjects do
+
+                match r with
+                | FSharpReferencedProjectSnapshot.FSharpReference (nm, opts) ->
+                    // Don't use cross-project references for FSharp.Core, since various bits of code
+                    // require a concrete FSharp.Core to exist on-disk. The only solutions that have
+                    // these cross-project references to FSharp.Core are VisualFSharp.sln and FSharp.sln. The ramification
+                    // of this is that you need to build FSharp.Core to get intellisense in those projects.
+
+                    if
+                        (try
+                            Path.GetFileNameWithoutExtension(nm)
+                         with _ ->
+                             "")
+                        <> GetFSharpCoreLibraryName()
+                    then
+                        { new IProjectReference with
+                            member x.EvaluateRawContents() =
+                                node {
+                                    Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "GetAssemblyData", nm)
+                                    return! backgroundCompiler.GetAssemblyData(opts.ToOptions(), userOpName + ".CheckReferencedProject(" + nm + ")")
+                                }
+
+                            member x.TryGetLogicalTimeStamp(cache) =
+                                // TODO:
+                                None
+
+                            member x.FileName = nm
+                        }
+        ]
+
+
+    let ComputeFrameworkImports (tcConfig: TcConfig) _key = node {
+        let tcConfigP = TcConfigProvider.Constant tcConfig
+        return! TcImports.BuildFrameworkTcImports (tcConfigP, frameworkDLLs, nonFrameworkResolutions)
+    }
+
+
+    let ComputeBootstapInfo (projectSnapshot: FSharpProjectSnapshot) =
+        node {
+
+            let useSimpleResolutionSwitch = "--simpleresolution"
+            let commandLineArgs = projectSnapshot.OtherOptions
+            let defaultFSharpBinariesDir = FSharpCheckerResultsSettings.defaultFSharpBinariesDir
+            let useScriptResolutionRules = projectSnapshot.UseScriptResolutionRules
+
+            let projectReferences = getProjectReferences projectSnapshot "ComputeBootstapInfo"
+            let sourceFiles = projectSnapshot.SourceFileNames
+
+            // TODO: script support
+            let loadClosureOpt: LoadClosure option = None
+
+            let tcConfigB, sourceFiles =
+
+                let getSwitchValue switchString =
+                    match commandLineArgs |> List.tryFindIndex(fun s -> s.StartsWithOrdinal switchString) with
+                    | Some idx -> Some(commandLineArgs[idx].Substring(switchString.Length))
+                    | _ -> None
+
+                let sdkDirOverride =
+                    match loadClosureOpt with
+                    | None -> None
+                    | Some loadClosure -> loadClosure.SdkDirOverride
+
+                // see also fsc.fs: runFromCommandLineToImportingAssemblies(), as there are many similarities to where the PS creates a tcConfigB
+                let tcConfigB =
+                    TcConfigBuilder.CreateNew(legacyReferenceResolver,
+                         defaultFSharpBinariesDir,
+                         implicitIncludeDir=projectSnapshot.ProjectDirectory,
+                         reduceMemoryUsage=ReduceMemoryFlag.Yes,
+                         isInteractive=useScriptResolutionRules,
+                         isInvalidationSupported=true,
+                         defaultCopyFSharpCore=CopyFSharpCoreFlag.No,
+                         tryGetMetadataSnapshot=tryGetMetadataSnapshot,
+                         sdkDirOverride=sdkDirOverride,
+                         rangeForErrors=range0)
+
+                tcConfigB.primaryAssembly <-
+                    match loadClosureOpt with
+                    | None -> PrimaryAssembly.Mscorlib
+                    | Some loadClosure ->
+                        if loadClosure.UseDesktopFramework then
+                            PrimaryAssembly.Mscorlib
+                        else
+                            PrimaryAssembly.System_Runtime
+
+                tcConfigB.resolutionEnvironment <- (LegacyResolutionEnvironment.EditingOrCompilation true)
+
+                tcConfigB.conditionalDefines <-
+                    let define = if useScriptResolutionRules then "INTERACTIVE" else "COMPILED"
+                    define :: tcConfigB.conditionalDefines
+
+                tcConfigB.projectReferences <- projectReferences
+
+                tcConfigB.useSimpleResolution <- (getSwitchValue useSimpleResolutionSwitch) |> Option.isSome
+
+                // Apply command-line arguments and collect more source files if they are in the arguments
+                let sourceFilesNew = ApplyCommandLineArgs(tcConfigB, sourceFiles, commandLineArgs)
+
+                // Never open PDB files for the language service, even if --standalone is specified
+                tcConfigB.openDebugInformationForLaterStaticLinking <- false
+
+                tcConfigB.xmlDocInfoLoader <-
+                    { new IXmlDocumentationInfoLoader with
+                        /// Try to load xml documentation associated with an assembly by the same file path with the extension ".xml".
+                        member _.TryLoad(assemblyFileName) =
+                            let xmlFileName = Path.ChangeExtension(assemblyFileName, ".xml")
+
+                            // REVIEW: File IO - Will eventually need to change this to use a file system interface of some sort.
+                            XmlDocumentationInfo.TryCreateFromFile(xmlFileName)
+                    }
+                    |> Some
+
+                tcConfigB.parallelReferenceResolution <- parallelReferenceResolution
+                tcConfigB.captureIdentifiersWhenParsing <- captureIdentifiersWhenParsing
+
+                tcConfigB, sourceFilesNew
+
+            // If this is a builder for a script, re-apply the settings inferred from the
+            // script and its load closure to the configuration.
+            //
+            // NOTE: it would probably be cleaner and more accurate to re-run the load closure at this point.
+            let setupConfigFromLoadClosure () =
+                match loadClosureOpt with
+                | Some loadClosure ->
+                    let dllReferences =
+                        [for reference in tcConfigB.referencedDLLs do
+                            // If there's (one or more) resolutions of closure references then yield them all
+                            match loadClosure.References  |> List.tryFind (fun (resolved, _)->resolved=reference.Text) with
+                            | Some (resolved, closureReferences) ->
+                                for closureReference in closureReferences do
+                                    yield AssemblyReference(closureReference.originalReference.Range, resolved, None)
+                            | None -> yield reference]
+                    tcConfigB.referencedDLLs <- []
+                    tcConfigB.primaryAssembly <- (if loadClosure.UseDesktopFramework then PrimaryAssembly.Mscorlib else PrimaryAssembly.System_Runtime)
+                    // Add one by one to remove duplicates
+                    dllReferences |> List.iter (fun dllReference ->
+                        tcConfigB.AddReferencedAssemblyByPath(dllReference.Range, dllReference.Text))
+                    tcConfigB.knownUnresolvedReferences <- loadClosure.UnresolvedReferences
+                | None -> ()
+
+            setupConfigFromLoadClosure()
+
+            let tcConfig = TcConfig.Create(tcConfigB, validate=true)
+            let outfile, _, assemblyName = tcConfigB.DecideNames sourceFiles
+
+            // Resolve assemblies and create the framework TcImports. This is done when constructing the
+            // builder itself, rather than as an incremental task. This caches a level of "system" references. No type providers are
+            // included in these references.
+            let! tcGlobals, frameworkTcImports, nonFrameworkResolutions, unresolvedReferences = frameworkTcImportsCache.Get(tcConfig)
+
+            // Note we are not calling diagnosticsLogger.GetDiagnostics() anywhere for this task.
+            // This is ok because not much can actually go wrong here.
+            let diagnosticsLogger = CompilationDiagnosticLogger("nonFrameworkAssemblyInputs", tcConfig.diagnosticsOptions)
+            use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parameter)
+
+            // Get the names and time stamps of all the non-framework referenced assemblies, which will act
+            // as inputs to one of the nodes in the build.
+            //
+            // This operation is done when constructing the builder itself, rather than as an incremental task.
+            let nonFrameworkAssemblyInputs =
+                // Note we are not calling diagnosticsLogger.GetDiagnostics() anywhere for this task.
+                // This is ok because not much can actually go wrong here.
+                let diagnosticsLogger = CompilationDiagnosticLogger("nonFrameworkAssemblyInputs", tcConfig.diagnosticsOptions)
+                // Return the disposable object that cleans up
+                use _holder = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parameter)
+
+                [ for r in nonFrameworkResolutions do
+                    let fileName = r.resolvedPath
+                    yield (Choice1Of2 fileName, (fun (cache: TimeStampCache) -> cache.GetFileTimeStamp fileName))
+
+                  for pr in projectReferences  do
+                    yield Choice2Of2 pr, (fun (cache: TimeStampCache) -> cache.GetProjectReferenceTimeStamp pr) ]
+
+            // Start importing
+
+            let tcConfigP = TcConfigProvider.Constant tcConfig
+            let beforeFileChecked = Event()
+            let fileChecked = Event()
+
+#if !NO_TYPEPROVIDERS
+            let importsInvalidatedByTypeProvider = Event()
+#endif
+
+            // Check for the existence of loaded sources and prepend them to the sources list if present.
+            let sourceFiles = tcConfig.GetAvailableLoadedSources() @ (sourceFiles |>List.map (fun s -> rangeStartup, s))
+
+            // Mark up the source files with an indicator flag indicating if they are the last source file in the project
+            let sourceFiles =
+                let flags, isExe = tcConfig.ComputeCanContainEntryPoint(sourceFiles |> List.map snd)
+                ((sourceFiles, flags) ||> List.map2 (fun (m, nm) flag -> (m, nm, (flag, isExe))))
+
+            let basicDependencies =
+                [ for UnresolvedAssemblyReference(referenceText, _)  in unresolvedReferences do
+                    // Exclude things that are definitely not a file name
+                    if not(FileSystem.IsInvalidPathShim referenceText) then
+                        let file = if FileSystem.IsPathRootedShim referenceText then referenceText else Path.Combine(projectDirectory, referenceText)
+                        yield file
+
+                  for r in nonFrameworkResolutions do
+                        yield  r.resolvedPath  ]
+
+            let allDependencies =
+                [| yield! basicDependencies
+                   for _, f, _ in sourceFiles do
+                        yield f |]
+
+            // For scripts, the dependency provider is already available.
+            // For projects create a fresh one for the project.
+            let dependencyProvider =
+                match dependencyProvider with
+                | None -> new DependencyProvider()
+                | Some dependencyProvider -> dependencyProvider
+
+            let defaultTimeStamp = DateTime.UtcNow
+
+            let! initialBoundModel = 
+                CombineImportedAssembliesTask(
+                    assemblyName,
+                    tcConfig,
+                    tcConfigP,
+                    tcGlobals,
+                    frameworkTcImports,
+                    nonFrameworkResolutions,
+                    unresolvedReferences,
+                    dependencyProvider,
+                    loadClosureOpt,
+                    basicDependencies,
+                    keepAssemblyContents,
+                    keepAllBackgroundResolutions,
+                    keepAllBackgroundSymbolUses,
+                    enableBackgroundItemKeyStoreAndSemanticClassification,
+                    enablePartialTypeChecking,
+                    beforeFileChecked,
+                    fileChecked
+#if !NO_TYPEPROVIDERS
+                    ,importsInvalidatedByTypeProvider
+#endif
+                )
+
+            let getFSharpSource fileName =
+                getSource
+                |> Option.map(fun getSource ->
+                    let timeStamp = DateTime.UtcNow
+                    let getTimeStamp = fun () -> timeStamp
+                    let getSourceText() = getSource fileName
+                    FSharpSource.Create(fileName, getTimeStamp, getSourceText))
+                |> Option.defaultWith(fun () -> FSharpSource.CreateFromFile(fileName))
+
+            let sourceFiles =
+                sourceFiles
+                |> List.map (fun (m, fileName, isLastCompiland) -> 
+                    { Range = m; Source = getFSharpSource fileName; Flags = isLastCompiland } )
+
+            return (), ()
+        }
+
+
+    let ComputeParseFile (file: FSharpFile) (projectSnapshot: FSharpProjectSnapshot) bootstrapInfo userOpName _key = node {
+
+        let parsingOptions =
+            FSharpParsingOptions.FromTcConfig(
+                bootstrapInfo.TcConfig,
+                projectSnapshot.SourceFiles |> Seq.map (fun f -> f.FileName) |> Array.ofSeq,
+                projectSnapshot.UseScriptResolutionRules
+            )
+
+        // TODO: what is this?
+        // GraphNode.SetPreferredUILang tcPrior.TcConfig.preferredUiLang
 
-    let ComputeParseFile (file: FSharpFile) (projectSnapshot: FSharpProjectSnapshot) userOpName _key = node {
+        let! sourceText = file.Source.GetSource() |> NodeCode.AwaitTask
 
-        return ()
+        return ParseAndCheckFile.parseFile (
+            sourceText,
+            file.Source.FileName,
+            parsingOptions,
+            userOpName,
+            suggestNamesForErrors,
+            captureIdentifiersWhenParsing
+        )
 
     }
 
 
-    let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: FSharpProjectSnapshot) _key =
+    let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: FSharpProjectSnapshot) userOpName _key =
         node {
 
-            let! bootstrapInfoOpt, creationDiags = getBootstrapInfo projectSnapshot // probably cache
+            let! bootstrapInfoOpt, creationDiags = ComputeBootstapInfo projectSnapshot // probably cache
 
             match bootstrapInfoOpt with
             | None ->
@@ -92,31 +380,10 @@ type internal TransparentCompiler
 
             | Some bootstrapInfo ->
 
+                let file = bootstrapInfo.SourceFiles |> List.find (fun f -> f.Source.FileName = fileName)
+                let! parseDiagnostics, parseTree, anyErrors = ParseFileCache.Get(file.Source.Key, ComputeParseFile file projectSnapshot bootstrapInfo userOpName)
 
-                
-
-                // Do the parsing.
-                let parsingOptions =
-                    FSharpParsingOptions.FromTcConfig(
-                        bootstrapInfo.TcConfig,
-                        projectSnapshot.SourceFiles |> Seq.map (fun f -> f.FileName) |> Array.ofSeq,
-                        projectSnapshot.UseScriptResolutionRules
-                    )
-
-                // TODO: what is this?
-                // GraphNode.SetPreferredUILang tcPrior.TcConfig.preferredUiLang
-
-                let parseDiagnostics, parseTree, anyErrors =
-                    ParseAndCheckFile.parseFile (
-                        sourceText,
-                        fileName,
-                        parsingOptions,
-                        userOpName,
-                        suggestNamesForErrors,
-                        captureIdentifiersWhenParsing
-                    )
-
-                // TODO: check if we need this in parse results
+                // TODO: check if we really need this in parse results
                 let dependencyFiles = [||]
 
                 let parseResults =
From beae07e39fdce0f581f057ab72e68133316587d9 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Tue, 18 Apr 2023 11:54:54 +0200
Subject: [PATCH 005/222] wip
---
 src/Compiler/Service/IncrementalBuild.fsi   |  3 +
 src/Compiler/Service/TransparentCompiler.fs | 85 ++++++++++++++-------
 2 files changed, 60 insertions(+), 28 deletions(-)
diff --git a/src/Compiler/Service/IncrementalBuild.fsi b/src/Compiler/Service/IncrementalBuild.fsi
index 9ffc66a2fdb..fc095cda82a 100644
--- a/src/Compiler/Service/IncrementalBuild.fsi
+++ b/src/Compiler/Service/IncrementalBuild.fsi
@@ -23,6 +23,9 @@ open FSharp.Compiler.Text
 open FSharp.Compiler.TypedTree
 open FSharp.Compiler.BuildGraph
 
+
+type FrameworkImportsCacheKey = FrameworkImportsCacheKey of resolvedpath: string list * assemblyName: string * targetFrameworkDirectories: string list * fsharpBinaries: string * langVersion: decimal
+
 /// Lookup the global static cache for building the FrameworkTcImports
 type internal FrameworkImportsCache =
     new: size: int -> FrameworkImportsCache
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 01cc8bfaccb..d82b2b79acb 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -1,25 +1,29 @@
 namespace FSharp.Compiler.CodeAnalysis
 
-open FSharp.Compiler.Text
+open System
+open System.Diagnostics
+open System.IO
+
+open Internal.Utilities.Collections
+open Internal.Utilities.Library
+
+open FSharp.Compiler
+open FSharp.Compiler.AbstractIL.IL
+open FSharp.Compiler.AbstractIL.ILBinaryReader
 open FSharp.Compiler.BuildGraph
-open FSharp.Compiler.Symbols
+open FSharp.Compiler.CodeAnalysis
 open FSharp.Compiler.CompilerConfig
+open FSharp.Compiler.CompilerImports
+open FSharp.Compiler.CompilerOptions
+open FSharp.Compiler.DependencyManager
 open FSharp.Compiler.Diagnostics
-open System
-open FSharp.Compiler
-open Internal.Utilities.Collections
-open FSharp.Compiler.ParseAndCheckInputs
+open FSharp.Compiler.DiagnosticsLogger
+open FSharp.Compiler.IO
 open FSharp.Compiler.ScriptClosure
-open FSharp.Compiler.AbstractIL.ILBinaryReader
+open FSharp.Compiler.Symbols
+open FSharp.Compiler.Text
 open FSharp.Compiler.Text.Range
-open FSharp.Compiler.AbstractIL.IL
-open FSharp.Compiler.ConstraintSolver
-open System.Diagnostics
-open System.IO
-open FSharp.Compiler.CompilerOptions
 open FSharp.Compiler.Xml
-open FSharp.Compiler.CompilerImports
-
 
 
 type internal FSharpFile = {
@@ -61,6 +65,14 @@ type internal TransparentCompiler
     let ParseAndCheckFileInProjectCache = AsyncMemoize()
     let FrameworkImportsCache = AsyncMemoize()
 
+    // We currently share one global dependency provider for all scripts for the FSharpChecker.
+    // For projects, one is used per project.
+    //
+    // Sharing one for all scripts is necessary for good performance from GetProjectOptionsFromScript,
+    // which requires a dependency provider to process through the project options prior to working out
+    // if the cached incremental builder can be used for the project.
+    let dependencyProviderForScripts = new DependencyProvider()
+
     // use this to process not-yet-implemented tasks
     let backgroundCompiler =
         BackgroundCompiler(
@@ -115,13 +127,13 @@ type internal TransparentCompiler
         ]
 
 
-    let ComputeFrameworkImports (tcConfig: TcConfig) _key = node {
+    let ComputeFrameworkImports (tcConfig: TcConfig) frameworkDLLs nonFrameworkResolutions _key = node {
         let tcConfigP = TcConfigProvider.Constant tcConfig
         return! TcImports.BuildFrameworkTcImports (tcConfigP, frameworkDLLs, nonFrameworkResolutions)
     }
 
 
-    let ComputeBootstapInfo (projectSnapshot: FSharpProjectSnapshot) =
+    let ComputeBootstrapInfo (projectSnapshot: FSharpProjectSnapshot) =
         node {
 
             let useSimpleResolutionSwitch = "--simpleresolution"
@@ -129,7 +141,7 @@ type internal TransparentCompiler
             let defaultFSharpBinariesDir = FSharpCheckerResultsSettings.defaultFSharpBinariesDir
             let useScriptResolutionRules = projectSnapshot.UseScriptResolutionRules
 
-            let projectReferences = getProjectReferences projectSnapshot "ComputeBootstapInfo"
+            let projectReferences = getProjectReferences projectSnapshot "ComputeBootstrapInfo"
             let sourceFiles = projectSnapshot.SourceFileNames
 
             // TODO: script support
@@ -137,7 +149,7 @@ type internal TransparentCompiler
 
             let tcConfigB, sourceFiles =
 
-                let getSwitchValue switchString =
+                let getSwitchValue (switchString: string) =
                     match commandLineArgs |> List.tryFindIndex(fun s -> s.StartsWithOrdinal switchString) with
                     | Some idx -> Some(commandLineArgs[idx].Substring(switchString.Length))
                     | _ -> None
@@ -229,10 +241,29 @@ type internal TransparentCompiler
             let tcConfig = TcConfig.Create(tcConfigB, validate=true)
             let outfile, _, assemblyName = tcConfigB.DecideNames sourceFiles
 
-            // Resolve assemblies and create the framework TcImports. This is done when constructing the
-            // builder itself, rather than as an incremental task. This caches a level of "system" references. No type providers are
+            // Resolve assemblies and create the framework TcImports. This caches a level of "system" references. No type providers are
             // included in these references.
-            let! tcGlobals, frameworkTcImports, nonFrameworkResolutions, unresolvedReferences = frameworkTcImportsCache.Get(tcConfig)
+
+            let frameworkDLLs, nonFrameworkResolutions, unresolvedReferences = TcAssemblyResolutions.SplitNonFoundationalResolutions(tcConfig)
+
+            let frameworkDLLsKey =
+                frameworkDLLs
+                |> List.map (fun ar->ar.resolvedPath) // The cache key. Just the minimal data.
+                |> List.sort  // Sort to promote cache hits.
+
+            // Prepare the frameworkTcImportsCache
+            //
+            // The data elements in this key are very important. There should be nothing else in the TcConfig that logically affects
+            // the import of a set of framework DLLs into F# CCUs. That is, the F# CCUs that result from a set of DLLs (including
+            // FSharp.Core.dll and mscorlib.dll) must be logically invariant of all the other compiler configuration parameters.
+            let key =
+                FrameworkImportsCacheKey(frameworkDLLsKey,
+                        tcConfig.primaryAssembly.Name,
+                        tcConfig.GetTargetFrameworkDirectories(),
+                        tcConfig.fsharpBinariesDir,
+                        tcConfig.langVersion.SpecifiedVersion)
+
+            let! tcGlobals, frameworkTcImports = FrameworkImportsCache.Get(key, ComputeFrameworkImports tcConfig frameworkDLLs nonFrameworkResolutions)
 
             // Note we are not calling diagnosticsLogger.GetDiagnostics() anywhere for this task.
             // This is ok because not much can actually go wrong here.
@@ -279,7 +310,7 @@ type internal TransparentCompiler
                 [ for UnresolvedAssemblyReference(referenceText, _)  in unresolvedReferences do
                     // Exclude things that are definitely not a file name
                     if not(FileSystem.IsInvalidPathShim referenceText) then
-                        let file = if FileSystem.IsPathRootedShim referenceText then referenceText else Path.Combine(projectDirectory, referenceText)
+                        let file = if FileSystem.IsPathRootedShim referenceText then referenceText else Path.Combine(projectSnapshot.ProjectDirectory, referenceText)
                         yield file
 
                   for r in nonFrameworkResolutions do
@@ -293,11 +324,9 @@ type internal TransparentCompiler
             // For scripts, the dependency provider is already available.
             // For projects create a fresh one for the project.
             let dependencyProvider =
-                match dependencyProvider with
-                | None -> new DependencyProvider()
-                | Some dependencyProvider -> dependencyProvider
-
-            let defaultTimeStamp = DateTime.UtcNow
+                if projectSnapshot.UseScriptResolutionRules
+                then dependencyProviderForScripts
+                else new DependencyProvider()
 
             let! initialBoundModel = 
                 CombineImportedAssembliesTask(
@@ -370,7 +399,7 @@ type internal TransparentCompiler
     let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: FSharpProjectSnapshot) userOpName _key =
         node {
 
-            let! bootstrapInfoOpt, creationDiags = ComputeBootstapInfo projectSnapshot // probably cache
+            let! bootstrapInfoOpt, creationDiags = ComputeBootstrapInfo projectSnapshot // probably cache
 
             match bootstrapInfoOpt with
             | None ->
From 0af5d0ef775ac74740d1389327df8b754e2df3fc Mon Sep 17 00:00:00 2001
From: Petr Pokorny 
Date: Fri, 21 Apr 2023 12:32:42 +0200
Subject: [PATCH 006/222] wip
---
 src/Compiler/Driver/GraphChecking/Graph.fs    |  46 ++-
 src/Compiler/Driver/GraphChecking/Graph.fsi   |   2 +
 src/Compiler/Service/FSharpCheckerResults.fs  |   5 +-
 src/Compiler/Service/FSharpCheckerResults.fsi |   3 +
 src/Compiler/Service/TransparentCompiler.fs   | 328 +++++++++++++-----
 src/Compiler/Service/service.fs               |   1 +
 .../FSharp.Compiler.ComponentTests.fsproj     |   1 +
 .../TypeChecks/Graph/GraphOperations.fs       |  30 ++
 8 files changed, 324 insertions(+), 92 deletions(-)
 create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs
diff --git a/src/Compiler/Driver/GraphChecking/Graph.fs b/src/Compiler/Driver/GraphChecking/Graph.fs
index 0e776181a63..4a2cbb29661 100644
--- a/src/Compiler/Driver/GraphChecking/Graph.fs
+++ b/src/Compiler/Driver/GraphChecking/Graph.fs
@@ -27,26 +27,36 @@ module internal Graph =
         |> Array.map (fun (KeyValue (k, v)) -> k, v)
         |> readOnlyDict
 
-    let transitive<'Node when 'Node: equality> (graph: Graph<'Node>) : Graph<'Node> =
-        /// Find transitive dependencies of a single node.
-        let transitiveDeps (node: 'Node) =
-            let visited = HashSet<'Node>()
+    /// Find transitive dependencies of a single node.
+    let transitiveDeps (node: 'Node) (graph: Graph<'Node>) =
+        let visited = HashSet<'Node>()
 
-            let rec dfs (node: 'Node) =
-                graph[node]
-                // Add direct dependencies.
-                // Use HashSet.Add return value semantics to filter out those that were added previously.
-                |> Array.filter visited.Add
-                |> Array.iter dfs
+        let rec dfs (node: 'Node) =
+            graph[node]
+            // Add direct dependencies.
+            // Use HashSet.Add return value semantics to filter out those that were added previously.
+            |> Array.filter visited.Add
+            |> Array.iter dfs
 
-            dfs node
-            visited |> Seq.toArray
+        dfs node
+        visited |> Seq.toArray
 
+    let transitive<'Node when 'Node: equality> (graph: Graph<'Node>) : Graph<'Node> = 
         graph.Keys
         |> Seq.toArray
-        |> Array.Parallel.map (fun node -> node, transitiveDeps node)
+        |> Array.Parallel.map (fun node -> node, graph |> transitiveDeps node)
         |> readOnlyDict
 
+    /// Get subgraph of the given graph that contains only nodes that are reachable from the given node.
+    let subGraphFor node graph =
+        let allDeps = graph |> transitiveDeps node
+        let relevant n = n = node || allDeps |> Array.contains n
+        graph
+        |> Seq.choose (fun (KeyValue (src, deps)) ->
+            if relevant src then Some (src, deps |> Array.filter relevant) else None)
+        |> make
+
+
     /// Create a reverse of the graph
     let reverse (originalGraph: Graph<'Node>) : Graph<'Node> =
         originalGraph
@@ -59,6 +69,16 @@ module internal Graph =
         |> readOnlyDict
         |> addIfMissing originalGraph.Keys
 
+    let cutLeaves (graph: Graph<'Node>) =
+        let notLeaves = set [ for (KeyValue (node, deps)) in graph do if deps.Length > 0 then node ]
+        let leaves =
+            set [ for (KeyValue (node, deps)) in graph do
+                    if deps.Length = 0 then node
+                    yield! deps |> Array.filter (notLeaves.Contains >> not) ]
+        leaves, seq { for (KeyValue (node, deps)) in graph do
+                        if deps.Length > 0 then
+                            node, deps |> Array.filter (leaves.Contains >> not) } |> make
+
     let printCustom (graph: Graph<'Node>) (nodePrinter: 'Node -> string) : unit =
         printfn "Graph:"
         let join (xs: string[]) = System.String.Join(", ", xs)
diff --git a/src/Compiler/Driver/GraphChecking/Graph.fsi b/src/Compiler/Driver/GraphChecking/Graph.fsi
index 95542470d8a..c6afc3ee768 100644
--- a/src/Compiler/Driver/GraphChecking/Graph.fsi
+++ b/src/Compiler/Driver/GraphChecking/Graph.fsi
@@ -13,6 +13,8 @@ module internal Graph =
     /// Create a transitive closure of the graph in O(n^2) time (but parallelize it).
     /// The resulting graph contains edge A -> C iff the input graph contains a (directed) non-zero length path from A to C.
     val transitive<'Node when 'Node: equality> : graph: Graph<'Node> -> Graph<'Node>
+    /// Get a sub-graph of the graph containing only the nodes reachable from the given node.
+    val subGraphFor: node: 'Node -> graph: Graph<'Node> -> Graph<'Node> when 'Node: equality
     /// Create a reverse of the graph.
     val reverse<'Node when 'Node: equality> : originalGraph: Graph<'Node> -> Graph<'Node>
     /// Print the contents of the graph to the standard output.
diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs
index ae8778b9135..4a07c23c66e 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fs
+++ b/src/Compiler/Service/FSharpCheckerResults.fs
@@ -146,7 +146,6 @@ type FSharpFileSnapshot = {
     override this.GetHashCode() = this.Key.GetHashCode()
 
 
-
 []
 type FSharpProjectSnapshot =
     {
@@ -193,6 +192,10 @@ type FSharpProjectSnapshot =
 
     member po.ProjectDirectory = Path.GetDirectoryName(po.ProjectFileName)
 
+    member this.UpTo fileName =
+        let fileIndex = this.SourceFiles |> List.findIndex (fun x -> x.FileName = fileName)
+        { this with SourceFiles = this.SourceFiles[..fileIndex] }
+
     member this.Key = {
         ProjectFileName = this.ProjectFileName
         SourceFiles = this.SourceFiles |> List.map (fun x -> x.Key)
diff --git a/src/Compiler/Service/FSharpCheckerResults.fsi b/src/Compiler/Service/FSharpCheckerResults.fsi
index 361665a68da..3fe91074124 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fsi
+++ b/src/Compiler/Service/FSharpCheckerResults.fsi
@@ -116,6 +116,9 @@ type FSharpProjectSnapshot =
 
     member SourceFileNames: string list
 
+    /// A snapshot of the same project but only up to the given file (including).
+    member UpTo: fileName: string -> FSharpProjectSnapshot
+
     member Key: FSharpProjectSnapshotKey
 
 
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index d82b2b79acb..9ee1aa8b5d6 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -1,4 +1,4 @@
-namespace FSharp.Compiler.CodeAnalysis
+namespace FSharp.Compiler.CodeAnalysis.TransparentCompiler
 
 open System
 open System.Diagnostics
@@ -21,9 +21,14 @@ open FSharp.Compiler.DiagnosticsLogger
 open FSharp.Compiler.IO
 open FSharp.Compiler.ScriptClosure
 open FSharp.Compiler.Symbols
+open FSharp.Compiler.TcGlobals
 open FSharp.Compiler.Text
 open FSharp.Compiler.Text.Range
 open FSharp.Compiler.Xml
+open System.Threading.Tasks
+open FSharp.Compiler.ParseAndCheckInputs
+open FSharp.Compiler.GraphChecking
+open FSharp.Compiler.Syntax
 
 
 type internal FSharpFile = {
@@ -34,12 +39,15 @@ type internal FSharpFile = {
 }
 
 /// Things we need to start parsing and checking files for a given project snapshot
-type BootstrapInfo = {
+type internal BootstrapInfo = {
     TcConfig: TcConfig
+    TcImports: TcImports
+    TcGlobals: TcGlobals
+    InitialTcInfo: TcInfo
     SourceFiles: FSharpFile list
+    LoadClosure: LoadClosure option
 }
 
-
 type internal TransparentCompiler
     (
         legacyReferenceResolver,
@@ -59,11 +67,14 @@ type internal TransparentCompiler
     ) =
 
     // Is having just one of these ok?
-    let lexResourceManager = Lexhelp.LexResourceManager()
+    let _lexResourceManager = Lexhelp.LexResourceManager()
 
     let ParseFileCache = AsyncMemoize()
     let ParseAndCheckFileInProjectCache = AsyncMemoize()
     let FrameworkImportsCache = AsyncMemoize()
+    let BootstrapInfoCache = AsyncMemoize()
+    let TcPriorCache = AsyncMemoize()
+    let DependencyGraphForLastFileCache = AsyncMemoize()
 
     // We currently share one global dependency provider for all scripts for the FSharpChecker.
     // For projects, one is used per project.
@@ -132,17 +143,92 @@ type internal TransparentCompiler
         return! TcImports.BuildFrameworkTcImports (tcConfigP, frameworkDLLs, nonFrameworkResolutions)
     }
 
+    // Link all the assemblies together and produce the input typecheck accumulator
+    let CombineImportedAssembliesTask (
+        assemblyName, 
+        tcConfig: TcConfig, 
+        tcConfigP, 
+        tcGlobals, 
+        frameworkTcImports, 
+        nonFrameworkResolutions, 
+        unresolvedReferences, 
+        dependencyProvider, 
+        loadClosureOpt: LoadClosure option, 
+        basicDependencies
+#if !NO_TYPEPROVIDERS
+        ,importsInvalidatedByTypeProvider: Event
+#endif
+        ) =
 
-    let ComputeBootstrapInfo (projectSnapshot: FSharpProjectSnapshot) =
-        node {
+      node {
+        let diagnosticsLogger = CompilationDiagnosticLogger("CombineImportedAssembliesTask", tcConfig.diagnosticsOptions)
+        use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parameter)
 
+        let! tcImports =
+          node {
+            try
+                let! tcImports = TcImports.BuildNonFrameworkTcImports(tcConfigP, frameworkTcImports, nonFrameworkResolutions, unresolvedReferences, dependencyProvider)
+#if !NO_TYPEPROVIDERS
+                tcImports.GetCcusExcludingBase() |> Seq.iter (fun ccu ->
+                    // When a CCU reports an invalidation, merge them together and just report a
+                    // general "imports invalidated". This triggers a rebuild.
+                    //
+                    // We are explicit about what the handler closure captures to help reason about the
+                    // lifetime of captured objects, especially in case the type provider instance gets leaked
+                    // or keeps itself alive mistakenly, e.g. via some global state in the type provider instance.
+                    //
+                    // The handler only captures
+                    //    1. a weak reference to the importsInvalidated event.
+                    //
+                    // The IncrementalBuilder holds the strong reference the importsInvalidated event.
+                    //
+                    // In the invalidation handler we use a weak reference to allow the IncrementalBuilder to
+                    // be collected if, for some reason, a TP instance is not disposed or not GC'd.
+                    let capturedImportsInvalidated = WeakReference<_>(importsInvalidatedByTypeProvider)
+                    ccu.Deref.InvalidateEvent.Add(fun _ ->
+                        match capturedImportsInvalidated.TryGetTarget() with
+                        | true, tg -> tg.Trigger()
+                        | _ -> ()))
+#endif
+                return tcImports
+            with exn ->
+                Debug.Assert(false, sprintf "Could not BuildAllReferencedDllTcImports %A" exn)
+                diagnosticsLogger.Warning exn
+                return frameworkTcImports
+          }
+
+        let tcInitial, openDecls0 = GetInitialTcEnv (assemblyName, rangeStartup, tcConfig, tcImports, tcGlobals)
+        let tcState = GetInitialTcState (rangeStartup, assemblyName, tcConfig, tcGlobals, tcImports, tcInitial, openDecls0)
+        let loadClosureErrors =
+           [ match loadClosureOpt with
+             | None -> ()
+             | Some loadClosure ->
+                for inp in loadClosure.Inputs do
+                    yield! inp.MetaCommandDiagnostics ]
+
+        let initialErrors = Array.append (Array.ofList loadClosureErrors) (diagnosticsLogger.GetDiagnostics())
+        let tcInfo =
+            {
+              tcState=tcState
+              tcEnvAtEndOfFile=tcInitial
+              topAttribs=None
+              latestCcuSigForFile=None
+              tcDiagnosticsRev = [ initialErrors ]
+              moduleNamesDict = Map.empty
+              tcDependencyFiles = basicDependencies
+              sigNameOpt = None
+            }
+        return tcImports, tcInfo
+      }
+
+    let ComputeBootstrapInfoInner (projectSnapshot: FSharpProjectSnapshot) =
+        node {
             let useSimpleResolutionSwitch = "--simpleresolution"
             let commandLineArgs = projectSnapshot.OtherOptions
             let defaultFSharpBinariesDir = FSharpCheckerResultsSettings.defaultFSharpBinariesDir
             let useScriptResolutionRules = projectSnapshot.UseScriptResolutionRules
 
             let projectReferences = getProjectReferences projectSnapshot "ComputeBootstrapInfo"
-            let sourceFiles = projectSnapshot.SourceFileNames
 
             // TODO: script support
             let loadClosureOpt: LoadClosure option = None
@@ -192,7 +278,7 @@ type internal TransparentCompiler
                 tcConfigB.useSimpleResolution <- (getSwitchValue useSimpleResolutionSwitch) |> Option.isSome
 
                 // Apply command-line arguments and collect more source files if they are in the arguments
-                let sourceFilesNew = ApplyCommandLineArgs(tcConfigB, sourceFiles, commandLineArgs)
+                let sourceFilesNew = ApplyCommandLineArgs(tcConfigB, projectSnapshot.SourceFileNames, commandLineArgs)
 
                 // Never open PDB files for the language service, even if --standalone is specified
                 tcConfigB.openDebugInformationForLaterStaticLinking <- false
@@ -239,7 +325,7 @@ type internal TransparentCompiler
             setupConfigFromLoadClosure()
 
             let tcConfig = TcConfig.Create(tcConfigB, validate=true)
-            let outfile, _, assemblyName = tcConfigB.DecideNames sourceFiles
+            let _outfile, _, assemblyName = tcConfigB.DecideNames sourceFiles
 
             // Resolve assemblies and create the framework TcImports. This caches a level of "system" references. No type providers are
             // included in these references.
@@ -270,36 +356,33 @@ type internal TransparentCompiler
             let diagnosticsLogger = CompilationDiagnosticLogger("nonFrameworkAssemblyInputs", tcConfig.diagnosticsOptions)
             use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parameter)
 
-            // Get the names and time stamps of all the non-framework referenced assemblies, which will act
-            // as inputs to one of the nodes in the build.
-            //
-            // This operation is done when constructing the builder itself, rather than as an incremental task.
-            let nonFrameworkAssemblyInputs =
-                // Note we are not calling diagnosticsLogger.GetDiagnostics() anywhere for this task.
-                // This is ok because not much can actually go wrong here.
-                let diagnosticsLogger = CompilationDiagnosticLogger("nonFrameworkAssemblyInputs", tcConfig.diagnosticsOptions)
-                // Return the disposable object that cleans up
-                use _holder = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parameter)
-
-                [ for r in nonFrameworkResolutions do
-                    let fileName = r.resolvedPath
-                    yield (Choice1Of2 fileName, (fun (cache: TimeStampCache) -> cache.GetFileTimeStamp fileName))
-
-                  for pr in projectReferences  do
-                    yield Choice2Of2 pr, (fun (cache: TimeStampCache) -> cache.GetProjectReferenceTimeStamp pr) ]
-
-            // Start importing
+            // TODO: might need to put something like this somewhere
+            //// Get the names and time stamps of all the non-framework referenced assemblies, which will act
+            //// as inputs to one of the nodes in the build.
+            ////
+            //// This operation is done when constructing the builder itself, rather than as an incremental task.
+            //let nonFrameworkAssemblyInputs =
+            //    // Note we are not calling diagnosticsLogger.GetDiagnostics() anywhere for this task.
+            //    // This is ok because not much can actually go wrong here.
+            //    let diagnosticsLogger = CompilationDiagnosticLogger("nonFrameworkAssemblyInputs", tcConfig.diagnosticsOptions)
+            //    // Return the disposable object that cleans up
+            //    use _holder = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parameter)
+
+            //    [ for r in nonFrameworkResolutions do
+            //        let fileName = r.resolvedPath
+            //        yield (Choice1Of2 fileName, (fun (cache: TimeStampCache) -> cache.GetFileTimeStamp fileName))
+
+            //      for pr in projectReferences  do
+            //        yield Choice2Of2 pr, (fun (cache: TimeStampCache) -> cache.GetProjectReferenceTimeStamp pr) ]
 
             let tcConfigP = TcConfigProvider.Constant tcConfig
-            let beforeFileChecked = Event()
-            let fileChecked = Event()
 
-#if !NO_TYPEPROVIDERS
+                #if !NO_TYPEPROVIDERS
             let importsInvalidatedByTypeProvider = Event()
-#endif
+                #endif
 
             // Check for the existence of loaded sources and prepend them to the sources list if present.
-            let sourceFiles = tcConfig.GetAvailableLoadedSources() @ (sourceFiles |>List.map (fun s -> rangeStartup, s))
+            let sourceFiles = tcConfig.GetAvailableLoadedSources() @ (sourceFiles |> List.map (fun s -> rangeStartup, s))
 
             // Mark up the source files with an indicator flag indicating if they are the last source file in the project
             let sourceFiles =
@@ -314,12 +397,7 @@ type internal TransparentCompiler
                         yield file
 
                   for r in nonFrameworkResolutions do
-                        yield  r.resolvedPath  ]
-
-            let allDependencies =
-                [| yield! basicDependencies
-                   for _, f, _ in sourceFiles do
-                        yield f |]
+                        yield r.resolvedPath ]
 
             // For scripts, the dependency provider is already available.
             // For projects create a fresh one for the project.
@@ -328,7 +406,7 @@ type internal TransparentCompiler
                 then dependencyProviderForScripts
                 else new DependencyProvider()
 
-            let! initialBoundModel = 
+            let! tcImports, initialTcInfo = 
                 CombineImportedAssembliesTask(
                     assemblyName,
                     tcConfig,
@@ -339,36 +417,67 @@ type internal TransparentCompiler
                     unresolvedReferences,
                     dependencyProvider,
                     loadClosureOpt,
-                    basicDependencies,
-                    keepAssemblyContents,
-                    keepAllBackgroundResolutions,
-                    keepAllBackgroundSymbolUses,
-                    enableBackgroundItemKeyStoreAndSemanticClassification,
-                    enablePartialTypeChecking,
-                    beforeFileChecked,
-                    fileChecked
-#if !NO_TYPEPROVIDERS
+                    basicDependencies
+                #if !NO_TYPEPROVIDERS
                     ,importsInvalidatedByTypeProvider
-#endif
+                #endif
                 )
 
-            let getFSharpSource fileName =
-                getSource
-                |> Option.map(fun getSource ->
-                    let timeStamp = DateTime.UtcNow
-                    let getTimeStamp = fun () -> timeStamp
-                    let getSourceText() = getSource fileName
-                    FSharpSource.Create(fileName, getTimeStamp, getSourceText))
-                |> Option.defaultWith(fun () -> FSharpSource.CreateFromFile(fileName))
+            let fileSnapshots = Map [ for f in projectSnapshot.SourceFiles -> f.FileName, f ]
 
             let sourceFiles =
                 sourceFiles
-                |> List.map (fun (m, fileName, isLastCompiland) -> 
-                    { Range = m; Source = getFSharpSource fileName; Flags = isLastCompiland } )
-
-            return (), ()
+                |> List.map (fun (m, fileName, (isLastCompiland, isExe)) ->
+                    let source =
+                        fileSnapshots.TryFind fileName
+                        |> Option.defaultWith (fun () ->
+                            // TODO: does this commonly happen?
+                            {
+                                FileName = fileName
+                                Version = (FileSystem.GetLastWriteTimeShim fileName).Ticks.ToString()
+                                GetSource = (fun () -> fileName |> File.ReadAllText |> SourceText.ofString |> Task.FromResult)
+                            })
+                    { Range = m; Source = source; IsLastCompiland = isLastCompiland; IsExe = isExe })
+
+            return Some {
+                TcConfig = tcConfig
+                TcImports = tcImports
+                TcGlobals = tcGlobals
+                InitialTcInfo = initialTcInfo
+                SourceFiles = sourceFiles
+                LoadClosure = loadClosureOpt
+            }
         }
 
+    let ComputeBootstrapInfo (projectSnapshot: FSharpProjectSnapshot) _key =
+        node {
+
+            // Trap and report diagnostics from creation.
+            let delayedLogger = CapturingDiagnosticsLogger("IncrementalBuilderCreation")
+            use _ = new CompilationGlobalsScope(delayedLogger, BuildPhase.Parameter)
+
+            let! bootstrapInfoOpt =
+                node {
+                    try
+                        return! ComputeBootstrapInfoInner projectSnapshot
+                    with exn ->
+                        errorRecoveryNoRange exn
+                        return None
+                }
+
+            let diagnostics =
+                match bootstrapInfoOpt with
+                | Some bootstrapInfo ->
+                    let diagnosticsOptions = bootstrapInfo.TcConfig.diagnosticsOptions
+                    let diagnosticsLogger = CompilationDiagnosticLogger("IncrementalBuilderCreation", diagnosticsOptions)
+                    delayedLogger.CommitDelayedDiagnostics diagnosticsLogger
+                    diagnosticsLogger.GetDiagnostics()
+                | _ ->
+                    Array.ofList delayedLogger.Diagnostics
+                |> Array.map (fun (diagnostic, severity) ->
+                    FSharpDiagnostic.CreateFromException(diagnostic, severity, range.Zero, suggestNamesForErrors))
+            return bootstrapInfoOpt, diagnostics
+        }
 
     let ComputeParseFile (file: FSharpFile) (projectSnapshot: FSharpProjectSnapshot) bootstrapInfo userOpName _key = node {
 
@@ -383,8 +492,7 @@ type internal TransparentCompiler
         // GraphNode.SetPreferredUILang tcPrior.TcConfig.preferredUiLang
 
         let! sourceText = file.Source.GetSource() |> NodeCode.AwaitTask
-
-        return ParseAndCheckFile.parseFile (
+        let diagnostics, parsedInput, anyErrors = ParseAndCheckFile.parseFile(
             sourceText,
             file.Source.FileName,
             parsingOptions,
@@ -392,14 +500,64 @@ type internal TransparentCompiler
             suggestNamesForErrors,
             captureIdentifiersWhenParsing
         )
-
+        return diagnostics, parsedInput, anyErrors, sourceText
     }
 
+    let ComputeDependencyGraphForLastFile parsedInputs (tcConfig: TcConfig) _key =
+        node {
+            let sourceFiles: FileInProject array =
+                parsedInputs
+                |> Seq.toArray
+                |> Array.mapi (fun idx (input: ParsedInput) ->
+                    {
+                        Idx = idx
+                        FileName = input.FileName
+                        ParsedInput = input
+                    })
+
+            let filePairs = FilePairMap(sourceFiles)
+
+            // TODO: we will probably want to cache and re-use larger graphs if available
+            let graph =
+                DependencyResolution.mkGraph tcConfig.compilingFSharpCore filePairs sourceFiles
+                |> Graph.subGraphFor (sourceFiles |> Array.last).Idx
+
+            return graph, filePairs
+        }
+
+    // Type check everything that is needed to check given file
+    let ComputeTcPrior (file: FSharpFile) (bootstrapInfo: BootstrapInfo) (projectSnapshot: FSharpProjectSnapshot) userOpName _key: NodeCode =
+        node {
+
+            // parse required files
+            let files = seq {
+                yield! bootstrapInfo.SourceFiles |> Seq.takeWhile ((<>) file)
+                file
+            }
+
+            let! parsedInputs =
+                files
+                |> Seq.map (fun f ->
+                    node {
+                        let! _diagnostics, parsedInput, _anyErrors, _sourceText = ParseFileCache.Get((f.Source.Key, f.IsLastCompiland, f.IsExe), ComputeParseFile f projectSnapshot bootstrapInfo userOpName)
+                        // TODO: Do we need to do something here when we get parse errors?
+                        return parsedInput
+                    })
+                |> NodeCode.Parallel
+
+            // compute dependency graph
+            let graphKey = projectSnapshot.UpTo(file.Source.FileName).SourceFileNames
+            let! _graph, _filePairs = DependencyGraphForLastFileCache.Get(graphKey, ComputeDependencyGraphForLastFile parsedInputs bootstrapInfo.TcConfig)
+
+
+
+            return bootstrapInfo.InitialTcInfo
+        }
 
     let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: FSharpProjectSnapshot) userOpName _key =
         node {
 
-            let! bootstrapInfoOpt, creationDiags = ComputeBootstrapInfo projectSnapshot // probably cache
+            let! bootstrapInfoOpt, creationDiags = BootstrapInfoCache.Get(projectSnapshot.Key, ComputeBootstrapInfo projectSnapshot) // probably cache
 
             match bootstrapInfoOpt with
             | None ->
@@ -410,7 +568,11 @@ type internal TransparentCompiler
             | Some bootstrapInfo ->
 
                 let file = bootstrapInfo.SourceFiles |> List.find (fun f -> f.Source.FileName = fileName)
-                let! parseDiagnostics, parseTree, anyErrors = ParseFileCache.Get(file.Source.Key, ComputeParseFile file projectSnapshot bootstrapInfo userOpName)
+
+                let priorSnapshot = projectSnapshot.UpTo fileName
+                let! tcInfo = TcPriorCache.Get(priorSnapshot.Key, ComputeTcPrior file bootstrapInfo priorSnapshot userOpName)
+
+                let! parseDiagnostics, parseTree, anyErrors, sourceText = ParseFileCache.Get((file.Source.Key, file.IsLastCompiland, file.IsExe), ComputeParseFile file projectSnapshot bootstrapInfo userOpName)
 
                 // TODO: check if we really need this in parse results
                 let dependencyFiles = [||]
@@ -419,19 +581,30 @@ type internal TransparentCompiler
                     FSharpParseFileResults(parseDiagnostics, parseTree, anyErrors, dependencyFiles)
 
                 let! checkResults =
-                    bc.CheckOneFileImpl(
+                    FSharpCheckFileResults.CheckOneFile(
                         parseResults,
                         sourceText,
                         fileName,
-                        options,
-                        fileVersion,
-                        builder,
-                        tcPrior,
-                        tcInfo,
-                        creationDiags
+                        projectSnapshot.ProjectFileName,
+                        bootstrapInfo.TcConfig,
+                        bootstrapInfo.TcGlobals,
+                        bootstrapInfo.TcImports,
+                        tcInfo.tcState,
+                        tcInfo.moduleNamesDict,
+                        bootstrapInfo.LoadClosure,
+                        tcInfo.TcDiagnostics,
+                        projectSnapshot.IsIncompleteTypeCheckEnvironment,
+                        projectSnapshot.ToOptions(),
+                        None,
+                        Array.ofList tcInfo.tcDependencyFiles,
+                        creationDiags,
+                        parseResults.Diagnostics,
+                        keepAssemblyContents,
+                        suggestNamesForErrors
                     )
+                    |> NodeCode.FromCancellable
 
-                return (parseResults, checkResults)
+                return (parseResults, FSharpCheckFileAnswer.Succeeded checkResults)
         }
 
     member _.ParseAndCheckFileInProject
@@ -439,10 +612,9 @@ type internal TransparentCompiler
             fileName: string,
             projectSnapshot: FSharpProjectSnapshot,
             userOpName: string
-        ) : NodeCode = node {
-            ignore userOpName // TODO
+        ) = node {
             let key = fileName, projectSnapshot.Key
-            return! ParseAndCheckFileInProjectCache.Get(key, ComputeParseAndCheckFileInProject fileName projectSnapshot)
+            return! ParseAndCheckFileInProjectCache.Get(key, ComputeParseAndCheckFileInProject fileName projectSnapshot userOpName)
         }
 
 
diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs
index bd7501463d1..22d9e69da7d 100644
--- a/src/Compiler/Service/service.fs
+++ b/src/Compiler/Service/service.fs
@@ -17,6 +17,7 @@ open FSharp.Compiler.AbstractIL.IL
 open FSharp.Compiler.AbstractIL.ILBinaryReader
 open FSharp.Compiler.AbstractIL.ILDynamicAssemblyWriter
 open FSharp.Compiler.CodeAnalysis
+open FSharp.Compiler.CodeAnalysis.TransparentCompiler
 open FSharp.Compiler.CompilerConfig
 open FSharp.Compiler.CompilerDiagnostics
 open FSharp.Compiler.CompilerImports
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
index 9470772e261..bc4a072aee6 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
+++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
@@ -197,6 +197,7 @@
     
     
     
+    
     
     
     
diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs
new file mode 100644
index 00000000000..0c18032e33b
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs
@@ -0,0 +1,30 @@
+module FSharp.Compiler.ComponentTests.TypeChecks.Graph.GraphOperations
+
+open Xunit
+open FSharp.Compiler.GraphChecking
+
+
+[]
+let ``Transform graph to layers of leaves`` () = 
+
+    let g = Graph.make [
+        'B', [|'A'|]
+        'C', [|'A'|]
+        'E', [|'A'; 'B'; 'C'|]
+        'F', [|'C'; 'D'|]
+    ]
+
+    //let layers = g |> Graph.leaves |> Seq.toList
+
+    let _expected = [
+        [|'A'; 'D'|]
+        [|'B'; 'C'|]
+        [|'E'; 'F'|]
+    ]
+
+    let _x = Graph.reverse g
+
+    ()
+
+    //Assert.Equal(expected, layers)
+
From a0d4e854642da9d6e64a289abe26a65675ecb8a8 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Wed, 26 Apr 2023 12:33:24 +0200
Subject: [PATCH 007/222] wip
---
 src/Compiler/Driver/GraphChecking/Graph.fs    |   9 ++
 src/Compiler/Driver/GraphChecking/Graph.fsi   |   2 +
 src/Compiler/Driver/ParseAndCheckInputs.fs    |   6 +-
 src/Compiler/Service/FSharpCheckerResults.fs  |   5 +-
 src/Compiler/Service/FSharpCheckerResults.fsi |   3 +
 src/Compiler/Service/IncrementalBuild.fs      |   8 +-
 src/Compiler/Service/TransparentCompiler.fs   | 110 ++++++++++++++++--
 .../TypeChecks/Graph/GraphOperations.fs       |  70 +++++++++--
 .../ProjectGeneration.fs                      |  13 +++
 .../LanguageService/LanguageService.fs        |   3 +-
 10 files changed, 201 insertions(+), 28 deletions(-)
diff --git a/src/Compiler/Driver/GraphChecking/Graph.fs b/src/Compiler/Driver/GraphChecking/Graph.fs
index 4a2cbb29661..c3e6de9731c 100644
--- a/src/Compiler/Driver/GraphChecking/Graph.fs
+++ b/src/Compiler/Driver/GraphChecking/Graph.fs
@@ -69,6 +69,7 @@ module internal Graph =
         |> readOnlyDict
         |> addIfMissing originalGraph.Keys
 
+    /// Returns leaves of the graph and the remaining graph without the leaves.
     let cutLeaves (graph: Graph<'Node>) =
         let notLeaves = set [ for (KeyValue (node, deps)) in graph do if deps.Length > 0 then node ]
         let leaves =
@@ -79,6 +80,14 @@ module internal Graph =
                         if deps.Length > 0 then
                             node, deps |> Array.filter (leaves.Contains >> not) } |> make
 
+    /// Returns layers of leaves repeatedly removed from the graph until there's nothing left
+    let leafSequence (graph: Graph<'Node>) =
+        let rec loop (graph: Graph<'Node>) acc =
+            match graph |> cutLeaves with
+            | leaves, _ when leaves.IsEmpty -> acc
+            | leaves, graph -> seq { yield! acc; leaves } |> loop graph
+        loop graph Seq.empty
+
     let printCustom (graph: Graph<'Node>) (nodePrinter: 'Node -> string) : unit =
         printfn "Graph:"
         let join (xs: string[]) = System.String.Join(", ", xs)
diff --git a/src/Compiler/Driver/GraphChecking/Graph.fsi b/src/Compiler/Driver/GraphChecking/Graph.fsi
index c6afc3ee768..8c6b9c29079 100644
--- a/src/Compiler/Driver/GraphChecking/Graph.fsi
+++ b/src/Compiler/Driver/GraphChecking/Graph.fsi
@@ -17,6 +17,8 @@ module internal Graph =
     val subGraphFor: node: 'Node -> graph: Graph<'Node> -> Graph<'Node> when 'Node: equality
     /// Create a reverse of the graph.
     val reverse<'Node when 'Node: equality> : originalGraph: Graph<'Node> -> Graph<'Node>
+    /// Returns layers of leaves repeatedly removed from the graph until there's nothing left
+    val leafSequence: graph: Graph<'Node> -> Set<'Node> seq
     /// Print the contents of the graph to the standard output.
     val print: graph: Graph<'Node> -> unit
     /// Create a simple Mermaid graph and save it under the path specified.
diff --git a/src/Compiler/Driver/ParseAndCheckInputs.fs b/src/Compiler/Driver/ParseAndCheckInputs.fs
index 66327892688..55c200bf6fc 100644
--- a/src/Compiler/Driver/ParseAndCheckInputs.fs
+++ b/src/Compiler/Driver/ParseAndCheckInputs.fs
@@ -1467,14 +1467,14 @@ let CheckOneInputWithCallback
       prefixPathOpt,
       tcSink,
       tcState: TcState,
-      inp: ParsedInput,
+      input: ParsedInput,
       _skipImplIfSigExists: bool): (unit -> bool) * TcConfig * TcImports * TcGlobals * LongIdent option * TcResultsSink * TcState * ParsedInput * bool)
     : Cancellable> =
     cancellable {
         try
             CheckSimulateException tcConfig
 
-            let m = inp.Range
+            let m = input.Range
             let amap = tcImports.GetImportMap()
 
             let conditionalDefines =
@@ -1483,7 +1483,7 @@ let CheckOneInputWithCallback
                 else
                     Some tcConfig.conditionalDefines
 
-            match inp with
+            match input with
             | ParsedInput.SigFile file ->
                 let qualNameOfFile = file.QualifiedName
 
diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs
index 4a07c23c66e..9c3855789e0 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fs
+++ b/src/Compiler/Service/FSharpCheckerResults.fs
@@ -192,9 +192,12 @@ type FSharpProjectSnapshot =
 
     member po.ProjectDirectory = Path.GetDirectoryName(po.ProjectFileName)
 
+    member this.UpTo fileIndex =
+        { this with SourceFiles = this.SourceFiles[..fileIndex] }
+
     member this.UpTo fileName =
         let fileIndex = this.SourceFiles |> List.findIndex (fun x -> x.FileName = fileName)
-        { this with SourceFiles = this.SourceFiles[..fileIndex] }
+        this.UpTo fileIndex
 
     member this.Key = {
         ProjectFileName = this.ProjectFileName
diff --git a/src/Compiler/Service/FSharpCheckerResults.fsi b/src/Compiler/Service/FSharpCheckerResults.fsi
index 3fe91074124..cf7f6f45714 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fsi
+++ b/src/Compiler/Service/FSharpCheckerResults.fsi
@@ -116,6 +116,9 @@ type FSharpProjectSnapshot =
 
     member SourceFileNames: string list
 
+    /// A snapshot of the same project but only up to the given file index (including).
+    member UpTo: fileIndex: int -> FSharpProjectSnapshot
+
     /// A snapshot of the same project but only up to the given file (including).
     member UpTo: fileName: string -> FSharpProjectSnapshot
 
diff --git a/src/Compiler/Service/IncrementalBuild.fs b/src/Compiler/Service/IncrementalBuild.fs
index 4d88e39c428..03b540bc256 100644
--- a/src/Compiler/Service/IncrementalBuild.fs
+++ b/src/Compiler/Service/IncrementalBuild.fs
@@ -325,7 +325,7 @@ type BoundModel private (
 
     let getTcInfoExtras (typeCheck: GraphNode) =
         node {
-            let! _ , sink, implFile, fileName = typeCheck.GetOrComputeValue()
+            let! _x , sink, implFile, fileName = typeCheck.GetOrComputeValue()
             // Build symbol keys
             let itemKeyStore, semanticClassification =
                 if enableBackgroundItemKeyStoreAndSemanticClassification then
@@ -914,7 +914,7 @@ module IncrementalBuilderStateHelpers =
             return! prevBoundModel.Next(syntaxTree)
         })
 
-    let rec createFinalizeBoundModelGraphNode (initialState: IncrementalBuilderInitialState) (boundModels: GraphNode seq) =
+    let createFinalizeBoundModelGraphNode (initialState: IncrementalBuilderInitialState) (boundModels: GraphNode seq) =
         GraphNode(node {
             use _ = Activity.start "GetCheckResultsAndImplementationsForProject" [|Activity.Tags.project, initialState.outfile|]
             let! result = 
@@ -928,7 +928,7 @@ module IncrementalBuilderStateHelpers =
             return result, DateTime.UtcNow
         })
 
-    and computeStampedFileNames (initialState: IncrementalBuilderInitialState) (state: IncrementalBuilderState) (cache: TimeStampCache) =
+    let computeStampedFileNames (initialState: IncrementalBuilderInitialState) (state: IncrementalBuilderState) (cache: TimeStampCache) =
         let slots = 
             if initialState.useChangeNotifications then
                 state.slots
@@ -967,7 +967,7 @@ module IncrementalBuilderStateHelpers =
         else
             state
 
-    and computeStampedReferencedAssemblies (initialState: IncrementalBuilderInitialState) state canTriggerInvalidation (cache: TimeStampCache) =
+    let computeStampedReferencedAssemblies (initialState: IncrementalBuilderInitialState) state canTriggerInvalidation (cache: TimeStampCache) =
         let stampedReferencedAssemblies = state.stampedReferencedAssemblies.ToBuilder()
 
         let mutable referencesUpdated = false
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 9ee1aa8b5d6..8d2825ee6c7 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -29,6 +29,8 @@ open System.Threading.Tasks
 open FSharp.Compiler.ParseAndCheckInputs
 open FSharp.Compiler.GraphChecking
 open FSharp.Compiler.Syntax
+open FSharp.Compiler.CompilerDiagnostics
+open FSharp.Compiler.NameResolution
 
 
 type internal FSharpFile = {
@@ -48,6 +50,8 @@ type internal BootstrapInfo = {
     LoadClosure: LoadClosure option
 }
 
+//type ParseResults 
+
 type internal TransparentCompiler
     (
         legacyReferenceResolver,
@@ -67,13 +71,14 @@ type internal TransparentCompiler
     ) =
 
     // Is having just one of these ok?
-    let _lexResourceManager = Lexhelp.LexResourceManager()
+    let lexResourceManager = Lexhelp.LexResourceManager()
 
     let ParseFileCache = AsyncMemoize()
     let ParseAndCheckFileInProjectCache = AsyncMemoize()
     let FrameworkImportsCache = AsyncMemoize()
     let BootstrapInfoCache = AsyncMemoize()
     let TcPriorCache = AsyncMemoize()
+    let TcIntermediateCache = AsyncMemoize()
     let DependencyGraphForLastFileCache = AsyncMemoize()
 
     // We currently share one global dependency provider for all scripts for the FSharpChecker.
@@ -221,7 +226,7 @@ type internal TransparentCompiler
         return tcImports, tcInfo
       }
 
-    let ComputeBootstrapInfoInner (projectSnapshot: FSharpProjectSnapshot) =
+    let computeBootstrapInfoInner (projectSnapshot: FSharpProjectSnapshot) =
         node {
             let useSimpleResolutionSwitch = "--simpleresolution"
             let commandLineArgs = projectSnapshot.OtherOptions
@@ -459,7 +464,7 @@ type internal TransparentCompiler
             let! bootstrapInfoOpt =
                 node {
                     try
-                        return! ComputeBootstrapInfoInner projectSnapshot
+                        return! computeBootstrapInfoInner projectSnapshot
                     with exn ->
                         errorRecoveryNoRange exn
                         return None
@@ -479,7 +484,7 @@ type internal TransparentCompiler
             return bootstrapInfoOpt, diagnostics
         }
 
-    let ComputeParseFile (file: FSharpFile) (projectSnapshot: FSharpProjectSnapshot) bootstrapInfo userOpName _key = node {
+    let ComputeParseFile' (file: FSharpFile) (projectSnapshot: FSharpProjectSnapshot) bootstrapInfo userOpName _key = node {
 
         let parsingOptions =
             FSharpParsingOptions.FromTcConfig(
@@ -503,6 +508,22 @@ type internal TransparentCompiler
         return diagnostics, parsedInput, anyErrors, sourceText
     }
 
+    let ComputeParseFile (file: FSharpFile) bootstrapInfo _key =
+        node {
+            let tcConfig = bootstrapInfo.TcConfig
+            let diagnosticsLogger = CompilationDiagnosticLogger("Parse", tcConfig.diagnosticsOptions)
+            // Return the disposable object that cleans up
+            use _holder = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parse)
+
+            let flags = file.IsLastCompiland, file.IsExe
+            let fileName = file.Source.FileName
+            let! sourceText = file.Source.GetSource() |> NodeCode.AwaitTask
+
+            let input = ParseOneInputSourceText(tcConfig, lexResourceManager, fileName, flags, diagnosticsLogger, sourceText)
+
+            return input, diagnosticsLogger.GetDiagnostics()
+        }
+
     let ComputeDependencyGraphForLastFile parsedInputs (tcConfig: TcConfig) _key =
         node {
             let sourceFiles: FileInProject array =
@@ -525,6 +546,63 @@ type internal TransparentCompiler
             return graph, filePairs
         }
 
+    let ComputeTcIntermediate (parsedInput: ParsedInput) bootstrapInfo prevTcInfo _key =
+        node {
+            let input = parsedInput
+            let fileName = input.FileName
+            let tcConfig = bootstrapInfo.TcConfig
+            let tcGlobals = bootstrapInfo.TcGlobals
+            let tcImports = bootstrapInfo.TcImports
+
+            let capturingDiagnosticsLogger = CapturingDiagnosticsLogger("TypeCheck")
+            let diagnosticsLogger = GetDiagnosticsLoggerFilteringByScopedPragmas(false, input.ScopedPragmas, tcConfig.diagnosticsOptions, capturingDiagnosticsLogger)
+            use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.TypeCheck)
+
+            //beforeFileChecked.Trigger fileName
+
+            ApplyMetaCommandsFromInputToTcConfig (tcConfig, input, Path.GetDirectoryName fileName, tcImports.DependencyProvider) |> ignore
+            let sink = TcResultsSinkImpl(tcGlobals)
+            let hadParseErrors = not (Array.isEmpty parseErrors)
+            let input, moduleNamesDict = DeduplicateParsedInputModuleName prevTcInfo.moduleNamesDict input
+
+            let! (tcEnvAtEndOfFile, topAttribs, implFile, ccuSigForFile), tcState =
+                CheckOneInput (
+                        (fun () -> hadParseErrors || diagnosticsLogger.ErrorCount > 0),
+                        tcConfig, tcImports,
+                        tcGlobals,
+                        None,
+                        TcResultsSink.WithSink sink,
+                        prevTcInfo.tcState, input )
+                |> NodeCode.FromCancellable
+
+            //fileChecked.Trigger fileName
+
+            let newErrors = Array.append parseErrors (capturingDiagnosticsLogger.Diagnostics |> List.toArray)
+            let tcEnvAtEndOfFile = if keepAllBackgroundResolutions then tcEnvAtEndOfFile else tcState.TcEnvFromImpls
+
+            let tcInfo =
+                {
+                    tcState = tcState
+                    tcEnvAtEndOfFile = tcEnvAtEndOfFile
+                    moduleNamesDict = moduleNamesDict
+                    latestCcuSigForFile = Some ccuSigForFile
+                    tcDiagnosticsRev = newErrors :: prevTcInfo.tcDiagnosticsRev
+                    topAttribs = Some topAttribs
+                    tcDependencyFiles = fileName :: prevTcInfo.tcDependencyFiles
+                    sigNameOpt =
+                        match input with
+                        | ParsedInput.SigFile sigFile ->
+                            Some(sigFile.FileName, sigFile.QualifiedName)
+                        | _ ->
+                            None
+                }
+            return tcInfo, sink, implFile, fileName
+
+            
+        }
+
+    
+
     // Type check everything that is needed to check given file
     let ComputeTcPrior (file: FSharpFile) (bootstrapInfo: BootstrapInfo) (projectSnapshot: FSharpProjectSnapshot) userOpName _key: NodeCode =
         node {
@@ -546,11 +624,25 @@ type internal TransparentCompiler
                 |> NodeCode.Parallel
 
             // compute dependency graph
-            let graphKey = projectSnapshot.UpTo(file.Source.FileName).SourceFileNames
-            let! _graph, _filePairs = DependencyGraphForLastFileCache.Get(graphKey, ComputeDependencyGraphForLastFile parsedInputs bootstrapInfo.TcConfig)
-
-
-
+            let graphKey = projectSnapshot.UpTo(file.Source.FileName).SourceFiles |> List.map (fun s -> s.Key)
+            let! graph, _filePairs = DependencyGraphForLastFileCache.Get(graphKey, ComputeDependencyGraphForLastFile parsedInputs bootstrapInfo.TcConfig)
+
+            // layers that can be processed in parallel
+            let layers = Graph.leafSequence graph
+
+            let rec processLayer (layers: Set list) state = node {
+                match layers with
+                | [] -> return state
+                | layer::rest ->
+                    let! results =
+                        layer
+                        |> Seq.map (fun fileIndex ->
+                            let key = projectSnapshot.UpTo(fileIndex).Key
+                            TcIntermediateCache.Get(key, ComputeTcIntermediate parsedInputs[fileIndex] bootstrapInfo state))
+                        |> NodeCode.Parallel
+                    return! processLayer rest (combineResults state results)
+            }
+            
             return bootstrapInfo.InitialTcInfo
         }
 
diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs
index 0c18032e33b..95d966441e1 100644
--- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs
+++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs
@@ -1,11 +1,15 @@
 module FSharp.Compiler.ComponentTests.TypeChecks.Graph.GraphOperations
 
+open System.IO
 open Xunit
 open FSharp.Compiler.GraphChecking
+open FSharp.Test.ProjectGeneration
+open FSharp.Compiler.Text
+open FSharp.Compiler
 
 
 []
-let ``Transform graph to layers of leaves`` () = 
+let ``Transform graph to layers of leaves`` () =
 
     let g = Graph.make [
         'B', [|'A'|]
@@ -14,17 +18,63 @@ let ``Transform graph to layers of leaves`` () =
         'F', [|'C'; 'D'|]
     ]
 
-    //let layers = g |> Graph.leaves |> Seq.toList
-
-    let _expected = [
-        [|'A'; 'D'|]
-        [|'B'; 'C'|]
-        [|'E'; 'F'|]
+    let expected = [
+        set [ 'A'; 'D' ]
+        set [ 'B'; 'C' ]
+        set [ 'E'; 'F' ]
     ]
 
-    let _x = Graph.reverse g
+    let result = Graph.leafSequence g |> Seq.toList
+
+    Assert.Equal list>(expected, result)
+
+
+[]
+let ``See what this does`` () =
+
+    SyntheticProject.Create(
+        sourceFile "A" [] |> addSignatureFile,
+        sourceFile "B" ["A"] |> addSignatureFile,
+        sourceFile "C" ["A"] |> addSignatureFile,
+        sourceFile "D" [] |> addSignatureFile,
+        sourceFile "E" ["A"; "B"; "C"] |> addSignatureFile,
+        sourceFile "F" ["C"; "D"] |> addSignatureFile
+    ).Workflow {
+        withProject (fun project checker -> 
+            async {
+                let options = project.GetProjectOptions checker
+                let options, _ = checker.GetParsingOptionsFromProjectOptions options
+                let! inputs =
+                    project.SourceFilePaths 
+                    |> Seq.map (fun path -> path, File.ReadAllText path |> SourceText.ofString)
+                    |> Seq.map (fun (path, text) -> checker.ParseFile(path, text, options))
+                    |> Async.Parallel
+
+                let sourceFiles: FileInProject array =
+                    inputs
+                    |> Seq.map (fun x -> x.ParseTree)
+                    |> Seq.toArray
+                    |> Array.mapi (fun idx (input: Syntax.ParsedInput) ->
+                        {
+                            Idx = idx
+                            FileName = input.FileName
+                            ParsedInput = input
+                        })
+
+                let filePairs = FilePairMap(sourceFiles)
+
+                let fullGraph =
+                    DependencyResolution.mkGraph false filePairs sourceFiles
+                    |> Graph.map (fun idx -> project.SourceFilePaths[idx] |> Path.GetFileName)
+
+                let subGraph = fullGraph |> Graph.subGraphFor "FileF.fs"
+
+                let layers = Graph.leafSequence subGraph |> Seq.toList
 
-    ()
+                ignore layers
 
-    //Assert.Equal(expected, layers)
+                return ()
+            }
+        )
+    }
 
diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
index 37173dc901d..7a3ca688eb5 100644
--- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs
+++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
@@ -193,6 +193,11 @@ type SyntheticProject with
     member this.GetFilePath fileId = this.Find fileId |> getFilePath this
     member this.GetSignatureFilePath fileId = this.Find fileId |> getSignatureFilePath this
 
+    member this.SourceFilePaths =
+        [ for f in this.SourceFiles do
+            if f.HasSignatureFile then this.GetSignatureFilePath f.Id
+            this.GetFilePath f.Id ]
+
 
 let private renderNamespaceModule (project: SyntheticProject) (f: SyntheticSourceFile) =
     seq {
@@ -617,6 +622,14 @@ type ProjectWorkflowBuilder
             if initialContext.IsNone then
                 this.DeleteProjectDir()
 
+    []
+    member this.WithProject(workflow: Async, f) =
+        workflow |> mapProjectAsync (fun project -> 
+            async {
+                do! f project checker
+                return project
+            })
+
     /// Change contents of given file using `processFile` function.
     /// Does not save the file to disk.
     []
diff --git a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs
index dcbafaa0fa0..5fbb21edc2b 100644
--- a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs
+++ b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs
@@ -156,7 +156,8 @@ type internal FSharpWorkspaceServiceFactory [
Date: Thu, 27 Apr 2023 11:03:33 +0200
Subject: [PATCH 008/222] wip
---
 src/Compiler/Service/TransparentCompiler.fs | 45 ++++++++++++---------
 1 file changed, 27 insertions(+), 18 deletions(-)
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 8d2825ee6c7..853632507a8 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -546,7 +546,7 @@ type internal TransparentCompiler
             return graph, filePairs
         }
 
-    let ComputeTcIntermediate (parsedInput: ParsedInput) bootstrapInfo prevTcInfo _key =
+    let ComputeTcIntermediate (parsedInput: ParsedInput, parseErrors) bootstrapInfo prevTcInfo _key =
         node {
             let input = parsedInput
             let fileName = input.FileName
@@ -586,9 +586,9 @@ type internal TransparentCompiler
                     tcEnvAtEndOfFile = tcEnvAtEndOfFile
                     moduleNamesDict = moduleNamesDict
                     latestCcuSigForFile = Some ccuSigForFile
-                    tcDiagnosticsRev = newErrors :: prevTcInfo.tcDiagnosticsRev
+                    tcDiagnosticsRev = [newErrors]
                     topAttribs = Some topAttribs
-                    tcDependencyFiles = fileName :: prevTcInfo.tcDependencyFiles
+                    tcDependencyFiles = [fileName]
                     sigNameOpt =
                         match input with
                         | ParsedInput.SigFile sigFile ->
@@ -597,12 +597,8 @@ type internal TransparentCompiler
                             None
                 }
             return tcInfo, sink, implFile, fileName
-
-            
         }
 
-    
-
     // Type check everything that is needed to check given file
     let ComputeTcPrior (file: FSharpFile) (bootstrapInfo: BootstrapInfo) (projectSnapshot: FSharpProjectSnapshot) userOpName _key: NodeCode =
         node {
@@ -616,16 +612,13 @@ type internal TransparentCompiler
             let! parsedInputs =
                 files
                 |> Seq.map (fun f ->
-                    node {
-                        let! _diagnostics, parsedInput, _anyErrors, _sourceText = ParseFileCache.Get((f.Source.Key, f.IsLastCompiland, f.IsExe), ComputeParseFile f projectSnapshot bootstrapInfo userOpName)
-                        // TODO: Do we need to do something here when we get parse errors?
-                        return parsedInput
-                    })
+                    let key = f.Source.Key, f.IsLastCompiland, f.IsExe
+                    ParseFileCache.Get(key, ComputeParseFile f bootstrapInfo))
                 |> NodeCode.Parallel
 
             // compute dependency graph
             let graphKey = projectSnapshot.UpTo(file.Source.FileName).SourceFiles |> List.map (fun s -> s.Key)
-            let! graph, _filePairs = DependencyGraphForLastFileCache.Get(graphKey, ComputeDependencyGraphForLastFile parsedInputs bootstrapInfo.TcConfig)
+            let! graph, _filePairs = DependencyGraphForLastFileCache.Get(graphKey, ComputeDependencyGraphForLastFile (parsedInputs |> Seq.map fst) bootstrapInfo.TcConfig)
 
             // layers that can be processed in parallel
             let layers = Graph.leafSequence graph
@@ -642,7 +635,7 @@ type internal TransparentCompiler
                         |> NodeCode.Parallel
                     return! processLayer rest (combineResults state results)
             }
-            
+
             return bootstrapInfo.InitialTcInfo
         }
 
@@ -664,14 +657,30 @@ type internal TransparentCompiler
                 let priorSnapshot = projectSnapshot.UpTo fileName
                 let! tcInfo = TcPriorCache.Get(priorSnapshot.Key, ComputeTcPrior file bootstrapInfo priorSnapshot userOpName)
 
-                let! parseDiagnostics, parseTree, anyErrors, sourceText = ParseFileCache.Get((file.Source.Key, file.IsLastCompiland, file.IsExe), ComputeParseFile file projectSnapshot bootstrapInfo userOpName)
+                let! parseTree, parseDiagnostics = ParseFileCache.Get((file.Source.Key, file.IsLastCompiland, file.IsExe), ComputeParseFile file bootstrapInfo)
 
-                // TODO: check if we really need this in parse results
-                let dependencyFiles = [||]
+                let parseDiagnostics =
+                    DiagnosticHelpers.CreateDiagnostics(
+                        bootstrapInfo.TcConfig.diagnosticsOptions,
+                        false,
+                        fileName,
+                        parseDiagnostics,
+                        suggestNamesForErrors
+                    )
+
+                let diagnostics = [| yield! creationDiags; yield! parseDiagnostics |]
 
                 let parseResults =
-                    FSharpParseFileResults(parseDiagnostics, parseTree, anyErrors, dependencyFiles)
+                    FSharpParseFileResults(
+                        diagnostics = diagnostics,
+                        input = parseTree,
+                        parseHadErrors = (parseDiagnostics.Length > 0),
+                        // TODO: check if we really need this in parse results
+                        dependencyFiles = [||]
+                    )
 
+                // TODO: this might be replaced... probably should use intermediate TC result
+                let sourceText = Unchecked.defaultof<_>
                 let! checkResults =
                     FSharpCheckFileResults.CheckOneFile(
                         parseResults,
From e162b0a218f5464c997125640d2db592b8bfffa1 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Thu, 27 Apr 2023 12:52:58 +0200
Subject: [PATCH 009/222] wip
---
 src/Compiler/Driver/GraphChecking/Graph.fs    |  48 +-
 src/Compiler/Service/FSharpCheckerResults.fs  |  81 ++-
 src/Compiler/Service/FSharpCheckerResults.fsi |  36 +-
 src/Compiler/Service/IncrementalBuild.fs      |   2 +-
 src/Compiler/Service/IncrementalBuild.fsi     |   9 +-
 src/Compiler/Service/TransparentCompiler.fs   | 630 +++++++++++-------
 src/Compiler/Service/service.fs               |   8 +-
 7 files changed, 502 insertions(+), 312 deletions(-)
diff --git a/src/Compiler/Driver/GraphChecking/Graph.fs b/src/Compiler/Driver/GraphChecking/Graph.fs
index c3e6de9731c..688fffc29bb 100644
--- a/src/Compiler/Driver/GraphChecking/Graph.fs
+++ b/src/Compiler/Driver/GraphChecking/Graph.fs
@@ -41,7 +41,7 @@ module internal Graph =
         dfs node
         visited |> Seq.toArray
 
-    let transitive<'Node when 'Node: equality> (graph: Graph<'Node>) : Graph<'Node> = 
+    let transitive<'Node when 'Node: equality> (graph: Graph<'Node>) : Graph<'Node> =
         graph.Keys
         |> Seq.toArray
         |> Array.Parallel.map (fun node -> node, graph |> transitiveDeps node)
@@ -51,12 +51,15 @@ module internal Graph =
     let subGraphFor node graph =
         let allDeps = graph |> transitiveDeps node
         let relevant n = n = node || allDeps |> Array.contains n
+
         graph
         |> Seq.choose (fun (KeyValue (src, deps)) ->
-            if relevant src then Some (src, deps |> Array.filter relevant) else None)
+            if relevant src then
+                Some(src, deps |> Array.filter relevant)
+            else
+                None)
         |> make
 
-
     /// Create a reverse of the graph
     let reverse (originalGraph: Graph<'Node>) : Graph<'Node> =
         originalGraph
@@ -71,21 +74,44 @@ module internal Graph =
 
     /// Returns leaves of the graph and the remaining graph without the leaves.
     let cutLeaves (graph: Graph<'Node>) =
-        let notLeaves = set [ for (KeyValue (node, deps)) in graph do if deps.Length > 0 then node ]
-        let leaves =
-            set [ for (KeyValue (node, deps)) in graph do
-                    if deps.Length = 0 then node
-                    yield! deps |> Array.filter (notLeaves.Contains >> not) ]
-        leaves, seq { for (KeyValue (node, deps)) in graph do
+        let notLeaves =
+            set
+                [
+                    for (KeyValue (node, deps)) in graph do
                         if deps.Length > 0 then
-                            node, deps |> Array.filter (leaves.Contains >> not) } |> make
+                            node
+                ]
+
+        let leaves =
+            set
+                [
+                    for (KeyValue (node, deps)) in graph do
+                        if deps.Length = 0 then
+                            node
+
+                        yield! deps |> Array.filter (notLeaves.Contains >> not)
+                ]
+
+        leaves,
+        seq {
+            for (KeyValue (node, deps)) in graph do
+                if deps.Length > 0 then
+                    node, deps |> Array.filter (leaves.Contains >> not)
+        }
+        |> make
 
     /// Returns layers of leaves repeatedly removed from the graph until there's nothing left
     let leafSequence (graph: Graph<'Node>) =
         let rec loop (graph: Graph<'Node>) acc =
             match graph |> cutLeaves with
             | leaves, _ when leaves.IsEmpty -> acc
-            | leaves, graph -> seq { yield! acc; leaves } |> loop graph
+            | leaves, graph ->
+                seq {
+                    yield! acc
+                    leaves
+                }
+                |> loop graph
+
         loop graph Seq.empty
 
     let printCustom (graph: Graph<'Node>) (nodePrinter: 'Node -> string) : unit =
diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs
index 9c3855789e0..bf6480fd8df 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fs
+++ b/src/Compiler/Service/FSharpCheckerResults.fs
@@ -115,8 +115,6 @@ type internal DelayedILModuleReader =
             }
         | _ -> cancellable.Return(Some this.result)
 
-
-
 type FSharpFileKey = string * string
 
 type FSharpProjectSnapshotKey =
@@ -132,12 +130,15 @@ type FSharpProjectSnapshotKey =
     }
 
 []
-type FSharpFileSnapshot = {
-    FileName: string
-    Version: string
-    GetSource: unit -> Task
-} with
+type FSharpFileSnapshot =
+    {
+        FileName: string
+        Version: string
+        GetSource: unit -> Task
+    }
+
     member this.Key = this.FileName, this.Version
+
     override this.Equals(o) =
         match o with
         | :? FSharpFileSnapshot as o -> o.FileName = this.FileName && o.Version = this.Version
@@ -145,7 +146,6 @@ type FSharpFileSnapshot = {
 
     override this.GetHashCode() = this.Key.GetHashCode()
 
-
 []
 type FSharpProjectSnapshot =
     {
@@ -161,6 +161,7 @@ type FSharpProjectSnapshot =
         OriginalLoadReferences: (range * string * string) list
         Stamp: int64 option
     }
+
     static member UseSameProject(options1, options2) =
         match options1.ProjectId, options2.ProjectId with
         | Some (projectId1), Some (projectId2) when
@@ -193,20 +194,26 @@ type FSharpProjectSnapshot =
     member po.ProjectDirectory = Path.GetDirectoryName(po.ProjectFileName)
 
     member this.UpTo fileIndex =
-        { this with SourceFiles = this.SourceFiles[..fileIndex] }
+        { this with
+            SourceFiles = this.SourceFiles[..fileIndex]
+        }
 
     member this.UpTo fileName =
         let fileIndex = this.SourceFiles |> List.findIndex (fun x -> x.FileName = fileName)
         this.UpTo fileIndex
 
-    member this.Key = {
-        ProjectFileName = this.ProjectFileName
-        SourceFiles = this.SourceFiles |> List.map (fun x -> x.Key)
-        OtherOptions = this.OtherOptions
-        ReferencedProjects = this.ReferencedProjects |> List.map (function FSharpReference (_, x) -> x.Key)
-        IsIncompleteTypeCheckEnvironment = this.IsIncompleteTypeCheckEnvironment
-        UseScriptResolutionRules = this.UseScriptResolutionRules
-    }
+    member this.Key =
+        {
+            ProjectFileName = this.ProjectFileName
+            SourceFiles = this.SourceFiles |> List.map (fun x -> x.Key)
+            OtherOptions = this.OtherOptions
+            ReferencedProjects =
+                this.ReferencedProjects
+                |> List.map (function
+                    | FSharpReference (_, x) -> x.Key)
+            IsIncompleteTypeCheckEnvironment = this.IsIncompleteTypeCheckEnvironment
+            UseScriptResolutionRules = this.UseScriptResolutionRules
+        }
 
     member this.SourceFileNames = this.SourceFiles |> List.map (fun x -> x.FileName)
 
@@ -226,14 +233,17 @@ and [] public FSharpReferencedProjectSnapshot =
     /// The fully qualified path to the output of the referenced project. This should be the same value as the -r
     /// reference in the project options for this referenced project.
     /// 
-    member this.OutputFile = match this with FSharpReference (projectOutputFile, _) -> projectOutputFile
+    member this.OutputFile =
+        match this with
+        | FSharpReference (projectOutputFile, _) -> projectOutputFile
 
     /// 
     /// Creates a reference for an F# project. The physical data for it is stored/cached inside of the compiler service.
     /// 
     /// The fully qualified path to the output of the referenced project. This should be the same value as the -r reference in the project options for this referenced project.
     /// The Project Options for this F# project
-    static member CreateFSharp(projectOutputFile, options: FSharpProjectSnapshot) = FSharpReference (projectOutputFile, options)
+    static member CreateFSharp(projectOutputFile, options: FSharpProjectSnapshot) =
+        FSharpReference(projectOutputFile, options)
 
     override this.Equals(o) =
         match o with
@@ -246,7 +256,6 @@ and [] public FSharpReferencedProjectSnapshot =
 
     override this.GetHashCode() = this.OutputFile.GetHashCode()
 
-
 []
 type FSharpReferencedProject =
     | FSharpReference of projectOutputFile: string * options: FSharpProjectOptions
@@ -336,19 +345,25 @@ and FSharpProjectOptions =
         "FSharpProjectOptions(" + this.ProjectFileName + ")"
 
 type FSharpProjectSnapshot with
-    member this.ToOptions (): FSharpProjectOptions = {
-        ProjectFileName = this.ProjectFileName
-        ProjectId = this.ProjectId
-        SourceFiles = this.SourceFiles |> Seq.map (fun x -> x.FileName) |> Seq.toArray
-        OtherOptions = this.OtherOptions |> List.toArray
-        ReferencedProjects = this.ReferencedProjects |> Seq.map (function FSharpReference (name, opts) -> FSharpReferencedProject.FSharpReference (name, opts.ToOptions())) |> Seq.toArray
-        IsIncompleteTypeCheckEnvironment = this.IsIncompleteTypeCheckEnvironment
-        UseScriptResolutionRules = this.UseScriptResolutionRules
-        LoadTime = this.LoadTime
-        UnresolvedReferences = this.UnresolvedReferences
-        OriginalLoadReferences = this.OriginalLoadReferences
-        Stamp = this.Stamp
-    }
+
+    member this.ToOptions() : FSharpProjectOptions =
+        {
+            ProjectFileName = this.ProjectFileName
+            ProjectId = this.ProjectId
+            SourceFiles = this.SourceFiles |> Seq.map (fun x -> x.FileName) |> Seq.toArray
+            OtherOptions = this.OtherOptions |> List.toArray
+            ReferencedProjects =
+                this.ReferencedProjects
+                |> Seq.map (function
+                    | FSharpReference (name, opts) -> FSharpReferencedProject.FSharpReference(name, opts.ToOptions()))
+                |> Seq.toArray
+            IsIncompleteTypeCheckEnvironment = this.IsIncompleteTypeCheckEnvironment
+            UseScriptResolutionRules = this.UseScriptResolutionRules
+            LoadTime = this.LoadTime
+            UnresolvedReferences = this.UnresolvedReferences
+            OriginalLoadReferences = this.OriginalLoadReferences
+            Stamp = this.Stamp
+        }
 
 []
 module internal FSharpCheckerResultsSettings =
diff --git a/src/Compiler/Service/FSharpCheckerResults.fsi b/src/Compiler/Service/FSharpCheckerResults.fsi
index cf7f6f45714..04e6667ca06 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fsi
+++ b/src/Compiler/Service/FSharpCheckerResults.fsi
@@ -39,27 +39,25 @@ type internal DelayedILModuleReader =
 /// Unused in this API
 type public FSharpUnresolvedReferencesSet = internal FSharpUnresolvedReferencesSet of UnresolvedAssemblyReference list
 
-
 type FSharpFileKey = string * string
 
 type FSharpProjectSnapshotKey =
-    {
-        ProjectFileName: string
-        SourceFiles: FSharpFileKey list
-        OtherOptions: string list
-        ReferencedProjects: FSharpProjectSnapshotKey list
+    { ProjectFileName: string
+      SourceFiles: FSharpFileKey list
+      OtherOptions: string list
+      ReferencedProjects: FSharpProjectSnapshotKey list
 
-        // Do we need these?
-        IsIncompleteTypeCheckEnvironment: bool
-        UseScriptResolutionRules: bool
-    }
+      // Do we need these?
+      IsIncompleteTypeCheckEnvironment: bool
+      UseScriptResolutionRules: bool }
 
 []
-type FSharpFileSnapshot = {
-    FileName: string
-    Version: string
-    GetSource: unit -> System.Threading.Tasks.Task
-} with member Key: FSharpFileKey
+type FSharpFileSnapshot =
+    { FileName: string
+      Version: string
+      GetSource: unit -> System.Threading.Tasks.Task }
+
+    member Key: FSharpFileKey
 
 []
 type FSharpProjectSnapshot =
@@ -124,7 +122,6 @@ type FSharpProjectSnapshot =
 
     member Key: FSharpProjectSnapshotKey
 
-
 and [] public FSharpReferencedProjectSnapshot =
     internal
     | FSharpReference of projectOutputFile: string * options: FSharpProjectSnapshot
@@ -145,9 +142,8 @@ and [] public FSharpReferencedProjectSnapshot =
     /// 
     /// The fully qualified path to the output of the referenced project. This should be the same value as the -r reference in the project options for this referenced project.
     /// The Project Options for this F# project
-    static member CreateFSharp: projectOutputFile: string * options: FSharpProjectSnapshot -> FSharpReferencedProjectSnapshot
-
-
+    static member CreateFSharp:
+        projectOutputFile: string * options: FSharpProjectSnapshot -> FSharpReferencedProjectSnapshot
 
 /// A set of information describing a project or script build configuration.
 type public FSharpProjectOptions =
@@ -248,8 +244,8 @@ and [] public FSharpReferencedProject =
             FSharpReferencedProject
 
 type FSharpProjectSnapshot with
-    member ToOptions: unit -> FSharpProjectOptions
 
+    member ToOptions: unit -> FSharpProjectOptions
 
 /// Represents the use of an F# symbol from F# source code
 []
diff --git a/src/Compiler/Service/IncrementalBuild.fs b/src/Compiler/Service/IncrementalBuild.fs
index 6d579ebcd12..0977a2fe129 100644
--- a/src/Compiler/Service/IncrementalBuild.fs
+++ b/src/Compiler/Service/IncrementalBuild.fs
@@ -247,7 +247,7 @@ type BoundModel private (
         syntaxTreeOpt: SyntaxTree option,
         ?tcStateOpt: GraphNode * GraphNode
     ) =
-
+    
     let getTypeCheck (syntaxTree: SyntaxTree) : NodeCode =
         node {
             let! input, _sourceRange, fileName, parseErrors = syntaxTree.ParseNode.GetOrComputeValue()
diff --git a/src/Compiler/Service/IncrementalBuild.fsi b/src/Compiler/Service/IncrementalBuild.fsi
index 1ecd34a4b85..252f2b57a83 100644
--- a/src/Compiler/Service/IncrementalBuild.fsi
+++ b/src/Compiler/Service/IncrementalBuild.fsi
@@ -23,8 +23,13 @@ open FSharp.Compiler.Text
 open FSharp.Compiler.TypedTree
 open FSharp.Compiler.BuildGraph
 
-
-type FrameworkImportsCacheKey = FrameworkImportsCacheKey of resolvedpath: string list * assemblyName: string * targetFrameworkDirectories: string list * fsharpBinaries: string * langVersion: decimal
+type FrameworkImportsCacheKey =
+    | FrameworkImportsCacheKey of
+        resolvedpath: string list *
+        assemblyName: string *
+        targetFrameworkDirectories: string list *
+        fsharpBinaries: string *
+        langVersion: decimal
 
 /// Lookup the global static cache for building the FrameworkTcImports
 type internal FrameworkImportsCache =
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 853632507a8..6a4d503f569 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -31,26 +31,28 @@ open FSharp.Compiler.GraphChecking
 open FSharp.Compiler.Syntax
 open FSharp.Compiler.CompilerDiagnostics
 open FSharp.Compiler.NameResolution
-
-
-type internal FSharpFile = {
-    Range: range
-    Source: FSharpFileSnapshot
-    IsLastCompiland: bool
-    IsExe: bool
-}
+open Internal.Utilities.Library.Extras
+
+type internal FSharpFile =
+    {
+        Range: range
+        Source: FSharpFileSnapshot
+        IsLastCompiland: bool
+        IsExe: bool
+    }
 
 /// Things we need to start parsing and checking files for a given project snapshot
-type internal BootstrapInfo = {
-    TcConfig: TcConfig
-    TcImports: TcImports
-    TcGlobals: TcGlobals
-    InitialTcInfo: TcInfo
-    SourceFiles: FSharpFile list
-    LoadClosure: LoadClosure option
-}
+type internal BootstrapInfo =
+    {
+        TcConfig: TcConfig
+        TcImports: TcImports
+        TcGlobals: TcGlobals
+        InitialTcInfo: TcInfo
+        SourceFiles: FSharpFile list
+        LoadClosure: LoadClosure option
+    }
 
-//type ParseResults 
+//type ParseResults
 
 type internal TransparentCompiler
     (
@@ -131,7 +133,12 @@ type internal TransparentCompiler
                             member x.EvaluateRawContents() =
                                 node {
                                     Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "GetAssemblyData", nm)
-                                    return! backgroundCompiler.GetAssemblyData(opts.ToOptions(), userOpName + ".CheckReferencedProject(" + nm + ")")
+
+                                    return!
+                                        backgroundCompiler.GetAssemblyData(
+                                            opts.ToOptions(),
+                                            userOpName + ".CheckReferencedProject(" + nm + ")"
+                                        )
                                 }
 
                             member x.TryGetLogicalTimeStamp(cache) =
@@ -142,89 +149,109 @@ type internal TransparentCompiler
                         }
         ]
 
-
-    let ComputeFrameworkImports (tcConfig: TcConfig) frameworkDLLs nonFrameworkResolutions _key = node {
-        let tcConfigP = TcConfigProvider.Constant tcConfig
-        return! TcImports.BuildFrameworkTcImports (tcConfigP, frameworkDLLs, nonFrameworkResolutions)
-    }
+    let ComputeFrameworkImports (tcConfig: TcConfig) frameworkDLLs nonFrameworkResolutions _key =
+        node {
+            let tcConfigP = TcConfigProvider.Constant tcConfig
+            return! TcImports.BuildFrameworkTcImports(tcConfigP, frameworkDLLs, nonFrameworkResolutions)
+        }
 
     // Link all the assemblies together and produce the input typecheck accumulator
-    let CombineImportedAssembliesTask (
-        assemblyName, 
-        tcConfig: TcConfig, 
-        tcConfigP, 
-        tcGlobals, 
-        frameworkTcImports, 
-        nonFrameworkResolutions, 
-        unresolvedReferences, 
-        dependencyProvider, 
-        loadClosureOpt: LoadClosure option, 
-        basicDependencies
-#if !NO_TYPEPROVIDERS
-        ,importsInvalidatedByTypeProvider: Event
-#endif
+    let CombineImportedAssembliesTask
+        (
+            assemblyName,
+            tcConfig: TcConfig,
+            tcConfigP,
+            tcGlobals,
+            frameworkTcImports,
+            nonFrameworkResolutions,
+            unresolvedReferences,
+            dependencyProvider,
+            loadClosureOpt: LoadClosure option,
+            basicDependencies,
+            importsInvalidatedByTypeProvider: Event
+        //#endif
         ) =
 
-      node {
-        let diagnosticsLogger = CompilationDiagnosticLogger("CombineImportedAssembliesTask", tcConfig.diagnosticsOptions)
-        use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parameter)
-
-        let! tcImports =
-          node {
-            try
-                let! tcImports = TcImports.BuildNonFrameworkTcImports(tcConfigP, frameworkTcImports, nonFrameworkResolutions, unresolvedReferences, dependencyProvider)
-#if !NO_TYPEPROVIDERS
-                tcImports.GetCcusExcludingBase() |> Seq.iter (fun ccu ->
-                    // When a CCU reports an invalidation, merge them together and just report a
-                    // general "imports invalidated". This triggers a rebuild.
-                    //
-                    // We are explicit about what the handler closure captures to help reason about the
-                    // lifetime of captured objects, especially in case the type provider instance gets leaked
-                    // or keeps itself alive mistakenly, e.g. via some global state in the type provider instance.
-                    //
-                    // The handler only captures
-                    //    1. a weak reference to the importsInvalidated event.
-                    //
-                    // The IncrementalBuilder holds the strong reference the importsInvalidated event.
-                    //
-                    // In the invalidation handler we use a weak reference to allow the IncrementalBuilder to
-                    // be collected if, for some reason, a TP instance is not disposed or not GC'd.
-                    let capturedImportsInvalidated = WeakReference<_>(importsInvalidatedByTypeProvider)
-                    ccu.Deref.InvalidateEvent.Add(fun _ ->
-                        match capturedImportsInvalidated.TryGetTarget() with
-                        | true, tg -> tg.Trigger()
-                        | _ -> ()))
-#endif
-                return tcImports
-            with exn ->
-                Debug.Assert(false, sprintf "Could not BuildAllReferencedDllTcImports %A" exn)
-                diagnosticsLogger.Warning exn
-                return frameworkTcImports
-          }
-
-        let tcInitial, openDecls0 = GetInitialTcEnv (assemblyName, rangeStartup, tcConfig, tcImports, tcGlobals)
-        let tcState = GetInitialTcState (rangeStartup, assemblyName, tcConfig, tcGlobals, tcImports, tcInitial, openDecls0)
-        let loadClosureErrors =
-           [ match loadClosureOpt with
-             | None -> ()
-             | Some loadClosure ->
-                for inp in loadClosure.Inputs do
-                    yield! inp.MetaCommandDiagnostics ]
-
-        let initialErrors = Array.append (Array.ofList loadClosureErrors) (diagnosticsLogger.GetDiagnostics())
-        let tcInfo =
-            {
-              tcState=tcState
-              tcEnvAtEndOfFile=tcInitial
-              topAttribs=None
-              latestCcuSigForFile=None
-              tcDiagnosticsRev = [ initialErrors ]
-              moduleNamesDict = Map.empty
-              tcDependencyFiles = basicDependencies
-              sigNameOpt = None
-            }
-        return tcImports, tcInfo
-      }
+        node {
+            let diagnosticsLogger =
+                CompilationDiagnosticLogger("CombineImportedAssembliesTask", tcConfig.diagnosticsOptions)
+
+            use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parameter)
+
+            let! tcImports =
+                node {
+                    try
+                        let! tcImports =
+                            TcImports.BuildNonFrameworkTcImports(
+                                tcConfigP,
+                                frameworkTcImports,
+                                nonFrameworkResolutions,
+                                unresolvedReferences,
+                                dependencyProvider
+                            )
+                        //#if !NO_TYPEPROVIDERS
+                        tcImports.GetCcusExcludingBase()
+                        |> Seq.iter (fun ccu ->
+                            // When a CCU reports an invalidation, merge them together and just report a
+                            // general "imports invalidated". This triggers a rebuild.
+                            //
+                            // We are explicit about what the handler closure captures to help reason about the
+                            // lifetime of captured objects, especially in case the type provider instance gets leaked
+                            // or keeps itself alive mistakenly, e.g. via some global state in the type provider instance.
+                            //
+                            // The handler only captures
+                            //    1. a weak reference to the importsInvalidated event.
+                            //
+                            // The IncrementalBuilder holds the strong reference the importsInvalidated event.
+                            //
+                            // In the invalidation handler we use a weak reference to allow the IncrementalBuilder to
+                            // be collected if, for some reason, a TP instance is not disposed or not GC'd.
+                            let capturedImportsInvalidated = WeakReference<_>(importsInvalidatedByTypeProvider)
+
+                            ccu.Deref.InvalidateEvent.Add(fun _ ->
+                                match capturedImportsInvalidated.TryGetTarget() with
+                                | true, tg -> tg.Trigger()
+                                | _ -> ()))
+                        //#endif
+                        return tcImports
+                    with exn ->
+                        Debug.Assert(false, sprintf "Could not BuildAllReferencedDllTcImports %A" exn)
+                        diagnosticsLogger.Warning exn
+                        return frameworkTcImports
+                }
+
+            let tcInitial, openDecls0 =
+                GetInitialTcEnv(assemblyName, rangeStartup, tcConfig, tcImports, tcGlobals)
+
+            let tcState =
+                GetInitialTcState(rangeStartup, assemblyName, tcConfig, tcGlobals, tcImports, tcInitial, openDecls0)
+
+            let loadClosureErrors =
+                [
+                    match loadClosureOpt with
+                    | None -> ()
+                    | Some loadClosure ->
+                        for inp in loadClosure.Inputs do
+                            yield! inp.MetaCommandDiagnostics
+                ]
+
+            let initialErrors =
+                Array.append (Array.ofList loadClosureErrors) (diagnosticsLogger.GetDiagnostics())
+
+            let tcInfo =
+                {
+                    tcState = tcState
+                    tcEnvAtEndOfFile = tcInitial
+                    topAttribs = None
+                    latestCcuSigForFile = None
+                    tcDiagnosticsRev = [ initialErrors ]
+                    moduleNamesDict = Map.empty
+                    tcDependencyFiles = basicDependencies
+                    sigNameOpt = None
+                }
+
+            return tcImports, tcInfo
+        }
 
     let computeBootstrapInfoInner (projectSnapshot: FSharpProjectSnapshot) =
         node {
@@ -241,8 +268,8 @@ type internal TransparentCompiler
             let tcConfigB, sourceFiles =
 
                 let getSwitchValue (switchString: string) =
-                    match commandLineArgs |> List.tryFindIndex(fun s -> s.StartsWithOrdinal switchString) with
-                    | Some idx -> Some(commandLineArgs[idx].Substring(switchString.Length))
+                    match commandLineArgs |> List.tryFindIndex (fun s -> s.StartsWithOrdinal switchString) with
+                    | Some idx -> Some(commandLineArgs[ idx ].Substring(switchString.Length))
                     | _ -> None
 
                 let sdkDirOverride =
@@ -252,16 +279,18 @@ type internal TransparentCompiler
 
                 // see also fsc.fs: runFromCommandLineToImportingAssemblies(), as there are many similarities to where the PS creates a tcConfigB
                 let tcConfigB =
-                    TcConfigBuilder.CreateNew(legacyReferenceResolver,
-                         defaultFSharpBinariesDir,
-                         implicitIncludeDir=projectSnapshot.ProjectDirectory,
-                         reduceMemoryUsage=ReduceMemoryFlag.Yes,
-                         isInteractive=useScriptResolutionRules,
-                         isInvalidationSupported=true,
-                         defaultCopyFSharpCore=CopyFSharpCoreFlag.No,
-                         tryGetMetadataSnapshot=tryGetMetadataSnapshot,
-                         sdkDirOverride=sdkDirOverride,
-                         rangeForErrors=range0)
+                    TcConfigBuilder.CreateNew(
+                        legacyReferenceResolver,
+                        defaultFSharpBinariesDir,
+                        implicitIncludeDir = projectSnapshot.ProjectDirectory,
+                        reduceMemoryUsage = ReduceMemoryFlag.Yes,
+                        isInteractive = useScriptResolutionRules,
+                        isInvalidationSupported = true,
+                        defaultCopyFSharpCore = CopyFSharpCoreFlag.No,
+                        tryGetMetadataSnapshot = tryGetMetadataSnapshot,
+                        sdkDirOverride = sdkDirOverride,
+                        rangeForErrors = range0
+                    )
 
                 tcConfigB.primaryAssembly <-
                     match loadClosureOpt with
@@ -275,7 +304,12 @@ type internal TransparentCompiler
                 tcConfigB.resolutionEnvironment <- (LegacyResolutionEnvironment.EditingOrCompilation true)
 
                 tcConfigB.conditionalDefines <-
-                    let define = if useScriptResolutionRules then "INTERACTIVE" else "COMPILED"
+                    let define =
+                        if useScriptResolutionRules then
+                            "INTERACTIVE"
+                        else
+                            "COMPILED"
+
                     define :: tcConfigB.conditionalDefines
 
                 tcConfigB.projectReferences <- projectReferences
@@ -283,7 +317,8 @@ type internal TransparentCompiler
                 tcConfigB.useSimpleResolution <- (getSwitchValue useSimpleResolutionSwitch) |> Option.isSome
 
                 // Apply command-line arguments and collect more source files if they are in the arguments
-                let sourceFilesNew = ApplyCommandLineArgs(tcConfigB, projectSnapshot.SourceFileNames, commandLineArgs)
+                let sourceFilesNew =
+                    ApplyCommandLineArgs(tcConfigB, projectSnapshot.SourceFileNames, commandLineArgs)
 
                 // Never open PDB files for the language service, even if --standalone is specified
                 tcConfigB.openDebugInformationForLaterStaticLinking <- false
@@ -312,35 +347,48 @@ type internal TransparentCompiler
                 match loadClosureOpt with
                 | Some loadClosure ->
                     let dllReferences =
-                        [for reference in tcConfigB.referencedDLLs do
-                            // If there's (one or more) resolutions of closure references then yield them all
-                            match loadClosure.References  |> List.tryFind (fun (resolved, _)->resolved=reference.Text) with
-                            | Some (resolved, closureReferences) ->
-                                for closureReference in closureReferences do
-                                    yield AssemblyReference(closureReference.originalReference.Range, resolved, None)
-                            | None -> yield reference]
+                        [
+                            for reference in tcConfigB.referencedDLLs do
+                                // If there's (one or more) resolutions of closure references then yield them all
+                                match
+                                    loadClosure.References
+                                    |> List.tryFind (fun (resolved, _) -> resolved = reference.Text)
+                                with
+                                | Some (resolved, closureReferences) ->
+                                    for closureReference in closureReferences do
+                                        yield AssemblyReference(closureReference.originalReference.Range, resolved, None)
+                                | None -> yield reference
+                        ]
+
                     tcConfigB.referencedDLLs <- []
-                    tcConfigB.primaryAssembly <- (if loadClosure.UseDesktopFramework then PrimaryAssembly.Mscorlib else PrimaryAssembly.System_Runtime)
+
+                    tcConfigB.primaryAssembly <-
+                        (if loadClosure.UseDesktopFramework then
+                             PrimaryAssembly.Mscorlib
+                         else
+                             PrimaryAssembly.System_Runtime)
                     // Add one by one to remove duplicates
-                    dllReferences |> List.iter (fun dllReference ->
-                        tcConfigB.AddReferencedAssemblyByPath(dllReference.Range, dllReference.Text))
+                    dllReferences
+                    |> List.iter (fun dllReference -> tcConfigB.AddReferencedAssemblyByPath(dllReference.Range, dllReference.Text))
+
                     tcConfigB.knownUnresolvedReferences <- loadClosure.UnresolvedReferences
                 | None -> ()
 
-            setupConfigFromLoadClosure()
+            setupConfigFromLoadClosure ()
 
-            let tcConfig = TcConfig.Create(tcConfigB, validate=true)
+            let tcConfig = TcConfig.Create(tcConfigB, validate = true)
             let _outfile, _, assemblyName = tcConfigB.DecideNames sourceFiles
 
             // Resolve assemblies and create the framework TcImports. This caches a level of "system" references. No type providers are
             // included in these references.
 
-            let frameworkDLLs, nonFrameworkResolutions, unresolvedReferences = TcAssemblyResolutions.SplitNonFoundationalResolutions(tcConfig)
+            let frameworkDLLs, nonFrameworkResolutions, unresolvedReferences =
+                TcAssemblyResolutions.SplitNonFoundationalResolutions(tcConfig)
 
             let frameworkDLLsKey =
                 frameworkDLLs
-                |> List.map (fun ar->ar.resolvedPath) // The cache key. Just the minimal data.
-                |> List.sort  // Sort to promote cache hits.
+                |> List.map (fun ar -> ar.resolvedPath) // The cache key. Just the minimal data.
+                |> List.sort // Sort to promote cache hits.
 
             // Prepare the frameworkTcImportsCache
             //
@@ -348,17 +396,22 @@ type internal TransparentCompiler
             // the import of a set of framework DLLs into F# CCUs. That is, the F# CCUs that result from a set of DLLs (including
             // FSharp.Core.dll and mscorlib.dll) must be logically invariant of all the other compiler configuration parameters.
             let key =
-                FrameworkImportsCacheKey(frameworkDLLsKey,
-                        tcConfig.primaryAssembly.Name,
-                        tcConfig.GetTargetFrameworkDirectories(),
-                        tcConfig.fsharpBinariesDir,
-                        tcConfig.langVersion.SpecifiedVersion)
+                FrameworkImportsCacheKey(
+                    frameworkDLLsKey,
+                    tcConfig.primaryAssembly.Name,
+                    tcConfig.GetTargetFrameworkDirectories(),
+                    tcConfig.fsharpBinariesDir,
+                    tcConfig.langVersion.SpecifiedVersion
+                )
 
-            let! tcGlobals, frameworkTcImports = FrameworkImportsCache.Get(key, ComputeFrameworkImports tcConfig frameworkDLLs nonFrameworkResolutions)
+            let! tcGlobals, frameworkTcImports =
+                FrameworkImportsCache.Get(key, ComputeFrameworkImports tcConfig frameworkDLLs nonFrameworkResolutions)
 
             // Note we are not calling diagnosticsLogger.GetDiagnostics() anywhere for this task.
             // This is ok because not much can actually go wrong here.
-            let diagnosticsLogger = CompilationDiagnosticLogger("nonFrameworkAssemblyInputs", tcConfig.diagnosticsOptions)
+            let diagnosticsLogger =
+                CompilationDiagnosticLogger("nonFrameworkAssemblyInputs", tcConfig.diagnosticsOptions)
+
             use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parameter)
 
             // TODO: might need to put something like this somewhere
@@ -382,12 +435,14 @@ type internal TransparentCompiler
 
             let tcConfigP = TcConfigProvider.Constant tcConfig
 
-                #if !NO_TYPEPROVIDERS
+            //#if !NO_TYPEPROVIDERS
             let importsInvalidatedByTypeProvider = Event()
-                #endif
+            //#endif
 
             // Check for the existence of loaded sources and prepend them to the sources list if present.
-            let sourceFiles = tcConfig.GetAvailableLoadedSources() @ (sourceFiles |> List.map (fun s -> rangeStartup, s))
+            let sourceFiles =
+                tcConfig.GetAvailableLoadedSources()
+                @ (sourceFiles |> List.map (fun s -> rangeStartup, s))
 
             // Mark up the source files with an indicator flag indicating if they are the last source file in the project
             let sourceFiles =
@@ -395,23 +450,31 @@ type internal TransparentCompiler
                 ((sourceFiles, flags) ||> List.map2 (fun (m, nm) flag -> (m, nm, (flag, isExe))))
 
             let basicDependencies =
-                [ for UnresolvedAssemblyReference(referenceText, _)  in unresolvedReferences do
-                    // Exclude things that are definitely not a file name
-                    if not(FileSystem.IsInvalidPathShim referenceText) then
-                        let file = if FileSystem.IsPathRootedShim referenceText then referenceText else Path.Combine(projectSnapshot.ProjectDirectory, referenceText)
-                        yield file
-
-                  for r in nonFrameworkResolutions do
-                        yield r.resolvedPath ]
+                [
+                    for UnresolvedAssemblyReference (referenceText, _) in unresolvedReferences do
+                        // Exclude things that are definitely not a file name
+                        if not (FileSystem.IsInvalidPathShim referenceText) then
+                            let file =
+                                if FileSystem.IsPathRootedShim referenceText then
+                                    referenceText
+                                else
+                                    Path.Combine(projectSnapshot.ProjectDirectory, referenceText)
+
+                            yield file
+
+                    for r in nonFrameworkResolutions do
+                        yield r.resolvedPath
+                ]
 
             // For scripts, the dependency provider is already available.
             // For projects create a fresh one for the project.
             let dependencyProvider =
-                if projectSnapshot.UseScriptResolutionRules
-                then dependencyProviderForScripts
-                else new DependencyProvider()
+                if projectSnapshot.UseScriptResolutionRules then
+                    dependencyProviderForScripts
+                else
+                    new DependencyProvider()
 
-            let! tcImports, initialTcInfo = 
+            let! tcImports, initialTcInfo =
                 CombineImportedAssembliesTask(
                     assemblyName,
                     tcConfig,
@@ -422,10 +485,10 @@ type internal TransparentCompiler
                     unresolvedReferences,
                     dependencyProvider,
                     loadClosureOpt,
-                    basicDependencies
-                #if !NO_TYPEPROVIDERS
-                    ,importsInvalidatedByTypeProvider
-                #endif
+                    basicDependencies,
+                    //#if !NO_TYPEPROVIDERS
+                    importsInvalidatedByTypeProvider
+                //#endif
                 )
 
             let fileSnapshots = Map [ for f in projectSnapshot.SourceFiles -> f.FileName, f ]
@@ -442,16 +505,24 @@ type internal TransparentCompiler
                                 Version = (FileSystem.GetLastWriteTimeShim fileName).Ticks.ToString()
                                 GetSource = (fun () -> fileName |> File.ReadAllText |> SourceText.ofString |> Task.FromResult)
                             })
-                    { Range = m; Source = source; IsLastCompiland = isLastCompiland; IsExe = isExe })
-
-            return Some {
-                TcConfig = tcConfig
-                TcImports = tcImports
-                TcGlobals = tcGlobals
-                InitialTcInfo = initialTcInfo
-                SourceFiles = sourceFiles
-                LoadClosure = loadClosureOpt
-            }
+
+                    {
+                        Range = m
+                        Source = source
+                        IsLastCompiland = isLastCompiland
+                        IsExe = isExe
+                    })
+
+            return
+                Some
+                    {
+                        TcConfig = tcConfig
+                        TcImports = tcImports
+                        TcGlobals = tcGlobals
+                        InitialTcInfo = initialTcInfo
+                        SourceFiles = sourceFiles
+                        LoadClosure = loadClosureOpt
+                    }
         }
 
     let ComputeBootstrapInfo (projectSnapshot: FSharpProjectSnapshot) _key =
@@ -474,44 +545,53 @@ type internal TransparentCompiler
                 match bootstrapInfoOpt with
                 | Some bootstrapInfo ->
                     let diagnosticsOptions = bootstrapInfo.TcConfig.diagnosticsOptions
-                    let diagnosticsLogger = CompilationDiagnosticLogger("IncrementalBuilderCreation", diagnosticsOptions)
+
+                    let diagnosticsLogger =
+                        CompilationDiagnosticLogger("IncrementalBuilderCreation", diagnosticsOptions)
+
                     delayedLogger.CommitDelayedDiagnostics diagnosticsLogger
                     diagnosticsLogger.GetDiagnostics()
-                | _ ->
-                    Array.ofList delayedLogger.Diagnostics
+                | _ -> Array.ofList delayedLogger.Diagnostics
                 |> Array.map (fun (diagnostic, severity) ->
                     FSharpDiagnostic.CreateFromException(diagnostic, severity, range.Zero, suggestNamesForErrors))
+
             return bootstrapInfoOpt, diagnostics
         }
 
-    let ComputeParseFile' (file: FSharpFile) (projectSnapshot: FSharpProjectSnapshot) bootstrapInfo userOpName _key = node {
+    let ComputeParseFile' (file: FSharpFile) (projectSnapshot: FSharpProjectSnapshot) bootstrapInfo userOpName _key =
+        node {
 
-        let parsingOptions =
-            FSharpParsingOptions.FromTcConfig(
-                bootstrapInfo.TcConfig,
-                projectSnapshot.SourceFiles |> Seq.map (fun f -> f.FileName) |> Array.ofSeq,
-                projectSnapshot.UseScriptResolutionRules
-            )
+            let parsingOptions =
+                FSharpParsingOptions.FromTcConfig(
+                    bootstrapInfo.TcConfig,
+                    projectSnapshot.SourceFiles |> Seq.map (fun f -> f.FileName) |> Array.ofSeq,
+                    projectSnapshot.UseScriptResolutionRules
+                )
 
-        // TODO: what is this?
-        // GraphNode.SetPreferredUILang tcPrior.TcConfig.preferredUiLang
+            // TODO: what is this?
+            // GraphNode.SetPreferredUILang tcPrior.TcConfig.preferredUiLang
 
-        let! sourceText = file.Source.GetSource() |> NodeCode.AwaitTask
-        let diagnostics, parsedInput, anyErrors = ParseAndCheckFile.parseFile(
-            sourceText,
-            file.Source.FileName,
-            parsingOptions,
-            userOpName,
-            suggestNamesForErrors,
-            captureIdentifiersWhenParsing
-        )
-        return diagnostics, parsedInput, anyErrors, sourceText
-    }
+            let! sourceText = file.Source.GetSource() |> NodeCode.AwaitTask
+
+            let diagnostics, parsedInput, anyErrors =
+                ParseAndCheckFile.parseFile (
+                    sourceText,
+                    file.Source.FileName,
+                    parsingOptions,
+                    userOpName,
+                    suggestNamesForErrors,
+                    captureIdentifiersWhenParsing
+                )
+
+            return diagnostics, parsedInput, anyErrors, sourceText
+        }
 
     let ComputeParseFile (file: FSharpFile) bootstrapInfo _key =
         node {
             let tcConfig = bootstrapInfo.TcConfig
-            let diagnosticsLogger = CompilationDiagnosticLogger("Parse", tcConfig.diagnosticsOptions)
+
+            let diagnosticsLogger =
+                CompilationDiagnosticLogger("Parse", tcConfig.diagnosticsOptions)
             // Return the disposable object that cleans up
             use _holder = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parse)
 
@@ -519,7 +599,8 @@ type internal TransparentCompiler
             let fileName = file.Source.FileName
             let! sourceText = file.Source.GetSource() |> NodeCode.AwaitTask
 
-            let input = ParseOneInputSourceText(tcConfig, lexResourceManager, fileName, flags, diagnosticsLogger, sourceText)
+            let input =
+                ParseOneInputSourceText(tcConfig, lexResourceManager, fileName, flags, diagnosticsLogger, sourceText)
 
             return input, diagnosticsLogger.GetDiagnostics()
         }
@@ -555,30 +636,51 @@ type internal TransparentCompiler
             let tcImports = bootstrapInfo.TcImports
 
             let capturingDiagnosticsLogger = CapturingDiagnosticsLogger("TypeCheck")
-            let diagnosticsLogger = GetDiagnosticsLoggerFilteringByScopedPragmas(false, input.ScopedPragmas, tcConfig.diagnosticsOptions, capturingDiagnosticsLogger)
+
+            let diagnosticsLogger =
+                GetDiagnosticsLoggerFilteringByScopedPragmas(
+                    false,
+                    input.ScopedPragmas,
+                    tcConfig.diagnosticsOptions,
+                    capturingDiagnosticsLogger
+                )
+
             use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.TypeCheck)
 
             //beforeFileChecked.Trigger fileName
 
-            ApplyMetaCommandsFromInputToTcConfig (tcConfig, input, Path.GetDirectoryName fileName, tcImports.DependencyProvider) |> ignore
+            ApplyMetaCommandsFromInputToTcConfig(tcConfig, input, Path.GetDirectoryName fileName, tcImports.DependencyProvider)
+            |> ignore
+
             let sink = TcResultsSinkImpl(tcGlobals)
             let hadParseErrors = not (Array.isEmpty parseErrors)
-            let input, moduleNamesDict = DeduplicateParsedInputModuleName prevTcInfo.moduleNamesDict input
+
+            let input, moduleNamesDict =
+                DeduplicateParsedInputModuleName prevTcInfo.moduleNamesDict input
 
             let! (tcEnvAtEndOfFile, topAttribs, implFile, ccuSigForFile), tcState =
-                CheckOneInput (
-                        (fun () -> hadParseErrors || diagnosticsLogger.ErrorCount > 0),
-                        tcConfig, tcImports,
-                        tcGlobals,
-                        None,
-                        TcResultsSink.WithSink sink,
-                        prevTcInfo.tcState, input )
+                CheckOneInput(
+                    (fun () -> hadParseErrors || diagnosticsLogger.ErrorCount > 0),
+                    tcConfig,
+                    tcImports,
+                    tcGlobals,
+                    None,
+                    TcResultsSink.WithSink sink,
+                    prevTcInfo.tcState,
+                    input
+                )
                 |> NodeCode.FromCancellable
 
             //fileChecked.Trigger fileName
 
-            let newErrors = Array.append parseErrors (capturingDiagnosticsLogger.Diagnostics |> List.toArray)
-            let tcEnvAtEndOfFile = if keepAllBackgroundResolutions then tcEnvAtEndOfFile else tcState.TcEnvFromImpls
+            let newErrors =
+                Array.append parseErrors (capturingDiagnosticsLogger.Diagnostics |> List.toArray)
+
+            let tcEnvAtEndOfFile =
+                if keepAllBackgroundResolutions then
+                    tcEnvAtEndOfFile
+                else
+                    tcState.TcEnvFromImpls
 
             let tcInfo =
                 {
@@ -586,28 +688,47 @@ type internal TransparentCompiler
                     tcEnvAtEndOfFile = tcEnvAtEndOfFile
                     moduleNamesDict = moduleNamesDict
                     latestCcuSigForFile = Some ccuSigForFile
-                    tcDiagnosticsRev = [newErrors]
+                    tcDiagnosticsRev = [ newErrors ]
                     topAttribs = Some topAttribs
-                    tcDependencyFiles = [fileName]
+                    tcDependencyFiles = [ fileName ]
                     sigNameOpt =
                         match input with
-                        | ParsedInput.SigFile sigFile ->
-                            Some(sigFile.FileName, sigFile.QualifiedName)
-                        | _ ->
-                            None
+                        | ParsedInput.SigFile sigFile -> Some(sigFile.FileName, sigFile.QualifiedName)
+                        | _ -> None
                 }
+
             return tcInfo, sink, implFile, fileName
         }
 
+    let mergeTcInfos =
+        Array.fold (fun a b ->
+            { a with
+                tcState = b.tcState
+                tcEnvAtEndOfFile = b.tcEnvAtEndOfFile
+                moduleNamesDict = b.moduleNamesDict
+                latestCcuSigForFile = b.latestCcuSigForFile
+                tcDiagnosticsRev = b.tcDiagnosticsRev @ a.tcDiagnosticsRev
+                topAttribs = b.topAttribs
+                tcDependencyFiles = b.tcDependencyFiles
+                sigNameOpt = b.sigNameOpt
+            })
+
     // Type check everything that is needed to check given file
-    let ComputeTcPrior (file: FSharpFile) (bootstrapInfo: BootstrapInfo) (projectSnapshot: FSharpProjectSnapshot) userOpName _key: NodeCode =
+    let ComputeTcPrior
+        (file: FSharpFile)
+        (bootstrapInfo: BootstrapInfo)
+        (projectSnapshot: FSharpProjectSnapshot)
+        _userOpName
+        _key
+        : NodeCode =
         node {
 
             // parse required files
-            let files = seq {
-                yield! bootstrapInfo.SourceFiles |> Seq.takeWhile ((<>) file)
-                file
-            }
+            let files =
+                seq {
+                    yield! bootstrapInfo.SourceFiles |> Seq.takeWhile ((<>) file)
+                    file
+                }
 
             let! parsedInputs =
                 files
@@ -617,26 +738,36 @@ type internal TransparentCompiler
                 |> NodeCode.Parallel
 
             // compute dependency graph
-            let graphKey = projectSnapshot.UpTo(file.Source.FileName).SourceFiles |> List.map (fun s -> s.Key)
-            let! graph, _filePairs = DependencyGraphForLastFileCache.Get(graphKey, ComputeDependencyGraphForLastFile (parsedInputs |> Seq.map fst) bootstrapInfo.TcConfig)
+            let graphKey =
+                projectSnapshot.UpTo(file.Source.FileName).SourceFiles
+                |> List.map (fun s -> s.Key)
+
+            let! graph, _filePairs =
+                DependencyGraphForLastFileCache.Get(
+                    graphKey,
+                    ComputeDependencyGraphForLastFile (parsedInputs |> Seq.map fst) bootstrapInfo.TcConfig
+                )
 
             // layers that can be processed in parallel
-            let layers = Graph.leafSequence graph
-
-            let rec processLayer (layers: Set list) state = node {
-                match layers with
-                | [] -> return state
-                | layer::rest ->
-                    let! results =
-                        layer
-                        |> Seq.map (fun fileIndex ->
-                            let key = projectSnapshot.UpTo(fileIndex).Key
-                            TcIntermediateCache.Get(key, ComputeTcIntermediate parsedInputs[fileIndex] bootstrapInfo state))
-                        |> NodeCode.Parallel
-                    return! processLayer rest (combineResults state results)
-            }
-
-            return bootstrapInfo.InitialTcInfo
+            let layers = Graph.leafSequence graph |> Seq.toList
+
+            let rec processLayer (layers: Set list) state =
+                node {
+                    match layers with
+                    | [] -> return state
+                    | layer :: rest ->
+                        let! results =
+                            layer
+                            |> Seq.map (fun fileIndex ->
+                                let key = projectSnapshot.UpTo(fileIndex).Key
+                                TcIntermediateCache.Get(key, ComputeTcIntermediate parsedInputs[fileIndex] bootstrapInfo state))
+                            |> NodeCode.Parallel
+
+                        return! processLayer rest (mergeTcInfos state (results |> Array.map p14))
+                }
+
+            let! tcInfo = processLayer layers bootstrapInfo.InitialTcInfo
+            return tcInfo
         }
 
     let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: FSharpProjectSnapshot) userOpName _key =
@@ -652,12 +783,14 @@ type internal TransparentCompiler
 
             | Some bootstrapInfo ->
 
-                let file = bootstrapInfo.SourceFiles |> List.find (fun f -> f.Source.FileName = fileName)
+                let file =
+                    bootstrapInfo.SourceFiles |> List.find (fun f -> f.Source.FileName = fileName)
 
                 let priorSnapshot = projectSnapshot.UpTo fileName
                 let! tcInfo = TcPriorCache.Get(priorSnapshot.Key, ComputeTcPrior file bootstrapInfo priorSnapshot userOpName)
 
-                let! parseTree, parseDiagnostics = ParseFileCache.Get((file.Source.Key, file.IsLastCompiland, file.IsExe), ComputeParseFile file bootstrapInfo)
+                let! parseTree, parseDiagnostics =
+                    ParseFileCache.Get((file.Source.Key, file.IsLastCompiland, file.IsExe), ComputeParseFile file bootstrapInfo)
 
                 let parseDiagnostics =
                     DiagnosticHelpers.CreateDiagnostics(
@@ -681,6 +814,7 @@ type internal TransparentCompiler
 
                 // TODO: this might be replaced... probably should use intermediate TC result
                 let sourceText = Unchecked.defaultof<_>
+
                 let! checkResults =
                     FSharpCheckFileResults.CheckOneFile(
                         parseResults,
@@ -708,17 +842,12 @@ type internal TransparentCompiler
                 return (parseResults, FSharpCheckFileAnswer.Succeeded checkResults)
         }
 
-    member _.ParseAndCheckFileInProject
-        (
-            fileName: string,
-            projectSnapshot: FSharpProjectSnapshot,
-            userOpName: string
-        ) = node {
+    member _.ParseAndCheckFileInProject(fileName: string, projectSnapshot: FSharpProjectSnapshot, userOpName: string) =
+        node {
             let key = fileName, projectSnapshot.Key
             return! ParseAndCheckFileInProjectCache.Get(key, ComputeParseAndCheckFileInProject fileName projectSnapshot userOpName)
         }
 
-
     interface IBackgroundCompiler with
         member this.BeforeBackgroundFileCheck: IEvent =
             backgroundCompiler.BeforeBackgroundFileCheck
@@ -743,13 +872,26 @@ type internal TransparentCompiler
                 options: FSharpProjectOptions,
                 userOpName: string
             ) : NodeCode =
-            backgroundCompiler.CheckFileInProjectAllowingStaleCachedResults(parseResults, fileName, fileVersion, sourceText, options, userOpName)
+            backgroundCompiler.CheckFileInProjectAllowingStaleCachedResults(
+                parseResults,
+                fileName,
+                fileVersion,
+                sourceText,
+                options,
+                userOpName
+            )
+
+        member _.ClearCache(options: seq, userOpName: string) : unit =
+            backgroundCompiler.ClearCache(options, userOpName)
 
-        member _.ClearCache(options: seq, userOpName: string) : unit = backgroundCompiler.ClearCache(options, userOpName)
         member _.ClearCaches() : unit = backgroundCompiler.ClearCaches()
         member _.DownsizeCaches() : unit = backgroundCompiler.DownsizeCaches()
-        member _.FileChecked: IEvent = backgroundCompiler.FileChecked
-        member _.FileParsed: IEvent = backgroundCompiler.FileParsed
+
+        member _.FileChecked: IEvent =
+            backgroundCompiler.FileChecked
+
+        member _.FileParsed: IEvent =
+            backgroundCompiler.FileParsed
 
         member _.FindReferencesInFile
             (
@@ -761,7 +903,8 @@ type internal TransparentCompiler
             ) : NodeCode> =
             backgroundCompiler.FindReferencesInFile(fileName, options, symbol, canInvalidateProject, userOpName)
 
-        member _.FrameworkImportsCache: FrameworkImportsCache = backgroundCompiler.FrameworkImportsCache
+        member _.FrameworkImportsCache: FrameworkImportsCache =
+            backgroundCompiler.FrameworkImportsCache
 
         member _.GetAssemblyData(options: FSharpProjectOptions, userOpName: string) : NodeCode =
             backgroundCompiler.GetAssemblyData(options, userOpName)
@@ -860,7 +1003,8 @@ type internal TransparentCompiler
             ) : Async =
             backgroundCompiler.ParseFile(fileName, sourceText, options, cache, userOpName)
 
-        member _.ProjectChecked: IEvent = backgroundCompiler.ProjectChecked
+        member _.ProjectChecked: IEvent =
+            backgroundCompiler.ProjectChecked
 
         member _.TryGetRecentCheckResultsForFile
             (
diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs
index 22d9e69da7d..0dd0083f706 100644
--- a/src/Compiler/Service/service.fs
+++ b/src/Compiler/Service/service.fs
@@ -149,7 +149,9 @@ type FSharpChecker
                 captureIdentifiersWhenParsing,
                 getSource,
                 useChangeNotifications,
-                useSyntaxTreeCache) :> IBackgroundCompiler
+                useSyntaxTreeCache
+            )
+            :> IBackgroundCompiler
         else
             BackgroundCompiler(
                 legacyReferenceResolver,
@@ -165,7 +167,9 @@ type FSharpChecker
                 captureIdentifiersWhenParsing,
                 getSource,
                 useChangeNotifications,
-                useSyntaxTreeCache) :> IBackgroundCompiler
+                useSyntaxTreeCache
+            )
+            :> IBackgroundCompiler
 
     static let globalInstance = lazy FSharpChecker.Create()
 
From e8ea40cd7ffcd9268e8893ff1bb12ff68baa81b1 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Fri, 28 Apr 2023 15:34:43 +0200
Subject: [PATCH 010/222] wip
---
 src/Compiler/Service/BackgroundCompiler.fs    | 13 +++
 src/Compiler/Service/FSharpCheckerResults.fs  |  1 +
 src/Compiler/Service/FSharpCheckerResults.fsi |  3 +-
 src/Compiler/Service/IncrementalBuild.fs      |  4 +-
 src/Compiler/Service/TransparentCompiler.fs   | 65 +++++++-------
 src/Compiler/Service/service.fs               |  6 ++
 src/Compiler/Service/service.fsi              |  4 +
 .../LanguageService/LanguageService.fs        |  5 +-
 .../LanguageService/WorkspaceExtensions.fs    | 85 ++++++++++++++++---
 .../FSharp.Editor/Options/EditorOptions.fs    |  5 ++
 .../AdvancedOptionsControl.xaml               |  4 +
 .../FSharp.UIResources/Strings.Designer.cs    | 18 ++++
 .../src/FSharp.UIResources/Strings.resx       |  6 ++
 .../src/FSharp.UIResources/xlf/Strings.cs.xlf | 10 +++
 .../src/FSharp.UIResources/xlf/Strings.de.xlf | 10 +++
 .../src/FSharp.UIResources/xlf/Strings.es.xlf | 10 +++
 .../src/FSharp.UIResources/xlf/Strings.fr.xlf | 10 +++
 .../src/FSharp.UIResources/xlf/Strings.it.xlf | 10 +++
 .../src/FSharp.UIResources/xlf/Strings.ja.xlf | 10 +++
 .../src/FSharp.UIResources/xlf/Strings.ko.xlf | 10 +++
 .../src/FSharp.UIResources/xlf/Strings.pl.xlf | 10 +++
 .../FSharp.UIResources/xlf/Strings.pt-BR.xlf  | 10 +++
 .../src/FSharp.UIResources/xlf/Strings.ru.xlf | 10 +++
 .../src/FSharp.UIResources/xlf/Strings.tr.xlf | 10 +++
 .../xlf/Strings.zh-Hans.xlf                   | 10 +++
 .../xlf/Strings.zh-Hant.xlf                   | 10 +++
 26 files changed, 298 insertions(+), 51 deletions(-)
diff --git a/src/Compiler/Service/BackgroundCompiler.fs b/src/Compiler/Service/BackgroundCompiler.fs
index 36758b75afc..ddf9d3f0c04 100644
--- a/src/Compiler/Service/BackgroundCompiler.fs
+++ b/src/Compiler/Service/BackgroundCompiler.fs
@@ -124,6 +124,10 @@ type internal IBackgroundCompiler =
         fileName: string * fileVersion: int * sourceText: ISourceText * options: FSharpProjectOptions * userOpName: string ->
             NodeCode
 
+    abstract member ParseAndCheckFileInProject:
+        fileName: string * projectSnapshot: FSharpProjectSnapshot * userOpName: string ->
+            NodeCode
+
     /// Parse and typecheck the whole project.
     abstract member ParseAndCheckProject: options: FSharpProjectOptions * userOpName: string -> NodeCode
 
@@ -1373,6 +1377,7 @@ type internal BackgroundCompiler
     static member ActualCheckFileCount = actualCheckFileCount
 
     interface IBackgroundCompiler with
+
         member _.BeforeBackgroundFileCheck = self.BeforeBackgroundFileCheck
 
         member _.CheckFileInProject
@@ -1498,6 +1503,14 @@ type internal BackgroundCompiler
             ) : NodeCode =
             self.ParseAndCheckFileInProject(fileName, fileVersion, sourceText, options, userOpName)
 
+        member this.ParseAndCheckFileInProject
+            (
+                _fileName: string,
+                _projectSnapshot: FSharpProjectSnapshot,
+                _userOpName: string
+            ) : NodeCode =
+            raise (System.NotImplementedException())
+
         member _.ParseAndCheckProject(options: FSharpProjectOptions, userOpName: string) : NodeCode =
             self.ParseAndCheckProject(options, userOpName)
 
diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs
index a5767cd3564..5b2dbb3cd54 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fs
+++ b/src/Compiler/Service/FSharpCheckerResults.fs
@@ -117,6 +117,7 @@ type internal DelayedILModuleReader =
 
 type FSharpFileKey = string * string
 
+// TODO: use stamp if we have it?
 type FSharpProjectSnapshotKey =
     {
         ProjectFileName: string
diff --git a/src/Compiler/Service/FSharpCheckerResults.fsi b/src/Compiler/Service/FSharpCheckerResults.fsi
index 04e6667ca06..20ecde853ea 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fsi
+++ b/src/Compiler/Service/FSharpCheckerResults.fsi
@@ -5,6 +5,7 @@ namespace FSharp.Compiler.CodeAnalysis
 open System
 open System.IO
 open System.Threading
+open System.Threading.Tasks
 open Internal.Utilities.Library
 open FSharp.Compiler.AbstractIL.IL
 open FSharp.Compiler.AbstractIL.ILBinaryReader
@@ -55,7 +56,7 @@ type FSharpProjectSnapshotKey =
 type FSharpFileSnapshot =
     { FileName: string
       Version: string
-      GetSource: unit -> System.Threading.Tasks.Task }
+      GetSource: unit -> Task }
 
     member Key: FSharpFileKey
 
diff --git a/src/Compiler/Service/IncrementalBuild.fs b/src/Compiler/Service/IncrementalBuild.fs
index 3178af6868b..8d48ec4503b 100644
--- a/src/Compiler/Service/IncrementalBuild.fs
+++ b/src/Compiler/Service/IncrementalBuild.fs
@@ -250,7 +250,7 @@ type BoundModel private (
         syntaxTreeOpt: SyntaxTree option,
         ?tcStateOpt: GraphNode * GraphNode
     ) =
-    
+
     let getTypeCheck (syntaxTree: SyntaxTree) : NodeCode =
         node {
             let! input, _sourceRange, fileName, parseErrors = syntaxTree.ParseNode.GetOrComputeValue()
@@ -262,7 +262,7 @@ type BoundModel private (
             use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.TypeCheck)
 
             beforeFileChecked.Trigger fileName
-                    
+
             ApplyMetaCommandsFromInputToTcConfig (tcConfig, input, Path.GetDirectoryName fileName, tcImports.DependencyProvider) |> ignore
             let sink = TcResultsSinkImpl(tcGlobals)
             let hadParseErrors = not (Array.isEmpty parseErrors)
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index dd24c89ed3d..81a2406d811 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -52,8 +52,6 @@ type internal BootstrapInfo =
         LoadClosure: LoadClosure option
     }
 
-//type ParseResults
-
 type internal TransparentCompiler
     (
         legacyReferenceResolver,
@@ -168,8 +166,9 @@ type internal TransparentCompiler
             dependencyProvider,
             loadClosureOpt: LoadClosure option,
             basicDependencies,
+#if !NO_TYPEPROVIDERS
             importsInvalidatedByTypeProvider: Event
-        //#endif
+#endif
         ) =
 
         node {
@@ -189,7 +188,7 @@ type internal TransparentCompiler
                                 unresolvedReferences,
                                 dependencyProvider
                             )
-                        //#if !NO_TYPEPROVIDERS
+#if !NO_TYPEPROVIDERS
                         tcImports.GetCcusExcludingBase()
                         |> Seq.iter (fun ccu ->
                             // When a CCU reports an invalidation, merge them together and just report a
@@ -212,7 +211,7 @@ type internal TransparentCompiler
                                 match capturedImportsInvalidated.TryGetTarget() with
                                 | true, tg -> tg.Trigger()
                                 | _ -> ()))
-                        //#endif
+#endif
                         return tcImports
                     with exn ->
                         Debug.Assert(false, sprintf "Could not BuildAllReferencedDllTcImports %A" exn)
@@ -435,9 +434,9 @@ type internal TransparentCompiler
 
             let tcConfigP = TcConfigProvider.Constant tcConfig
 
-            //#if !NO_TYPEPROVIDERS
+#if !NO_TYPEPROVIDERS
             let importsInvalidatedByTypeProvider = Event()
-            //#endif
+#endif
 
             // Check for the existence of loaded sources and prepend them to the sources list if present.
             let sourceFiles =
@@ -486,9 +485,9 @@ type internal TransparentCompiler
                     dependencyProvider,
                     loadClosureOpt,
                     basicDependencies,
-                    //#if !NO_TYPEPROVIDERS
+#if !NO_TYPEPROVIDERS
                     importsInvalidatedByTypeProvider
-                //#endif
+#endif
                 )
 
             let fileSnapshots = Map [ for f in projectSnapshot.SourceFiles -> f.FileName, f ]
@@ -602,7 +601,7 @@ type internal TransparentCompiler
             let input =
                 ParseOneInputSourceText(tcConfig, lexResourceManager, fileName, flags, diagnosticsLogger, sourceText)
 
-            return input, diagnosticsLogger.GetDiagnostics()
+            return input, diagnosticsLogger.GetDiagnostics(), sourceText
         }
 
     let ComputeDependencyGraphForLastFile parsedInputs (tcConfig: TcConfig) _key =
@@ -691,10 +690,8 @@ type internal TransparentCompiler
                     tcDiagnosticsRev = [ newErrors ]
                     topAttribs = Some topAttribs
                     tcDependencyFiles = [ fileName ]
-                    sigNameOpt =
-                        match input with
-                        | ParsedInput.SigFile sigFile -> Some(sigFile.FileName, sigFile.QualifiedName)
-                        | _ -> None
+                    // we shouldn't need this with graph checking (?)
+                    sigNameOpt = None
                 }
 
             return tcInfo, sink, implFile, fileName
@@ -709,18 +706,13 @@ type internal TransparentCompiler
                 latestCcuSigForFile = b.latestCcuSigForFile
                 tcDiagnosticsRev = b.tcDiagnosticsRev @ a.tcDiagnosticsRev
                 topAttribs = b.topAttribs
-                tcDependencyFiles = b.tcDependencyFiles
-                sigNameOpt = b.sigNameOpt
+                tcDependencyFiles = b.tcDependencyFiles @ a.tcDependencyFiles
+                // we shouldn't need this with graph checking (?)
+                sigNameOpt = None
             })
 
     // Type check everything that is needed to check given file
-    let ComputeTcPrior
-        (file: FSharpFile)
-        (bootstrapInfo: BootstrapInfo)
-        (projectSnapshot: FSharpProjectSnapshot)
-        _userOpName
-        _key
-        : NodeCode =
+    let ComputeTcPrior (file: FSharpFile) (bootstrapInfo: BootstrapInfo) (projectSnapshot: FSharpProjectSnapshot) _userOpName _key =
         node {
 
             // parse required files
@@ -745,29 +737,32 @@ type internal TransparentCompiler
             let! graph, _filePairs =
                 DependencyGraphForLastFileCache.Get(
                     graphKey,
-                    ComputeDependencyGraphForLastFile (parsedInputs |> Seq.map fst) bootstrapInfo.TcConfig
+                    ComputeDependencyGraphForLastFile (parsedInputs |> Seq.map p13) bootstrapInfo.TcConfig
                 )
 
             // layers that can be processed in parallel
             let layers = Graph.leafSequence graph |> Seq.toList
 
-            let rec processLayer (layers: Set list) state =
+            // remove the final layer, which should be the target file
+            let layers = layers |> List.take (layers.Length - 1)
+
+            let rec processLayer (layers: Set list) tcInfo =
                 node {
                     match layers with
-                    | [] -> return state
+                    | [] -> return tcInfo
                     | layer :: rest ->
                         let! results =
                             layer
                             |> Seq.map (fun fileIndex ->
                                 let key = projectSnapshot.UpTo(fileIndex).Key
-                                TcIntermediateCache.Get(key, ComputeTcIntermediate parsedInputs[fileIndex] bootstrapInfo state))
+                                let parsedInput, parseErrors, _ = parsedInputs[fileIndex]
+                                TcIntermediateCache.Get(key, ComputeTcIntermediate (parsedInput, parseErrors) bootstrapInfo tcInfo))
                             |> NodeCode.Parallel
 
-                        return! processLayer rest (mergeTcInfos state (results |> Array.map p14))
+                        return! processLayer rest (mergeTcInfos tcInfo (results |> Array.map p14))
                 }
 
-            let! tcInfo = processLayer layers bootstrapInfo.InitialTcInfo
-            return tcInfo
+            return! processLayer layers bootstrapInfo.InitialTcInfo
         }
 
     let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: FSharpProjectSnapshot) userOpName _key =
@@ -789,7 +784,8 @@ type internal TransparentCompiler
                 let priorSnapshot = projectSnapshot.UpTo fileName
                 let! tcInfo = TcPriorCache.Get(priorSnapshot.Key, ComputeTcPrior file bootstrapInfo priorSnapshot userOpName)
 
-                let! parseTree, parseDiagnostics =
+                // We could also bubble this through ComputeTcPrior
+                let! parseTree, parseDiagnostics, sourceText =
                     ParseFileCache.Get((file.Source.Key, file.IsLastCompiland, file.IsExe), ComputeParseFile file bootstrapInfo)
 
                 let parseDiagnostics =
@@ -812,9 +808,6 @@ type internal TransparentCompiler
                         dependencyFiles = [||]
                     )
 
-                // TODO: this might be replaced... probably should use intermediate TC result
-                let sourceText = Unchecked.defaultof<_>
-
                 let! checkResults =
                     FSharpCheckFileResults.CheckOneFile(
                         parseResults,
@@ -849,6 +842,7 @@ type internal TransparentCompiler
         }
 
     interface IBackgroundCompiler with
+
         member this.BeforeBackgroundFileCheck: IEvent =
             backgroundCompiler.BeforeBackgroundFileCheck
 
@@ -990,6 +984,9 @@ type internal TransparentCompiler
 
             backgroundCompiler.ParseAndCheckFileInProject(fileName, fileVersion, sourceText, options, userOpName)
 
+        member this.ParseAndCheckFileInProject(fileName: string, projectSnapshot: FSharpProjectSnapshot, userOpName: string) =
+            this.ParseAndCheckFileInProject(fileName, projectSnapshot, userOpName)
+
         member _.ParseAndCheckProject(options: FSharpProjectOptions, userOpName: string) : NodeCode =
             backgroundCompiler.ParseAndCheckProject(options, userOpName)
 
diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs
index fdbf6a1df36..69b6f7186dc 100644
--- a/src/Compiler/Service/service.fs
+++ b/src/Compiler/Service/service.fs
@@ -431,6 +431,12 @@ type FSharpChecker
         backgroundCompiler.ParseAndCheckFileInProject(fileName, fileVersion, sourceText, options, userOpName)
         |> Async.AwaitNodeCode
 
+    member _.ParseAndCheckFileInProject(fileName: string, projectSnapshot: FSharpProjectSnapshot, ?userOpName: string) =
+        let userOpName = defaultArg userOpName "Unknown"
+
+        backgroundCompiler.ParseAndCheckFileInProject(fileName, projectSnapshot, userOpName)
+        |> Async.AwaitNodeCode
+
     member _.ParseAndCheckProject(options, ?userOpName: string) =
         let userOpName = defaultArg userOpName "Unknown"
 
diff --git a/src/Compiler/Service/service.fsi b/src/Compiler/Service/service.fsi
index 9a7472c0841..45522fa3126 100644
--- a/src/Compiler/Service/service.fsi
+++ b/src/Compiler/Service/service.fsi
@@ -193,6 +193,10 @@ type public FSharpChecker =
         ?userOpName: string ->
             Async
 
+    member ParseAndCheckFileInProject:
+        fileName: string * projectSnapshot: FSharpProjectSnapshot * ?userOpName: string ->
+            Async
+
     /// 
     /// Parse and typecheck all files in a project.
     /// All files are read from the FileSystem API
diff --git a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs
index 6b8fd616027..a9680b20653 100644
--- a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs
+++ b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs
@@ -143,6 +143,8 @@ type internal FSharpWorkspaceServiceFactory [ Seq.map (fun d -> d.FilePath, d) |> Map
+
+                let! sourceFiles =
+                    options.SourceFiles
+                    |> Seq.map (fun path ->
+                        async {
+                            let document = documents[path]
+                            let! version = document.GetTextVersionAsync() |> Async.AwaitTask
+
+                            let getSource () =
+                                task {
+                                    let! sourceText = document.GetTextAsync()
+                                    return sourceText.ToFSharpSourceText()
+                                }
+
+                            return
+                                {
+                                    FileName = path
+                                    Version = version.ToString()
+                                    GetSource = getSource
+                                }
+                        })
+                    |> Async.Parallel
+
+                // TODO: referenced projects
+                let referencedProjects = []
+
+                let projectSnapshot: FSharpProjectSnapshot =
+                    {
+                        ProjectFileName = options.ProjectFileName
+                        ProjectId = options.ProjectId
+                        SourceFiles = sourceFiles |> List.ofArray
+                        OtherOptions = options.OtherOptions |> List.ofArray
+                        ReferencedProjects = referencedProjects
+                        IsIncompleteTypeCheckEnvironment = options.IsIncompleteTypeCheckEnvironment
+                        UseScriptResolutionRules = options.UseScriptResolutionRules
+                        LoadTime = options.LoadTime
+                        UnresolvedReferences = options.UnresolvedReferences
+                        OriginalLoadReferences = options.OriginalLoadReferences
+                        Stamp = options.Stamp
+                    }
+
+                let! (parseResults, checkFileAnswer) = checker.ParseAndCheckFileInProject(fileName, projectSnapshot, userOpName)
+
+                return
+                    match checkFileAnswer with
+                    | FSharpCheckFileAnswer.Aborted -> None
+                    | FSharpCheckFileAnswer.Succeeded (checkFileResults) -> Some(parseResults, checkFileResults)
+            }
+
         /// Parse and check the source text from the Roslyn document with possible stale results.
         member checker.ParseAndCheckDocumentWithPossibleStaleResults
             (
@@ -77,11 +136,6 @@ module private CheckerExtensions =
                             return None // worker is cancelled at this point, we cannot return it and wait its completion anymore
                     }
 
-                let bindParsedInput (results: (FSharpParseFileResults * FSharpCheckFileResults) option) =
-                    match results with
-                    | Some (parseResults, checkResults) -> Some(parseResults, parseResults.ParseTree, checkResults)
-                    | None -> None
-
                 if allowStaleResults then
                     let! freshResults = tryGetFreshResultsWithTimeout ()
 
@@ -95,10 +149,10 @@ module private CheckerExtensions =
                                 | None -> return! parseAndCheckFile
                             }
 
-                    return bindParsedInput results
+                    return results
                 else
                     let! results = parseAndCheckFile
-                    return bindParsedInput results
+                    return results
             }
 
         /// Parse and check the source text from the Roslyn document.
@@ -110,12 +164,17 @@ module private CheckerExtensions =
                 ?allowStaleResults: bool
             ) =
             async {
-                let allowStaleResults =
-                    match allowStaleResults with
-                    | Some b -> b
-                    | _ -> document.Project.IsFSharpStaleCompletionResultsEnabled
 
-                return! checker.ParseAndCheckDocumentWithPossibleStaleResults(document, options, allowStaleResults, userOpName = userOpName)
+                if document.Project.UseTransparentCompiiler then
+                    return! checker.ParseAndCheckDocumentUsingTransparentCompiler(document, options, userOpName)
+                else
+                    let allowStaleResults =
+                        match allowStaleResults with
+                        | Some b -> b
+                        | _ -> document.Project.IsFSharpStaleCompletionResultsEnabled
+
+                    return!
+                        checker.ParseAndCheckDocumentWithPossibleStaleResults(document, options, allowStaleResults, userOpName = userOpName)
             }
 
 []
@@ -215,7 +274,7 @@ type Document with
             let! checker, _, _, projectOptions = this.GetFSharpCompilationOptionsAsync(userOpName)
 
             match! checker.ParseAndCheckDocument(this, projectOptions, userOpName, allowStaleResults = false) with
-            | Some (parseResults, _, checkResults) -> return (parseResults, checkResults)
+            | Some results -> return results
             | _ -> return raise (System.OperationCanceledException("Unable to get FSharp parse and check results."))
         }
 
diff --git a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs
index 9ecda0ff396..cd07b46b18e 100644
--- a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs
+++ b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs
@@ -105,6 +105,7 @@ type AdvancedOptions =
         IsInlineParameterNameHintsEnabled: bool
         IsInlineReturnTypeHintsEnabled: bool
         IsLiveBuffersEnabled: bool
+        UseTransparentCompiler: bool
     }
 
     static member Default =
@@ -115,6 +116,7 @@ type AdvancedOptions =
             IsInlineParameterNameHintsEnabled = false
             IsInlineReturnTypeHintsEnabled = false
             IsLiveBuffersEnabled = FSharpExperimentalFeaturesEnabledAutomatically
+            UseTransparentCompiler = false
         }
 
 []
@@ -238,3 +240,6 @@ module EditorOptionsExtensions =
 
         member this.IsFastFindReferencesEnabled =
             this.EditorOptions.LanguageServicePerformance.EnableFastFindReferencesAndRename
+
+        member this.UseTransparentCompiiler =
+            this.EditorOptions.Advanced.UseTransparentCompiler
diff --git a/vsintegration/src/FSharp.UIResources/AdvancedOptionsControl.xaml b/vsintegration/src/FSharp.UIResources/AdvancedOptionsControl.xaml
index 78afe373f84..7ecefa11f6f 100644
--- a/vsintegration/src/FSharp.UIResources/AdvancedOptionsControl.xaml
+++ b/vsintegration/src/FSharp.UIResources/AdvancedOptionsControl.xaml
@@ -38,6 +38,10 @@
                     
                 
+                
+                    
+                
             
         
     
diff --git a/vsintegration/src/FSharp.UIResources/Strings.Designer.cs b/vsintegration/src/FSharp.UIResources/Strings.Designer.cs
index 05c26ae57a3..5185ce665cc 100644
--- a/vsintegration/src/FSharp.UIResources/Strings.Designer.cs
+++ b/vsintegration/src/FSharp.UIResources/Strings.Designer.cs
@@ -447,6 +447,15 @@ public static string Tooltip_preferred_description_width_in_characters {
             }
         }
         
+        /// 
+        ///   Looks up a localized string similar to Transparent Compiler (experimental).
+        /// 
+        public static string TransparentCompiler {
+            get {
+                return ResourceManager.GetString("TransparentCompiler", resourceCulture);
+            }
+        }
+        
         /// 
         ///   Looks up a localized string similar to Analyze and suggest fixes for unused values.
         /// 
@@ -473,5 +482,14 @@ public static string Use_syntax_tree_cache {
                 return ResourceManager.GetString("Use_syntax_tree_cache", resourceCulture);
             }
         }
+        
+        /// 
+        ///   Looks up a localized string similar to Use Transparent Compiler (restart required).
+        /// 
+        public static string Use_Transparent_Compiler {
+            get {
+                return ResourceManager.GetString("Use_Transparent_Compiler", resourceCulture);
+            }
+        }
     }
 }
diff --git a/vsintegration/src/FSharp.UIResources/Strings.resx b/vsintegration/src/FSharp.UIResources/Strings.resx
index 98d089b053b..3db260b4c0f 100644
--- a/vsintegration/src/FSharp.UIResources/Strings.resx
+++ b/vsintegration/src/FSharp.UIResources/Strings.resx
@@ -255,4 +255,10 @@
   
     Display return type hints (preview)
   
+  
+    Transparent Compiler (experimental)
+  
+  
+    Use Transparent Compiler (restart required)
+  
 
\ No newline at end of file
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf
index 8d56d2adbdd..5853389fa82 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf
@@ -147,6 +147,11 @@
         Umožňuje formátovat podpis na danou šířku přidáním konců řádků odpovídajících pravidlům syntaxe F#. 
         
       
+      
+        Transparent Compiler (experimental)
+        Transparent Compiler (experimental)
+        
+      
       
         Remove unused open statements
         Odebrat nepoužívané otevřené výkazy
@@ -227,6 +232,11 @@
         Navrhovat názvy pro nerozpoznané identifikátory
         
       
+      
+        Use Transparent Compiler (restart required)
+        Use Transparent Compiler (restart required)
+        
+      
       
         Cache parsing results (experimental)
         Výsledky analýzy mezipaměti (experimentální)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf
index ea47f390c09..7d86580264b 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf
@@ -147,6 +147,11 @@
         Formatieren Sie die Signatur in der angegebenen Breite, indem Sie Zeilenumbrüche hinzufügen, die F#-Syntaxregeln entsprechen. 
         
       
+      
+        Transparent Compiler (experimental)
+        Transparent Compiler (experimental)
+        
+      
       
         Remove unused open statements
         Nicht verwendete "open"-Anweisungen entfernen
@@ -227,6 +232,11 @@
         Namen für nicht aufgelöste Bezeichner vorschlagen
         
       
+      
+        Use Transparent Compiler (restart required)
+        Use Transparent Compiler (restart required)
+        
+      
       
         Cache parsing results (experimental)
         Cacheanalyseergebnisse (experimentell)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf
index d58237d68ba..49697e5b010 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf
@@ -147,6 +147,11 @@
         Da formato a la firma al ancho dado agregando saltos de línea conforme a las reglas de sintaxis de F#. 
         
       
+      
+        Transparent Compiler (experimental)
+        Transparent Compiler (experimental)
+        
+      
       
         Remove unused open statements
         Quitar instrucciones open no usadas
@@ -227,6 +232,11 @@
         Sugerir nombres para los identificadores no resueltos
         
       
+      
+        Use Transparent Compiler (restart required)
+        Use Transparent Compiler (restart required)
+        
+      
       
         Cache parsing results (experimental)
         Resultados del análisis de la caché (experimental)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf
index 30ee652da68..4aa94e96d46 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf
@@ -147,6 +147,11 @@
         Formatez la signature à la largeur donnée en ajoutant des sauts de ligne conformes aux règles de syntaxe F#. 
         
       
+      
+        Transparent Compiler (experimental)
+        Transparent Compiler (experimental)
+        
+      
       
         Remove unused open statements
         Supprimer les instructions open inutilisées
@@ -227,6 +232,11 @@
         Suggérer des noms pour les identificateurs non résolus
         
       
+      
+        Use Transparent Compiler (restart required)
+        Use Transparent Compiler (restart required)
+        
+      
       
         Cache parsing results (experimental)
         Résultats de l'analyse du cache (expérimental)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf
index 6b4009249b8..c146e523ef4 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf
@@ -147,6 +147,11 @@
         Consente di formattare la firma in base alla larghezza specificata aggiungendo interruzioni di riga conformi alle regole di sintassi F#. 
         
       
+      
+        Transparent Compiler (experimental)
+        Transparent Compiler (experimental)
+        
+      
       
         Remove unused open statements
         Rimuovi istruzioni OPEN inutilizzate
@@ -227,6 +232,11 @@
         Suggerisci nomi per gli identificatori non risolti
         
       
+      
+        Use Transparent Compiler (restart required)
+        Use Transparent Compiler (restart required)
+        
+      
       
         Cache parsing results (experimental)
         Risultati dell'analisi della cache (sperimentale)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf
index 074852e1f72..1367bd628ff 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf
@@ -147,6 +147,11 @@
         F# 構文規則に準拠した改行を追加して、署名を指定された幅に書式設定します。
         
       
+      
+        Transparent Compiler (experimental)
+        Transparent Compiler (experimental)
+        
+      
       
         Remove unused open statements
         未使用の Open ステートメントを削除する
@@ -227,6 +232,11 @@
         未解決の識別子の名前を提案します
         
       
+      
+        Use Transparent Compiler (restart required)
+        Use Transparent Compiler (restart required)
+        
+      
       
         Cache parsing results (experimental)
         キャッシュ解析の結果 (試験段階)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf
index 369dc3d81cc..ce8eeb81b88 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf
@@ -147,6 +147,11 @@
         F# 구문 규칙에 맞는 줄 바꿈을 추가하여 지정된 너비에 시그니처의 서식을 지정합니다. 
         
       
+      
+        Transparent Compiler (experimental)
+        Transparent Compiler (experimental)
+        
+      
       
         Remove unused open statements
         사용되지 않는 open 문 제거
@@ -227,6 +232,11 @@
         확인되지 않은 식별자의 이름 제안
         
       
+      
+        Use Transparent Compiler (restart required)
+        Use Transparent Compiler (restart required)
+        
+      
       
         Cache parsing results (experimental)
         캐시 구문 분석 결과(실험적)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf
index 8f85bfb4f67..947a7bfff5f 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf
@@ -147,6 +147,11 @@
         Sformatuj sygnaturę na daną szerokość, dodając podziały wierszy zgodne z regułami składni języka F#. 
         
       
+      
+        Transparent Compiler (experimental)
+        Transparent Compiler (experimental)
+        
+      
       
         Remove unused open statements
         Usuń nieużywane otwarte instrukcje
@@ -227,6 +232,11 @@
         Sugeruj nazwy w przypadku nierozpoznanych identyfikatorów
         
       
+      
+        Use Transparent Compiler (restart required)
+        Use Transparent Compiler (restart required)
+        
+      
       
         Cache parsing results (experimental)
         Wyniki analizy pamięci podręcznej (eksperymentalne)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf
index 257b0f3f57a..9064b2678ff 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf
@@ -147,6 +147,11 @@
         Formate a assinatura para a largura fornecida adicionando quebras de linha em conformidade com as regras de sintaxe F#. 
         
       
+      
+        Transparent Compiler (experimental)
+        Transparent Compiler (experimental)
+        
+      
       
         Remove unused open statements
         Remover instruções abertas não usadas
@@ -227,6 +232,11 @@
         Sugerir nomes para identificadores não resolvidos
         
       
+      
+        Use Transparent Compiler (restart required)
+        Use Transparent Compiler (restart required)
+        
+      
       
         Cache parsing results (experimental)
         Resultados da análise de cache (experimental)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf
index ed978ec293a..0c1210c1d2b 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf
@@ -147,6 +147,11 @@
         Форматирование подписи до заданной ширины путем добавления разрывов строк, соответствующих правилам синтаксиса F#. 
         
       
+      
+        Transparent Compiler (experimental)
+        Transparent Compiler (experimental)
+        
+      
       
         Remove unused open statements
         Удалить неиспользуемые открытые операторы
@@ -227,6 +232,11 @@
         Предлагать имена для неразрешенных идентификаторов
         
       
+      
+        Use Transparent Compiler (restart required)
+        Use Transparent Compiler (restart required)
+        
+      
       
         Cache parsing results (experimental)
         Результаты анализа кэша (экспериментальная функция)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf
index 181076a632d..aea8a281677 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf
@@ -147,6 +147,11 @@
         F# söz dizimi kurallarına uyan satır sonları ekleyerek imzayı belirtilen genişliğe biçimlendirin. 
         
       
+      
+        Transparent Compiler (experimental)
+        Transparent Compiler (experimental)
+        
+      
       
         Remove unused open statements
         Kullanılmayan açık deyimleri kaldır
@@ -227,6 +232,11 @@
         Çözümlenmemiş tanımlayıcılar için ad öner
         
       
+      
+        Use Transparent Compiler (restart required)
+        Use Transparent Compiler (restart required)
+        
+      
       
         Cache parsing results (experimental)
         Ayrıştırma sonuçlarını önbelleğe al (deneysel)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf
index 4fc3ff63c93..6012f77e8b7 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf
@@ -147,6 +147,11 @@
         通过添加符合 F# 语法规则的换行符,将签名设置为给定宽度的格式。
         
       
+      
+        Transparent Compiler (experimental)
+        Transparent Compiler (experimental)
+        
+      
       
         Remove unused open statements
         删除未使用的 open 语句
@@ -227,6 +232,11 @@
         为未解析标识符建议名称
         
       
+      
+        Use Transparent Compiler (restart required)
+        Use Transparent Compiler (restart required)
+        
+      
       
         Cache parsing results (experimental)
         缓存分析结果(实验性)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf
index 1b0248ea005..a62f9671cd9 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf
@@ -147,6 +147,11 @@
         透過新增符合 F# 語法規則的分行符號,將簽章格式設定為指定寬度。 
         
       
+      
+        Transparent Compiler (experimental)
+        Transparent Compiler (experimental)
+        
+      
       
         Remove unused open statements
         移除未使用的 open 陳述式
@@ -227,6 +232,11 @@
         為未解析的識別碼建議名稱
         
       
+      
+        Use Transparent Compiler (restart required)
+        Use Transparent Compiler (restart required)
+        
+      
       
         Cache parsing results (experimental)
         快取剖析結果 (實驗性)
From c3fd50cf674f42419c3b14de7e151e5e7c07d36a Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Tue, 2 May 2023 12:11:45 +0200
Subject: [PATCH 011/222] wip
---
 src/Compiler/Service/FSharpCheckerResults.fs  | 35 +++++++++
 src/Compiler/Service/FSharpCheckerResults.fsi |  2 +
 src/Compiler/Service/service.fs               |  2 +
 src/Compiler/Service/service.fsi              |  3 +
 .../FSharp.Compiler.ComponentTests.fsproj     | 13 ++--
 .../ProjectGeneration.fs                      | 36 +++++++++-
 .../LanguageService/WorkspaceExtensions.fs    | 71 ++++++++-----------
 7 files changed, 111 insertions(+), 51 deletions(-)
diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs
index 5b2dbb3cd54..5e419ab9431 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fs
+++ b/src/Compiler/Service/FSharpCheckerResults.fs
@@ -366,6 +366,41 @@ type FSharpProjectSnapshot with
             Stamp = this.Stamp
         }
 
+    static member FromOptions(options: FSharpProjectOptions, getFileSnapshot) =
+        async {
+            let! sourceFiles =
+                options.SourceFiles
+                |> Seq.map (getFileSnapshot options)
+                |> Async.Parallel
+
+            let! referencedProjects =
+                options.ReferencedProjects
+                |> Seq.choose (function
+                    | FSharpReferencedProject.FSharpReference (outputName, options) -> Some (
+                        async {
+                            let! snapshot = FSharpProjectSnapshot.FromOptions(options, getFileSnapshot)
+                            return FSharpReferencedProjectSnapshot.FSharpReference (outputName, snapshot)
+                        })
+                    // TODO: other types
+                    | _ -> None)
+                |> Async.Parallel
+
+            return
+                {
+                    ProjectFileName = options.ProjectFileName
+                    ProjectId = options.ProjectId
+                    SourceFiles = sourceFiles |> List.ofArray
+                    OtherOptions = options.OtherOptions |> List.ofArray
+                    ReferencedProjects = referencedProjects |> List.ofArray
+                    IsIncompleteTypeCheckEnvironment = options.IsIncompleteTypeCheckEnvironment
+                    UseScriptResolutionRules = options.UseScriptResolutionRules
+                    LoadTime = options.LoadTime
+                    UnresolvedReferences = options.UnresolvedReferences
+                    OriginalLoadReferences = options.OriginalLoadReferences
+                    Stamp = options.Stamp
+                }
+        }
+
 []
 module internal FSharpCheckerResultsSettings =
 
diff --git a/src/Compiler/Service/FSharpCheckerResults.fsi b/src/Compiler/Service/FSharpCheckerResults.fsi
index 20ecde853ea..e07f31afe90 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fsi
+++ b/src/Compiler/Service/FSharpCheckerResults.fsi
@@ -248,6 +248,8 @@ type FSharpProjectSnapshot with
 
     member ToOptions: unit -> FSharpProjectOptions
 
+    static member FromOptions: options: FSharpProjectOptions * getFileSnapshot: (FSharpProjectOptions -> string -> Async) -> Async
+
 /// Represents the use of an F# symbol from F# source code
 []
 type public FSharpSymbolUse =
diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs
index 69b6f7186dc..83a005c258e 100644
--- a/src/Compiler/Service/service.fs
+++ b/src/Compiler/Service/service.fs
@@ -269,6 +269,8 @@ type FSharpChecker
             useTransparentCompiler
         )
 
+    member _.UsesTransparentCompiler = useTransparentCompiler = Some true
+
     member _.ReferenceResolver = legacyReferenceResolver
 
     member _.MatchBraces(fileName, sourceText: ISourceText, options: FSharpParsingOptions, ?userOpName: string) =
diff --git a/src/Compiler/Service/service.fsi b/src/Compiler/Service/service.fsi
index 45522fa3126..97bde85058f 100644
--- a/src/Compiler/Service/service.fsi
+++ b/src/Compiler/Service/service.fsi
@@ -60,6 +60,9 @@ type public FSharpChecker =
         [] ?useTransparentCompiler: bool ->
             FSharpChecker
 
+    []
+    member UsesTransparentCompiler: bool
+
     /// 
     ///   Parse a source code file, returning information about brace matching in the file.
     ///   Return an enumeration of the matching parenthetical tokens in the file.
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
index bc4a072aee6..b47712251d2 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
+++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
@@ -222,12 +222,9 @@
     
     
     
-	
-	  
-	  
-    
-      %(RelativeDir)TestSource\%(Filename)%(Extension)
-    
+    
+    
+    
     
     
     
@@ -249,8 +246,12 @@
     
     
     
+    
     
     
+    
+	    %(RelativeDir)TestSource\%(Filename)%(Extension)
+    
   
 
   
diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
index c43e0c88446..a395002d2b0 100644
--- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs
+++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
@@ -17,6 +17,7 @@ module FSharp.Test.ProjectGeneration
 
 open System
 open System.IO
+open System.Threading.Tasks
 open FSharp.Compiler.CodeAnalysis
 open FSharp.Compiler.Diagnostics
 open FSharp.Compiler.Text
@@ -328,7 +329,7 @@ module ProjectOperations =
     let addSignatureFile f =
         { f with SignatureFile = AutoGenerated }
 
-    let checkFile fileId (project: SyntheticProject) (checker: FSharpChecker) =
+    let checkFileWithIncrementalBuilder fileId (project: SyntheticProject) (checker: FSharpChecker) =
         let file = project.Find fileId
         let contents = renderSourceFile project file
         let absFileName = getFilePath project file
@@ -340,6 +341,33 @@ module ProjectOperations =
             project.GetProjectOptions checker
         )
 
+    let getFileSnapshot (project: SyntheticProject) _options path =
+        async {
+            let file = project.FindByPath path
+            let version = $"{file.PublicVersion}.{file.InternalVersion}.{file.Source.GetHashCode()}.{file.ExtraSource.GetHashCode()}"
+
+            return {
+                FileName = file.FileName
+                Version = version
+                GetSource = fun () -> renderSourceFile project file |> SourceText.ofString |> Task.FromResult
+            }
+        }
+
+    let checkFileWithTransparentCompiler fileId (project: SyntheticProject) (checker: FSharpChecker) =
+        async {
+            let file = project.Find fileId
+            let absFileName = getFilePath project file
+            let options = project.GetProjectOptions checker
+            let! projectSnapshot = FSharpProjectSnapshot.FromOptions(options, getFileSnapshot project)
+            return! checker.ParseAndCheckFileInProject(absFileName, projectSnapshot)
+        }
+
+    let checkFile fileId (project: SyntheticProject) (checker: FSharpChecker) =
+        (if checker.UsesTransparentCompiler then
+            checkFileWithTransparentCompiler
+        else
+            checkFileWithIncrementalBuilder) fileId project checker
+
     let getTypeCheckResult (parseResults: FSharpParseFileResults, checkResults: FSharpCheckFileAnswer) =
         Assert.True(not parseResults.ParseHadErrors)
 
@@ -545,11 +573,13 @@ type ProjectWorkflowBuilder
         ?checker: FSharpChecker,
         ?useGetSource,
         ?useChangeNotifications,
-        ?useSyntaxTreeCache
+        ?useSyntaxTreeCache,
+        ?useTransparentCompiler
     ) =
 
     let useGetSource = defaultArg useGetSource false
     let useChangeNotifications = defaultArg useChangeNotifications false
+    let useTransparentCompiler = defaultArg useTransparentCompiler false
 
     let mutable latestProject = initialProject
 
@@ -579,7 +609,7 @@ type ProjectWorkflowBuilder
                 captureIdentifiersWhenParsing = true,
                 documentSource = (if useGetSource then DocumentSource.Custom getSource else DocumentSource.FileSystem),
                 useSyntaxTreeCache = defaultArg useSyntaxTreeCache false,
-                useTransparentCompiler = true
+                useTransparentCompiler = useTransparentCompiler
             ))
 
     let mapProjectAsync f workflow =
diff --git a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs
index d7053340933..4e9f681dc96 100644
--- a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs
+++ b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs
@@ -31,51 +31,38 @@ module private CheckerExtensions =
                 userOpName: string
             ) =
             async {
-                let fileName = document.FilePath
+
                 let project = document.Project
-                let documents = project.Documents |> Seq.map (fun d -> d.FilePath, d) |> Map
-
-                let! sourceFiles =
-                    options.SourceFiles
-                    |> Seq.map (fun path ->
-                        async {
-                            let document = documents[path]
-                            let! version = document.GetTextVersionAsync() |> Async.AwaitTask
-
-                            let getSource () =
-                                task {
-                                    let! sourceText = document.GetTextAsync()
-                                    return sourceText.ToFSharpSourceText()
-                                }
-
-                            return
-                                {
-                                    FileName = path
-                                    Version = version.ToString()
-                                    GetSource = getSource
-                                }
-                        })
-                    |> Async.Parallel
-
-                // TODO: referenced projects
-                let referencedProjects = []
-
-                let projectSnapshot: FSharpProjectSnapshot =
-                    {
-                        ProjectFileName = options.ProjectFileName
-                        ProjectId = options.ProjectId
-                        SourceFiles = sourceFiles |> List.ofArray
-                        OtherOptions = options.OtherOptions |> List.ofArray
-                        ReferencedProjects = referencedProjects
-                        IsIncompleteTypeCheckEnvironment = options.IsIncompleteTypeCheckEnvironment
-                        UseScriptResolutionRules = options.UseScriptResolutionRules
-                        LoadTime = options.LoadTime
-                        UnresolvedReferences = options.UnresolvedReferences
-                        OriginalLoadReferences = options.OriginalLoadReferences
-                        Stamp = options.Stamp
+                let solution = project.Solution
+                // TODO cache?
+                let projects =
+                    solution.Projects
+                    |> Seq.map (fun p -> p.FilePath, p.Documents |> Seq.map (fun d -> d.FilePath, d) |> Map)
+                    |> Map
+
+                let getFileSnapshot (options: FSharpProjectOptions) path =
+                    async {
+                        let project = projects[options.ProjectFileName]
+                        let document = project[path]
+                        let! version = document.GetTextVersionAsync() |> Async.AwaitTask
+
+                        let getSource () =
+                            task {
+                                let! sourceText = document.GetTextAsync()
+                                return sourceText.ToFSharpSourceText()
+                            }
+
+                        return
+                            {
+                                FileName = path
+                                Version = version.ToString()
+                                GetSource = getSource
+                            }
                     }
 
-                let! (parseResults, checkFileAnswer) = checker.ParseAndCheckFileInProject(fileName, projectSnapshot, userOpName)
+                let! projectSnapshot = FSharpProjectSnapshot.FromOptions(options, getFileSnapshot)
+
+                let! (parseResults, checkFileAnswer) = checker.ParseAndCheckFileInProject(document.FilePath, projectSnapshot, userOpName)
 
                 return
                     match checkFileAnswer with
From 831ed47840851823248ac49244fbe5338fb17a4c Mon Sep 17 00:00:00 2001
From: Petr Pokorny 
Date: Tue, 2 May 2023 18:15:15 +0200
Subject: [PATCH 012/222] wip
---
 src/Compiler/Facilities/AsyncMemoize.fs       |  9 +-
 src/Compiler/Service/TransparentCompiler.fs   | 19 ++--
 .../CompilerService/AsyncMemoize.fs           |  7 +-
 .../FSharpChecker/CommonWorkflows.fs          |  1 -
 .../FSharpChecker/TransparentCompiler.fs      | 91 +++++++++++++++++++
 .../ProjectGeneration.fs                      | 24 +++--
 6 files changed, 126 insertions(+), 25 deletions(-)
 create mode 100644 tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
diff --git a/src/Compiler/Facilities/AsyncMemoize.fs b/src/Compiler/Facilities/AsyncMemoize.fs
index 960d2d0eeda..220c27c8e96 100644
--- a/src/Compiler/Facilities/AsyncMemoize.fs
+++ b/src/Compiler/Facilities/AsyncMemoize.fs
@@ -3,6 +3,7 @@ namespace Internal.Utilities.Collections
 open FSharp.Compiler.BuildGraph
 open System.Threading
 open System.Collections.Generic
+open FSharp.Compiler.Diagnostics
 
 type internal Action<'TKey, 'TValue> =
     | GetOrCompute of ('TKey -> NodeCode<'TValue>) * CancellationToken
@@ -26,10 +27,12 @@ type internal JobEvent<'TKey> =
         | Finished key -> key
         | Canceled key -> key
 
-type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?eventLog: ResizeArray>) =
+type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?logEvent: (JobEvent<'TKey> -> unit), ?name: string) =
 
     let tok = obj ()
 
+    let name = name |> Option.defaultValue "Unnamed"
+
     let cache =
         MruCache<_, 'TKey, Job<'TValue>>(keepStrongly = 10, areSame = (fun (x, y) -> x = y))
 
@@ -46,7 +49,7 @@ type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?eventLog: Resiz
         inbox.PostAndAsyncReply(fun rc -> key, msg, rc) |> Async.Ignore |> Async.Start
 
     let log event =
-        eventLog |> Option.iter (fun log -> log.Add event)
+        logEvent |> Option.iter ((|>) event)
 
     let agent =
         MailboxProcessor.Start(fun (inbox: MailboxProcessor>) ->
@@ -74,6 +77,8 @@ type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?eventLog: Resiz
                             Async.StartAsTask(
                                 Async.AwaitNodeCode(
                                     node {
+                                        use _ = Activity.start $"AsyncMemoize.{name}" [| |]
+
                                         let! result = computation key
                                         post key JobCompleted
                                         return result
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 81a2406d811..2ee026bc7aa 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -73,13 +73,13 @@ type internal TransparentCompiler
     // Is having just one of these ok?
     let lexResourceManager = Lexhelp.LexResourceManager()
 
-    let ParseFileCache = AsyncMemoize()
-    let ParseAndCheckFileInProjectCache = AsyncMemoize()
-    let FrameworkImportsCache = AsyncMemoize()
-    let BootstrapInfoCache = AsyncMemoize()
-    let TcPriorCache = AsyncMemoize()
-    let TcIntermediateCache = AsyncMemoize()
-    let DependencyGraphForLastFileCache = AsyncMemoize()
+    let ParseFileCache = AsyncMemoize(name = "ParseFile")
+    let ParseAndCheckFileInProjectCache = AsyncMemoize(name = "ParseAndCheckFileInProject")
+    let FrameworkImportsCache = AsyncMemoize(name = "FrameworkImports")
+    let BootstrapInfoCache = AsyncMemoize(name = "BootstrapInfo")
+    let TcPriorCache = AsyncMemoize(name = "TcPrior")
+    let TcIntermediateCache = AsyncMemoize(name = "TcIntermediate")
+    let DependencyGraphForLastFileCache = AsyncMemoize(name = "DependencyGraphForLastFile")
 
     // We currently share one global dependency provider for all scripts for the FSharpChecker.
     // For projects, one is used per project.
@@ -699,6 +699,7 @@ type internal TransparentCompiler
 
     let mergeTcInfos =
         Array.fold (fun a b ->
+            // TODO: proper merge
             { a with
                 tcState = b.tcState
                 tcEnvAtEndOfFile = b.tcEnvAtEndOfFile
@@ -768,7 +769,7 @@ type internal TransparentCompiler
     let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: FSharpProjectSnapshot) userOpName _key =
         node {
 
-            let! bootstrapInfoOpt, creationDiags = BootstrapInfoCache.Get(projectSnapshot.Key, ComputeBootstrapInfo projectSnapshot) // probably cache
+            let! bootstrapInfoOpt, creationDiags = BootstrapInfoCache.Get(projectSnapshot.Key, ComputeBootstrapInfo projectSnapshot)
 
             match bootstrapInfoOpt with
             | None ->
@@ -779,7 +780,7 @@ type internal TransparentCompiler
             | Some bootstrapInfo ->
 
                 let file =
-                    bootstrapInfo.SourceFiles |> List.find (fun f -> f.Source.FileName = fileName)
+                    bootstrapInfo.SourceFiles |> List.tryFind (fun f -> f.Source.FileName = fileName) |> Option.defaultWith (fun _ -> failwith ($"File {fileName} not found in project snapshot. Files in project: \n\n" + (bootstrapInfo.SourceFiles |> Seq.map (fun f -> f.Source.FileName) |> String.concat " \n")))
 
                 let priorSnapshot = projectSnapshot.UpTo fileName
                 let! tcInfo = TcPriorCache.Get(priorSnapshot.Key, ComputeTcPrior file bootstrapInfo priorSnapshot userOpName)
diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
index 78123ef4efd..4d18dbbbbac 100644
--- a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
+++ b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
@@ -18,7 +18,7 @@ let ``Basics``() =
 
     let eventLog = ResizeArray()
 
-    let memoize = AsyncMemoize(eventLog)
+    let memoize = AsyncMemoize(eventLog.Add)
 
     let task =
         NodeCode.Parallel(seq {
@@ -50,7 +50,7 @@ let ``We can cancel a job`` () =
     }
 
     let eventLog = ResizeArray()
-    let memoize = AsyncMemoize(eventLog)
+    let memoize = AsyncMemoize(eventLog.Add)
 
     use cts1 = new CancellationTokenSource()
     use cts2 = new CancellationTokenSource()
@@ -91,7 +91,7 @@ let ``Job keeps running even if first requestor cancels`` () =
     }
 
     let eventLog = ResizeArray()
-    let memoize = AsyncMemoize(eventLog)
+    let memoize = AsyncMemoize(eventLog.Add)
 
     use cts1 = new CancellationTokenSource()
     use cts2 = new CancellationTokenSource()
@@ -111,5 +111,6 @@ let ``Job keeps running even if first requestor cancels`` () =
     let result = _task2.Result
     Assert.Equal(2, result)
 
+    Thread.Sleep 1 // Wait for event log to be updated
     Assert.Equal array>([| Started key; Finished key |], eventLog |> Seq.toArray )
 
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/CommonWorkflows.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/CommonWorkflows.fs
index 7aa8dfc25a3..21864e64ed4 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/CommonWorkflows.fs
+++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/CommonWorkflows.fs
@@ -132,4 +132,3 @@ let ``Using getSource and notifications instead of filesystem`` () =
         checkFile middle expectSignatureChanged
         checkFile last expectSignatureChanged
     }
-
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
new file mode 100644
index 00000000000..4c93a1b4d0c
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
@@ -0,0 +1,91 @@
+module FSharp.Compiler.ComponentTests.FSharpChecker.TransparentCompiler
+
+open System
+open System.IO
+open System.Diagnostics
+
+open Xunit
+
+open FSharp.Test.ProjectGeneration
+open FSharp.Compiler.Text
+open FSharp.Compiler.CodeAnalysis
+
+module Activity =
+    let listen (filter: string) =
+        let indent (activity: Activity) =
+            let rec loop (activity: Activity) n =
+                if activity.Parent <> null then
+                    loop (activity.Parent) (n + 1)
+                else
+                    n
+
+            String.replicate (loop activity 0) "    "
+
+        let collectTags (activity: Activity) =
+            [ for tag in activity.Tags -> $"{tag.Key}: %A{tag.Value}" ]
+            |> String.concat ", "
+
+        let listener =
+            new ActivityListener(
+                ShouldListenTo = (fun source -> source.Name = FSharp.Compiler.Diagnostics.ActivityNames.FscSourceName),
+                Sample =
+                    (fun context ->
+                        if context.Name.Contains(filter) then
+                            ActivitySamplingResult.AllDataAndRecorded
+                        else
+                            ActivitySamplingResult.None),
+                ActivityStarted = (fun a -> Trace.TraceInformation $"{indent a}{a.OperationName}     {collectTags a}")
+            )
+
+        ActivitySource.AddActivityListener(listener)
+
+    let listenToAll () = listen ""
+
+
+[]
+let ``Use Transparent Compiler`` () =
+
+    let _logger = Activity.listenToAll ()
+
+    let size = 20
+
+    let project =
+        { SyntheticProject.Create() with
+            SourceFiles = [
+                sourceFile $"File%03d{0}" []
+                for i in 1..size do
+                    sourceFile $"File%03d{i}" [$"File%03d{i-1}"]
+            ]
+        }
+
+    let first = "File001"
+    let middle = $"File%03d{size / 2}"
+    let last = $"File%03d{size}"
+
+    ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
+        updateFile first updatePublicSurface
+        checkFile first expectSignatureChanged
+        checkFile last expectSignatureChanged
+        updateFile middle updatePublicSurface
+        checkFile last expectSignatureChanged
+        addFileAbove middle (sourceFile "addedFile" [first])
+        updateFile middle (addDependency "addedFile")
+        checkFile middle expectSignatureChanged
+        checkFile last expectSignatureChanged
+    }
+
+[]
+let ``Parallel processing`` () =
+
+    let _logger = Activity.listenToAll ()
+
+    let project = SyntheticProject.Create(
+        sourceFile "A" [],
+        sourceFile "B" ["A"],
+        sourceFile "C" ["A"],
+        sourceFile "D" ["A"],
+        sourceFile "E" ["B"; "C"; "D"])
+
+    ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
+        checkFile "E" expectOk
+    }
diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
index a395002d2b0..73082a5df5f 100644
--- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs
+++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
@@ -344,10 +344,11 @@ module ProjectOperations =
     let getFileSnapshot (project: SyntheticProject) _options path =
         async {
             let file = project.FindByPath path
-            let version = $"{file.PublicVersion}.{file.InternalVersion}.{file.Source.GetHashCode()}.{file.ExtraSource.GetHashCode()}"
+            let dependencies = file.DependsOn |> String.concat "|"
+            let version = $"{file.PublicVersion}.{file.InternalVersion}.{file.Source.GetHashCode()}.{file.ExtraSource.GetHashCode()}.{dependencies}"
 
             return {
-                FileName = file.FileName
+                FileName = getFilePath project file
                 Version = version
                 GetSource = fun () -> renderSourceFile project file |> SourceText.ofString |> Task.FromResult
             }
@@ -551,14 +552,17 @@ let SaveAndCheckProject project checker =
         if not (Array.isEmpty results.Diagnostics) then
             failwith $"Project {project.Name} failed initial check: \n%A{results.Diagnostics}"
 
-        let! signatures =
-            Async.Sequential
-                [ for file in project.SourceFiles do
-                      async {
-                          let! result = checkFile file.Id project checker
-                          let signature = getSignature result
-                          return file.Id, signature
-                      } ]
+        // TODO: re-enable
+        //let! signatures =
+        //    Async.Sequential
+        //        [ for file in project.SourceFiles do
+        //              async {
+        //                  let! result = checkFile file.Id project checker
+        //                  let signature = getSignature result
+        //                  return file.Id, signature
+        //              } ]
+
+        let signatures = [ for file in project.SourceFiles -> file.Id, "" ]
 
         return
             { Project = project
From 88593d0949316875708997b4ebe8c98a17f74acc Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Wed, 3 May 2023 13:23:42 +0200
Subject: [PATCH 013/222] wip
---
 src/Compiler/Service/IncrementalBuild.fs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Compiler/Service/IncrementalBuild.fs b/src/Compiler/Service/IncrementalBuild.fs
index 8d48ec4503b..dc27983338e 100644
--- a/src/Compiler/Service/IncrementalBuild.fs
+++ b/src/Compiler/Service/IncrementalBuild.fs
@@ -262,7 +262,7 @@ type BoundModel private (
             use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.TypeCheck)
 
             beforeFileChecked.Trigger fileName
-
+                    
             ApplyMetaCommandsFromInputToTcConfig (tcConfig, input, Path.GetDirectoryName fileName, tcImports.DependencyProvider) |> ignore
             let sink = TcResultsSinkImpl(tcGlobals)
             let hadParseErrors = not (Array.isEmpty parseErrors)
@@ -328,7 +328,7 @@ type BoundModel private (
 
     let getTcInfoExtras (typeCheck: GraphNode) =
         node {
-            let! _x , sink, implFile, fileName = typeCheck.GetOrComputeValue()
+            let! _ , sink, implFile, fileName = typeCheck.GetOrComputeValue()
             // Build symbol keys
             let itemKeyStore, semanticClassification =
                 if enableBackgroundItemKeyStoreAndSemanticClassification then
From 0dcc16393f0056ea37679fd68c34447019670640 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Wed, 3 May 2023 17:56:35 +0200
Subject: [PATCH 014/222] wip
---
 src/Compiler/Service/TransparentCompiler.fs | 29 +--------------------
 1 file changed, 1 insertion(+), 28 deletions(-)
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 2ee026bc7aa..de41d47b82b 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -557,34 +557,6 @@ type internal TransparentCompiler
             return bootstrapInfoOpt, diagnostics
         }
 
-    let ComputeParseFile' (file: FSharpFile) (projectSnapshot: FSharpProjectSnapshot) bootstrapInfo userOpName _key =
-        node {
-
-            let parsingOptions =
-                FSharpParsingOptions.FromTcConfig(
-                    bootstrapInfo.TcConfig,
-                    projectSnapshot.SourceFiles |> Seq.map (fun f -> f.FileName) |> Array.ofSeq,
-                    projectSnapshot.UseScriptResolutionRules
-                )
-
-            // TODO: what is this?
-            // GraphNode.SetPreferredUILang tcPrior.TcConfig.preferredUiLang
-
-            let! sourceText = file.Source.GetSource() |> NodeCode.AwaitTask
-
-            let diagnostics, parsedInput, anyErrors =
-                ParseAndCheckFile.parseFile (
-                    sourceText,
-                    file.Source.FileName,
-                    parsingOptions,
-                    userOpName,
-                    suggestNamesForErrors,
-                    captureIdentifiersWhenParsing
-                )
-
-            return diagnostics, parsedInput, anyErrors, sourceText
-        }
-
     let ComputeParseFile (file: FSharpFile) bootstrapInfo _key =
         node {
             let tcConfig = bootstrapInfo.TcConfig
@@ -621,6 +593,7 @@ type internal TransparentCompiler
             // TODO: we will probably want to cache and re-use larger graphs if available
             let graph =
                 DependencyResolution.mkGraph tcConfig.compilingFSharpCore filePairs sourceFiles
+                |> fst
                 |> Graph.subGraphFor (sourceFiles |> Array.last).Idx
 
             return graph, filePairs
From 68c1c03b4e988bff9030097ff3c13f541246230e Mon Sep 17 00:00:00 2001
From: Petr Pokorny 
Date: Thu, 4 May 2023 16:22:43 +0200
Subject: [PATCH 015/222] wip
---
 src/Compiler/Driver/ParseAndCheckInputs.fsi   | 13 +++++++
 src/Compiler/Service/TransparentCompiler.fs   | 37 ++++++++++++++-----
 .../TypeChecks/Graph/GraphOperations.fs       |  1 +
 3 files changed, 42 insertions(+), 9 deletions(-)
diff --git a/src/Compiler/Driver/ParseAndCheckInputs.fsi b/src/Compiler/Driver/ParseAndCheckInputs.fsi
index 745afa51be4..307236f8014 100644
--- a/src/Compiler/Driver/ParseAndCheckInputs.fsi
+++ b/src/Compiler/Driver/ParseAndCheckInputs.fsi
@@ -13,6 +13,7 @@ open FSharp.Compiler.CompilerImports
 open FSharp.Compiler.Diagnostics
 open FSharp.Compiler.DependencyManager
 open FSharp.Compiler.DiagnosticsLogger
+open FSharp.Compiler.NameResolution
 open FSharp.Compiler.Syntax
 open FSharp.Compiler.TcGlobals
 open FSharp.Compiler.Text
@@ -151,6 +152,18 @@ val CheckOneInput:
     input: ParsedInput ->
         Cancellable<(TcEnv * TopAttribs * CheckedImplFile option * ModuleOrNamespaceType) * TcState>
 
+val AddCheckResultsToTcState:
+    tcGlobals: TcGlobals *
+    amap: Import.ImportMap *
+    hadSig: bool *
+    prefixPathOpt: LongIdent option *
+    tcSink: TcResultsSink *
+    tcImplEnv: TcEnv *
+    qualNameOfFile: QualifiedNameOfFile *
+    implFileSigType: ModuleOrNamespaceType ->
+        tcState: TcState ->
+        ModuleOrNamespaceType * TcState
+
 /// Finish the checking of multiple inputs
 val CheckMultipleInputsFinish:
     (TcEnv * TopAttribs * 'T option * 'U) list * TcState -> (TcEnv * TopAttribs * 'T list * 'U list) * TcState
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index de41d47b82b..ccd2b065f7e 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -32,6 +32,7 @@ open FSharp.Compiler.Syntax
 open FSharp.Compiler.CompilerDiagnostics
 open FSharp.Compiler.NameResolution
 open Internal.Utilities.Library.Extras
+open FSharp.Compiler.TypedTree
 
 type internal FSharpFile =
     {
@@ -52,6 +53,8 @@ type internal BootstrapInfo =
         LoadClosure: LoadClosure option
     }
 
+type internal TcIntermediateResult = TcInfo * TcResultsSinkImpl * CheckedImplFile option * string
+
 type internal TransparentCompiler
     (
         legacyReferenceResolver,
@@ -165,9 +168,9 @@ type internal TransparentCompiler
             unresolvedReferences,
             dependencyProvider,
             loadClosureOpt: LoadClosure option,
-            basicDependencies,
+            basicDependencies
 #if !NO_TYPEPROVIDERS
-            importsInvalidatedByTypeProvider: Event
+            ,importsInvalidatedByTypeProvider: Event
 #endif
         ) =
 
@@ -484,9 +487,9 @@ type internal TransparentCompiler
                     unresolvedReferences,
                     dependencyProvider,
                     loadClosureOpt,
-                    basicDependencies,
+                    basicDependencies
 #if !NO_TYPEPROVIDERS
-                    importsInvalidatedByTypeProvider
+                    ,importsInvalidatedByTypeProvider
 #endif
                 )
 
@@ -670,11 +673,27 @@ type internal TransparentCompiler
             return tcInfo, sink, implFile, fileName
         }
 
-    let mergeTcInfos =
-        Array.fold (fun a b ->
+    let mergeIntermediateResults bootstrapInfo =
+        Array.reduce (fun (a: TcInfo, _: TcResultsSinkImpl, _, _) (b, bSink, implFileOpt: CheckedImplFile option, name) ->
             // TODO: proper merge
+
+            let amap = bootstrapInfo.TcImports.GetImportMap()
+
+            // TODO: figure out
+            let hadSig = false
+
+            let prefixPathOpt = None
+
+            // TODO:
+            let implFile = implFileOpt.Value
+
+            let _ccuSigForFile, tcState =
+                AddCheckResultsToTcState
+                    (bootstrapInfo.TcGlobals, amap, hadSig, prefixPathOpt, TcResultsSink.NoSink, b.tcState.TcEnvFromImpls, implFile.QualifiedNameOfFile, implFile.Signature)
+                    a.tcState
+
             { a with
-                tcState = b.tcState
+                tcState = tcState
                 tcEnvAtEndOfFile = b.tcEnvAtEndOfFile
                 moduleNamesDict = b.moduleNamesDict
                 latestCcuSigForFile = b.latestCcuSigForFile
@@ -683,7 +702,7 @@ type internal TransparentCompiler
                 tcDependencyFiles = b.tcDependencyFiles @ a.tcDependencyFiles
                 // we shouldn't need this with graph checking (?)
                 sigNameOpt = None
-            })
+            }, bSink, Some implFile, name)
 
     // Type check everything that is needed to check given file
     let ComputeTcPrior (file: FSharpFile) (bootstrapInfo: BootstrapInfo) (projectSnapshot: FSharpProjectSnapshot) _userOpName _key =
@@ -733,7 +752,7 @@ type internal TransparentCompiler
                                 TcIntermediateCache.Get(key, ComputeTcIntermediate (parsedInput, parseErrors) bootstrapInfo tcInfo))
                             |> NodeCode.Parallel
 
-                        return! processLayer rest (mergeTcInfos tcInfo (results |> Array.map p14))
+                        return! processLayer rest (mergeIntermediateResults bootstrapInfo results |> p14)
                 }
 
             return! processLayer layers bootstrapInfo.InitialTcInfo
diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs
index 95d966441e1..f8e58f352a9 100644
--- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs
+++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs
@@ -65,6 +65,7 @@ let ``See what this does`` () =
 
                 let fullGraph =
                     DependencyResolution.mkGraph false filePairs sourceFiles
+                    |> fst
                     |> Graph.map (fun idx -> project.SourceFilePaths[idx] |> Path.GetFileName)
 
                 let subGraph = fullGraph |> Graph.subGraphFor "FileF.fs"
From 09a522fc7482b92b826dddbfe028864911699ae6 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Thu, 4 May 2023 17:49:25 +0200
Subject: [PATCH 016/222] wip
---
 src/Compiler/Service/TransparentCompiler.fs   | 14 +++++++-------
 .../FSharpChecker/TransparentCompiler.fs      |  4 ++--
 .../ProjectGeneration.fs                      | 19 ++++++++-----------
 3 files changed, 17 insertions(+), 20 deletions(-)
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index ccd2b065f7e..9775fc871e4 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -674,7 +674,7 @@ type internal TransparentCompiler
         }
 
     let mergeIntermediateResults bootstrapInfo =
-        Array.reduce (fun (a: TcInfo, _: TcResultsSinkImpl, _, _) (b, bSink, implFileOpt: CheckedImplFile option, name) ->
+        Array.fold (fun (a: TcInfo, _, _, _) (b, sink, implFileOpt: CheckedImplFile option, name) ->
             // TODO: proper merge
 
             let amap = bootstrapInfo.TcImports.GetImportMap()
@@ -687,22 +687,22 @@ type internal TransparentCompiler
             // TODO:
             let implFile = implFileOpt.Value
 
-            let _ccuSigForFile, tcState =
+            let ccuSigForFile, tcState =
                 AddCheckResultsToTcState
-                    (bootstrapInfo.TcGlobals, amap, hadSig, prefixPathOpt, TcResultsSink.NoSink, b.tcState.TcEnvFromImpls, implFile.QualifiedNameOfFile, implFile.Signature)
-                    a.tcState
+                    (bootstrapInfo.TcGlobals, amap, hadSig, prefixPathOpt, TcResultsSink.NoSink, a.tcState.TcEnvFromImpls, implFile.QualifiedNameOfFile, implFile.Signature)
+                    b.tcState
 
             { a with
                 tcState = tcState
                 tcEnvAtEndOfFile = b.tcEnvAtEndOfFile
                 moduleNamesDict = b.moduleNamesDict
-                latestCcuSigForFile = b.latestCcuSigForFile
+                latestCcuSigForFile = Some ccuSigForFile
                 tcDiagnosticsRev = b.tcDiagnosticsRev @ a.tcDiagnosticsRev
                 topAttribs = b.topAttribs
                 tcDependencyFiles = b.tcDependencyFiles @ a.tcDependencyFiles
                 // we shouldn't need this with graph checking (?)
                 sigNameOpt = None
-            }, bSink, Some implFile, name)
+            }, sink, Some implFile, name)
 
     // Type check everything that is needed to check given file
     let ComputeTcPrior (file: FSharpFile) (bootstrapInfo: BootstrapInfo) (projectSnapshot: FSharpProjectSnapshot) _userOpName _key =
@@ -752,7 +752,7 @@ type internal TransparentCompiler
                                 TcIntermediateCache.Get(key, ComputeTcIntermediate (parsedInput, parseErrors) bootstrapInfo tcInfo))
                             |> NodeCode.Parallel
 
-                        return! processLayer rest (mergeIntermediateResults bootstrapInfo results |> p14)
+                        return! processLayer rest (mergeIntermediateResults bootstrapInfo (tcInfo, Unchecked.defaultof<_>, None, "") results |> p14)
                 }
 
             return! processLayer layers bootstrapInfo.InitialTcInfo
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
index 4c93a1b4d0c..d619d9e45c1 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
+++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
@@ -45,7 +45,7 @@ module Activity =
 []
 let ``Use Transparent Compiler`` () =
 
-    let _logger = Activity.listenToAll ()
+    Activity.listenToAll ()
 
     let size = 20
 
@@ -77,7 +77,7 @@ let ``Use Transparent Compiler`` () =
 []
 let ``Parallel processing`` () =
 
-    let _logger = Activity.listenToAll ()
+    Activity.listenToAll ()
 
     let project = SyntheticProject.Create(
         sourceFile "A" [],
diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
index 73082a5df5f..16d42718f1e 100644
--- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs
+++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
@@ -552,17 +552,14 @@ let SaveAndCheckProject project checker =
         if not (Array.isEmpty results.Diagnostics) then
             failwith $"Project {project.Name} failed initial check: \n%A{results.Diagnostics}"
 
-        // TODO: re-enable
-        //let! signatures =
-        //    Async.Sequential
-        //        [ for file in project.SourceFiles do
-        //              async {
-        //                  let! result = checkFile file.Id project checker
-        //                  let signature = getSignature result
-        //                  return file.Id, signature
-        //              } ]
-
-        let signatures = [ for file in project.SourceFiles -> file.Id, "" ]
+        let! signatures =
+            Async.Sequential
+                [ for file in project.SourceFiles do
+                      async {
+                          let! result = checkFile file.Id project checker
+                          let signature = getSignature result
+                          return file.Id, signature
+                      } ]
 
         return
             { Project = project
From dd518d825e12006fd01856528940646073a29e7f Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Thu, 4 May 2023 17:53:14 +0200
Subject: [PATCH 017/222] fantomas
---
 .fantomasignore                               |  1 +
 src/Compiler/Driver/ParseAndCheckInputs.fsi   |  2 +-
 src/Compiler/Facilities/AsyncMemoize.fs       |  5 ++---
 src/Compiler/Service/FSharpCheckerResults.fs  | 17 ++++++++---------
 src/Compiler/Service/FSharpCheckerResults.fsi |  4 +++-
 5 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/.fantomasignore b/.fantomasignore
index d2f57d7fc7f..f9924a137aa 100644
--- a/.fantomasignore
+++ b/.fantomasignore
@@ -91,6 +91,7 @@ src/FSharp.Core/seqcore.fs
 src/Compiler/AbstractIL/ilwrite.fs
 src/Compiler/Utilities/lib.fs
 src/Compiler/Service/IncrementalBuild.fs
+src/Compiler/Service/TransparentCompiler.fs
 src/Compiler/Service/ServiceAssemblyContent.fs
 src/Compiler/Service/ServiceDeclarationLists.fs
 src/Compiler/Service/ServiceErrorResolutionHints.fs
diff --git a/src/Compiler/Driver/ParseAndCheckInputs.fsi b/src/Compiler/Driver/ParseAndCheckInputs.fsi
index 307236f8014..9d2bb5b9e41 100644
--- a/src/Compiler/Driver/ParseAndCheckInputs.fsi
+++ b/src/Compiler/Driver/ParseAndCheckInputs.fsi
@@ -162,7 +162,7 @@ val AddCheckResultsToTcState:
     qualNameOfFile: QualifiedNameOfFile *
     implFileSigType: ModuleOrNamespaceType ->
         tcState: TcState ->
-        ModuleOrNamespaceType * TcState
+            ModuleOrNamespaceType * TcState
 
 /// Finish the checking of multiple inputs
 val CheckMultipleInputsFinish:
diff --git a/src/Compiler/Facilities/AsyncMemoize.fs b/src/Compiler/Facilities/AsyncMemoize.fs
index 220c27c8e96..8cb38c9540d 100644
--- a/src/Compiler/Facilities/AsyncMemoize.fs
+++ b/src/Compiler/Facilities/AsyncMemoize.fs
@@ -48,8 +48,7 @@ type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?logEvent: (JobE
     let sendAsync (inbox: MailboxProcessor<_>) key msg =
         inbox.PostAndAsyncReply(fun rc -> key, msg, rc) |> Async.Ignore |> Async.Start
 
-    let log event =
-        logEvent |> Option.iter ((|>) event)
+    let log event = logEvent |> Option.iter ((|>) event)
 
     let agent =
         MailboxProcessor.Start(fun (inbox: MailboxProcessor>) ->
@@ -77,7 +76,7 @@ type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?logEvent: (JobE
                             Async.StartAsTask(
                                 Async.AwaitNodeCode(
                                     node {
-                                        use _ = Activity.start $"AsyncMemoize.{name}" [| |]
+                                        use _ = Activity.start $"AsyncMemoize.{name}" [||]
 
                                         let! result = computation key
                                         post key JobCompleted
diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs
index 5e419ab9431..9f7973d90c7 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fs
+++ b/src/Compiler/Service/FSharpCheckerResults.fs
@@ -368,19 +368,18 @@ type FSharpProjectSnapshot with
 
     static member FromOptions(options: FSharpProjectOptions, getFileSnapshot) =
         async {
-            let! sourceFiles =
-                options.SourceFiles
-                |> Seq.map (getFileSnapshot options)
-                |> Async.Parallel
+            let! sourceFiles = options.SourceFiles |> Seq.map (getFileSnapshot options) |> Async.Parallel
 
             let! referencedProjects =
                 options.ReferencedProjects
                 |> Seq.choose (function
-                    | FSharpReferencedProject.FSharpReference (outputName, options) -> Some (
-                        async {
-                            let! snapshot = FSharpProjectSnapshot.FromOptions(options, getFileSnapshot)
-                            return FSharpReferencedProjectSnapshot.FSharpReference (outputName, snapshot)
-                        })
+                    | FSharpReferencedProject.FSharpReference (outputName, options) ->
+                        Some(
+                            async {
+                                let! snapshot = FSharpProjectSnapshot.FromOptions(options, getFileSnapshot)
+                                return FSharpReferencedProjectSnapshot.FSharpReference(outputName, snapshot)
+                            }
+                        )
                     // TODO: other types
                     | _ -> None)
                 |> Async.Parallel
diff --git a/src/Compiler/Service/FSharpCheckerResults.fsi b/src/Compiler/Service/FSharpCheckerResults.fsi
index e07f31afe90..43052e69f9c 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fsi
+++ b/src/Compiler/Service/FSharpCheckerResults.fsi
@@ -248,7 +248,9 @@ type FSharpProjectSnapshot with
 
     member ToOptions: unit -> FSharpProjectOptions
 
-    static member FromOptions: options: FSharpProjectOptions * getFileSnapshot: (FSharpProjectOptions -> string -> Async) -> Async
+    static member FromOptions:
+        options: FSharpProjectOptions * getFileSnapshot: (FSharpProjectOptions -> string -> Async) ->
+            Async
 
 /// Represents the use of an F# symbol from F# source code
 []
From f2bd3494e017f994aeb9cf72256c9990182d2a35 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Thu, 4 May 2023 19:34:39 +0200
Subject: [PATCH 018/222] tests
---
 .../CompilerService/AsyncMemoize.fs           |   2 +
 ...ervice.SurfaceArea.netstandard20.debug.bsl | 126 +++++++++++++++++-
 ...vice.SurfaceArea.netstandard20.release.bsl | 123 ++++++++++++++++-
 3 files changed, 248 insertions(+), 3 deletions(-)
diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
index 4d18dbbbbac..2dae1fab2e4 100644
--- a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
+++ b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
@@ -69,6 +69,8 @@ let ``We can cancel a job`` () =
     cts1.Cancel()
     cts2.Cancel()
 
+    Thread.Sleep 10
+
     Assert.Equal array>([| Started key |], eventLog |> Seq.toArray )
 
     cts3.Cancel()
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 7b5b7a8f4dd..32d9d761d36 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
@@ -1961,6 +1961,16 @@ FSharp.Compiler.CodeAnalysis.DocumentSource: FSharp.Compiler.CodeAnalysis.Docume
 FSharp.Compiler.CodeAnalysis.DocumentSource: Int32 Tag
 FSharp.Compiler.CodeAnalysis.DocumentSource: Int32 get_Tag()
 FSharp.Compiler.CodeAnalysis.DocumentSource: System.String ToString()
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 braceMatchCacheSize
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 checkFileInProjectCacheSize
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 frameworkTcImportsCacheStrongSize
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 get_braceMatchCacheSize()
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 get_checkFileInProjectCacheSize()
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 get_frameworkTcImportsCacheStrongSize()
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 get_parseFileCacheSize()
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 get_projectCacheSizeDefault()
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 parseFileCacheSize
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 projectCacheSizeDefault
 FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer+Succeeded: FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults Item
 FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer+Succeeded: FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults get_Item()
 FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer+Tags: Int32 Aborted
@@ -2031,7 +2041,9 @@ FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: FSharp.Compiler.Symbols.
 FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: System.String ToString()
 FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: System.String[] DependencyFiles
 FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: System.String[] get_DependencyFiles()
-FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker Create(Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.LegacyReferenceResolver], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`2[System.String,System.DateTime],Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[System.Object,System.IntPtr,System.Int32]]]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.DocumentSource], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean])
+FSharp.Compiler.CodeAnalysis.FSharpChecker: Boolean UsesTransparentCompiler
+FSharp.Compiler.CodeAnalysis.FSharpChecker: Boolean get_UsesTransparentCompiler()
+FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker Create(Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.LegacyReferenceResolver], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`2[System.String,System.DateTime],Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[System.Object,System.IntPtr,System.Int32]]]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.DocumentSource], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker Instance
 FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker get_Instance()
 FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpProjectOptions GetProjectOptionsFromCommandLineArgs(System.String, System.String[], Microsoft.FSharp.Core.FSharpOption`1[System.DateTime], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean])
@@ -2050,6 +2062,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync
 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])
+FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer]] ParseAndCheckFileInProject(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer]] ParseAndCheckFileInProject(System.String, Int32, FSharp.Compiler.Text.ISourceText, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults]] GetBackgroundCheckResultsForFileInProject(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]]] GetProjectOptionsFromScript(System.String, FSharp.Compiler.Text.ISourceText, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.DateTime], Microsoft.FSharp.Core.FSharpOption`1[System.String[]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Int64], Microsoft.FSharp.Core.FSharpOption`1[System.String])
@@ -2073,6 +2086,18 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Void ClearCache(System.Collections.G
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Void ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients()
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Void InvalidateAll()
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Void InvalidateConfiguration(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: Boolean Equals(System.Object)
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: Int32 GetHashCode()
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.Threading.Tasks.Task`1[FSharp.Compiler.Text.ISourceText]] GetSource
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.Threading.Tasks.Task`1[FSharp.Compiler.Text.ISourceText]] get_GetSource()
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.String FileName
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.String ToString()
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.String Version
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.String get_FileName()
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.String get_Version()
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.Tuple`2[System.String,System.String] Key
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.Tuple`2[System.String,System.String] get_Key()
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: Void .ctor(System.String, System.String, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.Threading.Tasks.Task`1[FSharp.Compiler.Text.ISourceText]])
 FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsBindingALambdaAtPosition(FSharp.Compiler.Text.Position)
 FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsPosContainedInApplication(FSharp.Compiler.Text.Position)
 FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsPositionContainedInACurriedParameter(FSharp.Compiler.Text.Position)
@@ -2165,6 +2190,65 @@ FSharp.Compiler.CodeAnalysis.FSharpProjectOptions: System.String[] SourceFiles
 FSharp.Compiler.CodeAnalysis.FSharpProjectOptions: System.String[] get_OtherOptions()
 FSharp.Compiler.CodeAnalysis.FSharpProjectOptions: System.String[] get_SourceFiles()
 FSharp.Compiler.CodeAnalysis.FSharpProjectOptions: Void .ctor(System.String, Microsoft.FSharp.Core.FSharpOption`1[System.String], System.String[], System.String[], FSharp.Compiler.CodeAnalysis.FSharpReferencedProject[], Boolean, Boolean, System.DateTime, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet], Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Text.Range,System.String,System.String]], Microsoft.FSharp.Core.FSharpOption`1[System.Int64])
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean Equals(FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean Equals(System.Object)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean IsIncompleteTypeCheckEnvironment
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean UseScriptResolutionRules
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean get_IsIncompleteTypeCheckEnvironment()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean get_UseScriptResolutionRules()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectOptions ToOptions()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot UpTo(Int32)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot UpTo(System.String)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey Key
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey get_Key()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Int32 GetHashCode()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Int32 GetHashCode(System.Collections.IEqualityComparer)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot] SourceFiles
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot] get_SourceFiles()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot] ReferencedProjects
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot] get_ReferencedProjects()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[System.String] OtherOptions
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[System.String] SourceFileNames
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_OtherOptions()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_SourceFileNames()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Text.Range,System.String,System.String]] OriginalLoadReferences
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Text.Range,System.String,System.String]] get_OriginalLoadReferences()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot] FromOptions(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions,Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot]]])
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet] UnresolvedReferences
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet] get_UnresolvedReferences()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Core.FSharpOption`1[System.Int64] Stamp
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Core.FSharpOption`1[System.Int64] get_Stamp()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Core.FSharpOption`1[System.String] ProjectId
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Core.FSharpOption`1[System.String] get_ProjectId()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: System.DateTime LoadTime
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: System.DateTime get_LoadTime()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: System.String ProjectFileName
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: System.String ToString()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: System.String get_ProjectFileName()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Void .ctor(System.String, Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot], Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot], Boolean, Boolean, System.DateTime, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet], Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Text.Range,System.String,System.String]], Microsoft.FSharp.Core.FSharpOption`1[System.Int64])
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean Equals(FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean Equals(System.Object)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean IsIncompleteTypeCheckEnvironment
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean UseScriptResolutionRules
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean get_IsIncompleteTypeCheckEnvironment()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean get_UseScriptResolutionRules()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 CompareTo(FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 CompareTo(System.Object)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 CompareTo(System.Object, System.Collections.IComparer)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 GetHashCode()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 GetHashCode(System.Collections.IEqualityComparer)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey] ReferencedProjects
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey] get_ReferencedProjects()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] OtherOptions
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_OtherOptions()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.String,System.String]] SourceFiles
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.String,System.String]] get_SourceFiles()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.String ProjectFileName
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.String ToString()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.String get_ProjectFileName()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Void .ctor(System.String, Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.String,System.String]], Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey], Boolean, Boolean)
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: Boolean Equals(System.Object)
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: FSharp.Compiler.CodeAnalysis.FSharpReferencedProject CreateFSharp(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions)
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: FSharp.Compiler.CodeAnalysis.FSharpReferencedProject CreateFromILModuleReader(System.String, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.DateTime], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,FSharp.Compiler.AbstractIL.ILBinaryReader+ILModuleReader])
@@ -2173,6 +2257,12 @@ FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: Int32 GetHashCode()
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: System.String OutputFile
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: System.String ToString()
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: System.String get_OutputFile()
+FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot: Boolean Equals(System.Object)
+FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot CreateFSharp(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot)
+FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot: Int32 GetHashCode()
+FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot: System.String OutputFile
+FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot: System.String ToString()
+FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot: System.String get_OutputFile()
 FSharp.Compiler.CodeAnalysis.FSharpSymbolUse: Boolean IsFromAttribute
 FSharp.Compiler.CodeAnalysis.FSharpSymbolUse: Boolean IsFromComputationExpression
 FSharp.Compiler.CodeAnalysis.FSharpSymbolUse: Boolean IsFromDefinition
@@ -2210,6 +2300,35 @@ FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: Boolean Equals(Syste
 FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: Int32 GetHashCode()
 FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: Int32 GetHashCode(System.Collections.IEqualityComparer)
 FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: System.String ToString()
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Boolean Equals(FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey)
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Boolean Equals(System.Object)
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey NewFrameworkImportsCacheKey(Microsoft.FSharp.Collections.FSharpList`1[System.String], System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String], System.String, System.Decimal)
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 CompareTo(FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey)
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 CompareTo(System.Object)
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 CompareTo(System.Object, System.Collections.IComparer)
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 GetHashCode()
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 GetHashCode(System.Collections.IEqualityComparer)
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 Tag
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 get_Tag()
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_resolvedpath()
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_targetFrameworkDirectories()
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] resolvedpath
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] targetFrameworkDirectories
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.Decimal get_langVersion()
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.Decimal langVersion
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String ToString()
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String assemblyName
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String fsharpBinaries
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String get_assemblyName()
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String get_fsharpBinaries()
+FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSameForChecking2(System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions], System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions])
+FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSameForChecking3(System.Tuple`3[System.String,System.Int64,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions], System.Tuple`3[System.String,System.Int64,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions])
+FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSameForParsing[a](System.Tuple`3[System.String,System.Int64,a], System.Tuple`3[System.String,System.Int64,a])
+FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSimilarForParsing[a,b,c,d,e](System.Tuple`3[a,b,c], System.Tuple`3[a,d,e])
+FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSubsumable2(System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions], System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions])
+FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSubsumable3[a,b](System.Tuple`3[System.String,a,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions], System.Tuple`3[System.String,b,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions])
+FSharp.Compiler.CodeAnalysis.Helpers: Boolean NamesContainAttribute(FSharp.Compiler.Symbols.FSharpSymbol, Microsoft.FSharp.Collections.FSharpSet`1[System.String])
 FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver: FSharp.Compiler.CodeAnalysis.LegacyResolvedFile[] Resolve(FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment, System.Tuple`2[System.String,System.String][], System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String], System.String, System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String], System.String, Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Core.FSharpFunc`2[System.Boolean,Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Core.Unit]]])
 FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver: System.String DotNetFrameworkReferenceAssembliesRootDirectory
 FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver: System.String HighestInstalledNetFrameworkVersion()
@@ -2253,6 +2372,8 @@ FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: System.String get_baggage()
 FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: System.String get_itemSpec()
 FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: System.String itemSpec
 FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: Void .ctor(System.String, Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`2[System.String,System.String],System.String], System.String)
+FSharp.Compiler.CodeAnalysis.ParseCacheLockToken: Void .ctor()
+FSharp.Compiler.CodeAnalysis.ScriptClosureCacheToken: Void .ctor()
 FSharp.Compiler.CompilerEnvironment: Boolean IsCheckerSupportedSubcategory(System.String)
 FSharp.Compiler.CompilerEnvironment: Boolean IsCompilable(System.String)
 FSharp.Compiler.CompilerEnvironment: Boolean IsScriptFile(System.String)
@@ -10133,7 +10254,7 @@ FSharp.Compiler.Tokenization.FSharpLineTokenizer: FSharp.Compiler.Tokenization.F
 FSharp.Compiler.Tokenization.FSharpLineTokenizer: System.Tuple`2[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Tokenization.FSharpTokenInfo],FSharp.Compiler.Tokenization.FSharpTokenizerLexState] ScanToken(FSharp.Compiler.Tokenization.FSharpTokenizerLexState)
 FSharp.Compiler.Tokenization.FSharpSourceTokenizer: FSharp.Compiler.Tokenization.FSharpLineTokenizer CreateBufferTokenizer(Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`3[System.Char[],System.Int32,System.Int32],System.Int32])
 FSharp.Compiler.Tokenization.FSharpSourceTokenizer: FSharp.Compiler.Tokenization.FSharpLineTokenizer CreateLineTokenizer(System.String)
-FSharp.Compiler.Tokenization.FSharpSourceTokenizer: Void .ctor(Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.String])
+FSharp.Compiler.Tokenization.FSharpSourceTokenizer: Void .ctor(Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.Tokenization.FSharpToken: Boolean IsCommentTrivia
 FSharp.Compiler.Tokenization.FSharpToken: Boolean IsIdentifier
 FSharp.Compiler.Tokenization.FSharpToken: Boolean IsKeyword
@@ -11302,6 +11423,7 @@ FSharp.Compiler.Tokenization.FSharpTokenizerColorState: FSharp.Compiler.Tokeniza
 FSharp.Compiler.Tokenization.FSharpTokenizerColorState: FSharp.Compiler.Tokenization.FSharpTokenizerColorState Comment
 FSharp.Compiler.Tokenization.FSharpTokenizerColorState: FSharp.Compiler.Tokenization.FSharpTokenizerColorState EndLineThenSkip
 FSharp.Compiler.Tokenization.FSharpTokenizerColorState: FSharp.Compiler.Tokenization.FSharpTokenizerColorState EndLineThenToken
+FSharp.Compiler.Tokenization.FSharpTokenizerColorState: FSharp.Compiler.Tokenization.FSharpTokenizerColorState ExtendedInterpolatedString
 FSharp.Compiler.Tokenization.FSharpTokenizerColorState: FSharp.Compiler.Tokenization.FSharpTokenizerColorState IfDefSkip
 FSharp.Compiler.Tokenization.FSharpTokenizerColorState: FSharp.Compiler.Tokenization.FSharpTokenizerColorState InitialState
 FSharp.Compiler.Tokenization.FSharpTokenizerColorState: FSharp.Compiler.Tokenization.FSharpTokenizerColorState SingleLineComment
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 f8b2c9dbd40..32d9d761d36 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
@@ -1961,6 +1961,16 @@ FSharp.Compiler.CodeAnalysis.DocumentSource: FSharp.Compiler.CodeAnalysis.Docume
 FSharp.Compiler.CodeAnalysis.DocumentSource: Int32 Tag
 FSharp.Compiler.CodeAnalysis.DocumentSource: Int32 get_Tag()
 FSharp.Compiler.CodeAnalysis.DocumentSource: System.String ToString()
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 braceMatchCacheSize
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 checkFileInProjectCacheSize
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 frameworkTcImportsCacheStrongSize
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 get_braceMatchCacheSize()
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 get_checkFileInProjectCacheSize()
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 get_frameworkTcImportsCacheStrongSize()
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 get_parseFileCacheSize()
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 get_projectCacheSizeDefault()
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 parseFileCacheSize
+FSharp.Compiler.CodeAnalysis.EnvMisc: Int32 projectCacheSizeDefault
 FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer+Succeeded: FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults Item
 FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer+Succeeded: FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults get_Item()
 FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer+Tags: Int32 Aborted
@@ -2031,7 +2041,9 @@ FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: FSharp.Compiler.Symbols.
 FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: System.String ToString()
 FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: System.String[] DependencyFiles
 FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: System.String[] get_DependencyFiles()
-FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker Create(Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.LegacyReferenceResolver], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`2[System.String,System.DateTime],Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[System.Object,System.IntPtr,System.Int32]]]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.DocumentSource], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean])
+FSharp.Compiler.CodeAnalysis.FSharpChecker: Boolean UsesTransparentCompiler
+FSharp.Compiler.CodeAnalysis.FSharpChecker: Boolean get_UsesTransparentCompiler()
+FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker Create(Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.LegacyReferenceResolver], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`2[System.String,System.DateTime],Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[System.Object,System.IntPtr,System.Int32]]]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.DocumentSource], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker Instance
 FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker get_Instance()
 FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpProjectOptions GetProjectOptionsFromCommandLineArgs(System.String, System.String[], Microsoft.FSharp.Core.FSharpOption`1[System.DateTime], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean])
@@ -2050,6 +2062,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync
 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])
+FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer]] ParseAndCheckFileInProject(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer]] ParseAndCheckFileInProject(System.String, Int32, FSharp.Compiler.Text.ISourceText, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults]] GetBackgroundCheckResultsForFileInProject(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]]] GetProjectOptionsFromScript(System.String, FSharp.Compiler.Text.ISourceText, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.DateTime], Microsoft.FSharp.Core.FSharpOption`1[System.String[]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Int64], Microsoft.FSharp.Core.FSharpOption`1[System.String])
@@ -2073,6 +2086,18 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Void ClearCache(System.Collections.G
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Void ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients()
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Void InvalidateAll()
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Void InvalidateConfiguration(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: Boolean Equals(System.Object)
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: Int32 GetHashCode()
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.Threading.Tasks.Task`1[FSharp.Compiler.Text.ISourceText]] GetSource
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.Threading.Tasks.Task`1[FSharp.Compiler.Text.ISourceText]] get_GetSource()
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.String FileName
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.String ToString()
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.String Version
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.String get_FileName()
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.String get_Version()
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.Tuple`2[System.String,System.String] Key
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.Tuple`2[System.String,System.String] get_Key()
+FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: Void .ctor(System.String, System.String, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.Threading.Tasks.Task`1[FSharp.Compiler.Text.ISourceText]])
 FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsBindingALambdaAtPosition(FSharp.Compiler.Text.Position)
 FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsPosContainedInApplication(FSharp.Compiler.Text.Position)
 FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsPositionContainedInACurriedParameter(FSharp.Compiler.Text.Position)
@@ -2165,6 +2190,65 @@ FSharp.Compiler.CodeAnalysis.FSharpProjectOptions: System.String[] SourceFiles
 FSharp.Compiler.CodeAnalysis.FSharpProjectOptions: System.String[] get_OtherOptions()
 FSharp.Compiler.CodeAnalysis.FSharpProjectOptions: System.String[] get_SourceFiles()
 FSharp.Compiler.CodeAnalysis.FSharpProjectOptions: Void .ctor(System.String, Microsoft.FSharp.Core.FSharpOption`1[System.String], System.String[], System.String[], FSharp.Compiler.CodeAnalysis.FSharpReferencedProject[], Boolean, Boolean, System.DateTime, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet], Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Text.Range,System.String,System.String]], Microsoft.FSharp.Core.FSharpOption`1[System.Int64])
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean Equals(FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean Equals(System.Object)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean IsIncompleteTypeCheckEnvironment
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean UseScriptResolutionRules
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean get_IsIncompleteTypeCheckEnvironment()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean get_UseScriptResolutionRules()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectOptions ToOptions()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot UpTo(Int32)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot UpTo(System.String)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey Key
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey get_Key()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Int32 GetHashCode()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Int32 GetHashCode(System.Collections.IEqualityComparer)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot] SourceFiles
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot] get_SourceFiles()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot] ReferencedProjects
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot] get_ReferencedProjects()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[System.String] OtherOptions
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[System.String] SourceFileNames
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_OtherOptions()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_SourceFileNames()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Text.Range,System.String,System.String]] OriginalLoadReferences
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Text.Range,System.String,System.String]] get_OriginalLoadReferences()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot] FromOptions(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions,Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot]]])
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet] UnresolvedReferences
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet] get_UnresolvedReferences()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Core.FSharpOption`1[System.Int64] Stamp
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Core.FSharpOption`1[System.Int64] get_Stamp()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Core.FSharpOption`1[System.String] ProjectId
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Core.FSharpOption`1[System.String] get_ProjectId()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: System.DateTime LoadTime
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: System.DateTime get_LoadTime()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: System.String ProjectFileName
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: System.String ToString()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: System.String get_ProjectFileName()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Void .ctor(System.String, Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot], Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot], Boolean, Boolean, System.DateTime, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet], Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Text.Range,System.String,System.String]], Microsoft.FSharp.Core.FSharpOption`1[System.Int64])
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean Equals(FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean Equals(System.Object)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean IsIncompleteTypeCheckEnvironment
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean UseScriptResolutionRules
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean get_IsIncompleteTypeCheckEnvironment()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean get_UseScriptResolutionRules()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 CompareTo(FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 CompareTo(System.Object)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 CompareTo(System.Object, System.Collections.IComparer)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 GetHashCode()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 GetHashCode(System.Collections.IEqualityComparer)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey] ReferencedProjects
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey] get_ReferencedProjects()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] OtherOptions
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_OtherOptions()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.String,System.String]] SourceFiles
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.String,System.String]] get_SourceFiles()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.String ProjectFileName
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.String ToString()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.String get_ProjectFileName()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Void .ctor(System.String, Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.String,System.String]], Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey], Boolean, Boolean)
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: Boolean Equals(System.Object)
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: FSharp.Compiler.CodeAnalysis.FSharpReferencedProject CreateFSharp(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions)
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: FSharp.Compiler.CodeAnalysis.FSharpReferencedProject CreateFromILModuleReader(System.String, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.DateTime], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,FSharp.Compiler.AbstractIL.ILBinaryReader+ILModuleReader])
@@ -2173,6 +2257,12 @@ FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: Int32 GetHashCode()
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: System.String OutputFile
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: System.String ToString()
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: System.String get_OutputFile()
+FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot: Boolean Equals(System.Object)
+FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot CreateFSharp(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot)
+FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot: Int32 GetHashCode()
+FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot: System.String OutputFile
+FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot: System.String ToString()
+FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot: System.String get_OutputFile()
 FSharp.Compiler.CodeAnalysis.FSharpSymbolUse: Boolean IsFromAttribute
 FSharp.Compiler.CodeAnalysis.FSharpSymbolUse: Boolean IsFromComputationExpression
 FSharp.Compiler.CodeAnalysis.FSharpSymbolUse: Boolean IsFromDefinition
@@ -2210,6 +2300,35 @@ FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: Boolean Equals(Syste
 FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: Int32 GetHashCode()
 FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: Int32 GetHashCode(System.Collections.IEqualityComparer)
 FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: System.String ToString()
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Boolean Equals(FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey)
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Boolean Equals(System.Object)
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey NewFrameworkImportsCacheKey(Microsoft.FSharp.Collections.FSharpList`1[System.String], System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String], System.String, System.Decimal)
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 CompareTo(FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey)
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 CompareTo(System.Object)
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 CompareTo(System.Object, System.Collections.IComparer)
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 GetHashCode()
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 GetHashCode(System.Collections.IEqualityComparer)
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 Tag
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 get_Tag()
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_resolvedpath()
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_targetFrameworkDirectories()
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] resolvedpath
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] targetFrameworkDirectories
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.Decimal get_langVersion()
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.Decimal langVersion
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String ToString()
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String assemblyName
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String fsharpBinaries
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String get_assemblyName()
+FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String get_fsharpBinaries()
+FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSameForChecking2(System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions], System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions])
+FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSameForChecking3(System.Tuple`3[System.String,System.Int64,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions], System.Tuple`3[System.String,System.Int64,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions])
+FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSameForParsing[a](System.Tuple`3[System.String,System.Int64,a], System.Tuple`3[System.String,System.Int64,a])
+FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSimilarForParsing[a,b,c,d,e](System.Tuple`3[a,b,c], System.Tuple`3[a,d,e])
+FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSubsumable2(System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions], System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions])
+FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSubsumable3[a,b](System.Tuple`3[System.String,a,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions], System.Tuple`3[System.String,b,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions])
+FSharp.Compiler.CodeAnalysis.Helpers: Boolean NamesContainAttribute(FSharp.Compiler.Symbols.FSharpSymbol, Microsoft.FSharp.Collections.FSharpSet`1[System.String])
 FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver: FSharp.Compiler.CodeAnalysis.LegacyResolvedFile[] Resolve(FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment, System.Tuple`2[System.String,System.String][], System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String], System.String, System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String], System.String, Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Core.FSharpFunc`2[System.Boolean,Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Core.Unit]]])
 FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver: System.String DotNetFrameworkReferenceAssembliesRootDirectory
 FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver: System.String HighestInstalledNetFrameworkVersion()
@@ -2253,6 +2372,8 @@ FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: System.String get_baggage()
 FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: System.String get_itemSpec()
 FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: System.String itemSpec
 FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: Void .ctor(System.String, Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`2[System.String,System.String],System.String], System.String)
+FSharp.Compiler.CodeAnalysis.ParseCacheLockToken: Void .ctor()
+FSharp.Compiler.CodeAnalysis.ScriptClosureCacheToken: Void .ctor()
 FSharp.Compiler.CompilerEnvironment: Boolean IsCheckerSupportedSubcategory(System.String)
 FSharp.Compiler.CompilerEnvironment: Boolean IsCompilable(System.String)
 FSharp.Compiler.CompilerEnvironment: Boolean IsScriptFile(System.String)
From b3e8b236ea8f067a4faf6656491311d6f0a2bbc8 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Fri, 5 May 2023 13:25:06 +0200
Subject: [PATCH 019/222] try to deflake test
---
 .../CompilerService/AsyncMemoize.fs                          | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
index 2dae1fab2e4..a2e6c84bdc7 100644
--- a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
+++ b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
@@ -43,7 +43,10 @@ let ``Basics``() =
 []
 let ``We can cancel a job`` () =
 
+    let resetEvent = new ManualResetEvent(false)
+
     let computation key = node {
+        resetEvent.Set() |> ignore
         do! Async.Sleep 1000 |> NodeCode.AwaitAsync
         failwith "Should be canceled before it gets here"
         return key * 2
@@ -62,7 +65,7 @@ let ``We can cancel a job`` () =
     let _task2 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation), cts2.Token)
     let _task3 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation), cts3.Token)
 
-    Thread.Sleep 10
+    resetEvent.WaitOne() |> ignore
 
     Assert.Equal array>([| Started key |], eventLog |> Seq.toArray )
 
From a3739866bafc94c0322bde7274354576ad338628 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Fri, 5 May 2023 14:23:03 +0200
Subject: [PATCH 020/222] fix fsproj
---
 src/Compiler/FSharp.Compiler.Service.fsproj | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj
index 1cd12ec49ae..5eaf378da62 100644
--- a/src/Compiler/FSharp.Compiler.Service.fsproj
+++ b/src/Compiler/FSharp.Compiler.Service.fsproj
@@ -470,7 +470,7 @@
     
 	  
 	  
-	  
+	  
     
     
     
From 9902755342a6c1966bfcc51cf94ab81f77427803 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Fri, 5 May 2023 15:08:05 +0200
Subject: [PATCH 021/222] tests
---
 src/Compiler/Facilities/AsyncMemoize.fs       |  4 +-
 .../FSharpChecker/TransparentCompiler.fs      | 81 +++++++++++++++++++
 .../ProjectGeneration.fs                      | 55 ++++++++-----
 3 files changed, 116 insertions(+), 24 deletions(-)
diff --git a/src/Compiler/Facilities/AsyncMemoize.fs b/src/Compiler/Facilities/AsyncMemoize.fs
index 8cb38c9540d..941cacb8013 100644
--- a/src/Compiler/Facilities/AsyncMemoize.fs
+++ b/src/Compiler/Facilities/AsyncMemoize.fs
@@ -77,7 +77,7 @@ type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?logEvent: (JobE
                                 Async.AwaitNodeCode(
                                     node {
                                         use _ = Activity.start $"AsyncMemoize.{name}" [||]
-
+                                        log (Started key)
                                         let! result = computation key
                                         post key JobCompleted
                                         return result
@@ -86,8 +86,6 @@ type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?logEvent: (JobE
                                 cancellationToken = cts.Token
                             )
 
-                        log (Started key)
-
                         let job = NodeCode.AwaitTask startedComputation
 
                         cache.Set(tok, key, (Running(job, cts)))
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
index d619d9e45c1..4fa464d9bac 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
+++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
@@ -89,3 +89,84 @@ let ``Parallel processing`` () =
     ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
         checkFile "E" expectOk
     }
+
+
+let makeTestProject () =
+    SyntheticProject.Create(
+        sourceFile "First" [],
+        sourceFile "Second" ["First"],
+        sourceFile "Third" ["First"],
+        { sourceFile "Last" ["Second"; "Third"] with EntryPoint = true })
+
+let testWorkflow () =
+    ProjectWorkflowBuilder(makeTestProject(), useTransparentCompiler = true)
+
+[]
+let ``Edit file, check it, then check dependent file`` () =
+    testWorkflow() {
+        updateFile "First" breakDependentFiles
+        checkFile "First" expectSignatureChanged
+        checkFile "Second" expectErrors
+    }
+
+[]
+let ``Edit file, don't check it, check dependent file`` () =
+    testWorkflow() {
+        updateFile "First" breakDependentFiles
+        checkFile "Second" expectErrors
+    }
+
+[]
+let ``Check transitive dependency`` () =
+    testWorkflow() {
+        updateFile "First" breakDependentFiles
+        checkFile "Last" expectSignatureChanged
+    }
+
+[]
+let ``Change multiple files at once`` () =
+    testWorkflow() {
+        updateFile "First" (setPublicVersion 2)
+        updateFile "Second" (setPublicVersion 2)
+        updateFile "Third" (setPublicVersion 2)
+        checkFile "Last" (expectSignatureContains "val f: x: 'a -> (ModuleFirst.TFirstV_2<'a> * ModuleSecond.TSecondV_2<'a>) * (ModuleFirst.TFirstV_2<'a> * ModuleThird.TThirdV_2<'a>) * TLastV_1<'a>")
+    }
+
+// TODO: []
+let ``Files depend on signature file if present`` () =
+    let project = makeTestProject() |> updateFile "First" addSignatureFile
+
+    ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
+        updateFile "First" breakDependentFiles
+        saveFile "First"
+        checkFile "Second" expectNoChanges
+    }
+
+[]
+let ``Adding a file`` () =
+    testWorkflow() {
+        addFileAbove "Second" (sourceFile "New" [])
+        updateFile "Second" (addDependency "New")
+        checkFile "Last" (expectSignatureContains "val f: x: 'a -> (ModuleNew.TNewV_1<'a> * ModuleFirst.TFirstV_1<'a> * ModuleSecond.TSecondV_1<'a>) * (ModuleFirst.TFirstV_1<'a> * ModuleThird.TThirdV_1<'a>) * TLastV_1<'a>")
+    }
+
+[]
+let ``Removing a file`` () =
+    testWorkflow() {
+        removeFile "Second"
+        checkFile "Last" expectErrors
+    }
+
+[]
+let ``Changes in a referenced project`` () =
+    let library = SyntheticProject.Create("library", sourceFile "Library" [])
+
+    let project =
+        { makeTestProject() with DependsOn = [library] }
+        |> updateFile "First" (addDependency "Library")
+
+    project.Workflow {
+        updateFile "Library" updatePublicSurface
+        saveFile "Library"
+        checkFile "Last" expectSignatureChanged
+    }
\ No newline at end of file
diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
index 16d42718f1e..388e16185d4 100644
--- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs
+++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
@@ -341,16 +341,43 @@ module ProjectOperations =
             project.GetProjectOptions checker
         )
 
-    let getFileSnapshot (project: SyntheticProject) _options path =
+    let getSourceText (project: SyntheticProject) (filePath: string) =
+        if filePath.EndsWith(".fsi") then
+            let implFilePath = filePath[..filePath.Length - 2]
+            let source = project.FindByPath implFilePath
+            match source.SignatureFile with
+            | No -> failwith $"{implFilePath} does not have a signature file"
+            | Custom _ -> renderCustomSignatureFile project source
+            | AutoGenerated ->
+                if File.Exists filePath then
+                    // TODO: could be outdated
+                    File.ReadAllText filePath
+                else
+                    failwith "AutoGenerated signatures not yet supported for getSource workflow"
+        else
+            filePath
+            |> project.FindByPath
+            |> renderSourceFile project
+        |> SourceText.ofString
+
+    let getFileSnapshot (project: SyntheticProject) _options (path: string) =
         async {
-            let file = project.FindByPath path
+            let file, filePath =
+                if path.EndsWith(".fsi") then
+                    let implFilePath = path[..path.Length - 2]
+                    let f = project.FindByPath implFilePath
+                    f, getSignatureFilePath project f
+                else
+                    let f = project.FindByPath path
+                    f, getFilePath project f
+
             let dependencies = file.DependsOn |> String.concat "|"
-            let version = $"{file.PublicVersion}.{file.InternalVersion}.{file.Source.GetHashCode()}.{file.ExtraSource.GetHashCode()}.{dependencies}"
+            let version = $"{file.PublicVersion}|{file.InternalVersion}|{file.FunctionName}|{file.Source.GetHashCode()}|{file.ExtraSource.GetHashCode()}|{dependencies}"
 
             return {
-                FileName = getFilePath project file
+                FileName = filePath
                 Version = version
-                GetSource = fun () -> renderSourceFile project file |> SourceText.ofString |> Task.FromResult
+                GetSource = fun () -> getSourceText project path |> Task.FromResult
             }
         }
 
@@ -457,7 +484,7 @@ module ProjectOperations =
 
                 match file.SignatureFile with
                 | AutoGenerated when generateSignatureFiles ->
-                    let project = { p with SourceFiles = p.SourceFiles[0..i] }
+                    let project = { p with SourceFiles = p.SourceFiles[0..i - 1] @ [ { file with SignatureFile = No }] }
                     let! results = checkFile file.Id project checker
                     let signature = getSignature results
                     writeFileIfChanged signatureFileName signature
@@ -584,21 +611,7 @@ type ProjectWorkflowBuilder
 
     let mutable latestProject = initialProject
 
-    let getSource (filePath: string) =
-        if filePath.EndsWith(".fsi") then
-            let implFilePath = filePath[..filePath.Length - 2]
-            let source = latestProject.FindByPath implFilePath
-            match source.SignatureFile with
-            | No -> failwith $"{implFilePath} does not have a signature file"
-            | Custom _ -> renderCustomSignatureFile latestProject source
-            | AutoGenerated -> failwith "AutoGenerated signatures not yet supported for getSource workflow"
-        else
-            filePath
-            |> latestProject.FindByPath
-            |> renderSourceFile latestProject
-        |> SourceText.ofString
-        |> Some
-        |> async.Return
+    let getSource f = f |> getSourceText latestProject |> Some |> async.Return
 
     let checker =
         defaultArg
From a2d7e567a5f77ce8ce99bb3bab6f3a859cd32210 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Fri, 5 May 2023 17:09:08 +0200
Subject: [PATCH 022/222] wip
---
 src/Compiler/Service/TransparentCompiler.fs   | 20 +++++++++++--------
 .../CompilerService/AsyncMemoize.fs           |  2 +-
 2 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 9775fc871e4..38a5a56fdbc 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -684,25 +684,29 @@ type internal TransparentCompiler
 
             let prefixPathOpt = None
 
-            // TODO:
-            let implFile = implFileOpt.Value
-
             let ccuSigForFile, tcState =
-                AddCheckResultsToTcState
-                    (bootstrapInfo.TcGlobals, amap, hadSig, prefixPathOpt, TcResultsSink.NoSink, a.tcState.TcEnvFromImpls, implFile.QualifiedNameOfFile, implFile.Signature)
-                    b.tcState
+                match implFileOpt with 
+                | Some implFile ->
+
+                    let ccuSigForFile, tcState =
+                        AddCheckResultsToTcState
+                            (bootstrapInfo.TcGlobals, amap, hadSig, prefixPathOpt, TcResultsSink.NoSink, a.tcState.TcEnvFromImpls, implFile.QualifiedNameOfFile, implFile.Signature)
+                            b.tcState
+                    Some ccuSigForFile, tcState
+                | None ->
+                    b.latestCcuSigForFile, b.tcState
 
             { a with
                 tcState = tcState
                 tcEnvAtEndOfFile = b.tcEnvAtEndOfFile
                 moduleNamesDict = b.moduleNamesDict
-                latestCcuSigForFile = Some ccuSigForFile
+                latestCcuSigForFile = ccuSigForFile
                 tcDiagnosticsRev = b.tcDiagnosticsRev @ a.tcDiagnosticsRev
                 topAttribs = b.topAttribs
                 tcDependencyFiles = b.tcDependencyFiles @ a.tcDependencyFiles
                 // we shouldn't need this with graph checking (?)
                 sigNameOpt = None
-            }, sink, Some implFile, name)
+            }, sink, implFileOpt, name)
 
     // Type check everything that is needed to check given file
     let ComputeTcPrior (file: FSharpFile) (bootstrapInfo: BootstrapInfo) (projectSnapshot: FSharpProjectSnapshot) _userOpName _key =
diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
index a2e6c84bdc7..41880ac0d96 100644
--- a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
+++ b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
@@ -78,7 +78,7 @@ let ``We can cancel a job`` () =
 
     cts3.Cancel()
 
-    Thread.Sleep 10
+    Thread.Sleep 100
 
     Assert.Equal array>([| Started key; Canceled key |], eventLog |> Seq.toArray )
 
From f1eb8080eddd5e1949b6268798cc99b281e9feb3 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Tue, 9 May 2023 12:05:24 +0200
Subject: [PATCH 023/222] wip
---
 src/Compiler/Driver/ParseAndCheckInputs.fs    | 73 ++++++++++---------
 src/Compiler/Driver/ParseAndCheckInputs.fsi   | 33 +++++++++
 .../FSharpChecker/TransparentCompiler.fs      |  2 +-
 .../TypeChecks/Graph/GraphOperations.fs       |  9 ++-
 4 files changed, 77 insertions(+), 40 deletions(-)
diff --git a/src/Compiler/Driver/ParseAndCheckInputs.fs b/src/Compiler/Driver/ParseAndCheckInputs.fs
index 55b9736ad56..171cc639580 100644
--- a/src/Compiler/Driver/ParseAndCheckInputs.fs
+++ b/src/Compiler/Driver/ParseAndCheckInputs.fs
@@ -1608,6 +1608,42 @@ let AddSignatureResultToTcImplEnv (tcImports: TcImports, tcGlobals, prefixPathOp
                 tcState.tcsTcSigEnv, EmptyTopAttrs, None, ccuSigForFile
 
             partialResult, tcState
+let TransformDependencyGraph (graph: Graph, filePairs: FilePairMap) =
+    let mkArtificialImplFile n = NodeToTypeCheck.ArtificialImplFile n
+    let mkPhysicalFile n = NodeToTypeCheck.PhysicalFile n
+
+    /// Map any signature dependencies to the ArtificialImplFile counterparts,
+    /// unless the signature dependency is the backing file of the current (implementation) file.
+    let mapDependencies idx deps =
+        Array.map
+            (fun dep ->
+                if filePairs.IsSignature dep then
+                    let implIdx = filePairs.GetImplementationIndex dep
+
+                    if implIdx = idx then
+                        // This is the matching signature for the implementation.
+                        // Retain the direct dependency onto the signature file.
+                        mkPhysicalFile dep
+                    else
+                        mkArtificialImplFile dep
+                else
+                    mkPhysicalFile dep)
+            deps
+
+    // Transform the graph to include ArtificialImplFile nodes when necessary.
+    graph
+    |> Seq.collect (fun (KeyValue (fileIdx, deps)) ->
+        if filePairs.IsSignature fileIdx then
+            // Add an additional ArtificialImplFile node for the signature file.
+            [|
+                // Mark the current file as physical and map the dependencies.
+                mkPhysicalFile fileIdx, mapDependencies fileIdx deps
+                // Introduce a new node that depends on the signature.
+                mkArtificialImplFile fileIdx, [| mkPhysicalFile fileIdx |]
+            |]
+        else
+            [| mkPhysicalFile fileIdx, mapDependencies fileIdx deps |])
+    |> Graph.make
 
 /// Constructs a file dependency graph and type-checks the files in parallel where possible.
 let CheckMultipleInputsUsingGraphMode
@@ -1630,42 +1666,7 @@ let CheckMultipleInputsUsingGraphMode
     let graph, trie =
         DependencyResolution.mkGraph tcConfig.compilingFSharpCore filePairs sourceFiles
 
-    let nodeGraph =
-        let mkArtificialImplFile n = NodeToTypeCheck.ArtificialImplFile n
-        let mkPhysicalFile n = NodeToTypeCheck.PhysicalFile n
-
-        /// Map any signature dependencies to the ArtificialImplFile counterparts,
-        /// unless the signature dependency is the backing file of the current (implementation) file.
-        let mapDependencies idx deps =
-            Array.map
-                (fun dep ->
-                    if filePairs.IsSignature dep then
-                        let implIdx = filePairs.GetImplementationIndex dep
-
-                        if implIdx = idx then
-                            // This is the matching signature for the implementation.
-                            // Retain the direct dependency onto the signature file.
-                            mkPhysicalFile dep
-                        else
-                            mkArtificialImplFile dep
-                    else
-                        mkPhysicalFile dep)
-                deps
-
-        // Transform the graph to include ArtificialImplFile nodes when necessary.
-        graph
-        |> Seq.collect (fun (KeyValue (fileIdx, deps)) ->
-            if filePairs.IsSignature fileIdx then
-                // Add an additional ArtificialImplFile node for the signature file.
-                [|
-                    // Mark the current file as physical and map the dependencies.
-                    mkPhysicalFile fileIdx, mapDependencies fileIdx deps
-                    // Introduce a new node that depends on the signature.
-                    mkArtificialImplFile fileIdx, [| mkPhysicalFile fileIdx |]
-                |]
-            else
-                [| mkPhysicalFile fileIdx, mapDependencies fileIdx deps |])
-        |> Graph.make
+    let nodeGraph = TransformDependencyGraph (graph, filePairs)
 
     // Persist the graph to a Mermaid diagram if specified.
     if tcConfig.typeCheckingConfig.DumpGraph then
diff --git a/src/Compiler/Driver/ParseAndCheckInputs.fsi b/src/Compiler/Driver/ParseAndCheckInputs.fsi
index 9d2bb5b9e41..813f99e8c2d 100644
--- a/src/Compiler/Driver/ParseAndCheckInputs.fsi
+++ b/src/Compiler/Driver/ParseAndCheckInputs.fsi
@@ -13,6 +13,7 @@ open FSharp.Compiler.CompilerImports
 open FSharp.Compiler.Diagnostics
 open FSharp.Compiler.DependencyManager
 open FSharp.Compiler.DiagnosticsLogger
+open FSharp.Compiler.GraphChecking
 open FSharp.Compiler.NameResolution
 open FSharp.Compiler.Syntax
 open FSharp.Compiler.TcGlobals
@@ -20,6 +21,36 @@ open FSharp.Compiler.Text
 open FSharp.Compiler.TypedTree
 open FSharp.Compiler.UnicodeLexing
 
+/// Auxiliary type for re-using signature information in TcEnvFromImpls.
+///
+/// TcState has two typing environments: TcEnvFromSignatures && TcEnvFromImpls
+/// When type checking a file, depending on the type (implementation or signature), it will use one of these typing environments (TcEnv).
+/// Checking a file will populate the respective TcEnv.
+///
+/// When a file has a dependencies, the information of the signature file in case a pair (implementation file backed by a signature) will suffice to type-check that file.
+/// Example: if `B.fs` has a dependency on `A`, the information of `A.fsi` is enough for `B.fs` to type-check, on condition that information is available in the TcEnvFromImpls.
+/// We introduce a special ArtificialImplFile node in the graph to satisfy this. `B.fs -> [ A.fsi ]` becomes `B.fs -> [ ArtificialImplFile A ].
+/// The `ArtificialImplFile A` node will duplicate the signature information which A.fsi provided earlier.
+/// Processing a `ArtificialImplFile` node will add the information from the TcEnvFromSignatures to the TcEnvFromImpls.
+/// This means `A` will be known in both TcEnvs and therefor `B.fs` can be type-checked.
+/// By doing this, we can speed up the graph processing as type checking a signature file is less expensive than its implementation counterpart.
+///
+/// When we need to actually type-check an implementation file backed by a signature, we cannot have the duplicate information of the signature file present in TcEnvFromImpls.
+/// Example `A.fs -> [ A.fsi ]`. An implementation file always depends on its signature.
+/// Type-checking `A.fs` will add the actual information to TcEnvFromImpls and we do not depend on the `ArtificialImplFile A` for `A.fs`.
+///
+/// In order to deal correctly with the `ArtificialImplFile` logic, we need to transform the resolved graph to contain the additional pair nodes.
+/// After we have type-checked the graph, we exclude the ArtificialImplFile nodes as they are not actual physical files in our project.
+[]
+type NodeToTypeCheck =
+    /// A real physical file in the current project.
+    /// This can be either an implementation or a signature file.
+    | PhysicalFile of fileIndex: FileIndex
+    /// An artificial node that will add the earlier processed signature information to the TcEnvFromImpls.
+    /// Dependants on this type of node will perceive that a file is known in both TcEnvFromSignatures and TcEnvFromImpls.
+    /// Even though the actual implementation file was not type-checked.
+    | ArtificialImplFile of signatureFileIndex: FileIndex
+
 val IsScript: string -> bool
 
 val ComputeQualifiedNameOfFileFromUniquePath: range * string list -> QualifiedNameOfFile
@@ -163,6 +194,8 @@ val AddCheckResultsToTcState:
     implFileSigType: ModuleOrNamespaceType ->
         tcState: TcState ->
             ModuleOrNamespaceType * TcState
+            
+val TransformDependencyGraph: graph: Graph * filePairs: FilePairMap -> Graph
 
 /// Finish the checking of multiple inputs
 val CheckMultipleInputsFinish:
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
index 4fa464d9bac..e4ee36efc92 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
+++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
@@ -132,7 +132,7 @@ let ``Change multiple files at once`` () =
         checkFile "Last" (expectSignatureContains "val f: x: 'a -> (ModuleFirst.TFirstV_2<'a> * ModuleSecond.TSecondV_2<'a>) * (ModuleFirst.TFirstV_2<'a> * ModuleThird.TThirdV_2<'a>) * TLastV_1<'a>")
     }
 
-// TODO: []
+[]
 let ``Files depend on signature file if present`` () =
     let project = makeTestProject() |> updateFile "First" addSignatureFile
 
diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs
index f8e58f352a9..757248d8add 100644
--- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs
+++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs
@@ -6,6 +6,7 @@ open FSharp.Compiler.GraphChecking
 open FSharp.Test.ProjectGeneration
 open FSharp.Compiler.Text
 open FSharp.Compiler
+open FSharp.Compiler.ParseAndCheckInputs
 
 
 []
@@ -66,13 +67,15 @@ let ``See what this does`` () =
                 let fullGraph =
                     DependencyResolution.mkGraph false filePairs sourceFiles
                     |> fst
-                    |> Graph.map (fun idx -> project.SourceFilePaths[idx] |> Path.GetFileName)
+                    //|> Graph.map (fun idx -> project.SourceFilePaths[idx] |> Path.GetFileName)
 
-                let subGraph = fullGraph |> Graph.subGraphFor "FileF.fs"
+                let subGraph = fullGraph |> Graph.subGraphFor 9  //"FileF.fs"
 
                 let layers = Graph.leafSequence subGraph |> Seq.toList
 
-                ignore layers
+                let transformed = TransformDependencyGraph (subGraph, filePairs)
+
+                ignore (layers, transformed)
 
                 return ()
             }
From 20ea96d085bdb36bc6196c9fffd0914e3d250e75 Mon Sep 17 00:00:00 2001
From: Petr Pokorny 
Date: Tue, 9 May 2023 18:11:36 +0200
Subject: [PATCH 024/222] wip
---
 src/Compiler/Driver/GraphChecking/Graph.fs    |  6 ++-
 src/Compiler/Driver/GraphChecking/Graph.fsi   |  4 +-
 src/Compiler/Driver/ParseAndCheckInputs.fs    |  5 +-
 src/Compiler/Driver/ParseAndCheckInputs.fsi   | 14 +++++-
 src/Compiler/Service/TransparentCompiler.fs   | 48 ++++++++++++++++---
 .../FSharpChecker/TransparentCompiler.fs      | 19 ++++++++
 .../TypeChecks/Graph/GraphOperations.fs       |  2 +-
 .../TypeChecks/Graph/TypedTreeGraph.fs        |  4 +-
 .../ProjectGeneration.fs                      |  2 +
 9 files changed, 88 insertions(+), 16 deletions(-)
diff --git a/src/Compiler/Driver/GraphChecking/Graph.fs b/src/Compiler/Driver/GraphChecking/Graph.fs
index 688fffc29bb..9cbce0b4b9b 100644
--- a/src/Compiler/Driver/GraphChecking/Graph.fs
+++ b/src/Compiler/Driver/GraphChecking/Graph.fs
@@ -124,7 +124,7 @@ module internal Graph =
     let print (graph: Graph<'Node>) : unit =
         printCustom graph (fun node -> node.ToString())
 
-    let serialiseToMermaid path (graph: Graph) =
+    let serialiseToMermaid (graph: Graph) =
         let sb = StringBuilder()
         let appendLine (line: string) = sb.AppendLine(line) |> ignore
 
@@ -139,8 +139,10 @@ module internal Graph =
                 appendLine $"    %i{idx} --> %i{depIdx}"
 
         appendLine "```"
+        sb.ToString()
 
+    let writeMermaidToFile path (graph: Graph) =
         use out =
             FileSystem.OpenFileForWriteShim(path, fileMode = System.IO.FileMode.Create)
 
-        out.WriteAllText(sb.ToString())
+        graph |> serialiseToMermaid |> out.WriteAllText
diff --git a/src/Compiler/Driver/GraphChecking/Graph.fsi b/src/Compiler/Driver/GraphChecking/Graph.fsi
index 8c6b9c29079..7d885f5c96a 100644
--- a/src/Compiler/Driver/GraphChecking/Graph.fsi
+++ b/src/Compiler/Driver/GraphChecking/Graph.fsi
@@ -21,5 +21,7 @@ module internal Graph =
     val leafSequence: graph: Graph<'Node> -> Set<'Node> seq
     /// Print the contents of the graph to the standard output.
     val print: graph: Graph<'Node> -> unit
+    /// Create a simple Mermaid graph
+    val serialiseToMermaid: graph: Graph -> string
     /// Create a simple Mermaid graph and save it under the path specified.
-    val serialiseToMermaid: path: string -> graph: Graph -> unit
+    val writeMermaidToFile: path: string -> graph: Graph -> unit
diff --git a/src/Compiler/Driver/ParseAndCheckInputs.fs b/src/Compiler/Driver/ParseAndCheckInputs.fs
index 171cc639580..7a70b6f5c51 100644
--- a/src/Compiler/Driver/ParseAndCheckInputs.fs
+++ b/src/Compiler/Driver/ParseAndCheckInputs.fs
@@ -1608,6 +1608,7 @@ let AddSignatureResultToTcImplEnv (tcImports: TcImports, tcGlobals, prefixPathOp
                 tcState.tcsTcSigEnv, EmptyTopAttrs, None, ccuSigForFile
 
             partialResult, tcState
+
 let TransformDependencyGraph (graph: Graph, filePairs: FilePairMap) =
     let mkArtificialImplFile n = NodeToTypeCheck.ArtificialImplFile n
     let mkPhysicalFile n = NodeToTypeCheck.PhysicalFile n
@@ -1666,7 +1667,7 @@ let CheckMultipleInputsUsingGraphMode
     let graph, trie =
         DependencyResolution.mkGraph tcConfig.compilingFSharpCore filePairs sourceFiles
 
-    let nodeGraph = TransformDependencyGraph (graph, filePairs)
+    let nodeGraph = TransformDependencyGraph(graph, filePairs)
 
     // Persist the graph to a Mermaid diagram if specified.
     if tcConfig.typeCheckingConfig.DumpGraph then
@@ -1686,7 +1687,7 @@ let CheckMultipleInputsUsingGraphMode
                         .TrimStart([| '\\'; '/' |])
 
                 (idx, friendlyFileName))
-            |> Graph.serialiseToMermaid graphFile)
+            |> Graph.writeMermaidToFile graphFile)
 
     let _ = ctok // TODO Use it
     let diagnosticsLogger = DiagnosticsThreadStatics.DiagnosticsLogger
diff --git a/src/Compiler/Driver/ParseAndCheckInputs.fsi b/src/Compiler/Driver/ParseAndCheckInputs.fsi
index 813f99e8c2d..718a9e3d746 100644
--- a/src/Compiler/Driver/ParseAndCheckInputs.fsi
+++ b/src/Compiler/Driver/ParseAndCheckInputs.fsi
@@ -194,7 +194,19 @@ val AddCheckResultsToTcState:
     implFileSigType: ModuleOrNamespaceType ->
         tcState: TcState ->
             ModuleOrNamespaceType * TcState
-            
+
+type PartialResult = TcEnv * TopAttribs * CheckedImplFile option * ModuleOrNamespaceType
+
+val AddSignatureResultToTcImplEnv:
+    tcImports: TcImports *
+    tcGlobals: TcGlobals *
+    prefixPathOpt: LongIdent option *
+    tcSink: TcResultsSink *
+    tcState: TcState *
+    input: ParsedInput ->
+        (TcState ->
+            PartialResult * TcState)
+
 val TransformDependencyGraph: graph: Graph * filePairs: FilePairMap -> Graph
 
 /// Finish the checking of multiple inputs
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 38a5a56fdbc..bf11cc15829 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -599,7 +599,7 @@ type internal TransparentCompiler
                 |> fst
                 |> Graph.subGraphFor (sourceFiles |> Array.last).Idx
 
-            return graph, filePairs
+            return TransformDependencyGraph(graph, filePairs), filePairs
         }
 
     let ComputeTcIntermediate (parsedInput: ParsedInput, parseErrors) bootstrapInfo prevTcInfo _key =
@@ -737,25 +737,59 @@ type internal TransparentCompiler
                     ComputeDependencyGraphForLastFile (parsedInputs |> Seq.map p13) bootstrapInfo.TcConfig
                 )
 
+            let fileNames = 
+                parsedInputs 
+                |> Seq.mapi (fun idx (input, _, _) -> idx, Path.GetFileName input.FileName)
+                |> Map.ofSeq
+
+            let debugGraph = 
+                graph
+                |> Graph.map (function NodeToTypeCheck.PhysicalFile i -> i, fileNames[i] | NodeToTypeCheck.ArtificialImplFile i -> -(i + 1), $"AIF : {fileNames[i]}")
+
+            Trace.TraceInformation("\n" + (debugGraph |> Graph.serialiseToMermaid))
+
             // layers that can be processed in parallel
             let layers = Graph.leafSequence graph |> Seq.toList
 
             // remove the final layer, which should be the target file
             let layers = layers |> List.take (layers.Length - 1)
 
-            let rec processLayer (layers: Set list) tcInfo =
+            let rec processLayer (layers: Set list) tcInfo =
                 node {
                     match layers with
                     | [] -> return tcInfo
                     | layer :: rest ->
                         let! results =
                             layer
-                            |> Seq.map (fun fileIndex ->
-                                let key = projectSnapshot.UpTo(fileIndex).Key
-                                let parsedInput, parseErrors, _ = parsedInputs[fileIndex]
-                                TcIntermediateCache.Get(key, ComputeTcIntermediate (parsedInput, parseErrors) bootstrapInfo tcInfo))
+                            |> Seq.map (fun fileNode ->
+
+                                match fileNode with
+                                | NodeToTypeCheck.PhysicalFile fileIndex ->
+                                    let parsedInput, parseErrors, _ = parsedInputs[fileIndex]
+                                    let key = projectSnapshot.UpTo(fileIndex).Key
+                                    TcIntermediateCache.Get(key, ComputeTcIntermediate (parsedInput, parseErrors) bootstrapInfo tcInfo)
+                                | NodeToTypeCheck.ArtificialImplFile fileIndex ->
+                                    let parsedInput, _parseErrors, _ = parsedInputs[fileIndex]
+                                    let tcState = tcInfo.tcState
+                                    let prefixPathOpt = None
+                                    
+                                    let (tcEnv , topAttribs , checkedImplFileOpt , _moduleOrNamespaceType), newTcState =
+                                        // Retrieve the type-checked signature information and add it to the TcEnvFromImpls.
+                                        AddSignatureResultToTcImplEnv(bootstrapInfo.TcImports, bootstrapInfo.TcGlobals, prefixPathOpt, TcResultsSink.NoSink, tcState, parsedInput) tcState
+                                    let tcInfo =
+                                        { tcInfo with
+                                            tcState = newTcState
+                                            tcEnvAtEndOfFile = tcEnv
+
+                                            topAttribs = Some topAttribs
+                                            // we shouldn't need this with graph checking (?)
+                                            sigNameOpt = None
+                                        }
+
+                                    node.Return(tcInfo, Unchecked.defaultof<_>, checkedImplFileOpt, parsedInput.FileName))
                             |> NodeCode.Parallel
-
+                        let nodes = layer |> Seq.map (function NodeToTypeCheck.PhysicalFile i -> fileNames[i] | NodeToTypeCheck.ArtificialImplFile i -> $"AIF : {fileNames[i]}") |> String.concat " "
+                        Trace.TraceInformation $"Processed layer {nodes}"
                         return! processLayer rest (mergeIntermediateResults bootstrapInfo (tcInfo, Unchecked.defaultof<_>, None, "") results |> p14)
                 }
 
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
index e4ee36efc92..ea679f5476d 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
+++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
@@ -91,6 +91,25 @@ let ``Parallel processing`` () =
     }
 
 
+[]
+let ``Parallel processing with signatures`` () =
+
+    Activity.listenToAll ()
+
+    let project = SyntheticProject.Create(
+        sourceFile "A" [] |> addSignatureFile,
+        sourceFile "B" ["A"] |> addSignatureFile,
+        sourceFile "C" ["A"] |> addSignatureFile,
+        sourceFile "D" ["A"] |> addSignatureFile,
+        sourceFile "E" ["B"; "C"; "D"] |> addSignatureFile)
+
+    ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
+        checkFile "C" expectOk
+        //updateFile "A" updatePublicSurface
+        //checkFile "E" expectSignatureChanged
+    }
+
+
 let makeTestProject () =
     SyntheticProject.Create(
         sourceFile "First" [],
diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs
index 757248d8add..dedac14ba76 100644
--- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs
+++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs
@@ -76,7 +76,7 @@ let ``See what this does`` () =
                 let transformed = TransformDependencyGraph (subGraph, filePairs)
 
                 ignore (layers, transformed)
-
+                
                 return ()
             }
         )
diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/TypedTreeGraph.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/TypedTreeGraph.fs
index 284946eee9f..0eef5c79673 100644
--- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/TypedTreeGraph.fs
+++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/TypedTreeGraph.fs
@@ -140,7 +140,7 @@ let ``Create Graph from typed tree`` (projectArgumentsFilePath: string) =
 
             graphFromTypedTree
             |> Graph.map (fun n -> n,files.[n].File)
-            |> Graph.serialiseToMermaid $"{fileName}.typed-tree.deps.md"
+            |> Graph.writeMermaidToFile $"{fileName}.typed-tree.deps.md"
 
             let collectAllDeps (graph: Graph) =
                 (Map.empty, [ 0 .. (sourceFiles.Length - 1) ])
@@ -162,7 +162,7 @@ let ``Create Graph from typed tree`` (projectArgumentsFilePath: string) =
 
             graphFromHeuristic
             |> Graph.map (fun n -> n, files.[n].File)
-            |> Graph.serialiseToMermaid $"{fileName}.heuristic-tree.deps.md"
+            |> Graph.writeMermaidToFile $"{fileName}.heuristic-tree.deps.md"
 
             let heuristicMap = collectAllDeps graphFromHeuristic
 
diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
index 388e16185d4..0acd065dbe6 100644
--- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs
+++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
@@ -571,6 +571,8 @@ type WorkflowContext =
 
 let SaveAndCheckProject project checker =
     async {
+        use _ =
+            Activity.start "SaveAndCheckProject" [ Activity.Tags.project, project.Name ]
 
         do! saveProject project true checker
 
From 91fad38a78148758fd5b416a18d8023e9304b1c4 Mon Sep 17 00:00:00 2001
From: Petr Pokorny 
Date: Wed, 10 May 2023 18:28:55 +0200
Subject: [PATCH 025/222] wip
---
 src/Compiler/Driver/ParseAndCheckInputs.fsi   |  20 ++-
 src/Compiler/Service/TransparentCompiler.fs   | 121 ++++++++----------
 .../FSharpChecker/TransparentCompiler.fs      |  30 ++++-
 .../ProjectGeneration.fs                      |  15 +++
 4 files changed, 109 insertions(+), 77 deletions(-)
diff --git a/src/Compiler/Driver/ParseAndCheckInputs.fsi b/src/Compiler/Driver/ParseAndCheckInputs.fsi
index 718a9e3d746..37e76d82d48 100644
--- a/src/Compiler/Driver/ParseAndCheckInputs.fsi
+++ b/src/Compiler/Driver/ParseAndCheckInputs.fsi
@@ -163,6 +163,9 @@ type TcState =
 
     member CreatesGeneratedProvidedTypes: bool
 
+
+type PartialResult = TcEnv * TopAttribs * CheckedImplFile option * ModuleOrNamespaceType
+
 /// Get the initial type checking state for a set of inputs
 val GetInitialTcState: range * string * TcConfig * TcGlobals * TcImports * TcEnv * OpenDeclaration list -> TcState
 
@@ -183,6 +186,18 @@ val CheckOneInput:
     input: ParsedInput ->
         Cancellable<(TcEnv * TopAttribs * CheckedImplFile option * ModuleOrNamespaceType) * TcState>
 
+val CheckOneInputWithCallback:
+      checkForErrors: (unit -> bool) *
+      tcConfig: TcConfig *
+      tcImports: TcImports *
+      tcGlobals: TcGlobals *
+      prefixPathOpt: LongIdent option *
+      tcSink: TcResultsSink *
+      tcState: TcState *
+      input: ParsedInput *
+      _skipImplIfSigExists: bool -> Cancellable>
+
+
 val AddCheckResultsToTcState:
     tcGlobals: TcGlobals *
     amap: Import.ImportMap *
@@ -195,8 +210,6 @@ val AddCheckResultsToTcState:
         tcState: TcState ->
             ModuleOrNamespaceType * TcState
 
-type PartialResult = TcEnv * TopAttribs * CheckedImplFile option * ModuleOrNamespaceType
-
 val AddSignatureResultToTcImplEnv:
     tcImports: TcImports *
     tcGlobals: TcGlobals *
@@ -204,8 +217,7 @@ val AddSignatureResultToTcImplEnv:
     tcSink: TcResultsSink *
     tcState: TcState *
     input: ParsedInput ->
-        (TcState ->
-            PartialResult * TcState)
+        (TcState -> PartialResult * TcState)
 
 val TransformDependencyGraph: graph: Graph * filePairs: FilePairMap -> Graph
 
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index bf11cc15829..8df2390ea49 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -33,6 +33,7 @@ open FSharp.Compiler.CompilerDiagnostics
 open FSharp.Compiler.NameResolution
 open Internal.Utilities.Library.Extras
 open FSharp.Compiler.TypedTree
+open FSharp.Compiler.CheckDeclarations
 
 type internal FSharpFile =
     {
@@ -55,6 +56,23 @@ type internal BootstrapInfo =
 
 type internal TcIntermediateResult = TcInfo * TcResultsSinkImpl * CheckedImplFile option * string
 
+
+/// Accumulated results of type checking. The minimum amount of state in order to continue type-checking following files.
+[]
+type internal TcIntermediate =
+    {
+        finisher: Finisher
+        //tcEnvAtEndOfFile: TcEnv
+
+        /// Disambiguation table for module names
+        moduleNamesDict: ModuleNamesDict
+
+        /// Accumulated diagnostics, last file first
+        tcDiagnosticsRev:(PhasedDiagnostic * FSharpDiagnosticSeverity)[] list
+
+        tcDependencyFiles: string list
+    }
+
 type internal TransparentCompiler
     (
         legacyReferenceResolver,
@@ -602,7 +620,7 @@ type internal TransparentCompiler
             return TransformDependencyGraph(graph, filePairs), filePairs
         }
 
-    let ComputeTcIntermediate (parsedInput: ParsedInput, parseErrors) bootstrapInfo prevTcInfo _key =
+    let ComputeTcIntermediate (parsedInput: ParsedInput, parseErrors) bootstrapInfo (prevTcInfo: TcInfo) _key =
         node {
             let input = parsedInput
             let fileName = input.FileName
@@ -633,8 +651,8 @@ type internal TransparentCompiler
             let input, moduleNamesDict =
                 DeduplicateParsedInputModuleName prevTcInfo.moduleNamesDict input
 
-            let! (tcEnvAtEndOfFile, topAttribs, implFile, ccuSigForFile), tcState =
-                CheckOneInput(
+            let! finisher =
+                CheckOneInputWithCallback(
                     (fun () -> hadParseErrors || diagnosticsLogger.ErrorCount > 0),
                     tcConfig,
                     tcImports,
@@ -642,7 +660,8 @@ type internal TransparentCompiler
                     None,
                     TcResultsSink.WithSink sink,
                     prevTcInfo.tcState,
-                    input
+                    input,
+                    false
                 )
                 |> NodeCode.FromCancellable
 
@@ -651,62 +670,27 @@ type internal TransparentCompiler
             let newErrors =
                 Array.append parseErrors (capturingDiagnosticsLogger.Diagnostics |> List.toArray)
 
-            let tcEnvAtEndOfFile =
-                if keepAllBackgroundResolutions then
-                    tcEnvAtEndOfFile
-                else
-                    tcState.TcEnvFromImpls
-
-            let tcInfo =
+            return
                 {
-                    tcState = tcState
-                    tcEnvAtEndOfFile = tcEnvAtEndOfFile
+                    finisher = finisher
                     moduleNamesDict = moduleNamesDict
-                    latestCcuSigForFile = Some ccuSigForFile
                     tcDiagnosticsRev = [ newErrors ]
-                    topAttribs = Some topAttribs
                     tcDependencyFiles = [ fileName ]
-                    // we shouldn't need this with graph checking (?)
-                    sigNameOpt = None
                 }
-
-            return tcInfo, sink, implFile, fileName
         }
 
-    let mergeIntermediateResults bootstrapInfo =
-        Array.fold (fun (a: TcInfo, _, _, _) (b, sink, implFileOpt: CheckedImplFile option, name) ->
-            // TODO: proper merge
-
-            let amap = bootstrapInfo.TcImports.GetImportMap()
-
-            // TODO: figure out
-            let hadSig = false
-
-            let prefixPathOpt = None
-
-            let ccuSigForFile, tcState =
-                match implFileOpt with 
-                | Some implFile ->
-
-                    let ccuSigForFile, tcState =
-                        AddCheckResultsToTcState
-                            (bootstrapInfo.TcGlobals, amap, hadSig, prefixPathOpt, TcResultsSink.NoSink, a.tcState.TcEnvFromImpls, implFile.QualifiedNameOfFile, implFile.Signature)
-                            b.tcState
-                    Some ccuSigForFile, tcState
-                | None ->
-                    b.latestCcuSigForFile, b.tcState
-
-            { a with
+    let mergeIntermediateResults =
+        Array.fold (fun (tcInfo: TcInfo) (tcIntermediate: TcIntermediate) -> 
+            let (tcEnv, topAttribs, _checkImplFileOpt, ccuSigForFile), tcState = tcInfo.tcState |> tcIntermediate.finisher.Invoke
+            let tcEnvAtEndOfFile = if keepAllBackgroundResolutions then tcEnv else tcState.TcEnvFromImpls
+            { tcInfo with
                 tcState = tcState
-                tcEnvAtEndOfFile = b.tcEnvAtEndOfFile
-                moduleNamesDict = b.moduleNamesDict
-                latestCcuSigForFile = ccuSigForFile
-                tcDiagnosticsRev = b.tcDiagnosticsRev @ a.tcDiagnosticsRev
-                topAttribs = b.topAttribs
-                tcDependencyFiles = b.tcDependencyFiles @ a.tcDependencyFiles
-                // we shouldn't need this with graph checking (?)
-                sigNameOpt = None
-            }, sink, implFileOpt, name)
+                tcEnvAtEndOfFile = tcEnvAtEndOfFile
+                topAttribs = Some topAttribs
+                tcDiagnosticsRev = tcIntermediate.tcDiagnosticsRev @ tcInfo.tcDiagnosticsRev
+                tcDependencyFiles = tcIntermediate.tcDependencyFiles @ tcInfo.tcDependencyFiles
+                latestCcuSigForFile = Some ccuSigForFile })
+
 
     // Type check everything that is needed to check given file
     let ComputeTcPrior (file: FSharpFile) (bootstrapInfo: BootstrapInfo) (projectSnapshot: FSharpProjectSnapshot) _userOpName _key =
@@ -769,28 +753,25 @@ type internal TransparentCompiler
                                     let key = projectSnapshot.UpTo(fileIndex).Key
                                     TcIntermediateCache.Get(key, ComputeTcIntermediate (parsedInput, parseErrors) bootstrapInfo tcInfo)
                                 | NodeToTypeCheck.ArtificialImplFile fileIndex ->
-                                    let parsedInput, _parseErrors, _ = parsedInputs[fileIndex]
-                                    let tcState = tcInfo.tcState
-                                    let prefixPathOpt = None
-                                    
-                                    let (tcEnv , topAttribs , checkedImplFileOpt , _moduleOrNamespaceType), newTcState =
+
+                                    let finisher tcState = 
+                                        let parsedInput, _parseErrors, _ = parsedInputs[fileIndex]
+                                        let prefixPathOpt = None
                                         // Retrieve the type-checked signature information and add it to the TcEnvFromImpls.
                                         AddSignatureResultToTcImplEnv(bootstrapInfo.TcImports, bootstrapInfo.TcGlobals, prefixPathOpt, TcResultsSink.NoSink, tcState, parsedInput) tcState
-                                    let tcInfo =
-                                        { tcInfo with
-                                            tcState = newTcState
-                                            tcEnvAtEndOfFile = tcEnv
-
-                                            topAttribs = Some topAttribs
-                                            // we shouldn't need this with graph checking (?)
-                                            sigNameOpt = None
+                                    let tcIntermediate =
+                                        {
+                                            finisher = finisher
+                                            moduleNamesDict = tcInfo.moduleNamesDict
+                                            tcDiagnosticsRev = []
+                                            tcDependencyFiles = []
                                         }
 
-                                    node.Return(tcInfo, Unchecked.defaultof<_>, checkedImplFileOpt, parsedInput.FileName))
+                                    node.Return(tcIntermediate))
                             |> NodeCode.Parallel
-                        let nodes = layer |> Seq.map (function NodeToTypeCheck.PhysicalFile i -> fileNames[i] | NodeToTypeCheck.ArtificialImplFile i -> $"AIF : {fileNames[i]}") |> String.concat " "
-                        Trace.TraceInformation $"Processed layer {nodes}"
-                        return! processLayer rest (mergeIntermediateResults bootstrapInfo (tcInfo, Unchecked.defaultof<_>, None, "") results |> p14)
+                        //let nodes = layer |> Seq.map (function NodeToTypeCheck.PhysicalFile i -> fileNames[i] | NodeToTypeCheck.ArtificialImplFile i -> $"AIF : {fileNames[i]}") |> String.concat " "
+                        //Trace.TraceInformation $"Processed layer {nodes}"
+                        return! processLayer rest (mergeIntermediateResults tcInfo results)
                 }
 
             return! processLayer layers bootstrapInfo.InitialTcInfo
@@ -836,7 +817,7 @@ type internal TransparentCompiler
                         input = parseTree,
                         parseHadErrors = (parseDiagnostics.Length > 0),
                         // TODO: check if we really need this in parse results
-                        dependencyFiles = [||]
+                        dependencyFiles = Array.ofList tcInfo.tcDependencyFiles
                     )
 
                 let! checkResults =
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
index ea679f5476d..636e7cd7a64 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
+++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
@@ -41,6 +41,8 @@ module Activity =
 
     let listenToAll () = listen ""
 
+open Activity
+
 
 []
 let ``Use Transparent Compiler`` () =
@@ -88,6 +90,8 @@ let ``Parallel processing`` () =
 
     ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
         checkFile "E" expectOk
+        updateFile "A" updatePublicSurface
+        checkFile "E" expectSignatureChanged
     }
 
 
@@ -104,9 +108,15 @@ let ``Parallel processing with signatures`` () =
         sourceFile "E" ["B"; "C"; "D"] |> addSignatureFile)
 
     ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
-        checkFile "C" expectOk
-        //updateFile "A" updatePublicSurface
-        //checkFile "E" expectSignatureChanged
+        checkFile "E" expectOk
+        updateFile "A" updatePublicSurface
+        checkFile "E" expectNoChanges
+        regenerateSignature "A"
+        regenerateSignature "B"
+        regenerateSignature "C"
+        regenerateSignature "D"
+        regenerateSignature "E"
+        checkFile "E" expectSignatureChanged
     }
 
 
@@ -161,6 +171,20 @@ let ``Files depend on signature file if present`` () =
         checkFile "Second" expectNoChanges
     }
 
+[]
+let ``Signature update`` () =
+    listenToAll ()
+
+    let project = makeTestProject() |> updateFile "First" addSignatureFile
+
+    ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
+        updateFile "First" updatePublicSurface
+        saveFile "First"
+        checkFile "Second" expectNoChanges
+        regenerateSignature "First"
+        checkFile "Second" expectSignatureChanged
+    }
+
 []
 let ``Adding a file`` () =
     testWorkflow() {
diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
index 0acd065dbe6..4f8a36ebf06 100644
--- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs
+++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
@@ -696,6 +696,21 @@ type ProjectWorkflowBuilder
                 return project
             })
 
+    []
+    member this.RegenerateSignature(workflow: Async, fileId: string) =
+        workflow
+        |> mapProjectAsync (fun project ->
+            async {
+                use _ =
+                    Activity.start "ProjectWorkflowBuilder.RegenerateSignature" [ Activity.Tags.project, project.Name; "fileId", fileId ]
+                let project, file = project.FindInAllProjects fileId                
+                let! result = checkFile fileId project checker
+                let signature = getSignature result
+                let signatureFileName = getSignatureFilePath project file
+                writeFileIfChanged signatureFileName signature
+                return project
+            })
+
     /// Add a file above given file in the project.
     []
     member this.AddFileAbove(workflow: Async, addAboveId: string, newFile) =
From 2273ffe93c9f17db26256d2735b7d2d422d90dd0 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Thu, 11 May 2023 12:48:54 +0200
Subject: [PATCH 026/222] wip
---
 src/Compiler/Driver/ParseAndCheckInputs.fsi   | 21 +++++++++----------
 .../FSharpChecker/TransparentCompiler.fs      | 17 ++++++++-------
 .../TypeChecks/Graph/GraphOperations.fs       |  2 +-
 .../ProjectGeneration.fs                      | 17 ++++++++-------
 4 files changed, 30 insertions(+), 27 deletions(-)
diff --git a/src/Compiler/Driver/ParseAndCheckInputs.fsi b/src/Compiler/Driver/ParseAndCheckInputs.fsi
index 37e76d82d48..9758fc5d0b0 100644
--- a/src/Compiler/Driver/ParseAndCheckInputs.fsi
+++ b/src/Compiler/Driver/ParseAndCheckInputs.fsi
@@ -163,7 +163,6 @@ type TcState =
 
     member CreatesGeneratedProvidedTypes: bool
 
-
 type PartialResult = TcEnv * TopAttribs * CheckedImplFile option * ModuleOrNamespaceType
 
 /// Get the initial type checking state for a set of inputs
@@ -187,16 +186,16 @@ val CheckOneInput:
         Cancellable<(TcEnv * TopAttribs * CheckedImplFile option * ModuleOrNamespaceType) * TcState>
 
 val CheckOneInputWithCallback:
-      checkForErrors: (unit -> bool) *
-      tcConfig: TcConfig *
-      tcImports: TcImports *
-      tcGlobals: TcGlobals *
-      prefixPathOpt: LongIdent option *
-      tcSink: TcResultsSink *
-      tcState: TcState *
-      input: ParsedInput *
-      _skipImplIfSigExists: bool -> Cancellable>
-
+    checkForErrors: (unit -> bool) *
+    tcConfig: TcConfig *
+    tcImports: TcImports *
+    tcGlobals: TcGlobals *
+    prefixPathOpt: LongIdent option *
+    tcSink: TcResultsSink *
+    tcState: TcState *
+    input: ParsedInput *
+    _skipImplIfSigExists: bool ->
+        Cancellable>
 
 val AddCheckResultsToTcState:
     tcGlobals: TcGlobals *
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
index 636e7cd7a64..d474f5f0734 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
+++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
@@ -41,8 +41,6 @@ module Activity =
 
     let listenToAll () = listen ""
 
-open Activity
-
 
 []
 let ``Use Transparent Compiler`` () =
@@ -173,15 +171,18 @@ let ``Files depend on signature file if present`` () =
 
 []
 let ``Signature update`` () =
-    listenToAll ()
+    Activity.listenToAll ()
 
-    let project = makeTestProject() |> updateFile "First" addSignatureFile
+    let project = SyntheticProject.Create(
+        { sourceFile "First" [] with
+            Source = "let f x = x"
+            SignatureFile = Custom "val f: x: int -> int" },
+        { sourceFile "Second" ["First"] with
+            Source = "let a x = ModuleFirst.f x" })
 
     ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
-        updateFile "First" updatePublicSurface
-        saveFile "First"
-        checkFile "Second" expectNoChanges
-        regenerateSignature "First"
+        checkFile "Second" expectOk
+        updateFile "First" (fun f -> { f with SignatureFile = Custom "val f: x: string -> string" })
         checkFile "Second" expectSignatureChanged
     }
 
diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs
index dedac14ba76..b71add124ca 100644
--- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs
+++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphOperations.fs
@@ -41,7 +41,7 @@ let ``See what this does`` () =
         sourceFile "E" ["A"; "B"; "C"] |> addSignatureFile,
         sourceFile "F" ["C"; "D"] |> addSignatureFile
     ).Workflow {
-        withProject (fun project checker -> 
+        withProject (fun project checker ->
             async {
                 let options = project.GetProjectOptions checker
                 let options, _ = checker.GetParsingOptionsFromProjectOptions options
diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
index 4f8a36ebf06..8e1eac488e8 100644
--- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs
+++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
@@ -23,6 +23,7 @@ open FSharp.Compiler.Diagnostics
 open FSharp.Compiler.Text
 open Xunit
 open System.Collections.Concurrent
+open System.Text
 
 #nowarn "57" // Experimental feature use
 
@@ -362,22 +363,24 @@ module ProjectOperations =
 
     let getFileSnapshot (project: SyntheticProject) _options (path: string) =
         async {
-            let file, filePath =
+            let filePath =
                 if path.EndsWith(".fsi") then
                     let implFilePath = path[..path.Length - 2]
                     let f = project.FindByPath implFilePath
-                    f, getSignatureFilePath project f
+                    getSignatureFilePath project f
                 else
                     let f = project.FindByPath path
-                    f, getFilePath project f
+                    getFilePath project f
 
-            let dependencies = file.DependsOn |> String.concat "|"
-            let version = $"{file.PublicVersion}|{file.InternalVersion}|{file.FunctionName}|{file.Source.GetHashCode()}|{file.ExtraSource.GetHashCode()}|{dependencies}"
+            let source = getSourceText project path
+            use md5 = System.Security.Cryptography.MD5.Create()
+            let inputBytes = Encoding.UTF8.GetBytes(source.ToString())
+            let hash = md5.ComputeHash(inputBytes) |> Array.map (fun b -> b.ToString("X2")) |> String.concat ""
 
             return {
                 FileName = filePath
-                Version = version
-                GetSource = fun () -> getSourceText project path |> Task.FromResult
+                Version = hash
+                GetSource = fun () -> source |> Task.FromResult
             }
         }
 
From ff4d5e615b7f7e67915ff8f9ffa29788822870ef Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Fri, 12 May 2023 13:55:31 +0200
Subject: [PATCH 027/222] BootstrapInfoStatic, activity reorganization
---
 src/Compiler/Facilities/AsyncMemoize.fs       | 27 +++-------
 src/Compiler/Service/BackgroundCompiler.fs    |  6 +++
 src/Compiler/Service/FSharpCheckerResults.fs  |  5 ++
 src/Compiler/Service/FSharpCheckerResults.fsi |  3 ++
 src/Compiler/Service/TransparentCompiler.fs   | 54 ++++++++++++++-----
 src/Compiler/Service/service.fs               |  2 +
 src/Compiler/Service/service.fsi              |  2 +
 src/Compiler/Utilities/Activity.fs            |  1 +
 src/Compiler/Utilities/Activity.fsi           |  1 +
 .../CompilerService/AsyncMemoize.fs           | 12 ++---
 .../FSharpChecker/TransparentCompiler.fs      | 11 ++--
 11 files changed, 80 insertions(+), 44 deletions(-)
diff --git a/src/Compiler/Facilities/AsyncMemoize.fs b/src/Compiler/Facilities/AsyncMemoize.fs
index 941cacb8013..8211228e711 100644
--- a/src/Compiler/Facilities/AsyncMemoize.fs
+++ b/src/Compiler/Facilities/AsyncMemoize.fs
@@ -3,7 +3,6 @@ namespace Internal.Utilities.Collections
 open FSharp.Compiler.BuildGraph
 open System.Threading
 open System.Collections.Generic
-open FSharp.Compiler.Diagnostics
 
 type internal Action<'TKey, 'TValue> =
     | GetOrCompute of ('TKey -> NodeCode<'TValue>) * CancellationToken
@@ -16,23 +15,15 @@ type internal Job<'TValue> =
     | Running of NodeCode<'TValue> * CancellationTokenSource
     | Completed of NodeCode<'TValue>
 
-type internal JobEvent<'TKey> =
-    | Started of 'TKey
-    | Finished of 'TKey
-    | Canceled of 'TKey
+type internal JobEventType =
+    | Started
+    | Finished
+    | Canceled
 
-    member this.Key =
-        match this with
-        | Started key -> key
-        | Finished key -> key
-        | Canceled key -> key
-
-type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?logEvent: (JobEvent<'TKey> -> unit), ?name: string) =
+type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?logEvent: (JobEventType * 'TKey -> unit)) =
 
     let tok = obj ()
 
-    let name = name |> Option.defaultValue "Unnamed"
-
     let cache =
         MruCache<_, 'TKey, Job<'TValue>>(keepStrongly = 10, areSame = (fun (x, y) -> x = y))
 
@@ -76,8 +67,7 @@ type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?logEvent: (JobE
                             Async.StartAsTask(
                                 Async.AwaitNodeCode(
                                     node {
-                                        use _ = Activity.start $"AsyncMemoize.{name}" [||]
-                                        log (Started key)
+                                        log (Started, key)
                                         let! result = computation key
                                         post key JobCompleted
                                         return result
@@ -106,7 +96,7 @@ type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?logEvent: (JobE
                             cts.Cancel()
                             cache.RemoveAnySimilar(tok, key)
                             requestCounts.Remove key |> ignore
-                            log (Canceled key)
+                            log (Canceled, key)
 
                     | CancelRequest, None
                     | CancelRequest, Some (Completed _) -> ()
@@ -115,10 +105,9 @@ type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?logEvent: (JobE
                         // TODO: should we re-wrap the result?
                         cache.Set(tok, key, (Completed job))
                         requestCounts.Remove key |> ignore
-                        log (Finished key)
+                        log (Finished, key)
 
                     | JobCompleted, _ -> failwith "If this happens there's a bug"
-
             })
 
     member _.Get(key, computation) =
diff --git a/src/Compiler/Service/BackgroundCompiler.fs b/src/Compiler/Service/BackgroundCompiler.fs
index ddf9d3f0c04..3b1039066eb 100644
--- a/src/Compiler/Service/BackgroundCompiler.fs
+++ b/src/Compiler/Service/BackgroundCompiler.fs
@@ -150,6 +150,8 @@ type internal IBackgroundCompiler =
 
     abstract member ProjectChecked: IEvent
 
+    abstract member CacheEvent: IEvent
+
 type ParseCacheLockToken() =
     interface LockToken
 
@@ -234,6 +236,8 @@ type internal BackgroundCompiler
     let fileChecked = Event()
     let projectChecked = Event()
 
+    let cacheEvent = Event()
+
     // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.backgroundCompiler.scriptClosureCache
     /// Information about the derived script closure.
     let scriptClosureCache =
@@ -1378,6 +1382,8 @@ type internal BackgroundCompiler
 
     interface IBackgroundCompiler with
 
+        member _.CacheEvent = cacheEvent.Publish
+
         member _.BeforeBackgroundFileCheck = self.BeforeBackgroundFileCheck
 
         member _.CheckFileInProject
diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs
index 9f7973d90c7..8a92f3b229d 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fs
+++ b/src/Compiler/Service/FSharpCheckerResults.fs
@@ -218,6 +218,11 @@ type FSharpProjectSnapshot =
 
     member this.SourceFileNames = this.SourceFiles |> List.map (fun x -> x.FileName)
 
+    member this.WithoutFileVersions =
+        { this with
+            SourceFiles = this.SourceFiles |> List.map (fun x -> { x with Version = "" })
+        }
+
     override this.ToString() =
         "FSharpProjectSnapshot(" + this.ProjectFileName + ")"
 
diff --git a/src/Compiler/Service/FSharpCheckerResults.fsi b/src/Compiler/Service/FSharpCheckerResults.fsi
index 43052e69f9c..2bd4cbbd990 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fsi
+++ b/src/Compiler/Service/FSharpCheckerResults.fsi
@@ -121,6 +121,9 @@ type FSharpProjectSnapshot =
     /// A snapshot of the same project but only up to the given file (including).
     member UpTo: fileName: string -> FSharpProjectSnapshot
 
+    /// A snapshot of the same project with file versions removed.
+    member WithoutFileVersions: FSharpProjectSnapshot
+
     member Key: FSharpProjectSnapshotKey
 
 and [] public FSharpReferencedProjectSnapshot =
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 8df2390ea49..03f70792a0d 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -94,13 +94,17 @@ type internal TransparentCompiler
     // Is having just one of these ok?
     let lexResourceManager = Lexhelp.LexResourceManager()
 
-    let ParseFileCache = AsyncMemoize(name = "ParseFile")
-    let ParseAndCheckFileInProjectCache = AsyncMemoize(name = "ParseAndCheckFileInProject")
-    let FrameworkImportsCache = AsyncMemoize(name = "FrameworkImports")
-    let BootstrapInfoCache = AsyncMemoize(name = "BootstrapInfo")
-    let TcPriorCache = AsyncMemoize(name = "TcPrior")
-    let TcIntermediateCache = AsyncMemoize(name = "TcIntermediate")
-    let DependencyGraphForLastFileCache = AsyncMemoize(name = "DependencyGraphForLastFile")
+    let cacheEvent = new Event()
+
+    let ParseFileCache = 
+        AsyncMemoize(logEvent = fun (e, ((fileName, version), _, _)) -> cacheEvent.Trigger("ParseFile", e, [| fileName; version |] ))
+    let ParseAndCheckFileInProjectCache = AsyncMemoize()
+    let FrameworkImportsCache = AsyncMemoize()
+    let BootstrapInfoStaticCache = AsyncMemoize()
+    let BootstrapInfoCache = AsyncMemoize()
+    let TcPriorCache = AsyncMemoize()
+    let TcIntermediateCache = AsyncMemoize()
+    let DependencyGraphForLastFileCache = AsyncMemoize()
 
     // We currently share one global dependency provider for all scripts for the FSharpChecker.
     // For projects, one is used per project.
@@ -170,6 +174,7 @@ type internal TransparentCompiler
 
     let ComputeFrameworkImports (tcConfig: TcConfig) frameworkDLLs nonFrameworkResolutions _key =
         node {
+            use _ = Activity.start "ComputeFrameworkImports" []
             let tcConfigP = TcConfigProvider.Constant tcConfig
             return! TcImports.BuildFrameworkTcImports(tcConfigP, frameworkDLLs, nonFrameworkResolutions)
         }
@@ -273,8 +278,11 @@ type internal TransparentCompiler
             return tcImports, tcInfo
         }
 
-    let computeBootstrapInfoInner (projectSnapshot: FSharpProjectSnapshot) =
+    /// Bootstrap info that does not depend on contents of the files
+    let ComputeBootstrapInfoStatic (projectSnapshot: FSharpProjectSnapshot) _key =
         node {
+            use _ = Activity.start "ComputeBootstrapInfoStatic" [| Activity.Tags.project, projectSnapshot.ProjectFileName |> Path.GetFileName |]
+
             let useSimpleResolutionSwitch = "--simpleresolution"
             let commandLineArgs = projectSnapshot.OtherOptions
             let defaultFSharpBinariesDir = FSharpCheckerResultsSettings.defaultFSharpBinariesDir
@@ -455,9 +463,9 @@ type internal TransparentCompiler
 
             let tcConfigP = TcConfigProvider.Constant tcConfig
 
-#if !NO_TYPEPROVIDERS
+    #if !NO_TYPEPROVIDERS
             let importsInvalidatedByTypeProvider = Event()
-#endif
+    #endif
 
             // Check for the existence of loaded sources and prepend them to the sources list if present.
             let sourceFiles =
@@ -506,10 +514,18 @@ type internal TransparentCompiler
                     dependencyProvider,
                     loadClosureOpt,
                     basicDependencies
-#if !NO_TYPEPROVIDERS
+    #if !NO_TYPEPROVIDERS
                     ,importsInvalidatedByTypeProvider
-#endif
+    #endif
                 )
+            return sourceFiles, tcConfig, tcImports, tcGlobals, initialTcInfo, loadClosureOpt
+        }
+
+    let computeBootstrapInfoInner (projectSnapshot: FSharpProjectSnapshot) =
+        node {
+            let bootstrapStaticKey = projectSnapshot.WithoutFileVersions.Key
+
+            let! sourceFiles, tcConfig, tcImports, tcGlobals, initialTcInfo, loadClosureOpt = BootstrapInfoStaticCache.Get(bootstrapStaticKey, ComputeBootstrapInfoStatic projectSnapshot)
 
             let fileSnapshots = Map [ for f in projectSnapshot.SourceFiles -> f.FileName, f ]
 
@@ -547,6 +563,7 @@ type internal TransparentCompiler
 
     let ComputeBootstrapInfo (projectSnapshot: FSharpProjectSnapshot) _key =
         node {
+            use _ = Activity.start "ComputeBootstrapInfo" [| Activity.Tags.project, projectSnapshot.ProjectFileName |> Path.GetFileName |]
 
             // Trap and report diagnostics from creation.
             let delayedLogger = CapturingDiagnosticsLogger("IncrementalBuilderCreation")
@@ -580,6 +597,8 @@ type internal TransparentCompiler
 
     let ComputeParseFile (file: FSharpFile) bootstrapInfo _key =
         node {
+            use _ = Activity.start "ComputeParseFile" [| Activity.Tags.fileName, file.Source.FileName |> Path.GetFileName; Activity.Tags.version, file.Source.Version |]
+            
             let tcConfig = bootstrapInfo.TcConfig
 
             let diagnosticsLogger =
@@ -599,6 +618,7 @@ type internal TransparentCompiler
 
     let ComputeDependencyGraphForLastFile parsedInputs (tcConfig: TcConfig) _key =
         node {
+
             let sourceFiles: FileInProject array =
                 parsedInputs
                 |> Seq.toArray
@@ -609,6 +629,8 @@ type internal TransparentCompiler
                         ParsedInput = input
                     })
 
+            use _ = Activity.start "ComputeDependencyGraphForLastFile" [| Activity.Tags.fileName, (sourceFiles |> Array.last).FileName |]    
+            
             let filePairs = FilePairMap(sourceFiles)
 
             // TODO: we will probably want to cache and re-use larger graphs if available
@@ -624,6 +646,9 @@ type internal TransparentCompiler
         node {
             let input = parsedInput
             let fileName = input.FileName
+            
+            use _ = Activity.start "ComputeTcIntermediate" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
+            
             let tcConfig = bootstrapInfo.TcConfig
             let tcGlobals = bootstrapInfo.TcGlobals
             let tcImports = bootstrapInfo.TcImports
@@ -695,6 +720,8 @@ type internal TransparentCompiler
     // Type check everything that is needed to check given file
     let ComputeTcPrior (file: FSharpFile) (bootstrapInfo: BootstrapInfo) (projectSnapshot: FSharpProjectSnapshot) _userOpName _key =
         node {
+            
+            use _ = Activity.start "ComputeTcPrior" [| Activity.Tags.fileName, file.Source.FileName |> Path.GetFileName |]
 
             // parse required files
             let files =
@@ -779,6 +806,8 @@ type internal TransparentCompiler
 
     let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: FSharpProjectSnapshot) userOpName _key =
         node {
+            
+            use _ = Activity.start "ComputeParseAndCheckFileInProject" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
 
             let! bootstrapInfoOpt, creationDiags = BootstrapInfoCache.Get(projectSnapshot.Key, ComputeBootstrapInfo projectSnapshot)
 
@@ -854,6 +883,7 @@ type internal TransparentCompiler
         }
 
     interface IBackgroundCompiler with
+        member _.CacheEvent = cacheEvent.Publish
 
         member this.BeforeBackgroundFileCheck: IEvent =
             backgroundCompiler.BeforeBackgroundFileCheck
diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs
index 83a005c258e..dacc23cd47f 100644
--- a/src/Compiler/Service/service.fs
+++ b/src/Compiler/Service/service.fs
@@ -586,6 +586,8 @@ type FSharpChecker
 
     member _.ProjectChecked = backgroundCompiler.ProjectChecked
 
+    member _.CacheEvent = backgroundCompiler.CacheEvent
+
     static member ActualParseFileCount = BackgroundCompiler.ActualParseFileCount
 
     static member ActualCheckFileCount = BackgroundCompiler.ActualCheckFileCount
diff --git a/src/Compiler/Service/service.fsi b/src/Compiler/Service/service.fsi
index 97bde85058f..d52e0c1f44e 100644
--- a/src/Compiler/Service/service.fsi
+++ b/src/Compiler/Service/service.fsi
@@ -428,6 +428,8 @@ type public FSharpChecker =
     /// The event may be raised on a background thread.
     member ProjectChecked: IEvent
 
+    member internal CacheEvent: IEvent
+
     []
     static member Instance: FSharpChecker
     member internal FrameworkImportsCache: FrameworkImportsCache
diff --git a/src/Compiler/Utilities/Activity.fs b/src/Compiler/Utilities/Activity.fs
index e3b29dd6fd0..b64100a02fd 100644
--- a/src/Compiler/Utilities/Activity.fs
+++ b/src/Compiler/Utilities/Activity.fs
@@ -33,6 +33,7 @@ module internal Activity =
         let gc2 = "gc2"
         let outputDllFile = "outputDllFile"
         let buildPhase = "buildPhase"
+        let version = "version"
 
         let AllKnownTags =
             [|
diff --git a/src/Compiler/Utilities/Activity.fsi b/src/Compiler/Utilities/Activity.fsi
index 94784c97f00..b05f0c4ba54 100644
--- a/src/Compiler/Utilities/Activity.fsi
+++ b/src/Compiler/Utilities/Activity.fsi
@@ -29,6 +29,7 @@ module internal Activity =
         val length: string
         val cache: string
         val buildPhase: string
+        val version: string
 
     module Events =
         val cacheHit: string
diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
index 41880ac0d96..0def4960fd6 100644
--- a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
+++ b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
@@ -35,10 +35,10 @@ let ``Basics``() =
 
     Assert.Equal(expected, result)
 
-    let groups = eventLog |> Seq.groupBy (fun e -> e.Key) |> Seq.toList
+    let groups = eventLog |> Seq.groupBy snd |> Seq.toList
     Assert.Equal(3, groups.Length)
     for key, events in groups do
-        Assert.Equal array>([| Started key; Finished key |], events |> Seq.toArray)
+        Assert.Equal<(JobEventType * int) array>([| Started, key; Finished, key |], events |> Seq.toArray)
 
 []
 let ``We can cancel a job`` () =
@@ -67,20 +67,20 @@ let ``We can cancel a job`` () =
 
     resetEvent.WaitOne() |> ignore
 
-    Assert.Equal array>([| Started key |], eventLog |> Seq.toArray )
+    Assert.Equal<(JobEventType * int) array>([| Started, key |], eventLog |> Seq.toArray )
 
     cts1.Cancel()
     cts2.Cancel()
 
     Thread.Sleep 10
 
-    Assert.Equal array>([| Started key |], eventLog |> Seq.toArray )
+    Assert.Equal<(JobEventType * int) array>([| Started, key |], eventLog |> Seq.toArray )
 
     cts3.Cancel()
 
     Thread.Sleep 100
 
-    Assert.Equal array>([| Started key; Canceled key |], eventLog |> Seq.toArray )
+    Assert.Equal<(JobEventType * int) array>([| Started, key; Canceled, key |], eventLog |> Seq.toArray )
 
     try
         Task.WaitAll(_task1, _task2, _task3)
@@ -117,5 +117,5 @@ let ``Job keeps running even if first requestor cancels`` () =
     Assert.Equal(2, result)
 
     Thread.Sleep 1 // Wait for event log to be updated
-    Assert.Equal array>([| Started key; Finished key |], eventLog |> Seq.toArray )
+    Assert.Equal<(JobEventType * int) array>([| Started, key; Finished, key |], eventLog |> Seq.toArray )
 
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
index d474f5f0734..9951aedfdb7 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
+++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
@@ -1,14 +1,11 @@
 module FSharp.Compiler.ComponentTests.FSharpChecker.TransparentCompiler
 
-open System
-open System.IO
+open System.Collections.Concurrent
 open System.Diagnostics
 
 open Xunit
 
 open FSharp.Test.ProjectGeneration
-open FSharp.Compiler.Text
-open FSharp.Compiler.CodeAnalysis
 
 module Activity =
     let listen (filter: string) =
@@ -41,7 +38,6 @@ module Activity =
 
     let listenToAll () = listen ""
 
-
 []
 let ``Use Transparent Compiler`` () =
 
@@ -92,7 +88,6 @@ let ``Parallel processing`` () =
         checkFile "E" expectSignatureChanged
     }
 
-
 []
 let ``Parallel processing with signatures`` () =
 
@@ -105,7 +100,10 @@ let ``Parallel processing with signatures`` () =
         sourceFile "D" ["A"] |> addSignatureFile,
         sourceFile "E" ["B"; "C"; "D"] |> addSignatureFile)
 
+    let cacheEvents = ConcurrentBag<_>()
+
     ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
+        withChecker (fun checker -> checker.CacheEvent.Add cacheEvents.Add)
         checkFile "E" expectOk
         updateFile "A" updatePublicSurface
         checkFile "E" expectNoChanges
@@ -117,7 +115,6 @@ let ``Parallel processing with signatures`` () =
         checkFile "E" expectSignatureChanged
     }
 
-
 let makeTestProject () =
     SyntheticProject.Create(
         sourceFile "First" [],
From 0b93dd14a9d2c0dc8bebf7214c259dd105d43760 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Fri, 12 May 2023 16:32:10 +0200
Subject: [PATCH 028/222] ...
---
 tests/FSharp.Test.Utilities/ProjectGeneration.fs | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
index 8e1eac488e8..2c223126984 100644
--- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs
+++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
@@ -680,6 +680,14 @@ type ProjectWorkflowBuilder
                 return project
             })
 
+    []
+    member this.WithChecker(workflow: Async, f) =
+        async {
+            let! ctx = workflow
+            f checker
+            return ctx
+        }
+
     /// Change contents of given file using `processFile` function.
     /// Does not save the file to disk.
     []
@@ -737,10 +745,11 @@ type ProjectWorkflowBuilder
     []
     member this.CheckFile(workflow: Async, fileId: string, processResults) =
         async {
+            let! ctx = workflow
+
             use _ =
                 Activity.start "ProjectWorkflowBuilder.CheckFile" [ Activity.Tags.project, initialProject.Name; "fileId", fileId ]
 
-            let! ctx = workflow
             let! results = checkFile fileId ctx.Project checker
 
             let oldSignature = ctx.Signatures[fileId]
@@ -753,10 +762,10 @@ type ProjectWorkflowBuilder
 
     member this.CheckFile(workflow: Async, fileId: string, processResults) =
         async {
+            let! ctx = workflow
             use _ =
                 Activity.start "ProjectWorkflowBuilder.CheckFile" [ Activity.Tags.project, initialProject.Name; "fileId", fileId ]
 
-            let! ctx = workflow
             let! results = checkFile fileId ctx.Project checker
             let typeCheckResults = getTypeCheckResult results
 
From c088cbbace76170941b2e0b25e3c647baf1822b7 Mon Sep 17 00:00:00 2001
From: Petr Pokorny 
Date: Mon, 15 May 2023 14:24:41 +0200
Subject: [PATCH 029/222] Local activity tracing for tests
---
 eng/Versions.props                            |  2 +-
 .../FSharp.Test.Utilities.fsproj              |  5 ++--
 .../ProjectGeneration.fs                      | 29 ++++++++++++++++---
 3 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/eng/Versions.props b/eng/Versions.props
index 9a57897d2ad..2f81dd45ef5 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -97,7 +97,7 @@
     4.5.1
     6.0.0
     1.6.0
-    6.0.0
+    7.0.0
     4.5.5
     4.7.0
     6.0.1
diff --git a/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj b/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj
index 0cd32d852f9..b6c455a5499 100644
--- a/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj
+++ b/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj
@@ -66,7 +66,7 @@
 
   
     
-    
+    
     
     
     
@@ -78,6 +78,7 @@
     
     
     
+    
   
 
   
@@ -107,6 +108,4 @@
     
   
 
-  
-
 
diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
index cd873ddbb0d..4501af8ffc1 100644
--- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs
+++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
@@ -23,6 +23,10 @@ open FSharp.Compiler.Text
 open Xunit
 open System.Collections.Concurrent
 
+open OpenTelemetry
+open OpenTelemetry.Resources
+open OpenTelemetry.Trace
+
 #nowarn "57" // Experimental feature use
 
 let private projectRoot = "test-projects"
@@ -546,6 +550,8 @@ type ProjectWorkflowBuilder
     let useChangeNotifications = defaultArg useChangeNotifications false
 
     let mutable latestProject = initialProject
+    let mutable activity = None
+    let mutable tracerProvider = None
 
     let getSource (filePath: string) =
         if filePath.EndsWith(".fsi") then
@@ -600,10 +606,21 @@ type ProjectWorkflowBuilder
 
     member this.Checker = checker
 
-    member this.Yield _ =
-        match initialContext with
-        | Some ctx -> async.Return ctx
-        | _ -> SaveAndCheckProject initialProject checker
+    member this.Yield _ = async {
+        let! ctx =
+            match initialContext with
+            | Some ctx -> async.Return ctx
+            | _ -> SaveAndCheckProject initialProject checker
+        tracerProvider <-
+            Sdk.CreateTracerProviderBuilder()
+                .AddSource("fsc")
+                .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(serviceName="F#", serviceVersion = "1"))
+                .AddJaegerExporter()
+                .Build()
+            |> Some
+        activity <- Activity.start ctx.Project.Name [ Activity.Tags.project, ctx.Project.Name ] |> Some
+        return ctx
+    }
 
     member this.DeleteProjectDir() =
         if Directory.Exists initialProject.ProjectDir then
@@ -615,6 +632,10 @@ type ProjectWorkflowBuilder
         finally
             if initialContext.IsNone then
                 this.DeleteProjectDir()
+            activity |> Option.iter (fun x -> x.Dispose())
+            tracerProvider |> Option.iter (fun x ->
+                x.ForceFlush() |> ignore
+                x.Dispose())
 
     /// Change contents of given file using `processFile` function.
     /// Does not save the file to disk.
From 33afd1f516f5392cd8db9d7f728fcb02ada0d5a0 Mon Sep 17 00:00:00 2001
From: Petr Pokorny 
Date: Mon, 15 May 2023 17:54:26 +0200
Subject: [PATCH 030/222] wip
---
 src/Compiler/Facilities/AsyncMemoize.fs       |  4 +-
 src/Compiler/Service/BackgroundCompiler.fs    |  7 ++
 src/Compiler/Service/TransparentCompiler.fs   | 59 ++++++++++++--
 src/Compiler/Service/service.fs               |  5 ++
 src/Compiler/Service/service.fsi              |  3 +
 .../CompilerService/AsyncMemoize.fs           | 24 +++---
 .../FSharpChecker/TransparentCompiler.fs      |  2 +-
 .../LanguageService/WorkspaceExtensions.fs    | 80 +++++++++++--------
 .../FSharp.Editor/Options/EditorOptions.fs    |  2 +-
 9 files changed, 129 insertions(+), 57 deletions(-)
diff --git a/src/Compiler/Facilities/AsyncMemoize.fs b/src/Compiler/Facilities/AsyncMemoize.fs
index 8211228e711..581e6201193 100644
--- a/src/Compiler/Facilities/AsyncMemoize.fs
+++ b/src/Compiler/Facilities/AsyncMemoize.fs
@@ -5,7 +5,7 @@ open System.Threading
 open System.Collections.Generic
 
 type internal Action<'TKey, 'TValue> =
-    | GetOrCompute of ('TKey -> NodeCode<'TValue>) * CancellationToken
+    | GetOrCompute of NodeCode<'TValue> * CancellationToken
     | CancelRequest
     | JobCompleted
 
@@ -68,7 +68,7 @@ type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?logEvent: (JobE
                                 Async.AwaitNodeCode(
                                     node {
                                         log (Started, key)
-                                        let! result = computation key
+                                        let! result = computation
                                         post key JobCompleted
                                         return result
                                     }
diff --git a/src/Compiler/Service/BackgroundCompiler.fs b/src/Compiler/Service/BackgroundCompiler.fs
index 3b1039066eb..72bba6b4bc3 100644
--- a/src/Compiler/Service/BackgroundCompiler.fs
+++ b/src/Compiler/Service/BackgroundCompiler.fs
@@ -134,6 +134,10 @@ type internal IBackgroundCompiler =
     abstract member ParseFile:
         fileName: string * sourceText: ISourceText * options: FSharpParsingOptions * cache: bool * userOpName: string ->
             Async
+            
+    abstract member ParseFile:
+        fileName: string * projectSnapshot: FSharpProjectSnapshot * userOpName: string ->
+            NodeCode
 
     /// Try to get recent approximate type check results for a file.
     abstract member TryGetRecentCheckResultsForFile:
@@ -1530,6 +1534,9 @@ type internal BackgroundCompiler
             ) : Async =
             self.ParseFile(fileName, sourceText, options, cache, userOpName)
 
+        member _.ParseFile(_fileName: string, _projectSnapshot: FSharpProjectSnapshot, _userOpName: string) =
+            raise (System.NotImplementedException())
+
         member _.ProjectChecked: IEvent = self.ProjectChecked
 
         member _.TryGetRecentCheckResultsForFile
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 03f70792a0d..771d707e43f 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -172,7 +172,7 @@ type internal TransparentCompiler
                         }
         ]
 
-    let ComputeFrameworkImports (tcConfig: TcConfig) frameworkDLLs nonFrameworkResolutions _key =
+    let ComputeFrameworkImports (tcConfig: TcConfig) frameworkDLLs nonFrameworkResolutions =
         node {
             use _ = Activity.start "ComputeFrameworkImports" []
             let tcConfigP = TcConfigProvider.Constant tcConfig
@@ -279,7 +279,7 @@ type internal TransparentCompiler
         }
 
     /// Bootstrap info that does not depend on contents of the files
-    let ComputeBootstrapInfoStatic (projectSnapshot: FSharpProjectSnapshot) _key =
+    let ComputeBootstrapInfoStatic (projectSnapshot: FSharpProjectSnapshot) =
         node {
             use _ = Activity.start "ComputeBootstrapInfoStatic" [| Activity.Tags.project, projectSnapshot.ProjectFileName |> Path.GetFileName |]
 
@@ -561,7 +561,7 @@ type internal TransparentCompiler
                     }
         }
 
-    let ComputeBootstrapInfo (projectSnapshot: FSharpProjectSnapshot) _key =
+    let ComputeBootstrapInfo (projectSnapshot: FSharpProjectSnapshot) =
         node {
             use _ = Activity.start "ComputeBootstrapInfo" [| Activity.Tags.project, projectSnapshot.ProjectFileName |> Path.GetFileName |]
 
@@ -595,7 +595,7 @@ type internal TransparentCompiler
             return bootstrapInfoOpt, diagnostics
         }
 
-    let ComputeParseFile (file: FSharpFile) bootstrapInfo _key =
+    let ComputeParseFile (file: FSharpFile) bootstrapInfo =
         node {
             use _ = Activity.start "ComputeParseFile" [| Activity.Tags.fileName, file.Source.FileName |> Path.GetFileName; Activity.Tags.version, file.Source.Version |]
             
@@ -616,7 +616,7 @@ type internal TransparentCompiler
             return input, diagnosticsLogger.GetDiagnostics(), sourceText
         }
 
-    let ComputeDependencyGraphForLastFile parsedInputs (tcConfig: TcConfig) _key =
+    let ComputeDependencyGraphForLastFile parsedInputs (tcConfig: TcConfig) =
         node {
 
             let sourceFiles: FileInProject array =
@@ -642,7 +642,7 @@ type internal TransparentCompiler
             return TransformDependencyGraph(graph, filePairs), filePairs
         }
 
-    let ComputeTcIntermediate (parsedInput: ParsedInput, parseErrors) bootstrapInfo (prevTcInfo: TcInfo) _key =
+    let ComputeTcIntermediate (parsedInput: ParsedInput, parseErrors) bootstrapInfo (prevTcInfo: TcInfo) =
         node {
             let input = parsedInput
             let fileName = input.FileName
@@ -718,7 +718,7 @@ type internal TransparentCompiler
 
 
     // Type check everything that is needed to check given file
-    let ComputeTcPrior (file: FSharpFile) (bootstrapInfo: BootstrapInfo) (projectSnapshot: FSharpProjectSnapshot) _userOpName _key =
+    let ComputeTcPrior (file: FSharpFile) (bootstrapInfo: BootstrapInfo) (projectSnapshot: FSharpProjectSnapshot) _userOpName =
         node {
             
             use _ = Activity.start "ComputeTcPrior" [| Activity.Tags.fileName, file.Source.FileName |> Path.GetFileName |]
@@ -804,7 +804,7 @@ type internal TransparentCompiler
             return! processLayer layers bootstrapInfo.InitialTcInfo
         }
 
-    let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: FSharpProjectSnapshot) userOpName _key =
+    let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: FSharpProjectSnapshot) userOpName =
         node {
             
             use _ = Activity.start "ComputeParseAndCheckFileInProject" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
@@ -876,6 +876,46 @@ type internal TransparentCompiler
                 return (parseResults, FSharpCheckFileAnswer.Succeeded checkResults)
         }
 
+    member _.ParseFile(fileName, projectSnapshot: FSharpProjectSnapshot, _userOpName) = 
+        node {
+            use _ = Activity.start "ParseFile" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
+            
+            let! bootstrapInfoOpt, creationDiags = BootstrapInfoCache.Get(projectSnapshot.Key, ComputeBootstrapInfo projectSnapshot)
+
+            match bootstrapInfoOpt with
+            | None ->
+                let parseTree = EmptyParsedInput(fileName, (false, false))
+                return FSharpParseFileResults(creationDiags, parseTree, true, [||])
+
+            | Some bootstrapInfo ->
+                
+                let file =
+                    bootstrapInfo.SourceFiles |> List.tryFind (fun f -> f.Source.FileName = fileName) |> Option.defaultWith (fun _ -> failwith ($"File {fileName} not found in project snapshot. Files in project: \n\n" + (bootstrapInfo.SourceFiles |> Seq.map (fun f -> f.Source.FileName) |> String.concat " \n")))
+
+                let! parseTree, parseDiagnostics, _sourceText =
+                    ParseFileCache.Get((file.Source.Key, file.IsLastCompiland, file.IsExe), ComputeParseFile file bootstrapInfo)
+
+                let parseDiagnostics =
+                    DiagnosticHelpers.CreateDiagnostics(
+                        bootstrapInfo.TcConfig.diagnosticsOptions,
+                        false,
+                        fileName,
+                        parseDiagnostics,
+                        suggestNamesForErrors
+                    )
+
+                let diagnostics = [| yield! creationDiags; yield! parseDiagnostics |]
+
+                return
+                    FSharpParseFileResults(
+                        diagnostics = diagnostics,
+                        input = parseTree,
+                        parseHadErrors = (parseDiagnostics.Length > 0),
+                        // TODO: check if we really need this in parse results
+                        dependencyFiles = [||]
+                    )
+        }
+
     member _.ParseAndCheckFileInProject(fileName: string, projectSnapshot: FSharpProjectSnapshot, userOpName: string) =
         node {
             let key = fileName, projectSnapshot.Key
@@ -1031,6 +1071,9 @@ type internal TransparentCompiler
 
         member _.ParseAndCheckProject(options: FSharpProjectOptions, userOpName: string) : NodeCode =
             backgroundCompiler.ParseAndCheckProject(options, userOpName)
+        
+        member this.ParseFile(fileName, projectSnapshot, userOpName) = 
+            this.ParseFile(fileName, projectSnapshot, userOpName)
 
         member _.ParseFile
             (
diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs
index dacc23cd47f..723ddeee6b1 100644
--- a/src/Compiler/Service/service.fs
+++ b/src/Compiler/Service/service.fs
@@ -307,6 +307,11 @@ type FSharpChecker
         let userOpName = defaultArg userOpName "Unknown"
         backgroundCompiler.ParseFile(fileName, sourceText, options, cache, userOpName)
 
+    member _.ParseFile(fileName, projectSnapshot, ?userOpName) =
+        let userOpName = defaultArg userOpName "Unknown"
+        backgroundCompiler.ParseFile(fileName, projectSnapshot, userOpName)
+        |> Async.AwaitNodeCode
+
     member ic.ParseFileInProject(fileName, source: string, options, ?cache: bool, ?userOpName: string) =
         let parsingOptions, _ = ic.GetParsingOptionsFromProjectOptions(options)
         ic.ParseFile(fileName, SourceText.ofString source, parsingOptions, ?cache = cache, ?userOpName = userOpName)
diff --git a/src/Compiler/Service/service.fsi b/src/Compiler/Service/service.fsi
index d52e0c1f44e..98d5c429680 100644
--- a/src/Compiler/Service/service.fsi
+++ b/src/Compiler/Service/service.fsi
@@ -103,6 +103,9 @@ type public FSharpChecker =
         fileName: string * sourceText: ISourceText * options: FSharpParsingOptions * ?cache: bool * ?userOpName: string ->
             Async
 
+    member ParseFile: fileName: string * projectSnapshot: FSharpProjectSnapshot * ?userOpName: string ->
+        Async
+
     /// 
     /// Parses a source code for a file. Returns an AST that can be traversed for various features.
     /// 
diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
index 0def4960fd6..80c137cc603 100644
--- a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
+++ b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
@@ -22,12 +22,12 @@ let ``Basics``() =
 
     let task =
         NodeCode.Parallel(seq {
-            memoize.Get(5, computation)
-            memoize.Get(5, computation)
-            memoize.Get(2, computation)
-            memoize.Get(5, computation)
-            memoize.Get(3, computation)
-            memoize.Get(2, computation)
+            memoize.Get(5, computation 5)
+            memoize.Get(5, computation 5)
+            memoize.Get(2, computation 2)
+            memoize.Get(5, computation 5)
+            memoize.Get(3, computation 3)
+            memoize.Get(2, computation 2)
         }) |> NodeCode.StartAsTask_ForTesting
 
     let result = task.Result
@@ -61,9 +61,9 @@ let ``We can cancel a job`` () =
 
     let key = 1
 
-    let _task1 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation), cts1.Token)
-    let _task2 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation), cts2.Token)
-    let _task3 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation), cts3.Token)
+    let _task1 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation key), cts1.Token)
+    let _task2 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation key), cts2.Token)
+    let _task3 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation key), cts3.Token)
 
     resetEvent.WaitOne() |> ignore
 
@@ -104,9 +104,9 @@ let ``Job keeps running even if first requestor cancels`` () =
 
     let key = 1
 
-    let _task1 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation), cts1.Token)
-    let _task2 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation), cts2.Token)
-    let _task3 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation), cts3.Token)
+    let _task1 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation key), cts1.Token)
+    let _task2 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation key), cts2.Token)
+    let _task3 = NodeCode.StartAsTask_ForTesting(memoize.Get(key, computation key), cts3.Token)
 
     Thread.Sleep 10
 
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
index 9951aedfdb7..d50980ce575 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
+++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
@@ -206,7 +206,7 @@ let ``Changes in a referenced project`` () =
         { makeTestProject() with DependsOn = [library] }
         |> updateFile "First" (addDependency "Library")
 
-    project.Workflow {
+    ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
         updateFile "Library" updatePublicSurface
         saveFile "Library"
         checkFile "Last" expectSignatureChanged
diff --git a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs
index 4e9f681dc96..5e623b51469 100644
--- a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs
+++ b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs
@@ -13,6 +13,40 @@ open FSharp.Compiler.Symbols
 []
 module private CheckerExtensions =
 
+    let getProjectSnapshot (document: Document, options: FSharpProjectOptions) =
+        async {
+             let project = document.Project
+             let solution = project.Solution
+             // TODO cache?
+             let projects =
+                 solution.Projects
+                 |> Seq.map (fun p -> p.FilePath, p.Documents |> Seq.map (fun d -> d.FilePath, d) |> Map)
+                 |> Map
+
+             let getFileSnapshot (options: FSharpProjectOptions) path =
+                 async {
+                     let project = projects[options.ProjectFileName]
+                     let document = project[path]
+                     let! version = document.GetTextVersionAsync() |> Async.AwaitTask
+
+                     let getSource () =
+                         task {
+                             let! sourceText = document.GetTextAsync()
+                             return sourceText.ToFSharpSourceText()
+                         }
+
+                     return
+                         {
+                             FileName = path
+                             Version = version.ToString()
+                             GetSource = getSource
+                         }
+                 }
+
+             return! FSharpProjectSnapshot.FromOptions(options, getFileSnapshot)
+        }
+
+
     type FSharpChecker with
 
         /// Parse the source text from the Roslyn document.
@@ -24,6 +58,12 @@ module private CheckerExtensions =
                 return! checker.ParseFile(document.FilePath, sourceText.ToFSharpSourceText(), parsingOptions, userOpName = userOpName)
             }
 
+        member checker.ParseDocumentUsingTransparentCompiler(document: Document, options: FSharpProjectOptions, userOpName: string) =
+            async {
+                let! projectSnapshot = getProjectSnapshot(document, options)
+                return! checker.ParseFile(document.FilePath, projectSnapshot, userOpName = userOpName)
+            }
+
         member checker.ParseAndCheckDocumentUsingTransparentCompiler
             (
                 document: Document,
@@ -31,36 +71,7 @@ module private CheckerExtensions =
                 userOpName: string
             ) =
             async {
-
-                let project = document.Project
-                let solution = project.Solution
-                // TODO cache?
-                let projects =
-                    solution.Projects
-                    |> Seq.map (fun p -> p.FilePath, p.Documents |> Seq.map (fun d -> d.FilePath, d) |> Map)
-                    |> Map
-
-                let getFileSnapshot (options: FSharpProjectOptions) path =
-                    async {
-                        let project = projects[options.ProjectFileName]
-                        let document = project[path]
-                        let! version = document.GetTextVersionAsync() |> Async.AwaitTask
-
-                        let getSource () =
-                            task {
-                                let! sourceText = document.GetTextAsync()
-                                return sourceText.ToFSharpSourceText()
-                            }
-
-                        return
-                            {
-                                FileName = path
-                                Version = version.ToString()
-                                GetSource = getSource
-                            }
-                    }
-
-                let! projectSnapshot = FSharpProjectSnapshot.FromOptions(options, getFileSnapshot)
+                let! projectSnapshot = getProjectSnapshot(document, options)
 
                 let! (parseResults, checkFileAnswer) = checker.ParseAndCheckFileInProject(document.FilePath, projectSnapshot, userOpName)
 
@@ -152,7 +163,7 @@ module private CheckerExtensions =
             ) =
             async {
 
-                if document.Project.UseTransparentCompiiler then
+                if document.Project.UseTransparentCompiler then
                     return! checker.ParseAndCheckDocumentUsingTransparentCompiler(document, options, userOpName)
                 else
                     let allowStaleResults =
@@ -251,8 +262,11 @@ type Document with
     /// Parses the given F# document.
     member this.GetFSharpParseResultsAsync(userOpName) =
         async {
-            let! checker, _, parsingOptions, _ = this.GetFSharpCompilationOptionsAsync(userOpName)
-            return! checker.ParseDocument(this, parsingOptions, userOpName)
+            let! checker, _, parsingOptions, options = this.GetFSharpCompilationOptionsAsync(userOpName)
+            if this.Project.UseTransparentCompiler then
+                return! checker.ParseDocumentUsingTransparentCompiler(this, options, userOpName)
+            else
+                return! checker.ParseDocument(this, parsingOptions, userOpName)
         }
 
     /// Parses and checks the given F# document.
diff --git a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs
index cd07b46b18e..bcc51aa6561 100644
--- a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs
+++ b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs
@@ -241,5 +241,5 @@ module EditorOptionsExtensions =
         member this.IsFastFindReferencesEnabled =
             this.EditorOptions.LanguageServicePerformance.EnableFastFindReferencesAndRename
 
-        member this.UseTransparentCompiiler =
+        member this.UseTransparentCompiler =
             this.EditorOptions.Advanced.UseTransparentCompiler
From 83ee2043bb15bc75c3dcd2833ad6491d0e7f1dc9 Mon Sep 17 00:00:00 2001
From: Petr Pokorny 
Date: Tue, 16 May 2023 17:17:21 +0200
Subject: [PATCH 031/222] wip
---
 src/Compiler/Service/BackgroundCompiler.fs    |  5 +-
 src/Compiler/Service/service.fs               |  1 +
 src/Compiler/Service/service.fsi              |  4 +-
 .../FSharpChecker/TransparentCompiler.fs      | 37 -----------
 ...ervice.SurfaceArea.netstandard20.debug.bsl |  3 +
 ...vice.SurfaceArea.netstandard20.release.bsl |  3 +
 .../ProjectGeneration.fs                      | 15 +++--
 .../LanguageService/LanguageService.fs        |  3 +-
 .../LanguageService/WorkspaceExtensions.fs    | 64 +++++++++----------
 .../FSharp.Editor/Options/EditorOptions.fs    |  3 +-
 10 files changed, 56 insertions(+), 82 deletions(-)
diff --git a/src/Compiler/Service/BackgroundCompiler.fs b/src/Compiler/Service/BackgroundCompiler.fs
index 72bba6b4bc3..a7e6924d3cb 100644
--- a/src/Compiler/Service/BackgroundCompiler.fs
+++ b/src/Compiler/Service/BackgroundCompiler.fs
@@ -134,10 +134,9 @@ type internal IBackgroundCompiler =
     abstract member ParseFile:
         fileName: string * sourceText: ISourceText * options: FSharpParsingOptions * cache: bool * userOpName: string ->
             Async
-            
+
     abstract member ParseFile:
-        fileName: string * projectSnapshot: FSharpProjectSnapshot * userOpName: string ->
-            NodeCode
+        fileName: string * projectSnapshot: FSharpProjectSnapshot * userOpName: string -> NodeCode
 
     /// Try to get recent approximate type check results for a file.
     abstract member TryGetRecentCheckResultsForFile:
diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs
index 723ddeee6b1..a12bfdccdf8 100644
--- a/src/Compiler/Service/service.fs
+++ b/src/Compiler/Service/service.fs
@@ -309,6 +309,7 @@ type FSharpChecker
 
     member _.ParseFile(fileName, projectSnapshot, ?userOpName) =
         let userOpName = defaultArg userOpName "Unknown"
+
         backgroundCompiler.ParseFile(fileName, projectSnapshot, userOpName)
         |> Async.AwaitNodeCode
 
diff --git a/src/Compiler/Service/service.fsi b/src/Compiler/Service/service.fsi
index 98d5c429680..fe484532dfa 100644
--- a/src/Compiler/Service/service.fsi
+++ b/src/Compiler/Service/service.fsi
@@ -103,8 +103,8 @@ type public FSharpChecker =
         fileName: string * sourceText: ISourceText * options: FSharpParsingOptions * ?cache: bool * ?userOpName: string ->
             Async
 
-    member ParseFile: fileName: string * projectSnapshot: FSharpProjectSnapshot * ?userOpName: string ->
-        Async
+    member ParseFile:
+        fileName: string * projectSnapshot: FSharpProjectSnapshot * ?userOpName: string -> Async
 
     /// 
     /// Parses a source code for a file. Returns an AST that can be traversed for various features.
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
index d50980ce575..23edbee1cfe 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
+++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
@@ -7,42 +7,10 @@ open Xunit
 
 open FSharp.Test.ProjectGeneration
 
-module Activity =
-    let listen (filter: string) =
-        let indent (activity: Activity) =
-            let rec loop (activity: Activity) n =
-                if activity.Parent <> null then
-                    loop (activity.Parent) (n + 1)
-                else
-                    n
-
-            String.replicate (loop activity 0) "    "
-
-        let collectTags (activity: Activity) =
-            [ for tag in activity.Tags -> $"{tag.Key}: %A{tag.Value}" ]
-            |> String.concat ", "
-
-        let listener =
-            new ActivityListener(
-                ShouldListenTo = (fun source -> source.Name = FSharp.Compiler.Diagnostics.ActivityNames.FscSourceName),
-                Sample =
-                    (fun context ->
-                        if context.Name.Contains(filter) then
-                            ActivitySamplingResult.AllDataAndRecorded
-                        else
-                            ActivitySamplingResult.None),
-                ActivityStarted = (fun a -> Trace.TraceInformation $"{indent a}{a.OperationName}     {collectTags a}")
-            )
-
-        ActivitySource.AddActivityListener(listener)
-
-    let listenToAll () = listen ""
 
 []
 let ``Use Transparent Compiler`` () =
 
-    Activity.listenToAll ()
-
     let size = 20
 
     let project =
@@ -73,8 +41,6 @@ let ``Use Transparent Compiler`` () =
 []
 let ``Parallel processing`` () =
 
-    Activity.listenToAll ()
-
     let project = SyntheticProject.Create(
         sourceFile "A" [],
         sourceFile "B" ["A"],
@@ -91,8 +57,6 @@ let ``Parallel processing`` () =
 []
 let ``Parallel processing with signatures`` () =
 
-    Activity.listenToAll ()
-
     let project = SyntheticProject.Create(
         sourceFile "A" [] |> addSignatureFile,
         sourceFile "B" ["A"] |> addSignatureFile,
@@ -168,7 +132,6 @@ let ``Files depend on signature file if present`` () =
 
 []
 let ``Signature update`` () =
-    Activity.listenToAll ()
 
     let project = SyntheticProject.Create(
         { sourceFile "First" [] with
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 011026eee11..03aeafb299a 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
@@ -2055,6 +2055,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Int32 get_ActualParseFileCount()
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer] CheckFileInProject(FSharp.Compiler.CodeAnalysis.FSharpParseFileResults, System.String, Int32, FSharp.Compiler.Text.ISourceText, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults] ParseAndCheckProject(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults] GetBackgroundParseResultsForFileInProject(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
+FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults] ParseFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults] ParseFile(System.String, FSharp.Compiler.Text.ISourceText, FSharp.Compiler.CodeAnalysis.FSharpParsingOptions, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults] ParseFileInProject(System.String, System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String])
 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])
@@ -2200,6 +2201,8 @@ FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean get_UseScriptResolut
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectOptions ToOptions()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot UpTo(Int32)
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot UpTo(System.String)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot WithoutFileVersions
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot get_WithoutFileVersions()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey Key
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey get_Key()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Int32 GetHashCode()
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 011026eee11..03aeafb299a 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
@@ -2055,6 +2055,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Int32 get_ActualParseFileCount()
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer] CheckFileInProject(FSharp.Compiler.CodeAnalysis.FSharpParseFileResults, System.String, Int32, FSharp.Compiler.Text.ISourceText, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults] ParseAndCheckProject(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults] GetBackgroundParseResultsForFileInProject(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
+FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults] ParseFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults] ParseFile(System.String, FSharp.Compiler.Text.ISourceText, FSharp.Compiler.CodeAnalysis.FSharpParsingOptions, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults] ParseFileInProject(System.String, System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String])
 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])
@@ -2200,6 +2201,8 @@ FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean get_UseScriptResolut
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectOptions ToOptions()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot UpTo(Int32)
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot UpTo(System.String)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot WithoutFileVersions
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot get_WithoutFileVersions()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey Key
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey get_Key()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Int32 GetHashCode()
diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
index 74356203b27..29e845d1ed8 100644
--- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs
+++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
@@ -126,6 +126,11 @@ type SyntheticProject =
         |> List.tryFind (fun f -> this.ProjectDir ++ f.FileName = path)
         |> Option.defaultWith (fun () -> failwith $"File {path} not found in project {this.Name}.")
 
+    member this.FindInAllProjectsByPath path =
+        this.GetAllFiles()
+        |> List.tryFind (fun (p, f) -> p.ProjectDir ++ f.FileName = path)
+        |> Option.defaultWith (fun () -> failwith $"File {path} not found in any project.")
+
     member this.ProjectFileName = this.ProjectDir ++ $"{this.Name}.fsproj"
 
     member this.OutputFilename = this.ProjectDir ++ $"{this.Name}.dll"
@@ -367,14 +372,14 @@ module ProjectOperations =
 
     let getFileSnapshot (project: SyntheticProject) _options (path: string) =
         async {
-            let filePath =
+            let project, filePath =
                 if path.EndsWith(".fsi") then
                     let implFilePath = path[..path.Length - 2]
-                    let f = project.FindByPath implFilePath
-                    getSignatureFilePath project f
+                    let p, f = project.FindInAllProjectsByPath implFilePath
+                    p, getSignatureFilePath p f
                 else
-                    let f = project.FindByPath path
-                    getFilePath project f
+                    let p, f = project.FindInAllProjectsByPath path
+                    p, getFilePath p f
 
             let source = getSourceText project path
             use md5 = System.Security.Cryptography.MD5.Create()
diff --git a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs
index 1501fac454a..5d4ebce7420 100644
--- a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs
+++ b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs
@@ -177,7 +177,8 @@ type internal FSharpWorkspaceServiceFactory [
diff --git a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs
index 5e623b51469..15304a77a34 100644
--- a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs
+++ b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs
@@ -15,38 +15,37 @@ module private CheckerExtensions =
 
     let getProjectSnapshot (document: Document, options: FSharpProjectOptions) =
         async {
-             let project = document.Project
-             let solution = project.Solution
-             // TODO cache?
-             let projects =
-                 solution.Projects
-                 |> Seq.map (fun p -> p.FilePath, p.Documents |> Seq.map (fun d -> d.FilePath, d) |> Map)
-                 |> Map
-
-             let getFileSnapshot (options: FSharpProjectOptions) path =
-                 async {
-                     let project = projects[options.ProjectFileName]
-                     let document = project[path]
-                     let! version = document.GetTextVersionAsync() |> Async.AwaitTask
-
-                     let getSource () =
-                         task {
-                             let! sourceText = document.GetTextAsync()
-                             return sourceText.ToFSharpSourceText()
-                         }
-
-                     return
-                         {
-                             FileName = path
-                             Version = version.ToString()
-                             GetSource = getSource
-                         }
-                 }
-
-             return! FSharpProjectSnapshot.FromOptions(options, getFileSnapshot)
+            let project = document.Project
+            let solution = project.Solution
+            // TODO cache?
+            let projects =
+                solution.Projects
+                |> Seq.map (fun p -> p.FilePath, p.Documents |> Seq.map (fun d -> d.FilePath, d) |> Map)
+                |> Map
+
+            let getFileSnapshot (options: FSharpProjectOptions) path =
+                async {
+                    let project = projects[options.ProjectFileName]
+                    let document = project[path]
+                    let! version = document.GetTextVersionAsync() |> Async.AwaitTask
+
+                    let getSource () =
+                        task {
+                            let! sourceText = document.GetTextAsync()
+                            return sourceText.ToFSharpSourceText()
+                        }
+
+                    return
+                        {
+                            FileName = path
+                            Version = version.ToString()
+                            GetSource = getSource
+                        }
+                }
+
+            return! FSharpProjectSnapshot.FromOptions(options, getFileSnapshot)
         }
 
-
     type FSharpChecker with
 
         /// Parse the source text from the Roslyn document.
@@ -60,7 +59,7 @@ module private CheckerExtensions =
 
         member checker.ParseDocumentUsingTransparentCompiler(document: Document, options: FSharpProjectOptions, userOpName: string) =
             async {
-                let! projectSnapshot = getProjectSnapshot(document, options)
+                let! projectSnapshot = getProjectSnapshot (document, options)
                 return! checker.ParseFile(document.FilePath, projectSnapshot, userOpName = userOpName)
             }
 
@@ -71,7 +70,7 @@ module private CheckerExtensions =
                 userOpName: string
             ) =
             async {
-                let! projectSnapshot = getProjectSnapshot(document, options)
+                let! projectSnapshot = getProjectSnapshot (document, options)
 
                 let! (parseResults, checkFileAnswer) = checker.ParseAndCheckFileInProject(document.FilePath, projectSnapshot, userOpName)
 
@@ -263,6 +262,7 @@ type Document with
     member this.GetFSharpParseResultsAsync(userOpName) =
         async {
             let! checker, _, parsingOptions, options = this.GetFSharpCompilationOptionsAsync(userOpName)
+
             if this.Project.UseTransparentCompiler then
                 return! checker.ParseDocumentUsingTransparentCompiler(this, options, userOpName)
             else
diff --git a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs
index b965e5595d8..ee9b6c65b65 100644
--- a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs
+++ b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs
@@ -243,5 +243,4 @@ module EditorOptionsExtensions =
         member this.IsFastFindReferencesEnabled =
             this.EditorOptions.LanguageServicePerformance.EnableFastFindReferencesAndRename
 
-        member this.UseTransparentCompiler =
-            this.EditorOptions.Advanced.UseTransparentCompiler
+        member this.UseTransparentCompiler = this.EditorOptions.Advanced.UseTransparentCompiler
From 348d6203fabeac70a7e7d2abf0b9f98d1423b1af Mon Sep 17 00:00:00 2001
From: Petr Pokorny 
Date: Tue, 16 May 2023 18:15:10 +0200
Subject: [PATCH 032/222] move cache key creation
---
 src/Compiler/Service/TransparentCompiler.fs | 170 +++++++++-----------
 1 file changed, 79 insertions(+), 91 deletions(-)
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 771d707e43f..50daf0beafd 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -96,7 +96,7 @@ type internal TransparentCompiler
 
     let cacheEvent = new Event()
 
-    let ParseFileCache = 
+    let ParseFileCache =
         AsyncMemoize(logEvent = fun (e, ((fileName, version), _, _)) -> cacheEvent.Trigger("ParseFile", e, [| fileName; version |] ))
     let ParseAndCheckFileInProjectCache = AsyncMemoize()
     let FrameworkImportsCache = AsyncMemoize()
@@ -173,11 +173,28 @@ type internal TransparentCompiler
         ]
 
     let ComputeFrameworkImports (tcConfig: TcConfig) frameworkDLLs nonFrameworkResolutions =
-        node {
+        let frameworkDLLsKey =
+            frameworkDLLs
+            |> List.map (fun ar -> ar.resolvedPath) // The cache key. Just the minimal data.
+            |> List.sort // Sort to promote cache hits.
+
+        // The data elements in this key are very important. There should be nothing else in the TcConfig that logically affects
+        // the import of a set of framework DLLs into F# CCUs. That is, the F# CCUs that result from a set of DLLs (including
+        // FSharp.Core.dll and mscorlib.dll) must be logically invariant of all the other compiler configuration parameters.
+        let key =
+            FrameworkImportsCacheKey(
+                frameworkDLLsKey,
+                tcConfig.primaryAssembly.Name,
+                tcConfig.GetTargetFrameworkDirectories(),
+                tcConfig.fsharpBinariesDir,
+                tcConfig.langVersion.SpecifiedVersion
+            )
+
+        FrameworkImportsCache.Get(key, node {
             use _ = Activity.start "ComputeFrameworkImports" []
             let tcConfigP = TcConfigProvider.Constant tcConfig
             return! TcImports.BuildFrameworkTcImports(tcConfigP, frameworkDLLs, nonFrameworkResolutions)
-        }
+        })
 
     // Link all the assemblies together and produce the input typecheck accumulator
     let CombineImportedAssembliesTask
@@ -280,7 +297,10 @@ type internal TransparentCompiler
 
     /// Bootstrap info that does not depend on contents of the files
     let ComputeBootstrapInfoStatic (projectSnapshot: FSharpProjectSnapshot) =
-        node {
+
+        let key = projectSnapshot.WithoutFileVersions.Key
+
+        BootstrapInfoStaticCache.Get(key, node {
             use _ = Activity.start "ComputeBootstrapInfoStatic" [| Activity.Tags.project, projectSnapshot.ProjectFileName |> Path.GetFileName |]
 
             let useSimpleResolutionSwitch = "--simpleresolution"
@@ -413,27 +433,8 @@ type internal TransparentCompiler
             let frameworkDLLs, nonFrameworkResolutions, unresolvedReferences =
                 TcAssemblyResolutions.SplitNonFoundationalResolutions(tcConfig)
 
-            let frameworkDLLsKey =
-                frameworkDLLs
-                |> List.map (fun ar -> ar.resolvedPath) // The cache key. Just the minimal data.
-                |> List.sort // Sort to promote cache hits.
-
             // Prepare the frameworkTcImportsCache
-            //
-            // The data elements in this key are very important. There should be nothing else in the TcConfig that logically affects
-            // the import of a set of framework DLLs into F# CCUs. That is, the F# CCUs that result from a set of DLLs (including
-            // FSharp.Core.dll and mscorlib.dll) must be logically invariant of all the other compiler configuration parameters.
-            let key =
-                FrameworkImportsCacheKey(
-                    frameworkDLLsKey,
-                    tcConfig.primaryAssembly.Name,
-                    tcConfig.GetTargetFrameworkDirectories(),
-                    tcConfig.fsharpBinariesDir,
-                    tcConfig.langVersion.SpecifiedVersion
-                )
-
-            let! tcGlobals, frameworkTcImports =
-                FrameworkImportsCache.Get(key, ComputeFrameworkImports tcConfig frameworkDLLs nonFrameworkResolutions)
+            let! tcGlobals, frameworkTcImports = ComputeFrameworkImports tcConfig frameworkDLLs nonFrameworkResolutions
 
             // Note we are not calling diagnosticsLogger.GetDiagnostics() anywhere for this task.
             // This is ok because not much can actually go wrong here.
@@ -519,13 +520,11 @@ type internal TransparentCompiler
     #endif
                 )
             return sourceFiles, tcConfig, tcImports, tcGlobals, initialTcInfo, loadClosureOpt
-        }
+        })
 
     let computeBootstrapInfoInner (projectSnapshot: FSharpProjectSnapshot) =
         node {
-            let bootstrapStaticKey = projectSnapshot.WithoutFileVersions.Key
-
-            let! sourceFiles, tcConfig, tcImports, tcGlobals, initialTcInfo, loadClosureOpt = BootstrapInfoStaticCache.Get(bootstrapStaticKey, ComputeBootstrapInfoStatic projectSnapshot)
+            let! sourceFiles, tcConfig, tcImports, tcGlobals, initialTcInfo, loadClosureOpt = ComputeBootstrapInfoStatic projectSnapshot
 
             let fileSnapshots = Map [ for f in projectSnapshot.SourceFiles -> f.FileName, f ]
 
@@ -562,7 +561,7 @@ type internal TransparentCompiler
         }
 
     let ComputeBootstrapInfo (projectSnapshot: FSharpProjectSnapshot) =
-        node {
+        BootstrapInfoCache.Get(projectSnapshot.Key, node {
             use _ = Activity.start "ComputeBootstrapInfo" [| Activity.Tags.project, projectSnapshot.ProjectFileName |> Path.GetFileName |]
 
             // Trap and report diagnostics from creation.
@@ -593,12 +592,13 @@ type internal TransparentCompiler
                     FSharpDiagnostic.CreateFromException(diagnostic, severity, range.Zero, suggestNamesForErrors))
 
             return bootstrapInfoOpt, diagnostics
-        }
+        })
 
-    let ComputeParseFile (file: FSharpFile) bootstrapInfo =
-        node {
+    let ComputeParseFile bootstrapInfo (file: FSharpFile)  =
+        let key = file.Source.Key, file.IsLastCompiland, file.IsExe
+        ParseFileCache.Get(key, node {
             use _ = Activity.start "ComputeParseFile" [| Activity.Tags.fileName, file.Source.FileName |> Path.GetFileName; Activity.Tags.version, file.Source.Version |]
-            
+
             let tcConfig = bootstrapInfo.TcConfig
 
             let diagnosticsLogger =
@@ -614,10 +614,11 @@ type internal TransparentCompiler
                 ParseOneInputSourceText(tcConfig, lexResourceManager, fileName, flags, diagnosticsLogger, sourceText)
 
             return input, diagnosticsLogger.GetDiagnostics(), sourceText
-        }
+        })
 
-    let ComputeDependencyGraphForLastFile parsedInputs (tcConfig: TcConfig) =
-        node {
+    let ComputeDependencyGraphForLastFile (priorSnapshot: FSharpProjectSnapshot) parsedInputs (tcConfig: TcConfig) =
+        let key = priorSnapshot.SourceFiles |> List.map (fun s -> s.Key)
+        DependencyGraphForLastFileCache.Get(key, node {
 
             let sourceFiles: FileInProject array =
                 parsedInputs
@@ -629,8 +630,8 @@ type internal TransparentCompiler
                         ParsedInput = input
                     })
 
-            use _ = Activity.start "ComputeDependencyGraphForLastFile" [| Activity.Tags.fileName, (sourceFiles |> Array.last).FileName |]    
-            
+            use _ = Activity.start "ComputeDependencyGraphForLastFile" [| Activity.Tags.fileName, (sourceFiles |> Array.last).FileName |]
+
             let filePairs = FilePairMap(sourceFiles)
 
             // TODO: we will probably want to cache and re-use larger graphs if available
@@ -639,16 +640,18 @@ type internal TransparentCompiler
                 |> fst
                 |> Graph.subGraphFor (sourceFiles |> Array.last).Idx
 
-            return TransformDependencyGraph(graph, filePairs), filePairs
-        }
+            return TransformDependencyGraph(graph, filePairs)
+        })
 
-    let ComputeTcIntermediate (parsedInput: ParsedInput, parseErrors) bootstrapInfo (prevTcInfo: TcInfo) =
-        node {
+    let ComputeTcIntermediate (projectSnapshot: FSharpProjectSnapshot) (fileIndex: FileIndex) (parsedInput: ParsedInput, parseErrors) bootstrapInfo (prevTcInfo: TcInfo) =
+        // TODO: we need to construct cache key based on only relevant files from the dependency graph
+        let key = projectSnapshot.UpTo(fileIndex).Key
+        TcIntermediateCache.Get(key, node {
             let input = parsedInput
             let fileName = input.FileName
-            
+
             use _ = Activity.start "ComputeTcIntermediate" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
-            
+
             let tcConfig = bootstrapInfo.TcConfig
             let tcGlobals = bootstrapInfo.TcGlobals
             let tcImports = bootstrapInfo.TcImports
@@ -702,10 +705,10 @@ type internal TransparentCompiler
                     tcDiagnosticsRev = [ newErrors ]
                     tcDependencyFiles = [ fileName ]
                 }
-        }
+        })
 
     let mergeIntermediateResults =
-        Array.fold (fun (tcInfo: TcInfo) (tcIntermediate: TcIntermediate) -> 
+        Array.fold (fun (tcInfo: TcInfo) (tcIntermediate: TcIntermediate) ->
             let (tcEnv, topAttribs, _checkImplFileOpt, ccuSigForFile), tcState = tcInfo.tcState |> tcIntermediate.finisher.Invoke
             let tcEnvAtEndOfFile = if keepAllBackgroundResolutions then tcEnv else tcState.TcEnvFromImpls
             { tcInfo with
@@ -716,11 +719,13 @@ type internal TransparentCompiler
                 tcDependencyFiles = tcIntermediate.tcDependencyFiles @ tcInfo.tcDependencyFiles
                 latestCcuSigForFile = Some ccuSigForFile })
 
-
     // Type check everything that is needed to check given file
     let ComputeTcPrior (file: FSharpFile) (bootstrapInfo: BootstrapInfo) (projectSnapshot: FSharpProjectSnapshot) _userOpName =
-        node {
-            
+
+        let priorSnapshot = projectSnapshot.UpTo file.Source.FileName
+        let key = priorSnapshot.Key
+
+        TcPriorCache.Get(key, node {
             use _ = Activity.start "ComputeTcPrior" [| Activity.Tags.fileName, file.Source.FileName |> Path.GetFileName |]
 
             // parse required files
@@ -732,28 +737,17 @@ type internal TransparentCompiler
 
             let! parsedInputs =
                 files
-                |> Seq.map (fun f ->
-                    let key = f.Source.Key, f.IsLastCompiland, f.IsExe
-                    ParseFileCache.Get(key, ComputeParseFile f bootstrapInfo))
+                |> Seq.map (ComputeParseFile bootstrapInfo)
                 |> NodeCode.Parallel
 
-            // compute dependency graph
-            let graphKey =
-                projectSnapshot.UpTo(file.Source.FileName).SourceFiles
-                |> List.map (fun s -> s.Key)
-
-            let! graph, _filePairs =
-                DependencyGraphForLastFileCache.Get(
-                    graphKey,
-                    ComputeDependencyGraphForLastFile (parsedInputs |> Seq.map p13) bootstrapInfo.TcConfig
-                )
+            let! graph = ComputeDependencyGraphForLastFile priorSnapshot (parsedInputs |> Seq.map p13) bootstrapInfo.TcConfig
 
-            let fileNames = 
-                parsedInputs 
+            let fileNames =
+                parsedInputs
                 |> Seq.mapi (fun idx (input, _, _) -> idx, Path.GetFileName input.FileName)
                 |> Map.ofSeq
 
-            let debugGraph = 
+            let debugGraph =
                 graph
                 |> Graph.map (function NodeToTypeCheck.PhysicalFile i -> i, fileNames[i] | NodeToTypeCheck.ArtificialImplFile i -> -(i + 1), $"AIF : {fileNames[i]}")
 
@@ -777,11 +771,10 @@ type internal TransparentCompiler
                                 match fileNode with
                                 | NodeToTypeCheck.PhysicalFile fileIndex ->
                                     let parsedInput, parseErrors, _ = parsedInputs[fileIndex]
-                                    let key = projectSnapshot.UpTo(fileIndex).Key
-                                    TcIntermediateCache.Get(key, ComputeTcIntermediate (parsedInput, parseErrors) bootstrapInfo tcInfo)
+                                    ComputeTcIntermediate projectSnapshot fileIndex (parsedInput, parseErrors) bootstrapInfo tcInfo
                                 | NodeToTypeCheck.ArtificialImplFile fileIndex ->
 
-                                    let finisher tcState = 
+                                    let finisher tcState =
                                         let parsedInput, _parseErrors, _ = parsedInputs[fileIndex]
                                         let prefixPathOpt = None
                                         // Retrieve the type-checked signature information and add it to the TcEnvFromImpls.
@@ -796,20 +789,20 @@ type internal TransparentCompiler
 
                                     node.Return(tcIntermediate))
                             |> NodeCode.Parallel
-                        //let nodes = layer |> Seq.map (function NodeToTypeCheck.PhysicalFile i -> fileNames[i] | NodeToTypeCheck.ArtificialImplFile i -> $"AIF : {fileNames[i]}") |> String.concat " "
-                        //Trace.TraceInformation $"Processed layer {nodes}"
+
                         return! processLayer rest (mergeIntermediateResults tcInfo results)
                 }
 
             return! processLayer layers bootstrapInfo.InitialTcInfo
-        }
+        })
 
     let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: FSharpProjectSnapshot) userOpName =
-        node {
-            
+        let key = fileName, projectSnapshot.Key
+        ParseAndCheckFileInProjectCache.Get(key, node {
+
             use _ = Activity.start "ComputeParseAndCheckFileInProject" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
 
-            let! bootstrapInfoOpt, creationDiags = BootstrapInfoCache.Get(projectSnapshot.Key, ComputeBootstrapInfo projectSnapshot)
+            let! bootstrapInfoOpt, creationDiags = ComputeBootstrapInfo projectSnapshot
 
             match bootstrapInfoOpt with
             | None ->
@@ -822,12 +815,10 @@ type internal TransparentCompiler
                 let file =
                     bootstrapInfo.SourceFiles |> List.tryFind (fun f -> f.Source.FileName = fileName) |> Option.defaultWith (fun _ -> failwith ($"File {fileName} not found in project snapshot. Files in project: \n\n" + (bootstrapInfo.SourceFiles |> Seq.map (fun f -> f.Source.FileName) |> String.concat " \n")))
 
-                let priorSnapshot = projectSnapshot.UpTo fileName
-                let! tcInfo = TcPriorCache.Get(priorSnapshot.Key, ComputeTcPrior file bootstrapInfo priorSnapshot userOpName)
+                let! tcInfo = ComputeTcPrior file bootstrapInfo projectSnapshot userOpName
 
                 // We could also bubble this through ComputeTcPrior
-                let! parseTree, parseDiagnostics, sourceText =
-                    ParseFileCache.Get((file.Source.Key, file.IsLastCompiland, file.IsExe), ComputeParseFile file bootstrapInfo)
+                let! parseTree, parseDiagnostics, sourceText = ComputeParseFile bootstrapInfo file
 
                 let parseDiagnostics =
                     DiagnosticHelpers.CreateDiagnostics(
@@ -874,13 +865,13 @@ type internal TransparentCompiler
                     |> NodeCode.FromCancellable
 
                 return (parseResults, FSharpCheckFileAnswer.Succeeded checkResults)
-        }
+        })
 
-    member _.ParseFile(fileName, projectSnapshot: FSharpProjectSnapshot, _userOpName) = 
+    member _.ParseFile(fileName, projectSnapshot: FSharpProjectSnapshot, _userOpName) =
         node {
             use _ = Activity.start "ParseFile" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
-            
-            let! bootstrapInfoOpt, creationDiags = BootstrapInfoCache.Get(projectSnapshot.Key, ComputeBootstrapInfo projectSnapshot)
+
+            let! bootstrapInfoOpt, creationDiags = ComputeBootstrapInfo projectSnapshot
 
             match bootstrapInfoOpt with
             | None ->
@@ -888,12 +879,11 @@ type internal TransparentCompiler
                 return FSharpParseFileResults(creationDiags, parseTree, true, [||])
 
             | Some bootstrapInfo ->
-                
+
                 let file =
                     bootstrapInfo.SourceFiles |> List.tryFind (fun f -> f.Source.FileName = fileName) |> Option.defaultWith (fun _ -> failwith ($"File {fileName} not found in project snapshot. Files in project: \n\n" + (bootstrapInfo.SourceFiles |> Seq.map (fun f -> f.Source.FileName) |> String.concat " \n")))
 
-                let! parseTree, parseDiagnostics, _sourceText =
-                    ParseFileCache.Get((file.Source.Key, file.IsLastCompiland, file.IsExe), ComputeParseFile file bootstrapInfo)
+                let! parseTree, parseDiagnostics, _sourceText = ComputeParseFile bootstrapInfo file
 
                 let parseDiagnostics =
                     DiagnosticHelpers.CreateDiagnostics(
@@ -917,10 +907,8 @@ type internal TransparentCompiler
         }
 
     member _.ParseAndCheckFileInProject(fileName: string, projectSnapshot: FSharpProjectSnapshot, userOpName: string) =
-        node {
-            let key = fileName, projectSnapshot.Key
-            return! ParseAndCheckFileInProjectCache.Get(key, ComputeParseAndCheckFileInProject fileName projectSnapshot userOpName)
-        }
+        ComputeParseAndCheckFileInProject fileName projectSnapshot userOpName
+
 
     interface IBackgroundCompiler with
         member _.CacheEvent = cacheEvent.Publish
@@ -1071,8 +1059,8 @@ type internal TransparentCompiler
 
         member _.ParseAndCheckProject(options: FSharpProjectOptions, userOpName: string) : NodeCode =
             backgroundCompiler.ParseAndCheckProject(options, userOpName)
-        
-        member this.ParseFile(fileName, projectSnapshot, userOpName) = 
+
+        member this.ParseFile(fileName, projectSnapshot, userOpName) =
             this.ParseFile(fileName, projectSnapshot, userOpName)
 
         member _.ParseFile
From 35135ceb8f676872404a380e808978c76c218c30 Mon Sep 17 00:00:00 2001
From: Petr Pokorny 
Date: Wed, 17 May 2023 16:52:57 +0200
Subject: [PATCH 033/222] Background semantic classification
---
 src/Compiler/Service/BackgroundCompiler.fs    | 16 +++-
 src/Compiler/Service/FSharpCheckerResults.fs  | 11 ++-
 src/Compiler/Service/FSharpCheckerResults.fsi |  4 +
 src/Compiler/Service/TransparentCompiler.fs   | 79 ++++++++++++++-----
 src/Compiler/Service/service.fs               |  6 ++
 src/Compiler/Service/service.fsi              | 13 ++-
 .../FSharpChecker/TransparentCompiler.fs      | 34 +++++++-
 ...vice.SurfaceArea.netstandard20.release.bsl |  4 +
 .../LanguageService/WorkspaceExtensions.fs    | 13 ++-
 9 files changed, 152 insertions(+), 28 deletions(-)
diff --git a/src/Compiler/Service/BackgroundCompiler.fs b/src/Compiler/Service/BackgroundCompiler.fs
index a7e6924d3cb..0fcf7918cc2 100644
--- a/src/Compiler/Service/BackgroundCompiler.fs
+++ b/src/Compiler/Service/BackgroundCompiler.fs
@@ -113,6 +113,10 @@ type internal IBackgroundCompiler =
         fileName: string * options: FSharpProjectOptions * userOpName: string ->
             NodeCode
 
+    abstract member GetSemanticClassificationForFile:
+        fileName: string * snapshot: FSharpProjectSnapshot * userOpName: string ->
+            NodeCode
+
     abstract member InvalidateConfiguration: options: FSharpProjectOptions * userOpName: string -> unit
 
     abstract member NotifyFileChanged: fileName: string * options: FSharpProjectOptions * userOpName: string -> NodeCode
@@ -153,7 +157,7 @@ type internal IBackgroundCompiler =
 
     abstract member ProjectChecked: IEvent
 
-    abstract member CacheEvent: IEvent
+    abstract member CacheEvent: IEvent
 
 type ParseCacheLockToken() =
     interface LockToken
@@ -239,7 +243,7 @@ type internal BackgroundCompiler
     let fileChecked = Event()
     let projectChecked = Event()
 
-    let cacheEvent = Event()
+    let cacheEvent = Event()
 
     // STATIC ROOT: FSharpLanguageServiceTestable.FSharpChecker.backgroundCompiler.scriptClosureCache
     /// Information about the derived script closure.
@@ -1493,6 +1497,14 @@ type internal BackgroundCompiler
             ) : NodeCode =
             self.GetSemanticClassificationForFile(fileName, options, userOpName)
 
+        member _.GetSemanticClassificationForFile
+            (
+                fileName: string,
+                snapshot: FSharpProjectSnapshot,
+                userOpName: string
+            ) : NodeCode =
+            self.GetSemanticClassificationForFile(fileName, snapshot.ToOptions(), userOpName)
+
         member _.InvalidateConfiguration(options: FSharpProjectOptions, userOpName: string) : unit =
             self.InvalidateConfiguration(options, userOpName)
 
diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs
index 673e08d0807..ab2d2f554d5 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fs
+++ b/src/Compiler/Service/FSharpCheckerResults.fs
@@ -129,6 +129,8 @@ type FSharpProjectSnapshotKey =
         IsIncompleteTypeCheckEnvironment: bool
         UseScriptResolutionRules: bool
     }
+    member this.LastFile = this.SourceFiles |> List.last
+
 
 []
 type FSharpFileSnapshot =
@@ -194,14 +196,17 @@ type FSharpProjectSnapshot =
 
     member po.ProjectDirectory = Path.GetDirectoryName(po.ProjectFileName)
 
+    member this.IndexOf fileName =
+        this.SourceFiles
+        |> List.tryFindIndex (fun x -> x.FileName = fileName)
+        |> Option.defaultWith (fun () -> failwith (sprintf "Unable to find file %s in project %s" fileName this.ProjectFileName))
+
     member this.UpTo fileIndex =
         { this with
             SourceFiles = this.SourceFiles[..fileIndex]
         }
 
-    member this.UpTo fileName =
-        let fileIndex = this.SourceFiles |> List.findIndex (fun x -> x.FileName = fileName)
-        this.UpTo fileIndex
+    member this.UpTo fileName = this.UpTo (this.IndexOf fileName)
 
     member this.Key =
         {
diff --git a/src/Compiler/Service/FSharpCheckerResults.fsi b/src/Compiler/Service/FSharpCheckerResults.fsi
index 2bd4cbbd990..ea55a296ec4 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fsi
+++ b/src/Compiler/Service/FSharpCheckerResults.fsi
@@ -52,6 +52,8 @@ type FSharpProjectSnapshotKey =
       IsIncompleteTypeCheckEnvironment: bool
       UseScriptResolutionRules: bool }
 
+    member LastFile: FSharpFileKey
+
 []
 type FSharpFileSnapshot =
     { FileName: string
@@ -115,6 +117,8 @@ type FSharpProjectSnapshot =
 
     member SourceFileNames: string list
 
+    member IndexOf: fileName: string -> FileIndex
+
     /// A snapshot of the same project but only up to the given file index (including).
     member UpTo: fileIndex: int -> FSharpProjectSnapshot
 
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 50daf0beafd..0ccd19d7846 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -34,6 +34,7 @@ open FSharp.Compiler.NameResolution
 open Internal.Utilities.Library.Extras
 open FSharp.Compiler.TypedTree
 open FSharp.Compiler.CheckDeclarations
+open FSharp.Compiler.EditorServices
 
 type internal FSharpFile =
     {
@@ -71,6 +72,8 @@ type internal TcIntermediate =
         tcDiagnosticsRev:(PhasedDiagnostic * FSharpDiagnosticSeverity)[] list
 
         tcDependencyFiles: string list
+
+        sink: TcResultsSinkImpl
     }
 
 type internal TransparentCompiler
@@ -94,17 +97,19 @@ type internal TransparentCompiler
     // Is having just one of these ok?
     let lexResourceManager = Lexhelp.LexResourceManager()
 
-    let cacheEvent = new Event()
+    let cacheEvent = new Event()
+    let triggerCacheEvent name (e, k) = cacheEvent.Trigger(name, e, k)
 
     let ParseFileCache =
-        AsyncMemoize(logEvent = fun (e, ((fileName, version), _, _)) -> cacheEvent.Trigger("ParseFile", e, [| fileName; version |] ))
-    let ParseAndCheckFileInProjectCache = AsyncMemoize()
-    let FrameworkImportsCache = AsyncMemoize()
-    let BootstrapInfoStaticCache = AsyncMemoize()
-    let BootstrapInfoCache = AsyncMemoize()
-    let TcPriorCache = AsyncMemoize()
-    let TcIntermediateCache = AsyncMemoize()
-    let DependencyGraphForLastFileCache = AsyncMemoize()
+        AsyncMemoize(triggerCacheEvent "ParseFile")
+    let ParseAndCheckFileInProjectCache = AsyncMemoize(triggerCacheEvent "ParseAndCheckFileInProject")
+    let FrameworkImportsCache = AsyncMemoize(triggerCacheEvent "FrameworkImports")
+    let BootstrapInfoStaticCache = AsyncMemoize(triggerCacheEvent "BootstrapInfoStatic")
+    let BootstrapInfoCache = AsyncMemoize(triggerCacheEvent "BootstrapInfo")
+    let TcPriorCache = AsyncMemoize(triggerCacheEvent "TcPrior")
+    let TcIntermediateCache = AsyncMemoize(triggerCacheEvent "TcIntermediate")
+    let DependencyGraphForLastFileCache = AsyncMemoize(triggerCacheEvent "DependencyGraphForLastFile")
+    let SemanticClassificationCache = AsyncMemoize(triggerCacheEvent "SemanticClassification")
 
     // We currently share one global dependency provider for all scripts for the FSharpChecker.
     // For projects, one is used per project.
@@ -704,6 +709,7 @@ type internal TransparentCompiler
                     moduleNamesDict = moduleNamesDict
                     tcDiagnosticsRev = [ newErrors ]
                     tcDependencyFiles = [ fileName ]
+                    sink = sink
                 }
         })
 
@@ -720,7 +726,7 @@ type internal TransparentCompiler
                 latestCcuSigForFile = Some ccuSigForFile })
 
     // Type check everything that is needed to check given file
-    let ComputeTcPrior (file: FSharpFile) (bootstrapInfo: BootstrapInfo) (projectSnapshot: FSharpProjectSnapshot) _userOpName =
+    let ComputeTcPrior (file: FSharpFile) (bootstrapInfo: BootstrapInfo) (projectSnapshot: FSharpProjectSnapshot) =
 
         let priorSnapshot = projectSnapshot.UpTo file.Source.FileName
         let key = priorSnapshot.Key
@@ -785,6 +791,7 @@ type internal TransparentCompiler
                                             moduleNamesDict = tcInfo.moduleNamesDict
                                             tcDiagnosticsRev = []
                                             tcDependencyFiles = []
+                                            sink = Unchecked.defaultof<_>
                                         }
 
                                     node.Return(tcIntermediate))
@@ -796,26 +803,24 @@ type internal TransparentCompiler
             return! processLayer layers bootstrapInfo.InitialTcInfo
         })
 
-    let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: FSharpProjectSnapshot) userOpName =
+    let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: FSharpProjectSnapshot) =
         let key = fileName, projectSnapshot.Key
         ParseAndCheckFileInProjectCache.Get(key, node {
 
             use _ = Activity.start "ComputeParseAndCheckFileInProject" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
 
-            let! bootstrapInfoOpt, creationDiags = ComputeBootstrapInfo projectSnapshot
-
-            match bootstrapInfoOpt with
-            | None ->
+            match! ComputeBootstrapInfo projectSnapshot with
+            | None, creationDiags ->
                 let parseTree = EmptyParsedInput(fileName, (false, false))
                 let parseResults = FSharpParseFileResults(creationDiags, parseTree, true, [||])
                 return (parseResults, FSharpCheckFileAnswer.Aborted)
 
-            | Some bootstrapInfo ->
+            | Some bootstrapInfo, creationDiags ->
 
                 let file =
                     bootstrapInfo.SourceFiles |> List.tryFind (fun f -> f.Source.FileName = fileName) |> Option.defaultWith (fun _ -> failwith ($"File {fileName} not found in project snapshot. Files in project: \n\n" + (bootstrapInfo.SourceFiles |> Seq.map (fun f -> f.Source.FileName) |> String.concat " \n")))
 
-                let! tcInfo = ComputeTcPrior file bootstrapInfo projectSnapshot userOpName
+                let! tcInfo = ComputeTcPrior file bootstrapInfo projectSnapshot
 
                 // We could also bubble this through ComputeTcPrior
                 let! parseTree, parseDiagnostics, sourceText = ComputeParseFile bootstrapInfo file
@@ -867,6 +872,34 @@ type internal TransparentCompiler
                 return (parseResults, FSharpCheckFileAnswer.Succeeded checkResults)
         })
 
+    let ComputeSemanticClassification(fileName: string, projectSnapshot: FSharpProjectSnapshot): NodeCode =
+        let key = (projectSnapshot.UpTo fileName).Key
+        SemanticClassificationCache.Get(key, node {
+            use _ = Activity.start "ComputeSemanticClassification" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
+
+            match! ComputeBootstrapInfo projectSnapshot with
+            | None, _ -> return None
+            | Some bootstrapInfo, _creationDiags ->
+
+                let file =
+                    bootstrapInfo.SourceFiles |> List.tryFind (fun f -> f.Source.FileName = fileName) |> Option.defaultWith (fun _ -> failwith ($"File {fileName} not found in project snapshot. Files in project: \n\n" + (bootstrapInfo.SourceFiles |> Seq.map (fun f -> f.Source.FileName) |> String.concat " \n")))
+
+                let! tcInfo = ComputeTcPrior file bootstrapInfo projectSnapshot
+                let! parseTree, parseDiagnostics, _sourceText = ComputeParseFile bootstrapInfo file
+
+                let fileIndex = projectSnapshot.IndexOf fileName
+                let! { sink = sink } = ComputeTcIntermediate projectSnapshot fileIndex (parseTree, parseDiagnostics) bootstrapInfo tcInfo
+
+                let sResolutions = sink.GetResolutions()
+
+                let semanticClassification = sResolutions.GetSemanticClassification(bootstrapInfo.TcGlobals, bootstrapInfo.TcImports.GetImportMap(), sink.GetFormatSpecifierLocations(), None)
+
+                let sckBuilder = SemanticClassificationKeyStoreBuilder()
+                sckBuilder.WriteAll semanticClassification
+
+                return sckBuilder.TryBuildAndReset() |> Option.map (fun sck -> sck.GetView())
+        })
+
     member _.ParseFile(fileName, projectSnapshot: FSharpProjectSnapshot, _userOpName) =
         node {
             use _ = Activity.start "ParseFile" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
@@ -907,7 +940,8 @@ type internal TransparentCompiler
         }
 
     member _.ParseAndCheckFileInProject(fileName: string, projectSnapshot: FSharpProjectSnapshot, userOpName: string) =
-        ComputeParseAndCheckFileInProject fileName projectSnapshot userOpName
+        ignore userOpName
+        ComputeParseAndCheckFileInProject fileName projectSnapshot
 
 
     interface IBackgroundCompiler with
@@ -1026,6 +1060,15 @@ type internal TransparentCompiler
                 userOpName
             )
 
+        member _.GetSemanticClassificationForFile
+            (
+                fileName: string,
+                snapshot: FSharpProjectSnapshot,
+                userOpName: string
+            ) =
+            ignore userOpName
+            ComputeSemanticClassification(fileName, snapshot)
+
         member _.GetSemanticClassificationForFile
             (
                 fileName: string,
diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs
index a12bfdccdf8..ae15a32bb00 100644
--- a/src/Compiler/Service/service.fs
+++ b/src/Compiler/Service/service.fs
@@ -485,6 +485,12 @@ type FSharpChecker
         backgroundCompiler.GetSemanticClassificationForFile(fileName, options, userOpName)
         |> Async.AwaitNodeCode
 
+    member _.GetBackgroundSemanticClassificationForFile(fileName: string, snapshot: FSharpProjectSnapshot, ?userOpName) =
+        let userOpName = defaultArg userOpName "Unknown"
+
+        backgroundCompiler.GetSemanticClassificationForFile(fileName, snapshot, userOpName)
+        |> Async.AwaitNodeCode
+
     /// For a given script file, get the ProjectOptions implied by the #load closure
     member _.GetProjectOptionsFromScript
         (
diff --git a/src/Compiler/Service/service.fsi b/src/Compiler/Service/service.fsi
index fe484532dfa..f7a035d9471 100644
--- a/src/Compiler/Service/service.fsi
+++ b/src/Compiler/Service/service.fsi
@@ -346,6 +346,17 @@ type public FSharpChecker =
         fileName: string * options: FSharpProjectOptions * ?userOpName: string ->
             Async
 
+    /// 
+    /// Get semantic classification for a file.
+    /// 
+    ///
+    /// The file name for the file.
+    /// The project snapshot for which we want to get the semantic classification.
+    /// An optional string used for tracing compiler operations associated with this request.
+    member GetBackgroundSemanticClassificationForFile:
+        fileName: string * snapshot: FSharpProjectSnapshot * ?userOpName: string ->
+            Async
+
     /// 
     /// Compile using the given flags.  Source files names are resolved via the FileSystem API.
     /// The output file must be given by a -o flag.
@@ -431,7 +442,7 @@ type public FSharpChecker =
     /// The event may be raised on a background thread.
     member ProjectChecked: IEvent
 
-    member internal CacheEvent: IEvent
+    member internal CacheEvent: IEvent
 
     []
     static member Instance: FSharpChecker
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
index 23edbee1cfe..acb508dea41 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
+++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
@@ -2,10 +2,13 @@
 
 open System.Collections.Concurrent
 open System.Diagnostics
+open FSharp.Compiler.CodeAnalysis
+open Internal.Utilities.Collections
 
 open Xunit
 
 open FSharp.Test.ProjectGeneration
+open System.IO
 
 
 []
@@ -173,4 +176,33 @@ let ``Changes in a referenced project`` () =
         updateFile "Library" updatePublicSurface
         saveFile "Library"
         checkFile "Last" expectSignatureChanged
-    }
\ No newline at end of file
+    }
+
+[]
+let ``We don't check files that are not depended on`` () =
+    let project = SyntheticProject.Create(
+        sourceFile "First" [],
+        sourceFile "Second" ["First"],
+        sourceFile "Third" ["First"],
+        sourceFile "Last" ["Third"])
+
+    let cacheEvents = ResizeArray()
+
+    ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
+        withChecker (fun checker -> checker.CacheEvent.Add cacheEvents.Add)
+        updateFile "First" updatePublicSurface
+        checkFile "Last" expectOk
+    } |> ignore
+
+    let intermediateTypeChecks =
+        cacheEvents
+        |> Seq.choose (function
+            | ("TcIntermediate", e, k) -> Some ((k :?> FSharpProjectSnapshotKey).LastFile |> fst |> Path.GetFileName, e)
+            | _ -> None)
+        |> Seq.groupBy fst
+        |> Seq.map (fun (k, g) -> k, g |> Seq.map snd |> Seq.toList)
+        |> Map
+
+    Assert.Equal([Started; Finished], intermediateTypeChecks["FileFirst.fs"])
+    Assert.Equal([Started; Finished], intermediateTypeChecks["FileThird.fs"])
+    Assert.False (intermediateTypeChecks.ContainsKey "FileSecond.fs")
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 03aeafb299a..5415b502e06 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
@@ -2060,6 +2060,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults] ParseFileInProject(System.String, System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String])
 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, FSharp.Compiler.CodeAnalysis.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])
@@ -2207,6 +2208,7 @@ FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey get_Key()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Int32 GetHashCode()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Int32 GetHashCode(System.Collections.IEqualityComparer)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Int32 IndexOf(System.String)
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot] SourceFiles
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot] get_SourceFiles()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot] ReferencedProjects
@@ -2251,6 +2253,8 @@ FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collecti
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.String ProjectFileName
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.String ToString()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.String get_ProjectFileName()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.Tuple`2[System.String,System.String] LastFile
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.Tuple`2[System.String,System.String] get_LastFile()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Void .ctor(System.String, Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.String,System.String]], Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey], Boolean, Boolean)
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: Boolean Equals(System.Object)
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: FSharp.Compiler.CodeAnalysis.FSharpReferencedProject CreateFSharp(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions)
diff --git a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs
index 15304a77a34..beeb7465daa 100644
--- a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs
+++ b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs
@@ -284,9 +284,16 @@ type Document with
         async {
             let! checker, _, _, projectOptions = this.GetFSharpCompilationOptionsAsync(userOpName)
 
-            match! checker.GetBackgroundSemanticClassificationForFile(this.FilePath, projectOptions) with
-            | Some results -> return results
-            | _ -> return raise (System.OperationCanceledException("Unable to get FSharp semantic classification."))
+            let! result =
+                if this.Project.UseTransparentCompiler then
+                    async {
+                        let! projectSnapshot = getProjectSnapshot (this, projectOptions)
+                        return! checker.GetBackgroundSemanticClassificationForFile(this.FilePath, projectSnapshot)
+                    }
+                else
+                    checker.GetBackgroundSemanticClassificationForFile(this.FilePath, projectOptions)
+
+            return result |> Option.defaultWith (fun _ -> raise (System.OperationCanceledException("Unable to get FSharp semantic classification.")))
         }
 
     /// Find F# references in the given F# document.
From 6cb3b2f33a68f87159a1a40cac20c348852a8a8c Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Wed, 17 May 2023 17:47:18 +0200
Subject: [PATCH 034/222] ..
---
 src/Compiler/Service/FSharpCheckerResults.fs                  | 4 ++--
 .../src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs  | 4 +++-
 2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs
index ab2d2f554d5..c2271aa1de4 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fs
+++ b/src/Compiler/Service/FSharpCheckerResults.fs
@@ -129,8 +129,8 @@ type FSharpProjectSnapshotKey =
         IsIncompleteTypeCheckEnvironment: bool
         UseScriptResolutionRules: bool
     }
-    member this.LastFile = this.SourceFiles |> List.last
 
+    member this.LastFile = this.SourceFiles |> List.last
 
 []
 type FSharpFileSnapshot =
@@ -206,7 +206,7 @@ type FSharpProjectSnapshot =
             SourceFiles = this.SourceFiles[..fileIndex]
         }
 
-    member this.UpTo fileName = this.UpTo (this.IndexOf fileName)
+    member this.UpTo fileName = this.UpTo(this.IndexOf fileName)
 
     member this.Key =
         {
diff --git a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs
index beeb7465daa..6d696487345 100644
--- a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs
+++ b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs
@@ -293,7 +293,9 @@ type Document with
                 else
                     checker.GetBackgroundSemanticClassificationForFile(this.FilePath, projectOptions)
 
-            return result |> Option.defaultWith (fun _ -> raise (System.OperationCanceledException("Unable to get FSharp semantic classification.")))
+            return
+                result
+                |> Option.defaultWith (fun _ -> raise (System.OperationCanceledException("Unable to get FSharp semantic classification.")))
         }
 
     /// Find F# references in the given F# document.
From cbbb2bb023d616714a8cb1a3ac5dd32080e93d7a Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Wed, 17 May 2023 20:09:34 +0200
Subject: [PATCH 035/222] find references
---
 src/Compiler/Service/BackgroundCompiler.fs    |  7 ++
 src/Compiler/Service/TransparentCompiler.fs   | 68 ++++++++++++++++---
 src/Compiler/Service/service.fs               | 16 +++++
 src/Compiler/Service/service.fsi              |  4 ++
 .../LanguageService/WorkspaceExtensions.fs    | 21 ++++--
 5 files changed, 101 insertions(+), 15 deletions(-)
diff --git a/src/Compiler/Service/BackgroundCompiler.fs b/src/Compiler/Service/BackgroundCompiler.fs
index 0fcf7918cc2..cc25ed2bed3 100644
--- a/src/Compiler/Service/BackgroundCompiler.fs
+++ b/src/Compiler/Service/BackgroundCompiler.fs
@@ -80,6 +80,10 @@ type internal IBackgroundCompiler =
         userOpName: string ->
             NodeCode>
 
+    abstract member FindReferencesInFile:
+        fileName: string * projectSnapshot: FSharpProjectSnapshot * symbol: FSharp.Compiler.Symbols.FSharpSymbol * userOpName: string ->
+            NodeCode>
+
     abstract member GetAssemblyData:
         options: FSharpProjectOptions * userOpName: string -> NodeCode
 
@@ -1431,6 +1435,9 @@ type internal BackgroundCompiler
             ) : NodeCode> =
             self.FindReferencesInFile(fileName, options, symbol, canInvalidateProject, userOpName)
 
+        member this.FindReferencesInFile(fileName, projectSnapshot, symbol, userOpName) =
+            this.FindReferencesInFile(fileName, projectSnapshot.ToOptions(), symbol, true, userOpName)
+
         member _.FrameworkImportsCache: FrameworkImportsCache = self.FrameworkImportsCache
 
         member _.GetAssemblyData(options: FSharpProjectOptions, userOpName: string) : NodeCode =
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 0ccd19d7846..d7affa00913 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -1,6 +1,7 @@
 namespace FSharp.Compiler.CodeAnalysis.TransparentCompiler
 
 open System
+open System.Collections.Generic
 open System.Diagnostics
 open System.IO
 
@@ -35,6 +36,7 @@ open Internal.Utilities.Library.Extras
 open FSharp.Compiler.TypedTree
 open FSharp.Compiler.CheckDeclarations
 open FSharp.Compiler.EditorServices
+open FSharp.Compiler.CodeAnalysis
 
 type internal FSharpFile =
     {
@@ -110,6 +112,7 @@ type internal TransparentCompiler
     let TcIntermediateCache = AsyncMemoize(triggerCacheEvent "TcIntermediate")
     let DependencyGraphForLastFileCache = AsyncMemoize(triggerCacheEvent "DependencyGraphForLastFile")
     let SemanticClassificationCache = AsyncMemoize(triggerCacheEvent "SemanticClassification")
+    let ItemKeyStoreCache = AsyncMemoize(triggerCacheEvent "ItemKeyStore")
 
     // We currently share one global dependency provider for all scripts for the FSharpChecker.
     // For projects, one is used per project.
@@ -872,9 +875,8 @@ type internal TransparentCompiler
                 return (parseResults, FSharpCheckFileAnswer.Succeeded checkResults)
         })
 
-    let ComputeSemanticClassification(fileName: string, projectSnapshot: FSharpProjectSnapshot): NodeCode =
-        let key = (projectSnapshot.UpTo fileName).Key
-        SemanticClassificationCache.Get(key, node {
+    let tryGetSink fileName (projectSnapshot: FSharpProjectSnapshot) =
+        node {
             use _ = Activity.start "ComputeSemanticClassification" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
 
             match! ComputeBootstrapInfo projectSnapshot with
@@ -890,14 +892,48 @@ type internal TransparentCompiler
                 let fileIndex = projectSnapshot.IndexOf fileName
                 let! { sink = sink } = ComputeTcIntermediate projectSnapshot fileIndex (parseTree, parseDiagnostics) bootstrapInfo tcInfo
 
-                let sResolutions = sink.GetResolutions()
+                return Some (sink, bootstrapInfo)
+        }
+
+    let ComputeSemanticClassification(fileName: string, projectSnapshot: FSharpProjectSnapshot) =
+        let key = (projectSnapshot.UpTo fileName).Key
+        SemanticClassificationCache.Get(key, node {
+            use _ = Activity.start "ComputeSemanticClassification" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
+            let! sinkOpt = tryGetSink fileName projectSnapshot
+            return
+                sinkOpt
+                |> Option.bind (fun (sink, bootstrapInfo) ->
+                    let sResolutions = sink.GetResolutions()
+                    let semanticClassification = sResolutions.GetSemanticClassification(bootstrapInfo.TcGlobals, bootstrapInfo.TcImports.GetImportMap(), sink.GetFormatSpecifierLocations(), None)
 
-                let semanticClassification = sResolutions.GetSemanticClassification(bootstrapInfo.TcGlobals, bootstrapInfo.TcImports.GetImportMap(), sink.GetFormatSpecifierLocations(), None)
+                    let sckBuilder = SemanticClassificationKeyStoreBuilder()
+                    sckBuilder.WriteAll semanticClassification
 
-                let sckBuilder = SemanticClassificationKeyStoreBuilder()
-                sckBuilder.WriteAll semanticClassification
+                    sckBuilder.TryBuildAndReset())
+                |> Option.map (fun sck -> sck.GetView())
+        })
 
-                return sckBuilder.TryBuildAndReset() |> Option.map (fun sck -> sck.GetView())
+    let ComputeItemKeyStore(fileName: string, projectSnapshot: FSharpProjectSnapshot) =
+        let key = (projectSnapshot.UpTo fileName).Key
+        ItemKeyStoreCache.Get(key, node {
+            use _ = Activity.start "ComputeItemKeyStore" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
+            let! sinkOpt = tryGetSink fileName projectSnapshot
+            return
+                sinkOpt
+                |> Option.bind (fun (sink, _) ->
+                    let sResolutions = sink.GetResolutions()
+
+                    let builder = ItemKeyStoreBuilder()
+                    let preventDuplicates = HashSet({ new IEqualityComparer with
+                                                        member _.Equals((s1, e1): struct(pos * pos), (s2, e2): struct(pos * pos)) = Position.posEq s1 s2 && Position.posEq e1 e2
+                                                        member _.GetHashCode o = o.GetHashCode() })
+                    sResolutions.CapturedNameResolutions
+                    |> Seq.iter (fun cnr ->
+                        let r = cnr.Range
+                        if preventDuplicates.Add struct(r.Start, r.End) then
+                            builder.Write(cnr.Range, cnr.Item))
+
+                    builder.TryBuildAndReset())
         })
 
     member _.ParseFile(fileName, projectSnapshot: FSharpProjectSnapshot, _userOpName) =
@@ -943,8 +979,22 @@ type internal TransparentCompiler
         ignore userOpName
         ComputeParseAndCheckFileInProject fileName projectSnapshot
 
+    member _.FindReferencesInFile
+        (
+            fileName: string,
+            projectSnapshot: FSharpProjectSnapshot,
+            symbol: FSharpSymbol,
+            userOpName: string
+        ) =
+        ignore userOpName
+        node {
+            match! ComputeItemKeyStore(fileName, projectSnapshot) with
+            | None -> return Seq.empty
+            | Some itemKeyStore -> return itemKeyStore.FindAll symbol.Item
+        }
 
     interface IBackgroundCompiler with
+
         member _.CacheEvent = cacheEvent.Publish
 
         member this.BeforeBackgroundFileCheck: IEvent =
@@ -1001,6 +1051,8 @@ type internal TransparentCompiler
             ) : NodeCode> =
             backgroundCompiler.FindReferencesInFile(fileName, options, symbol, canInvalidateProject, userOpName)
 
+        member this.FindReferencesInFile(fileName, projectSnapshot, symbol, userOpName) = this.FindReferencesInFile(fileName, projectSnapshot, symbol, userOpName)
+
         member _.FrameworkImportsCache: FrameworkImportsCache =
             backgroundCompiler.FrameworkImportsCache
 
diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs
index ae15a32bb00..ad2d1d0ee2a 100644
--- a/src/Compiler/Service/service.fs
+++ b/src/Compiler/Service/service.fs
@@ -479,6 +479,22 @@ type FSharpChecker
         }
         |> Async.AwaitNodeCode
 
+    member _.FindBackgroundReferencesInFile(fileName: string, projectSnapshot: FSharpProjectSnapshot, symbol: FSharpSymbol, ?userOpName: string) =
+        let userOpName = defaultArg userOpName "Unknown"
+
+        node {
+            let! parseResults = backgroundCompiler.ParseFile(fileName, projectSnapshot, userOpName)
+
+            if
+                parseResults.ParseTree.Identifiers |> Set.contains symbol.DisplayNameCore
+                || parseResults.ParseTree.Identifiers |> NamesContainAttribute symbol
+            then
+                return! backgroundCompiler.FindReferencesInFile(fileName, projectSnapshot, symbol, userOpName)
+            else
+                return Seq.empty
+        }
+        |> Async.AwaitNodeCode
+
     member _.GetBackgroundSemanticClassificationForFile(fileName: string, options: FSharpProjectOptions, ?userOpName) =
         let userOpName = defaultArg userOpName "Unknown"
 
diff --git a/src/Compiler/Service/service.fsi b/src/Compiler/Service/service.fsi
index f7a035d9471..30ce574813f 100644
--- a/src/Compiler/Service/service.fsi
+++ b/src/Compiler/Service/service.fsi
@@ -333,6 +333,10 @@ type public FSharpChecker =
         ?userOpName: string ->
             Async
 
+    member FindBackgroundReferencesInFile:
+        fileName: string * projectSnapshot: FSharpProjectSnapshot * symbol: FSharpSymbol * ?userOpName: string ->
+            Async
+
     /// 
     /// Get semantic classification for a file.
     /// All files are read from the FileSystem API, including the file being checked.
diff --git a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs
index 6d696487345..2c015d68e11 100644
--- a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs
+++ b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs
@@ -304,13 +304,20 @@ type Document with
             let! checker, _, _, projectOptions = this.GetFSharpCompilationOptionsAsync(userOpName)
 
             let! symbolUses =
-                checker.FindBackgroundReferencesInFile(
-                    this.FilePath,
-                    projectOptions,
-                    symbol,
-                    canInvalidateProject = false,
-                    fastCheck = this.Project.IsFastFindReferencesEnabled
-                )
+
+                if this.Project.UseTransparentCompiler then
+                    async {
+                        let! projectSnapshot = getProjectSnapshot (this, projectOptions)
+                        return! checker.FindBackgroundReferencesInFile(this.FilePath, projectSnapshot, symbol)
+                    }
+                else
+                    checker.FindBackgroundReferencesInFile(
+                        this.FilePath,
+                        projectOptions,
+                        symbol,
+                        canInvalidateProject = false,
+                        fastCheck = this.Project.IsFastFindReferencesEnabled
+                    )
 
             for symbolUse in symbolUses do
                 do! onFound symbolUse
From 371ee99d24f4af65cb31a8f46320b7b98229e824 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Thu, 18 May 2023 11:26:30 +0200
Subject: [PATCH 036/222] wip
---
 src/Compiler/Service/TransparentCompiler.fs | 128 +++++++++-----------
 1 file changed, 54 insertions(+), 74 deletions(-)
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index d7affa00913..8ef1500f04e 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -57,6 +57,10 @@ type internal BootstrapInfo =
         LoadClosure: LoadClosure option
     }
 
+    member this.GetFile fileName =
+        this.SourceFiles |> List.tryFind (fun f -> f.Source.FileName = fileName) |> Option.defaultWith (fun _ -> failwith ($"File {fileName} not found in project snapshot. Files in project: \n\n" + (this.SourceFiles |> Seq.map (fun f -> f.Source.FileName) |> String.concat " \n")))
+
+
 type internal TcIntermediateResult = TcInfo * TcResultsSinkImpl * CheckedImplFile option * string
 
 
@@ -216,10 +220,8 @@ type internal TransparentCompiler
             unresolvedReferences,
             dependencyProvider,
             loadClosureOpt: LoadClosure option,
-            basicDependencies
-#if !NO_TYPEPROVIDERS
-            ,importsInvalidatedByTypeProvider: Event
-#endif
+            basicDependencies,
+            importsInvalidatedByTypeProvider: Event
         ) =
 
         node {
@@ -240,6 +242,7 @@ type internal TransparentCompiler
                                 dependencyProvider
                             )
 #if !NO_TYPEPROVIDERS
+                        // TODO: review and handle the event
                         tcImports.GetCcusExcludingBase()
                         |> Seq.iter (fun ccu ->
                             // When a CCU reports an invalidation, merge them together and just report a
@@ -472,9 +475,9 @@ type internal TransparentCompiler
 
             let tcConfigP = TcConfigProvider.Constant tcConfig
 
-    #if !NO_TYPEPROVIDERS
+
             let importsInvalidatedByTypeProvider = Event()
-    #endif
+
 
             // Check for the existence of loaded sources and prepend them to the sources list if present.
             let sourceFiles =
@@ -522,17 +525,15 @@ type internal TransparentCompiler
                     unresolvedReferences,
                     dependencyProvider,
                     loadClosureOpt,
-                    basicDependencies
-    #if !NO_TYPEPROVIDERS
-                    ,importsInvalidatedByTypeProvider
-    #endif
+                    basicDependencies,
+                    importsInvalidatedByTypeProvider
                 )
-            return sourceFiles, tcConfig, tcImports, tcGlobals, initialTcInfo, loadClosureOpt
+            return sourceFiles, tcConfig, tcImports, tcGlobals, initialTcInfo, loadClosureOpt, importsInvalidatedByTypeProvider
         })
 
     let computeBootstrapInfoInner (projectSnapshot: FSharpProjectSnapshot) =
         node {
-            let! sourceFiles, tcConfig, tcImports, tcGlobals, initialTcInfo, loadClosureOpt = ComputeBootstrapInfoStatic projectSnapshot
+            let! sourceFiles, tcConfig, tcImports, tcGlobals, initialTcInfo, loadClosureOpt, _importsInvalidatedByTypeProvider = ComputeBootstrapInfoStatic projectSnapshot
 
             let fileSnapshots = Map [ for f in projectSnapshot.SourceFiles -> f.FileName, f ]
 
@@ -565,6 +566,7 @@ type internal TransparentCompiler
                         InitialTcInfo = initialTcInfo
                         SourceFiles = sourceFiles
                         LoadClosure = loadClosureOpt
+                        //ImportsInvalidatedByTypeProvider = importsInvalidatedByTypeProvider
                     }
         }
 
@@ -806,6 +808,37 @@ type internal TransparentCompiler
             return! processLayer layers bootstrapInfo.InitialTcInfo
         })
 
+    let getParseResult (bootstrapInfo: BootstrapInfo) creationDiags fileName =
+        node {
+            let file = bootstrapInfo.GetFile fileName
+
+            let! parseTree, parseDiagnostics, sourceText = ComputeParseFile bootstrapInfo file
+
+            let parseDiagnostics =
+                DiagnosticHelpers.CreateDiagnostics(
+                    bootstrapInfo.TcConfig.diagnosticsOptions,
+                    false,
+                    fileName,
+                    parseDiagnostics,
+                    suggestNamesForErrors
+                )
+
+            let diagnostics = [| yield! creationDiags; yield! parseDiagnostics |]
+
+            return
+                FSharpParseFileResults(
+                    diagnostics = diagnostics,
+                    input = parseTree,
+                    parseHadErrors = (parseDiagnostics.Length > 0),
+                    // TODO: check if we really need this in parse results
+                    dependencyFiles = [||]
+                ), sourceText
+        }
+
+    let emptyParseResult fileName diagnostics =
+        let parseTree = EmptyParsedInput(fileName, (false, false))
+        FSharpParseFileResults(diagnostics, parseTree, true, [||])
+
     let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: FSharpProjectSnapshot) =
         let key = fileName, projectSnapshot.Key
         ParseAndCheckFileInProjectCache.Get(key, node {
@@ -814,39 +847,15 @@ type internal TransparentCompiler
 
             match! ComputeBootstrapInfo projectSnapshot with
             | None, creationDiags ->
-                let parseTree = EmptyParsedInput(fileName, (false, false))
-                let parseResults = FSharpParseFileResults(creationDiags, parseTree, true, [||])
-                return (parseResults, FSharpCheckFileAnswer.Aborted)
+                return emptyParseResult fileName creationDiags, FSharpCheckFileAnswer.Aborted
 
             | Some bootstrapInfo, creationDiags ->
 
-                let file =
-                    bootstrapInfo.SourceFiles |> List.tryFind (fun f -> f.Source.FileName = fileName) |> Option.defaultWith (fun _ -> failwith ($"File {fileName} not found in project snapshot. Files in project: \n\n" + (bootstrapInfo.SourceFiles |> Seq.map (fun f -> f.Source.FileName) |> String.concat " \n")))
-
-                let! tcInfo = ComputeTcPrior file bootstrapInfo projectSnapshot
+                let file = bootstrapInfo.GetFile fileName
 
-                // We could also bubble this through ComputeTcPrior
-                let! parseTree, parseDiagnostics, sourceText = ComputeParseFile bootstrapInfo file
+                let! parseResults, sourceText = getParseResult bootstrapInfo creationDiags fileName
 
-                let parseDiagnostics =
-                    DiagnosticHelpers.CreateDiagnostics(
-                        bootstrapInfo.TcConfig.diagnosticsOptions,
-                        false,
-                        fileName,
-                        parseDiagnostics,
-                        suggestNamesForErrors
-                    )
-
-                let diagnostics = [| yield! creationDiags; yield! parseDiagnostics |]
-
-                let parseResults =
-                    FSharpParseFileResults(
-                        diagnostics = diagnostics,
-                        input = parseTree,
-                        parseHadErrors = (parseDiagnostics.Length > 0),
-                        // TODO: check if we really need this in parse results
-                        dependencyFiles = Array.ofList tcInfo.tcDependencyFiles
-                    )
+                let! tcInfo = ComputeTcPrior file bootstrapInfo projectSnapshot
 
                 let! checkResults =
                     FSharpCheckFileResults.CheckOneFile(
@@ -939,40 +948,11 @@ type internal TransparentCompiler
     member _.ParseFile(fileName, projectSnapshot: FSharpProjectSnapshot, _userOpName) =
         node {
             use _ = Activity.start "ParseFile" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
-
-            let! bootstrapInfoOpt, creationDiags = ComputeBootstrapInfo projectSnapshot
-
-            match bootstrapInfoOpt with
-            | None ->
-                let parseTree = EmptyParsedInput(fileName, (false, false))
-                return FSharpParseFileResults(creationDiags, parseTree, true, [||])
-
-            | Some bootstrapInfo ->
-
-                let file =
-                    bootstrapInfo.SourceFiles |> List.tryFind (fun f -> f.Source.FileName = fileName) |> Option.defaultWith (fun _ -> failwith ($"File {fileName} not found in project snapshot. Files in project: \n\n" + (bootstrapInfo.SourceFiles |> Seq.map (fun f -> f.Source.FileName) |> String.concat " \n")))
-
-                let! parseTree, parseDiagnostics, _sourceText = ComputeParseFile bootstrapInfo file
-
-                let parseDiagnostics =
-                    DiagnosticHelpers.CreateDiagnostics(
-                        bootstrapInfo.TcConfig.diagnosticsOptions,
-                        false,
-                        fileName,
-                        parseDiagnostics,
-                        suggestNamesForErrors
-                    )
-
-                let diagnostics = [| yield! creationDiags; yield! parseDiagnostics |]
-
-                return
-                    FSharpParseFileResults(
-                        diagnostics = diagnostics,
-                        input = parseTree,
-                        parseHadErrors = (parseDiagnostics.Length > 0),
-                        // TODO: check if we really need this in parse results
-                        dependencyFiles = [||]
-                    )
+            match! ComputeBootstrapInfo projectSnapshot with
+            | None, creationDiags -> return emptyParseResult fileName creationDiags
+            | Some bootstrapInfo, creationDiags ->
+                let! parseResult, _ = getParseResult bootstrapInfo creationDiags fileName
+                return parseResult
         }
 
     member _.ParseAndCheckFileInProject(fileName: string, projectSnapshot: FSharpProjectSnapshot, userOpName: string) =
From 3c6d3420f52cc4eb7d9bb37f47954383dda27201 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Thu, 18 May 2023 11:28:06 +0200
Subject: [PATCH 037/222] fantomas
---
 .fantomasignore                             |    1 -
 src/Compiler/Service/TransparentCompiler.fs | 1116 ++++++++++---------
 2 files changed, 611 insertions(+), 506 deletions(-)
diff --git a/.fantomasignore b/.fantomasignore
index 8b224eb8f65..45eb387fa16 100644
--- a/.fantomasignore
+++ b/.fantomasignore
@@ -95,7 +95,6 @@ src/FSharp.Core/seqcore.fs
 src/Compiler/AbstractIL/ilwrite.fs
 src/Compiler/Utilities/lib.fs
 src/Compiler/Service/IncrementalBuild.fs
-src/Compiler/Service/TransparentCompiler.fs
 src/Compiler/Service/ServiceAssemblyContent.fs
 src/Compiler/Service/ServiceDeclarationLists.fs
 src/Compiler/Service/ServiceErrorResolutionHints.fs
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 8ef1500f04e..bd0aa272ae8 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -58,12 +58,16 @@ type internal BootstrapInfo =
     }
 
     member this.GetFile fileName =
-        this.SourceFiles |> List.tryFind (fun f -> f.Source.FileName = fileName) |> Option.defaultWith (fun _ -> failwith ($"File {fileName} not found in project snapshot. Files in project: \n\n" + (this.SourceFiles |> Seq.map (fun f -> f.Source.FileName) |> String.concat " \n")))
-
+        this.SourceFiles
+        |> List.tryFind (fun f -> f.Source.FileName = fileName)
+        |> Option.defaultWith (fun _ ->
+            failwith (
+                $"File {fileName} not found in project snapshot. Files in project: \n\n"
+                + (this.SourceFiles |> Seq.map (fun f -> f.Source.FileName) |> String.concat " \n")
+            ))
 
 type internal TcIntermediateResult = TcInfo * TcResultsSinkImpl * CheckedImplFile option * string
 
-
 /// Accumulated results of type checking. The minimum amount of state in order to continue type-checking following files.
 []
 type internal TcIntermediate =
@@ -75,7 +79,7 @@ type internal TcIntermediate =
         moduleNamesDict: ModuleNamesDict
 
         /// Accumulated diagnostics, last file first
-        tcDiagnosticsRev:(PhasedDiagnostic * FSharpDiagnosticSeverity)[] list
+        tcDiagnosticsRev: (PhasedDiagnostic * FSharpDiagnosticSeverity)[] list
 
         tcDependencyFiles: string list
 
@@ -106,16 +110,23 @@ type internal TransparentCompiler
     let cacheEvent = new Event()
     let triggerCacheEvent name (e, k) = cacheEvent.Trigger(name, e, k)
 
-    let ParseFileCache =
-        AsyncMemoize(triggerCacheEvent "ParseFile")
-    let ParseAndCheckFileInProjectCache = AsyncMemoize(triggerCacheEvent "ParseAndCheckFileInProject")
+    let ParseFileCache = AsyncMemoize(triggerCacheEvent "ParseFile")
+
+    let ParseAndCheckFileInProjectCache =
+        AsyncMemoize(triggerCacheEvent "ParseAndCheckFileInProject")
+
     let FrameworkImportsCache = AsyncMemoize(triggerCacheEvent "FrameworkImports")
     let BootstrapInfoStaticCache = AsyncMemoize(triggerCacheEvent "BootstrapInfoStatic")
     let BootstrapInfoCache = AsyncMemoize(triggerCacheEvent "BootstrapInfo")
     let TcPriorCache = AsyncMemoize(triggerCacheEvent "TcPrior")
     let TcIntermediateCache = AsyncMemoize(triggerCacheEvent "TcIntermediate")
-    let DependencyGraphForLastFileCache = AsyncMemoize(triggerCacheEvent "DependencyGraphForLastFile")
-    let SemanticClassificationCache = AsyncMemoize(triggerCacheEvent "SemanticClassification")
+
+    let DependencyGraphForLastFileCache =
+        AsyncMemoize(triggerCacheEvent "DependencyGraphForLastFile")
+
+    let SemanticClassificationCache =
+        AsyncMemoize(triggerCacheEvent "SemanticClassification")
+
     let ItemKeyStoreCache = AsyncMemoize(triggerCacheEvent "ItemKeyStore")
 
     // We currently share one global dependency provider for all scripts for the FSharpChecker.
@@ -202,11 +213,14 @@ type internal TransparentCompiler
                 tcConfig.langVersion.SpecifiedVersion
             )
 
-        FrameworkImportsCache.Get(key, node {
-            use _ = Activity.start "ComputeFrameworkImports" []
-            let tcConfigP = TcConfigProvider.Constant tcConfig
-            return! TcImports.BuildFrameworkTcImports(tcConfigP, frameworkDLLs, nonFrameworkResolutions)
-        })
+        FrameworkImportsCache.Get(
+            key,
+            node {
+                use _ = Activity.start "ComputeFrameworkImports" []
+                let tcConfigP = TcConfigProvider.Constant tcConfig
+                return! TcImports.BuildFrameworkTcImports(tcConfigP, frameworkDLLs, nonFrameworkResolutions)
+            }
+        )
 
     // Link all the assemblies together and produce the input typecheck accumulator
     let CombineImportedAssembliesTask
@@ -311,229 +325,235 @@ type internal TransparentCompiler
 
         let key = projectSnapshot.WithoutFileVersions.Key
 
-        BootstrapInfoStaticCache.Get(key, node {
-            use _ = Activity.start "ComputeBootstrapInfoStatic" [| Activity.Tags.project, projectSnapshot.ProjectFileName |> Path.GetFileName |]
-
-            let useSimpleResolutionSwitch = "--simpleresolution"
-            let commandLineArgs = projectSnapshot.OtherOptions
-            let defaultFSharpBinariesDir = FSharpCheckerResultsSettings.defaultFSharpBinariesDir
-            let useScriptResolutionRules = projectSnapshot.UseScriptResolutionRules
-
-            let projectReferences = getProjectReferences projectSnapshot "ComputeBootstrapInfo"
-
-            // TODO: script support
-            let loadClosureOpt: LoadClosure option = None
-
-            let tcConfigB, sourceFiles =
-
-                let getSwitchValue (switchString: string) =
-                    match commandLineArgs |> List.tryFindIndex (fun s -> s.StartsWithOrdinal switchString) with
-                    | Some idx -> Some(commandLineArgs[ idx ].Substring(switchString.Length))
-                    | _ -> None
-
-                let sdkDirOverride =
-                    match loadClosureOpt with
-                    | None -> None
-                    | Some loadClosure -> loadClosure.SdkDirOverride
-
-                // see also fsc.fs: runFromCommandLineToImportingAssemblies(), as there are many similarities to where the PS creates a tcConfigB
-                let tcConfigB =
-                    TcConfigBuilder.CreateNew(
-                        legacyReferenceResolver,
-                        defaultFSharpBinariesDir,
-                        implicitIncludeDir = projectSnapshot.ProjectDirectory,
-                        reduceMemoryUsage = ReduceMemoryFlag.Yes,
-                        isInteractive = useScriptResolutionRules,
-                        isInvalidationSupported = true,
-                        defaultCopyFSharpCore = CopyFSharpCoreFlag.No,
-                        tryGetMetadataSnapshot = tryGetMetadataSnapshot,
-                        sdkDirOverride = sdkDirOverride,
-                        rangeForErrors = range0
-                    )
-
-                tcConfigB.primaryAssembly <-
-                    match loadClosureOpt with
-                    | None -> PrimaryAssembly.Mscorlib
-                    | Some loadClosure ->
-                        if loadClosure.UseDesktopFramework then
-                            PrimaryAssembly.Mscorlib
-                        else
-                            PrimaryAssembly.System_Runtime
-
-                tcConfigB.resolutionEnvironment <- (LegacyResolutionEnvironment.EditingOrCompilation true)
-
-                tcConfigB.conditionalDefines <-
-                    let define =
-                        if useScriptResolutionRules then
-                            "INTERACTIVE"
-                        else
-                            "COMPILED"
-
-                    define :: tcConfigB.conditionalDefines
-
-                tcConfigB.projectReferences <- projectReferences
-
-                tcConfigB.useSimpleResolution <- (getSwitchValue useSimpleResolutionSwitch) |> Option.isSome
-
-                // Apply command-line arguments and collect more source files if they are in the arguments
-                let sourceFilesNew =
-                    ApplyCommandLineArgs(tcConfigB, projectSnapshot.SourceFileNames, commandLineArgs)
-
-                // Never open PDB files for the language service, even if --standalone is specified
-                tcConfigB.openDebugInformationForLaterStaticLinking <- false
-
-                tcConfigB.xmlDocInfoLoader <-
-                    { new IXmlDocumentationInfoLoader with
-                        /// Try to load xml documentation associated with an assembly by the same file path with the extension ".xml".
-                        member _.TryLoad(assemblyFileName) =
-                            let xmlFileName = Path.ChangeExtension(assemblyFileName, ".xml")
-
-                            // REVIEW: File IO - Will eventually need to change this to use a file system interface of some sort.
-                            XmlDocumentationInfo.TryCreateFromFile(xmlFileName)
-                    }
-                    |> Some
-
-                tcConfigB.parallelReferenceResolution <- parallelReferenceResolution
-                tcConfigB.captureIdentifiersWhenParsing <- captureIdentifiersWhenParsing
-
-                tcConfigB, sourceFilesNew
-
-            // If this is a builder for a script, re-apply the settings inferred from the
-            // script and its load closure to the configuration.
-            //
-            // NOTE: it would probably be cleaner and more accurate to re-run the load closure at this point.
-            let setupConfigFromLoadClosure () =
-                match loadClosureOpt with
-                | Some loadClosure ->
-                    let dllReferences =
-                        [
-                            for reference in tcConfigB.referencedDLLs do
-                                // If there's (one or more) resolutions of closure references then yield them all
-                                match
-                                    loadClosure.References
-                                    |> List.tryFind (fun (resolved, _) -> resolved = reference.Text)
-                                with
-                                | Some (resolved, closureReferences) ->
-                                    for closureReference in closureReferences do
-                                        yield AssemblyReference(closureReference.originalReference.Range, resolved, None)
-                                | None -> yield reference
-                        ]
-
-                    tcConfigB.referencedDLLs <- []
+        BootstrapInfoStaticCache.Get(
+            key,
+            node {
+                use _ =
+                    Activity.start
+                        "ComputeBootstrapInfoStatic"
+                        [| Activity.Tags.project, projectSnapshot.ProjectFileName |> Path.GetFileName |]
+
+                let useSimpleResolutionSwitch = "--simpleresolution"
+                let commandLineArgs = projectSnapshot.OtherOptions
+                let defaultFSharpBinariesDir = FSharpCheckerResultsSettings.defaultFSharpBinariesDir
+                let useScriptResolutionRules = projectSnapshot.UseScriptResolutionRules
+
+                let projectReferences = getProjectReferences projectSnapshot "ComputeBootstrapInfo"
+
+                // TODO: script support
+                let loadClosureOpt: LoadClosure option = None
+
+                let tcConfigB, sourceFiles =
+
+                    let getSwitchValue (switchString: string) =
+                        match commandLineArgs |> List.tryFindIndex (fun s -> s.StartsWithOrdinal switchString) with
+                        | Some idx -> Some(commandLineArgs[ idx ].Substring(switchString.Length))
+                        | _ -> None
+
+                    let sdkDirOverride =
+                        match loadClosureOpt with
+                        | None -> None
+                        | Some loadClosure -> loadClosure.SdkDirOverride
+
+                    // see also fsc.fs: runFromCommandLineToImportingAssemblies(), as there are many similarities to where the PS creates a tcConfigB
+                    let tcConfigB =
+                        TcConfigBuilder.CreateNew(
+                            legacyReferenceResolver,
+                            defaultFSharpBinariesDir,
+                            implicitIncludeDir = projectSnapshot.ProjectDirectory,
+                            reduceMemoryUsage = ReduceMemoryFlag.Yes,
+                            isInteractive = useScriptResolutionRules,
+                            isInvalidationSupported = true,
+                            defaultCopyFSharpCore = CopyFSharpCoreFlag.No,
+                            tryGetMetadataSnapshot = tryGetMetadataSnapshot,
+                            sdkDirOverride = sdkDirOverride,
+                            rangeForErrors = range0
+                        )
 
                     tcConfigB.primaryAssembly <-
-                        (if loadClosure.UseDesktopFramework then
-                             PrimaryAssembly.Mscorlib
-                         else
-                             PrimaryAssembly.System_Runtime)
-                    // Add one by one to remove duplicates
-                    dllReferences
-                    |> List.iter (fun dllReference -> tcConfigB.AddReferencedAssemblyByPath(dllReference.Range, dllReference.Text))
-
-                    tcConfigB.knownUnresolvedReferences <- loadClosure.UnresolvedReferences
-                | None -> ()
-
-            setupConfigFromLoadClosure ()
-
-            let tcConfig = TcConfig.Create(tcConfigB, validate = true)
-            let _outfile, _, assemblyName = tcConfigB.DecideNames sourceFiles
+                        match loadClosureOpt with
+                        | None -> PrimaryAssembly.Mscorlib
+                        | Some loadClosure ->
+                            if loadClosure.UseDesktopFramework then
+                                PrimaryAssembly.Mscorlib
+                            else
+                                PrimaryAssembly.System_Runtime
 
-            // Resolve assemblies and create the framework TcImports. This caches a level of "system" references. No type providers are
-            // included in these references.
+                    tcConfigB.resolutionEnvironment <- (LegacyResolutionEnvironment.EditingOrCompilation true)
 
-            let frameworkDLLs, nonFrameworkResolutions, unresolvedReferences =
-                TcAssemblyResolutions.SplitNonFoundationalResolutions(tcConfig)
+                    tcConfigB.conditionalDefines <-
+                        let define =
+                            if useScriptResolutionRules then
+                                "INTERACTIVE"
+                            else
+                                "COMPILED"
 
-            // Prepare the frameworkTcImportsCache
-            let! tcGlobals, frameworkTcImports = ComputeFrameworkImports tcConfig frameworkDLLs nonFrameworkResolutions
-
-            // Note we are not calling diagnosticsLogger.GetDiagnostics() anywhere for this task.
-            // This is ok because not much can actually go wrong here.
-            let diagnosticsLogger =
-                CompilationDiagnosticLogger("nonFrameworkAssemblyInputs", tcConfig.diagnosticsOptions)
-
-            use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parameter)
+                        define :: tcConfigB.conditionalDefines
 
-            // TODO: might need to put something like this somewhere
-            //// Get the names and time stamps of all the non-framework referenced assemblies, which will act
-            //// as inputs to one of the nodes in the build.
-            ////
-            //// This operation is done when constructing the builder itself, rather than as an incremental task.
-            //let nonFrameworkAssemblyInputs =
-            //    // Note we are not calling diagnosticsLogger.GetDiagnostics() anywhere for this task.
-            //    // This is ok because not much can actually go wrong here.
-            //    let diagnosticsLogger = CompilationDiagnosticLogger("nonFrameworkAssemblyInputs", tcConfig.diagnosticsOptions)
-            //    // Return the disposable object that cleans up
-            //    use _holder = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parameter)
+                    tcConfigB.projectReferences <- projectReferences
 
-            //    [ for r in nonFrameworkResolutions do
-            //        let fileName = r.resolvedPath
-            //        yield (Choice1Of2 fileName, (fun (cache: TimeStampCache) -> cache.GetFileTimeStamp fileName))
+                    tcConfigB.useSimpleResolution <- (getSwitchValue useSimpleResolutionSwitch) |> Option.isSome
 
-            //      for pr in projectReferences  do
-            //        yield Choice2Of2 pr, (fun (cache: TimeStampCache) -> cache.GetProjectReferenceTimeStamp pr) ]
+                    // Apply command-line arguments and collect more source files if they are in the arguments
+                    let sourceFilesNew =
+                        ApplyCommandLineArgs(tcConfigB, projectSnapshot.SourceFileNames, commandLineArgs)
 
-            let tcConfigP = TcConfigProvider.Constant tcConfig
+                    // Never open PDB files for the language service, even if --standalone is specified
+                    tcConfigB.openDebugInformationForLaterStaticLinking <- false
 
+                    tcConfigB.xmlDocInfoLoader <-
+                        { new IXmlDocumentationInfoLoader with
+                            /// Try to load xml documentation associated with an assembly by the same file path with the extension ".xml".
+                            member _.TryLoad(assemblyFileName) =
+                                let xmlFileName = Path.ChangeExtension(assemblyFileName, ".xml")
 
-            let importsInvalidatedByTypeProvider = Event()
+                                // REVIEW: File IO - Will eventually need to change this to use a file system interface of some sort.
+                                XmlDocumentationInfo.TryCreateFromFile(xmlFileName)
+                        }
+                        |> Some
 
+                    tcConfigB.parallelReferenceResolution <- parallelReferenceResolution
+                    tcConfigB.captureIdentifiersWhenParsing <- captureIdentifiersWhenParsing
 
-            // Check for the existence of loaded sources and prepend them to the sources list if present.
-            let sourceFiles =
-                tcConfig.GetAvailableLoadedSources()
-                @ (sourceFiles |> List.map (fun s -> rangeStartup, s))
+                    tcConfigB, sourceFilesNew
 
-            // Mark up the source files with an indicator flag indicating if they are the last source file in the project
-            let sourceFiles =
-                let flags, isExe = tcConfig.ComputeCanContainEntryPoint(sourceFiles |> List.map snd)
-                ((sourceFiles, flags) ||> List.map2 (fun (m, nm) flag -> (m, nm, (flag, isExe))))
+                // If this is a builder for a script, re-apply the settings inferred from the
+                // script and its load closure to the configuration.
+                //
+                // NOTE: it would probably be cleaner and more accurate to re-run the load closure at this point.
+                let setupConfigFromLoadClosure () =
+                    match loadClosureOpt with
+                    | Some loadClosure ->
+                        let dllReferences =
+                            [
+                                for reference in tcConfigB.referencedDLLs do
+                                    // If there's (one or more) resolutions of closure references then yield them all
+                                    match
+                                        loadClosure.References
+                                        |> List.tryFind (fun (resolved, _) -> resolved = reference.Text)
+                                    with
+                                    | Some (resolved, closureReferences) ->
+                                        for closureReference in closureReferences do
+                                            yield AssemblyReference(closureReference.originalReference.Range, resolved, None)
+                                    | None -> yield reference
+                            ]
+
+                        tcConfigB.referencedDLLs <- []
+
+                        tcConfigB.primaryAssembly <-
+                            (if loadClosure.UseDesktopFramework then
+                                 PrimaryAssembly.Mscorlib
+                             else
+                                 PrimaryAssembly.System_Runtime)
+                        // Add one by one to remove duplicates
+                        dllReferences
+                        |> List.iter (fun dllReference -> tcConfigB.AddReferencedAssemblyByPath(dllReference.Range, dllReference.Text))
+
+                        tcConfigB.knownUnresolvedReferences <- loadClosure.UnresolvedReferences
+                    | None -> ()
 
-            let basicDependencies =
-                [
-                    for UnresolvedAssemblyReference (referenceText, _) in unresolvedReferences do
-                        // Exclude things that are definitely not a file name
-                        if not (FileSystem.IsInvalidPathShim referenceText) then
-                            let file =
-                                if FileSystem.IsPathRootedShim referenceText then
-                                    referenceText
-                                else
-                                    Path.Combine(projectSnapshot.ProjectDirectory, referenceText)
-
-                            yield file
-
-                    for r in nonFrameworkResolutions do
-                        yield r.resolvedPath
-                ]
+                setupConfigFromLoadClosure ()
+
+                let tcConfig = TcConfig.Create(tcConfigB, validate = true)
+                let _outfile, _, assemblyName = tcConfigB.DecideNames sourceFiles
+
+                // Resolve assemblies and create the framework TcImports. This caches a level of "system" references. No type providers are
+                // included in these references.
+
+                let frameworkDLLs, nonFrameworkResolutions, unresolvedReferences =
+                    TcAssemblyResolutions.SplitNonFoundationalResolutions(tcConfig)
+
+                // Prepare the frameworkTcImportsCache
+                let! tcGlobals, frameworkTcImports = ComputeFrameworkImports tcConfig frameworkDLLs nonFrameworkResolutions
+
+                // Note we are not calling diagnosticsLogger.GetDiagnostics() anywhere for this task.
+                // This is ok because not much can actually go wrong here.
+                let diagnosticsLogger =
+                    CompilationDiagnosticLogger("nonFrameworkAssemblyInputs", tcConfig.diagnosticsOptions)
+
+                use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parameter)
+
+                // TODO: might need to put something like this somewhere
+                //// Get the names and time stamps of all the non-framework referenced assemblies, which will act
+                //// as inputs to one of the nodes in the build.
+                ////
+                //// This operation is done when constructing the builder itself, rather than as an incremental task.
+                //let nonFrameworkAssemblyInputs =
+                //    // Note we are not calling diagnosticsLogger.GetDiagnostics() anywhere for this task.
+                //    // This is ok because not much can actually go wrong here.
+                //    let diagnosticsLogger = CompilationDiagnosticLogger("nonFrameworkAssemblyInputs", tcConfig.diagnosticsOptions)
+                //    // Return the disposable object that cleans up
+                //    use _holder = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parameter)
+
+                //    [ for r in nonFrameworkResolutions do
+                //        let fileName = r.resolvedPath
+                //        yield (Choice1Of2 fileName, (fun (cache: TimeStampCache) -> cache.GetFileTimeStamp fileName))
+
+                //      for pr in projectReferences  do
+                //        yield Choice2Of2 pr, (fun (cache: TimeStampCache) -> cache.GetProjectReferenceTimeStamp pr) ]
+
+                let tcConfigP = TcConfigProvider.Constant tcConfig
+
+                let importsInvalidatedByTypeProvider = Event()
+
+                // Check for the existence of loaded sources and prepend them to the sources list if present.
+                let sourceFiles =
+                    tcConfig.GetAvailableLoadedSources()
+                    @ (sourceFiles |> List.map (fun s -> rangeStartup, s))
+
+                // Mark up the source files with an indicator flag indicating if they are the last source file in the project
+                let sourceFiles =
+                    let flags, isExe = tcConfig.ComputeCanContainEntryPoint(sourceFiles |> List.map snd)
+                    ((sourceFiles, flags) ||> List.map2 (fun (m, nm) flag -> (m, nm, (flag, isExe))))
+
+                let basicDependencies =
+                    [
+                        for UnresolvedAssemblyReference (referenceText, _) in unresolvedReferences do
+                            // Exclude things that are definitely not a file name
+                            if not (FileSystem.IsInvalidPathShim referenceText) then
+                                let file =
+                                    if FileSystem.IsPathRootedShim referenceText then
+                                        referenceText
+                                    else
+                                        Path.Combine(projectSnapshot.ProjectDirectory, referenceText)
+
+                                yield file
+
+                        for r in nonFrameworkResolutions do
+                            yield r.resolvedPath
+                    ]
+
+                // For scripts, the dependency provider is already available.
+                // For projects create a fresh one for the project.
+                let dependencyProvider =
+                    if projectSnapshot.UseScriptResolutionRules then
+                        dependencyProviderForScripts
+                    else
+                        new DependencyProvider()
+
+                let! tcImports, initialTcInfo =
+                    CombineImportedAssembliesTask(
+                        assemblyName,
+                        tcConfig,
+                        tcConfigP,
+                        tcGlobals,
+                        frameworkTcImports,
+                        nonFrameworkResolutions,
+                        unresolvedReferences,
+                        dependencyProvider,
+                        loadClosureOpt,
+                        basicDependencies,
+                        importsInvalidatedByTypeProvider
+                    )
 
-            // For scripts, the dependency provider is already available.
-            // For projects create a fresh one for the project.
-            let dependencyProvider =
-                if projectSnapshot.UseScriptResolutionRules then
-                    dependencyProviderForScripts
-                else
-                    new DependencyProvider()
-
-            let! tcImports, initialTcInfo =
-                CombineImportedAssembliesTask(
-                    assemblyName,
-                    tcConfig,
-                    tcConfigP,
-                    tcGlobals,
-                    frameworkTcImports,
-                    nonFrameworkResolutions,
-                    unresolvedReferences,
-                    dependencyProvider,
-                    loadClosureOpt,
-                    basicDependencies,
-                    importsInvalidatedByTypeProvider
-                )
-            return sourceFiles, tcConfig, tcImports, tcGlobals, initialTcInfo, loadClosureOpt, importsInvalidatedByTypeProvider
-        })
+                return sourceFiles, tcConfig, tcImports, tcGlobals, initialTcInfo, loadClosureOpt, importsInvalidatedByTypeProvider
+            }
+        )
 
     let computeBootstrapInfoInner (projectSnapshot: FSharpProjectSnapshot) =
         node {
-            let! sourceFiles, tcConfig, tcImports, tcGlobals, initialTcInfo, loadClosureOpt, _importsInvalidatedByTypeProvider = ComputeBootstrapInfoStatic projectSnapshot
+            let! sourceFiles, tcConfig, tcImports, tcGlobals, initialTcInfo, loadClosureOpt, _importsInvalidatedByTypeProvider =
+                ComputeBootstrapInfoStatic projectSnapshot
 
             let fileSnapshots = Map [ for f in projectSnapshot.SourceFiles -> f.FileName, f ]
 
@@ -566,169 +586,207 @@ type internal TransparentCompiler
                         InitialTcInfo = initialTcInfo
                         SourceFiles = sourceFiles
                         LoadClosure = loadClosureOpt
-                        //ImportsInvalidatedByTypeProvider = importsInvalidatedByTypeProvider
+                    //ImportsInvalidatedByTypeProvider = importsInvalidatedByTypeProvider
                     }
         }
 
     let ComputeBootstrapInfo (projectSnapshot: FSharpProjectSnapshot) =
-        BootstrapInfoCache.Get(projectSnapshot.Key, node {
-            use _ = Activity.start "ComputeBootstrapInfo" [| Activity.Tags.project, projectSnapshot.ProjectFileName |> Path.GetFileName |]
-
-            // Trap and report diagnostics from creation.
-            let delayedLogger = CapturingDiagnosticsLogger("IncrementalBuilderCreation")
-            use _ = new CompilationGlobalsScope(delayedLogger, BuildPhase.Parameter)
-
-            let! bootstrapInfoOpt =
-                node {
-                    try
-                        return! computeBootstrapInfoInner projectSnapshot
-                    with exn ->
-                        errorRecoveryNoRange exn
-                        return None
-                }
+        BootstrapInfoCache.Get(
+            projectSnapshot.Key,
+            node {
+                use _ =
+                    Activity.start "ComputeBootstrapInfo" [| Activity.Tags.project, projectSnapshot.ProjectFileName |> Path.GetFileName |]
+
+                // Trap and report diagnostics from creation.
+                let delayedLogger = CapturingDiagnosticsLogger("IncrementalBuilderCreation")
+                use _ = new CompilationGlobalsScope(delayedLogger, BuildPhase.Parameter)
+
+                let! bootstrapInfoOpt =
+                    node {
+                        try
+                            return! computeBootstrapInfoInner projectSnapshot
+                        with exn ->
+                            errorRecoveryNoRange exn
+                            return None
+                    }
 
-            let diagnostics =
-                match bootstrapInfoOpt with
-                | Some bootstrapInfo ->
-                    let diagnosticsOptions = bootstrapInfo.TcConfig.diagnosticsOptions
+                let diagnostics =
+                    match bootstrapInfoOpt with
+                    | Some bootstrapInfo ->
+                        let diagnosticsOptions = bootstrapInfo.TcConfig.diagnosticsOptions
 
-                    let diagnosticsLogger =
-                        CompilationDiagnosticLogger("IncrementalBuilderCreation", diagnosticsOptions)
+                        let diagnosticsLogger =
+                            CompilationDiagnosticLogger("IncrementalBuilderCreation", diagnosticsOptions)
 
-                    delayedLogger.CommitDelayedDiagnostics diagnosticsLogger
-                    diagnosticsLogger.GetDiagnostics()
-                | _ -> Array.ofList delayedLogger.Diagnostics
-                |> Array.map (fun (diagnostic, severity) ->
-                    FSharpDiagnostic.CreateFromException(diagnostic, severity, range.Zero, suggestNamesForErrors))
+                        delayedLogger.CommitDelayedDiagnostics diagnosticsLogger
+                        diagnosticsLogger.GetDiagnostics()
+                    | _ -> Array.ofList delayedLogger.Diagnostics
+                    |> Array.map (fun (diagnostic, severity) ->
+                        FSharpDiagnostic.CreateFromException(diagnostic, severity, range.Zero, suggestNamesForErrors))
 
-            return bootstrapInfoOpt, diagnostics
-        })
+                return bootstrapInfoOpt, diagnostics
+            }
+        )
 
-    let ComputeParseFile bootstrapInfo (file: FSharpFile)  =
+    let ComputeParseFile bootstrapInfo (file: FSharpFile) =
         let key = file.Source.Key, file.IsLastCompiland, file.IsExe
-        ParseFileCache.Get(key, node {
-            use _ = Activity.start "ComputeParseFile" [| Activity.Tags.fileName, file.Source.FileName |> Path.GetFileName; Activity.Tags.version, file.Source.Version |]
-
-            let tcConfig = bootstrapInfo.TcConfig
-
-            let diagnosticsLogger =
-                CompilationDiagnosticLogger("Parse", tcConfig.diagnosticsOptions)
-            // Return the disposable object that cleans up
-            use _holder = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parse)
 
-            let flags = file.IsLastCompiland, file.IsExe
-            let fileName = file.Source.FileName
-            let! sourceText = file.Source.GetSource() |> NodeCode.AwaitTask
-
-            let input =
-                ParseOneInputSourceText(tcConfig, lexResourceManager, fileName, flags, diagnosticsLogger, sourceText)
-
-            return input, diagnosticsLogger.GetDiagnostics(), sourceText
-        })
+        ParseFileCache.Get(
+            key,
+            node {
+                use _ =
+                    Activity.start
+                        "ComputeParseFile"
+                        [|
+                            Activity.Tags.fileName, file.Source.FileName |> Path.GetFileName
+                            Activity.Tags.version, file.Source.Version
+                        |]
+
+                let tcConfig = bootstrapInfo.TcConfig
+
+                let diagnosticsLogger =
+                    CompilationDiagnosticLogger("Parse", tcConfig.diagnosticsOptions)
+                // Return the disposable object that cleans up
+                use _holder = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Parse)
+
+                let flags = file.IsLastCompiland, file.IsExe
+                let fileName = file.Source.FileName
+                let! sourceText = file.Source.GetSource() |> NodeCode.AwaitTask
+
+                let input =
+                    ParseOneInputSourceText(tcConfig, lexResourceManager, fileName, flags, diagnosticsLogger, sourceText)
+
+                return input, diagnosticsLogger.GetDiagnostics(), sourceText
+            }
+        )
 
     let ComputeDependencyGraphForLastFile (priorSnapshot: FSharpProjectSnapshot) parsedInputs (tcConfig: TcConfig) =
         let key = priorSnapshot.SourceFiles |> List.map (fun s -> s.Key)
-        DependencyGraphForLastFileCache.Get(key, node {
-
-            let sourceFiles: FileInProject array =
-                parsedInputs
-                |> Seq.toArray
-                |> Array.mapi (fun idx (input: ParsedInput) ->
-                    {
-                        Idx = idx
-                        FileName = input.FileName
-                        ParsedInput = input
-                    })
-
-            use _ = Activity.start "ComputeDependencyGraphForLastFile" [| Activity.Tags.fileName, (sourceFiles |> Array.last).FileName |]
-
-            let filePairs = FilePairMap(sourceFiles)
-
-            // TODO: we will probably want to cache and re-use larger graphs if available
-            let graph =
-                DependencyResolution.mkGraph tcConfig.compilingFSharpCore filePairs sourceFiles
-                |> fst
-                |> Graph.subGraphFor (sourceFiles |> Array.last).Idx
 
-            return TransformDependencyGraph(graph, filePairs)
-        })
+        DependencyGraphForLastFileCache.Get(
+            key,
+            node {
+
+                let sourceFiles: FileInProject array =
+                    parsedInputs
+                    |> Seq.toArray
+                    |> Array.mapi (fun idx (input: ParsedInput) ->
+                        {
+                            Idx = idx
+                            FileName = input.FileName
+                            ParsedInput = input
+                        })
+
+                use _ =
+                    Activity.start "ComputeDependencyGraphForLastFile" [| Activity.Tags.fileName, (sourceFiles |> Array.last).FileName |]
+
+                let filePairs = FilePairMap(sourceFiles)
+
+                // TODO: we will probably want to cache and re-use larger graphs if available
+                let graph =
+                    DependencyResolution.mkGraph tcConfig.compilingFSharpCore filePairs sourceFiles
+                    |> fst
+                    |> Graph.subGraphFor (sourceFiles |> Array.last).Idx
+
+                return TransformDependencyGraph(graph, filePairs)
+            }
+        )
 
-    let ComputeTcIntermediate (projectSnapshot: FSharpProjectSnapshot) (fileIndex: FileIndex) (parsedInput: ParsedInput, parseErrors) bootstrapInfo (prevTcInfo: TcInfo) =
+    let ComputeTcIntermediate
+        (projectSnapshot: FSharpProjectSnapshot)
+        (fileIndex: FileIndex)
+        (parsedInput: ParsedInput, parseErrors)
+        bootstrapInfo
+        (prevTcInfo: TcInfo)
+        =
         // TODO: we need to construct cache key based on only relevant files from the dependency graph
         let key = projectSnapshot.UpTo(fileIndex).Key
-        TcIntermediateCache.Get(key, node {
-            let input = parsedInput
-            let fileName = input.FileName
 
-            use _ = Activity.start "ComputeTcIntermediate" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
+        TcIntermediateCache.Get(
+            key,
+            node {
+                let input = parsedInput
+                let fileName = input.FileName
 
-            let tcConfig = bootstrapInfo.TcConfig
-            let tcGlobals = bootstrapInfo.TcGlobals
-            let tcImports = bootstrapInfo.TcImports
+                use _ =
+                    Activity.start "ComputeTcIntermediate" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
 
-            let capturingDiagnosticsLogger = CapturingDiagnosticsLogger("TypeCheck")
+                let tcConfig = bootstrapInfo.TcConfig
+                let tcGlobals = bootstrapInfo.TcGlobals
+                let tcImports = bootstrapInfo.TcImports
 
-            let diagnosticsLogger =
-                GetDiagnosticsLoggerFilteringByScopedPragmas(
-                    false,
-                    input.ScopedPragmas,
-                    tcConfig.diagnosticsOptions,
-                    capturingDiagnosticsLogger
-                )
+                let capturingDiagnosticsLogger = CapturingDiagnosticsLogger("TypeCheck")
 
-            use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.TypeCheck)
+                let diagnosticsLogger =
+                    GetDiagnosticsLoggerFilteringByScopedPragmas(
+                        false,
+                        input.ScopedPragmas,
+                        tcConfig.diagnosticsOptions,
+                        capturingDiagnosticsLogger
+                    )
 
-            //beforeFileChecked.Trigger fileName
+                use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.TypeCheck)
 
-            ApplyMetaCommandsFromInputToTcConfig(tcConfig, input, Path.GetDirectoryName fileName, tcImports.DependencyProvider)
-            |> ignore
+                //beforeFileChecked.Trigger fileName
 
-            let sink = TcResultsSinkImpl(tcGlobals)
-            let hadParseErrors = not (Array.isEmpty parseErrors)
+                ApplyMetaCommandsFromInputToTcConfig(tcConfig, input, Path.GetDirectoryName fileName, tcImports.DependencyProvider)
+                |> ignore
 
-            let input, moduleNamesDict =
-                DeduplicateParsedInputModuleName prevTcInfo.moduleNamesDict input
+                let sink = TcResultsSinkImpl(tcGlobals)
+                let hadParseErrors = not (Array.isEmpty parseErrors)
 
-            let! finisher =
-                CheckOneInputWithCallback(
-                    (fun () -> hadParseErrors || diagnosticsLogger.ErrorCount > 0),
-                    tcConfig,
-                    tcImports,
-                    tcGlobals,
-                    None,
-                    TcResultsSink.WithSink sink,
-                    prevTcInfo.tcState,
-                    input,
-                    false
-                )
-                |> NodeCode.FromCancellable
+                let input, moduleNamesDict =
+                    DeduplicateParsedInputModuleName prevTcInfo.moduleNamesDict input
 
-            //fileChecked.Trigger fileName
+                let! finisher =
+                    CheckOneInputWithCallback(
+                        (fun () -> hadParseErrors || diagnosticsLogger.ErrorCount > 0),
+                        tcConfig,
+                        tcImports,
+                        tcGlobals,
+                        None,
+                        TcResultsSink.WithSink sink,
+                        prevTcInfo.tcState,
+                        input,
+                        false
+                    )
+                    |> NodeCode.FromCancellable
 
-            let newErrors =
-                Array.append parseErrors (capturingDiagnosticsLogger.Diagnostics |> List.toArray)
+                //fileChecked.Trigger fileName
 
-            return
-                {
-                    finisher = finisher
-                    moduleNamesDict = moduleNamesDict
-                    tcDiagnosticsRev = [ newErrors ]
-                    tcDependencyFiles = [ fileName ]
-                    sink = sink
-                }
-        })
+                let newErrors =
+                    Array.append parseErrors (capturingDiagnosticsLogger.Diagnostics |> List.toArray)
+
+                return
+                    {
+                        finisher = finisher
+                        moduleNamesDict = moduleNamesDict
+                        tcDiagnosticsRev = [ newErrors ]
+                        tcDependencyFiles = [ fileName ]
+                        sink = sink
+                    }
+            }
+        )
 
     let mergeIntermediateResults =
         Array.fold (fun (tcInfo: TcInfo) (tcIntermediate: TcIntermediate) ->
-            let (tcEnv, topAttribs, _checkImplFileOpt, ccuSigForFile), tcState = tcInfo.tcState |> tcIntermediate.finisher.Invoke
-            let tcEnvAtEndOfFile = if keepAllBackgroundResolutions then tcEnv else tcState.TcEnvFromImpls
+            let (tcEnv, topAttribs, _checkImplFileOpt, ccuSigForFile), tcState =
+                tcInfo.tcState |> tcIntermediate.finisher.Invoke
+
+            let tcEnvAtEndOfFile =
+                if keepAllBackgroundResolutions then
+                    tcEnv
+                else
+                    tcState.TcEnvFromImpls
+
             { tcInfo with
                 tcState = tcState
                 tcEnvAtEndOfFile = tcEnvAtEndOfFile
                 topAttribs = Some topAttribs
                 tcDiagnosticsRev = tcIntermediate.tcDiagnosticsRev @ tcInfo.tcDiagnosticsRev
                 tcDependencyFiles = tcIntermediate.tcDependencyFiles @ tcInfo.tcDependencyFiles
-                latestCcuSigForFile = Some ccuSigForFile })
+                latestCcuSigForFile = Some ccuSigForFile
+            })
 
     // Type check everything that is needed to check given file
     let ComputeTcPrior (file: FSharpFile) (bootstrapInfo: BootstrapInfo) (projectSnapshot: FSharpProjectSnapshot) =
@@ -736,77 +794,88 @@ type internal TransparentCompiler
         let priorSnapshot = projectSnapshot.UpTo file.Source.FileName
         let key = priorSnapshot.Key
 
-        TcPriorCache.Get(key, node {
-            use _ = Activity.start "ComputeTcPrior" [| Activity.Tags.fileName, file.Source.FileName |> Path.GetFileName |]
-
-            // parse required files
-            let files =
-                seq {
-                    yield! bootstrapInfo.SourceFiles |> Seq.takeWhile ((<>) file)
-                    file
-                }
-
-            let! parsedInputs =
-                files
-                |> Seq.map (ComputeParseFile bootstrapInfo)
-                |> NodeCode.Parallel
-
-            let! graph = ComputeDependencyGraphForLastFile priorSnapshot (parsedInputs |> Seq.map p13) bootstrapInfo.TcConfig
-
-            let fileNames =
-                parsedInputs
-                |> Seq.mapi (fun idx (input, _, _) -> idx, Path.GetFileName input.FileName)
-                |> Map.ofSeq
-
-            let debugGraph =
-                graph
-                |> Graph.map (function NodeToTypeCheck.PhysicalFile i -> i, fileNames[i] | NodeToTypeCheck.ArtificialImplFile i -> -(i + 1), $"AIF : {fileNames[i]}")
-
-            Trace.TraceInformation("\n" + (debugGraph |> Graph.serialiseToMermaid))
-
-            // layers that can be processed in parallel
-            let layers = Graph.leafSequence graph |> Seq.toList
-
-            // remove the final layer, which should be the target file
-            let layers = layers |> List.take (layers.Length - 1)
+        TcPriorCache.Get(
+            key,
+            node {
+                use _ =
+                    Activity.start "ComputeTcPrior" [| Activity.Tags.fileName, file.Source.FileName |> Path.GetFileName |]
+
+                // parse required files
+                let files =
+                    seq {
+                        yield! bootstrapInfo.SourceFiles |> Seq.takeWhile ((<>) file)
+                        file
+                    }
 
-            let rec processLayer (layers: Set list) tcInfo =
-                node {
-                    match layers with
-                    | [] -> return tcInfo
-                    | layer :: rest ->
-                        let! results =
-                            layer
-                            |> Seq.map (fun fileNode ->
-
-                                match fileNode with
-                                | NodeToTypeCheck.PhysicalFile fileIndex ->
-                                    let parsedInput, parseErrors, _ = parsedInputs[fileIndex]
-                                    ComputeTcIntermediate projectSnapshot fileIndex (parsedInput, parseErrors) bootstrapInfo tcInfo
-                                | NodeToTypeCheck.ArtificialImplFile fileIndex ->
-
-                                    let finisher tcState =
-                                        let parsedInput, _parseErrors, _ = parsedInputs[fileIndex]
-                                        let prefixPathOpt = None
-                                        // Retrieve the type-checked signature information and add it to the TcEnvFromImpls.
-                                        AddSignatureResultToTcImplEnv(bootstrapInfo.TcImports, bootstrapInfo.TcGlobals, prefixPathOpt, TcResultsSink.NoSink, tcState, parsedInput) tcState
-                                    let tcIntermediate =
-                                        {
-                                            finisher = finisher
-                                            moduleNamesDict = tcInfo.moduleNamesDict
-                                            tcDiagnosticsRev = []
-                                            tcDependencyFiles = []
-                                            sink = Unchecked.defaultof<_>
-                                        }
-
-                                    node.Return(tcIntermediate))
-                            |> NodeCode.Parallel
-
-                        return! processLayer rest (mergeIntermediateResults tcInfo results)
-                }
+                let! parsedInputs = files |> Seq.map (ComputeParseFile bootstrapInfo) |> NodeCode.Parallel
+
+                let! graph = ComputeDependencyGraphForLastFile priorSnapshot (parsedInputs |> Seq.map p13) bootstrapInfo.TcConfig
+
+                let fileNames =
+                    parsedInputs
+                    |> Seq.mapi (fun idx (input, _, _) -> idx, Path.GetFileName input.FileName)
+                    |> Map.ofSeq
+
+                let debugGraph =
+                    graph
+                    |> Graph.map (function
+                        | NodeToTypeCheck.PhysicalFile i -> i, fileNames[i]
+                        | NodeToTypeCheck.ArtificialImplFile i -> -(i + 1), $"AIF : {fileNames[i]}")
+
+                Trace.TraceInformation("\n" + (debugGraph |> Graph.serialiseToMermaid))
+
+                // layers that can be processed in parallel
+                let layers = Graph.leafSequence graph |> Seq.toList
+
+                // remove the final layer, which should be the target file
+                let layers = layers |> List.take (layers.Length - 1)
+
+                let rec processLayer (layers: Set list) tcInfo =
+                    node {
+                        match layers with
+                        | [] -> return tcInfo
+                        | layer :: rest ->
+                            let! results =
+                                layer
+                                |> Seq.map (fun fileNode ->
+
+                                    match fileNode with
+                                    | NodeToTypeCheck.PhysicalFile fileIndex ->
+                                        let parsedInput, parseErrors, _ = parsedInputs[fileIndex]
+                                        ComputeTcIntermediate projectSnapshot fileIndex (parsedInput, parseErrors) bootstrapInfo tcInfo
+                                    | NodeToTypeCheck.ArtificialImplFile fileIndex ->
+
+                                        let finisher tcState =
+                                            let parsedInput, _parseErrors, _ = parsedInputs[fileIndex]
+                                            let prefixPathOpt = None
+                                            // Retrieve the type-checked signature information and add it to the TcEnvFromImpls.
+                                            AddSignatureResultToTcImplEnv
+                                                (bootstrapInfo.TcImports,
+                                                 bootstrapInfo.TcGlobals,
+                                                 prefixPathOpt,
+                                                 TcResultsSink.NoSink,
+                                                 tcState,
+                                                 parsedInput)
+                                                tcState
+
+                                        let tcIntermediate =
+                                            {
+                                                finisher = finisher
+                                                moduleNamesDict = tcInfo.moduleNamesDict
+                                                tcDiagnosticsRev = []
+                                                tcDependencyFiles = []
+                                                sink = Unchecked.defaultof<_>
+                                            }
+
+                                        node.Return(tcIntermediate))
+                                |> NodeCode.Parallel
+
+                            return! processLayer rest (mergeIntermediateResults tcInfo results)
+                    }
 
-            return! processLayer layers bootstrapInfo.InitialTcInfo
-        })
+                return! processLayer layers bootstrapInfo.InitialTcInfo
+            }
+        )
 
     let getParseResult (bootstrapInfo: BootstrapInfo) creationDiags fileName =
         node {
@@ -832,7 +901,8 @@ type internal TransparentCompiler
                     parseHadErrors = (parseDiagnostics.Length > 0),
                     // TODO: check if we really need this in parse results
                     dependencyFiles = [||]
-                ), sourceText
+                ),
+                sourceText
         }
 
     let emptyParseResult fileName diagnostics =
@@ -841,59 +911,72 @@ type internal TransparentCompiler
 
     let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: FSharpProjectSnapshot) =
         let key = fileName, projectSnapshot.Key
-        ParseAndCheckFileInProjectCache.Get(key, 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 file = bootstrapInfo.GetFile fileName
-
-                let! parseResults, sourceText = getParseResult bootstrapInfo creationDiags fileName
 
-                let! tcInfo = ComputeTcPrior file bootstrapInfo projectSnapshot
-
-                let! checkResults =
-                    FSharpCheckFileResults.CheckOneFile(
-                        parseResults,
-                        sourceText,
-                        fileName,
-                        projectSnapshot.ProjectFileName,
-                        bootstrapInfo.TcConfig,
-                        bootstrapInfo.TcGlobals,
-                        bootstrapInfo.TcImports,
-                        tcInfo.tcState,
-                        tcInfo.moduleNamesDict,
-                        bootstrapInfo.LoadClosure,
-                        tcInfo.TcDiagnostics,
-                        projectSnapshot.IsIncompleteTypeCheckEnvironment,
-                        projectSnapshot.ToOptions(),
-                        None,
-                        Array.ofList tcInfo.tcDependencyFiles,
-                        creationDiags,
-                        parseResults.Diagnostics,
-                        keepAssemblyContents,
-                        suggestNamesForErrors
-                    )
-                    |> NodeCode.FromCancellable
-
-                return (parseResults, FSharpCheckFileAnswer.Succeeded checkResults)
-        })
+        ParseAndCheckFileInProjectCache.Get(
+            key,
+            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 file = bootstrapInfo.GetFile fileName
+
+                    let! parseResults, sourceText = getParseResult bootstrapInfo creationDiags fileName
+
+                    let! tcInfo = ComputeTcPrior file bootstrapInfo projectSnapshot
+
+                    let! checkResults =
+                        FSharpCheckFileResults.CheckOneFile(
+                            parseResults,
+                            sourceText,
+                            fileName,
+                            projectSnapshot.ProjectFileName,
+                            bootstrapInfo.TcConfig,
+                            bootstrapInfo.TcGlobals,
+                            bootstrapInfo.TcImports,
+                            tcInfo.tcState,
+                            tcInfo.moduleNamesDict,
+                            bootstrapInfo.LoadClosure,
+                            tcInfo.TcDiagnostics,
+                            projectSnapshot.IsIncompleteTypeCheckEnvironment,
+                            projectSnapshot.ToOptions(),
+                            None,
+                            Array.ofList tcInfo.tcDependencyFiles,
+                            creationDiags,
+                            parseResults.Diagnostics,
+                            keepAssemblyContents,
+                            suggestNamesForErrors
+                        )
+                        |> NodeCode.FromCancellable
+
+                    return (parseResults, FSharpCheckFileAnswer.Succeeded checkResults)
+            }
+        )
 
     let tryGetSink fileName (projectSnapshot: FSharpProjectSnapshot) =
         node {
-            use _ = Activity.start "ComputeSemanticClassification" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
+            use _ =
+                Activity.start "ComputeSemanticClassification" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
 
             match! ComputeBootstrapInfo projectSnapshot with
             | None, _ -> return None
             | Some bootstrapInfo, _creationDiags ->
 
                 let file =
-                    bootstrapInfo.SourceFiles |> List.tryFind (fun f -> f.Source.FileName = fileName) |> Option.defaultWith (fun _ -> failwith ($"File {fileName} not found in project snapshot. Files in project: \n\n" + (bootstrapInfo.SourceFiles |> Seq.map (fun f -> f.Source.FileName) |> String.concat " \n")))
+                    bootstrapInfo.SourceFiles
+                    |> List.tryFind (fun f -> f.Source.FileName = fileName)
+                    |> Option.defaultWith (fun _ ->
+                        failwith (
+                            $"File {fileName} not found in project snapshot. Files in project: \n\n"
+                            + (bootstrapInfo.SourceFiles
+                               |> Seq.map (fun f -> f.Source.FileName)
+                               |> String.concat " \n")
+                        ))
 
                 let! tcInfo = ComputeTcPrior file bootstrapInfo projectSnapshot
                 let! parseTree, parseDiagnostics, _sourceText = ComputeParseFile bootstrapInfo file
@@ -901,53 +984,85 @@ type internal TransparentCompiler
                 let fileIndex = projectSnapshot.IndexOf fileName
                 let! { sink = sink } = ComputeTcIntermediate projectSnapshot fileIndex (parseTree, parseDiagnostics) bootstrapInfo tcInfo
 
-                return Some (sink, bootstrapInfo)
+                return Some(sink, bootstrapInfo)
         }
 
-    let ComputeSemanticClassification(fileName: string, projectSnapshot: FSharpProjectSnapshot) =
+    let ComputeSemanticClassification (fileName: string, projectSnapshot: FSharpProjectSnapshot) =
         let key = (projectSnapshot.UpTo fileName).Key
-        SemanticClassificationCache.Get(key, node {
-            use _ = Activity.start "ComputeSemanticClassification" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
-            let! sinkOpt = tryGetSink fileName projectSnapshot
-            return
-                sinkOpt
-                |> Option.bind (fun (sink, bootstrapInfo) ->
-                    let sResolutions = sink.GetResolutions()
-                    let semanticClassification = sResolutions.GetSemanticClassification(bootstrapInfo.TcGlobals, bootstrapInfo.TcImports.GetImportMap(), sink.GetFormatSpecifierLocations(), None)
 
-                    let sckBuilder = SemanticClassificationKeyStoreBuilder()
-                    sckBuilder.WriteAll semanticClassification
+        SemanticClassificationCache.Get(
+            key,
+            node {
+                use _ =
+                    Activity.start "ComputeSemanticClassification" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
+
+                let! sinkOpt = tryGetSink fileName projectSnapshot
 
-                    sckBuilder.TryBuildAndReset())
-                |> Option.map (fun sck -> sck.GetView())
-        })
+                return
+                    sinkOpt
+                    |> Option.bind (fun (sink, bootstrapInfo) ->
+                        let sResolutions = sink.GetResolutions()
 
-    let ComputeItemKeyStore(fileName: string, projectSnapshot: FSharpProjectSnapshot) =
+                        let semanticClassification =
+                            sResolutions.GetSemanticClassification(
+                                bootstrapInfo.TcGlobals,
+                                bootstrapInfo.TcImports.GetImportMap(),
+                                sink.GetFormatSpecifierLocations(),
+                                None
+                            )
+
+                        let sckBuilder = SemanticClassificationKeyStoreBuilder()
+                        sckBuilder.WriteAll semanticClassification
+
+                        sckBuilder.TryBuildAndReset())
+                    |> Option.map (fun sck -> sck.GetView())
+            }
+        )
+
+    let ComputeItemKeyStore (fileName: string, projectSnapshot: FSharpProjectSnapshot) =
         let key = (projectSnapshot.UpTo fileName).Key
-        ItemKeyStoreCache.Get(key, node {
-            use _ = Activity.start "ComputeItemKeyStore" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
-            let! sinkOpt = tryGetSink fileName projectSnapshot
-            return
-                sinkOpt
-                |> Option.bind (fun (sink, _) ->
-                    let sResolutions = sink.GetResolutions()
-
-                    let builder = ItemKeyStoreBuilder()
-                    let preventDuplicates = HashSet({ new IEqualityComparer with
-                                                        member _.Equals((s1, e1): struct(pos * pos), (s2, e2): struct(pos * pos)) = Position.posEq s1 s2 && Position.posEq e1 e2
-                                                        member _.GetHashCode o = o.GetHashCode() })
-                    sResolutions.CapturedNameResolutions
-                    |> Seq.iter (fun cnr ->
-                        let r = cnr.Range
-                        if preventDuplicates.Add struct(r.Start, r.End) then
-                            builder.Write(cnr.Range, cnr.Item))
-
-                    builder.TryBuildAndReset())
-        })
+
+        ItemKeyStoreCache.Get(
+            key,
+            node {
+                use _ =
+                    Activity.start "ComputeItemKeyStore" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
+
+                let! sinkOpt = tryGetSink fileName projectSnapshot
+
+                return
+                    sinkOpt
+                    |> Option.bind (fun (sink, _) ->
+                        let sResolutions = sink.GetResolutions()
+
+                        let builder = ItemKeyStoreBuilder()
+
+                        let preventDuplicates =
+                            HashSet(
+                                { new IEqualityComparer with
+                                    member _.Equals((s1, e1): struct (pos * pos), (s2, e2): struct (pos * pos)) =
+                                        Position.posEq s1 s2 && Position.posEq e1 e2
+
+                                    member _.GetHashCode o = o.GetHashCode()
+                                }
+                            )
+
+                        sResolutions.CapturedNameResolutions
+                        |> Seq.iter (fun cnr ->
+                            let r = cnr.Range
+
+                            if preventDuplicates.Add struct (r.Start, r.End) then
+                                builder.Write(cnr.Range, cnr.Item))
+
+                        builder.TryBuildAndReset())
+            }
+        )
 
     member _.ParseFile(fileName, projectSnapshot: FSharpProjectSnapshot, _userOpName) =
         node {
-            use _ = Activity.start "ParseFile" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
+            use _ =
+                Activity.start "ParseFile" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
+
             match! ComputeBootstrapInfo projectSnapshot with
             | None, creationDiags -> return emptyParseResult fileName creationDiags
             | Some bootstrapInfo, creationDiags ->
@@ -959,14 +1074,9 @@ type internal TransparentCompiler
         ignore userOpName
         ComputeParseAndCheckFileInProject fileName projectSnapshot
 
-    member _.FindReferencesInFile
-        (
-            fileName: string,
-            projectSnapshot: FSharpProjectSnapshot,
-            symbol: FSharpSymbol,
-            userOpName: string
-        ) =
+    member _.FindReferencesInFile(fileName: string, projectSnapshot: FSharpProjectSnapshot, symbol: FSharpSymbol, userOpName: string) =
         ignore userOpName
+
         node {
             match! ComputeItemKeyStore(fileName, projectSnapshot) with
             | None -> return Seq.empty
@@ -1031,7 +1141,8 @@ type internal TransparentCompiler
             ) : NodeCode> =
             backgroundCompiler.FindReferencesInFile(fileName, options, symbol, canInvalidateProject, userOpName)
 
-        member this.FindReferencesInFile(fileName, projectSnapshot, symbol, userOpName) = this.FindReferencesInFile(fileName, projectSnapshot, symbol, userOpName)
+        member this.FindReferencesInFile(fileName, projectSnapshot, symbol, userOpName) =
+            this.FindReferencesInFile(fileName, projectSnapshot, symbol, userOpName)
 
         member _.FrameworkImportsCache: FrameworkImportsCache =
             backgroundCompiler.FrameworkImportsCache
@@ -1092,12 +1203,7 @@ type internal TransparentCompiler
                 userOpName
             )
 
-        member _.GetSemanticClassificationForFile
-            (
-                fileName: string,
-                snapshot: FSharpProjectSnapshot,
-                userOpName: string
-            ) =
+        member _.GetSemanticClassificationForFile(fileName: string, snapshot: FSharpProjectSnapshot, userOpName: string) =
             ignore userOpName
             ComputeSemanticClassification(fileName, snapshot)
 
From c4329248c6d0601733cc149605d5ce428f02b743 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Thu, 18 May 2023 12:17:02 +0200
Subject: [PATCH 038/222] ...
---
 src/Compiler/Service/TransparentCompiler.fs | 19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index bd0aa272ae8..0edb0c46172 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -279,6 +279,9 @@ type internal TransparentCompiler
                                 match capturedImportsInvalidated.TryGetTarget() with
                                 | true, tg -> tg.Trigger()
                                 | _ -> ()))
+#endif
+#if NO_TYPEPROVIDERS
+                        ignore importsInvalidatedByTypeProvider
 #endif
                         return tcImports
                     with exn ->
@@ -924,10 +927,9 @@ type internal TransparentCompiler
 
                 | Some bootstrapInfo, creationDiags ->
 
-                    let file = bootstrapInfo.GetFile fileName
-
                     let! parseResults, sourceText = getParseResult bootstrapInfo creationDiags fileName
 
+                    let file = bootstrapInfo.GetFile fileName
                     let! tcInfo = ComputeTcPrior file bootstrapInfo projectSnapshot
 
                     let! checkResults =
@@ -954,7 +956,7 @@ type internal TransparentCompiler
                         )
                         |> NodeCode.FromCancellable
 
-                    return (parseResults, FSharpCheckFileAnswer.Succeeded checkResults)
+                    return parseResults, FSharpCheckFileAnswer.Succeeded checkResults
             }
         )
 
@@ -967,16 +969,7 @@ type internal TransparentCompiler
             | None, _ -> return None
             | Some bootstrapInfo, _creationDiags ->
 
-                let file =
-                    bootstrapInfo.SourceFiles
-                    |> List.tryFind (fun f -> f.Source.FileName = fileName)
-                    |> Option.defaultWith (fun _ ->
-                        failwith (
-                            $"File {fileName} not found in project snapshot. Files in project: \n\n"
-                            + (bootstrapInfo.SourceFiles
-                               |> Seq.map (fun f -> f.Source.FileName)
-                               |> String.concat " \n")
-                        ))
+                let file = bootstrapInfo.GetFile fileName
 
                 let! tcInfo = ComputeTcPrior file bootstrapInfo projectSnapshot
                 let! parseTree, parseDiagnostics, _sourceText = ComputeParseFile bootstrapInfo file
From 127ed3b604d6c04513ae57f06575c82f508d5f0d Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Thu, 18 May 2023 13:54:52 +0200
Subject: [PATCH 039/222] Files that are not depended on don't ivalidate cache
---
 src/Compiler/Service/FSharpCheckerResults.fs  |  9 ++++
 src/Compiler/Service/FSharpCheckerResults.fsi |  3 ++
 src/Compiler/Service/TransparentCompiler.fs   | 41 ++++++++++++-------
 .../FSharpChecker/TransparentCompiler.fs      | 39 ++++++++++++++++++
 ...ervice.SurfaceArea.netstandard20.debug.bsl |  6 +++
 ...vice.SurfaceArea.netstandard20.release.bsl |  2 +
 6 files changed, 85 insertions(+), 15 deletions(-)
diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs
index c2271aa1de4..449f50f45ba 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fs
+++ b/src/Compiler/Service/FSharpCheckerResults.fs
@@ -208,6 +208,15 @@ type FSharpProjectSnapshot =
 
     member this.UpTo fileName = this.UpTo(this.IndexOf fileName)
 
+    member this.OnlyWith fileIndexes =
+        { this with
+            SourceFiles =
+                fileIndexes
+                |> Set.toList
+                |> List.sort
+                |> List.choose (fun x -> this.SourceFiles |> List.tryItem x)
+        }
+
     member this.Key =
         {
             ProjectFileName = this.ProjectFileName
diff --git a/src/Compiler/Service/FSharpCheckerResults.fsi b/src/Compiler/Service/FSharpCheckerResults.fsi
index ea55a296ec4..a84a9a7c3aa 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fsi
+++ b/src/Compiler/Service/FSharpCheckerResults.fsi
@@ -125,6 +125,9 @@ type FSharpProjectSnapshot =
     /// A snapshot of the same project but only up to the given file (including).
     member UpTo: fileName: string -> FSharpProjectSnapshot
 
+    /// A snapshot of the same project but only with source files specified by given indexes.
+    member OnlyWith: fileIndexes: Set -> FSharpProjectSnapshot
+
     /// A snapshot of the same project with file versions removed.
     member WithoutFileVersions: FSharpProjectSnapshot
 
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 0edb0c46172..51be01b1d73 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -121,8 +121,7 @@ type internal TransparentCompiler
     let TcPriorCache = AsyncMemoize(triggerCacheEvent "TcPrior")
     let TcIntermediateCache = AsyncMemoize(triggerCacheEvent "TcIntermediate")
 
-    let DependencyGraphForLastFileCache =
-        AsyncMemoize(triggerCacheEvent "DependencyGraphForLastFile")
+    let DependencyGraphCache = AsyncMemoize(triggerCacheEvent "DependencyGraph")
 
     let SemanticClassificationCache =
         AsyncMemoize(triggerCacheEvent "SemanticClassification")
@@ -663,10 +662,10 @@ type internal TransparentCompiler
             }
         )
 
-    let ComputeDependencyGraphForLastFile (priorSnapshot: FSharpProjectSnapshot) parsedInputs (tcConfig: TcConfig) =
+    let ComputeDependencyGraph (priorSnapshot: FSharpProjectSnapshot) parsedInputs (tcConfig: TcConfig) =
         let key = priorSnapshot.SourceFiles |> List.map (fun s -> s.Key)
 
-        DependencyGraphForLastFileCache.Get(
+        DependencyGraphCache.Get(
             key,
             node {
 
@@ -681,7 +680,7 @@ type internal TransparentCompiler
                         })
 
                 use _ =
-                    Activity.start "ComputeDependencyGraphForLastFile" [| Activity.Tags.fileName, (sourceFiles |> Array.last).FileName |]
+                    Activity.start "ComputeDependencyGraph" [| Activity.Tags.fileName, (sourceFiles |> Array.last).FileName |]
 
                 let filePairs = FilePairMap(sourceFiles)
 
@@ -691,22 +690,24 @@ type internal TransparentCompiler
                     |> fst
                     |> Graph.subGraphFor (sourceFiles |> Array.last).Idx
 
-                return TransformDependencyGraph(graph, filePairs)
+                let fileIndexes =
+                    graph.Values |> Seq.collect id |> Seq.append graph.Keys |> Seq.distinct |> Set
+
+                return TransformDependencyGraph(graph, filePairs), fileIndexes
             }
         )
 
     let ComputeTcIntermediate
         (projectSnapshot: FSharpProjectSnapshot)
+        (dependencyFiles: Set)
         (fileIndex: FileIndex)
         (parsedInput: ParsedInput, parseErrors)
         bootstrapInfo
         (prevTcInfo: TcInfo)
         =
-        // TODO: we need to construct cache key based on only relevant files from the dependency graph
-        let key = projectSnapshot.UpTo(fileIndex).Key
 
         TcIntermediateCache.Get(
-            key,
+            projectSnapshot.UpTo(fileIndex).OnlyWith(dependencyFiles).Key,
             node {
                 let input = parsedInput
                 let fileName = input.FileName
@@ -812,7 +813,7 @@ type internal TransparentCompiler
 
                 let! parsedInputs = files |> Seq.map (ComputeParseFile bootstrapInfo) |> NodeCode.Parallel
 
-                let! graph = ComputeDependencyGraphForLastFile priorSnapshot (parsedInputs |> Seq.map p13) bootstrapInfo.TcConfig
+                let! graph, dependencyFiles = ComputeDependencyGraph priorSnapshot (parsedInputs |> Seq.map p13) bootstrapInfo.TcConfig
 
                 let fileNames =
                     parsedInputs
@@ -845,7 +846,14 @@ type internal TransparentCompiler
                                     match fileNode with
                                     | NodeToTypeCheck.PhysicalFile fileIndex ->
                                         let parsedInput, parseErrors, _ = parsedInputs[fileIndex]
-                                        ComputeTcIntermediate projectSnapshot fileIndex (parsedInput, parseErrors) bootstrapInfo tcInfo
+
+                                        ComputeTcIntermediate
+                                            projectSnapshot
+                                            dependencyFiles
+                                            fileIndex
+                                            (parsedInput, parseErrors)
+                                            bootstrapInfo
+                                            tcInfo
                                     | NodeToTypeCheck.ArtificialImplFile fileIndex ->
 
                                         let finisher tcState =
@@ -876,7 +884,8 @@ type internal TransparentCompiler
                             return! processLayer rest (mergeIntermediateResults tcInfo results)
                     }
 
-                return! processLayer layers bootstrapInfo.InitialTcInfo
+                let! tcInfo = processLayer layers bootstrapInfo.InitialTcInfo
+                return tcInfo, dependencyFiles
             }
         )
 
@@ -930,7 +939,7 @@ type internal TransparentCompiler
                     let! parseResults, sourceText = getParseResult bootstrapInfo creationDiags fileName
 
                     let file = bootstrapInfo.GetFile fileName
-                    let! tcInfo = ComputeTcPrior file bootstrapInfo projectSnapshot
+                    let! tcInfo, _ = ComputeTcPrior file bootstrapInfo projectSnapshot
 
                     let! checkResults =
                         FSharpCheckFileResults.CheckOneFile(
@@ -971,11 +980,13 @@ type internal TransparentCompiler
 
                 let file = bootstrapInfo.GetFile fileName
 
-                let! tcInfo = ComputeTcPrior file bootstrapInfo projectSnapshot
+                let! tcInfo, dependencyFiles = ComputeTcPrior file bootstrapInfo projectSnapshot
                 let! parseTree, parseDiagnostics, _sourceText = ComputeParseFile bootstrapInfo file
 
                 let fileIndex = projectSnapshot.IndexOf fileName
-                let! { sink = sink } = ComputeTcIntermediate projectSnapshot fileIndex (parseTree, parseDiagnostics) bootstrapInfo tcInfo
+
+                let! { sink = sink } =
+                    ComputeTcIntermediate projectSnapshot dependencyFiles fileIndex (parseTree, parseDiagnostics) bootstrapInfo tcInfo
 
                 return Some(sink, bootstrapInfo)
         }
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
index acb508dea41..44f7f6da304 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
+++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
@@ -206,3 +206,42 @@ let ``We don't check files that are not depended on`` () =
     Assert.Equal([Started; Finished], intermediateTypeChecks["FileFirst.fs"])
     Assert.Equal([Started; Finished], intermediateTypeChecks["FileThird.fs"])
     Assert.False (intermediateTypeChecks.ContainsKey "FileSecond.fs")
+
+[]
+let ``Files that are not depended on don't ivalidate cache`` () =
+    let project = SyntheticProject.Create(
+        sourceFile "First" [],
+        sourceFile "Second" ["First"],
+        sourceFile "Third" ["First"],
+        sourceFile "Last" ["Third"])
+
+    let cacheEvents = ResizeArray()
+
+    ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
+        checkFile "Last" expectOk
+        withChecker (fun checker -> checker.CacheEvent.Add cacheEvents.Add)
+        updateFile "Second" updatePublicSurface
+        checkFile "Last" expectOk
+    } |> ignore
+
+    let intermediateTypeChecks =
+        cacheEvents
+        |> Seq.choose (function
+            | ("TcIntermediate", e, k) -> Some ((k :?> FSharpProjectSnapshotKey).LastFile |> fst |> Path.GetFileName, e)
+            | _ -> None)
+        |> Seq.groupBy fst
+        |> Seq.map (fun (k, g) -> k, g |> Seq.map snd |> Seq.toList)
+        |> Map
+
+    let graphConstructions =
+        cacheEvents
+        |> Seq.choose (function
+            | ("DependencyGraph", e, k) -> Some ((k :?> FSharpFileKey list) |> List.last |> fst |> Path.GetFileName, e)
+            | _ -> None)
+        |> Seq.groupBy fst
+        |> Seq.map (fun (k, g) -> k, g |> Seq.map snd |> Seq.toList)
+        |> Map
+
+    Assert.Equal([Started; Finished], graphConstructions["FileLast.fs"])
+
+    Assert.True intermediateTypeChecks.IsEmpty
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 03aeafb299a..3fb4db8a604 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
@@ -2060,9 +2060,11 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults] ParseFileInProject(System.String, System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String])
 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, FSharp.Compiler.CodeAnalysis.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])
+FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Collections.Generic.IEnumerable`1[FSharp.Compiler.Text.Range]] FindBackgroundReferencesInFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot, FSharp.Compiler.Symbols.FSharpSymbol, Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer]] ParseAndCheckFileInProject(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer]] ParseAndCheckFileInProject(System.String, Int32, FSharp.Compiler.Text.ISourceText, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults]] GetBackgroundCheckResultsForFileInProject(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
@@ -2199,6 +2201,7 @@ FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean UseScriptResolutionR
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean get_IsIncompleteTypeCheckEnvironment()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean get_UseScriptResolutionRules()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectOptions ToOptions()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot OnlyWith(Microsoft.FSharp.Collections.FSharpSet`1[System.Int32])
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot UpTo(Int32)
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot UpTo(System.String)
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot WithoutFileVersions
@@ -2207,6 +2210,7 @@ FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey get_Key()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Int32 GetHashCode()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Int32 GetHashCode(System.Collections.IEqualityComparer)
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Int32 IndexOf(System.String)
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot] SourceFiles
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot] get_SourceFiles()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot] ReferencedProjects
@@ -2251,6 +2255,8 @@ FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collecti
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.String ProjectFileName
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.String ToString()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.String get_ProjectFileName()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.Tuple`2[System.String,System.String] LastFile
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.Tuple`2[System.String,System.String] get_LastFile()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Void .ctor(System.String, Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.String,System.String]], Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey], Boolean, Boolean)
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: Boolean Equals(System.Object)
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: FSharp.Compiler.CodeAnalysis.FSharpReferencedProject CreateFSharp(System.String, 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 5415b502e06..3fb4db8a604 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
@@ -2064,6 +2064,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync
 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])
+FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Collections.Generic.IEnumerable`1[FSharp.Compiler.Text.Range]] FindBackgroundReferencesInFile(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot, FSharp.Compiler.Symbols.FSharpSymbol, Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer]] ParseAndCheckFileInProject(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileAnswer]] ParseAndCheckFileInProject(System.String, Int32, FSharp.Compiler.Text.ISourceText, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
 FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults]] GetBackgroundCheckResultsForFileInProject(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
@@ -2200,6 +2201,7 @@ FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean UseScriptResolutionR
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean get_IsIncompleteTypeCheckEnvironment()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Boolean get_UseScriptResolutionRules()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectOptions ToOptions()
+FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot OnlyWith(Microsoft.FSharp.Collections.FSharpSet`1[System.Int32])
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot UpTo(Int32)
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot UpTo(System.String)
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot WithoutFileVersions
From fe60fb2f02acd46b49e4be6a84b5162cc227ab37 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Thu, 18 May 2023 14:21:35 +0200
Subject: [PATCH 040/222] try deflake linux test
---
 .../FSharpChecker/TransparentCompiler.fs               |  8 ++++++--
 tests/FSharp.Test.Utilities/ProjectGeneration.fs       | 10 +++++++++-
 2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
index 44f7f6da304..842dcefaf5c 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
+++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
@@ -189,7 +189,11 @@ let ``We don't check files that are not depended on`` () =
     let cacheEvents = ResizeArray()
 
     ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
-        withChecker (fun checker -> checker.CacheEvent.Add cacheEvents.Add)
+        withChecker (fun checker ->
+            async {
+                do! Async.Sleep 50 // wait for events from initial project check
+                checker.CacheEvent.Add cacheEvents.Add
+            })
         updateFile "First" updatePublicSurface
         checkFile "Last" expectOk
     } |> ignore
@@ -208,7 +212,7 @@ let ``We don't check files that are not depended on`` () =
     Assert.False (intermediateTypeChecks.ContainsKey "FileSecond.fs")
 
 []
-let ``Files that are not depended on don't ivalidate cache`` () =
+let ``Files that are not depended on don't invalidate cache`` () =
     let project = SyntheticProject.Create(
         sourceFile "First" [],
         sourceFile "Second" ["First"],
diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
index 29e845d1ed8..6861c256a26 100644
--- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs
+++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
@@ -700,7 +700,7 @@ type ProjectWorkflowBuilder
 
     []
     member this.WithProject(workflow: Async, f) =
-        workflow |> mapProjectAsync (fun project -> 
+        workflow |> mapProjectAsync (fun project ->
             async {
                 do! f project checker
                 return project
@@ -714,6 +714,14 @@ type ProjectWorkflowBuilder
             return ctx
         }
 
+    []
+    member this.WithChecker(workflow: Async, f) =
+        async {
+            let! ctx = workflow
+            do! f checker
+            return ctx
+        }
+
     /// Change contents of given file using `processFile` function.
     /// Does not save the file to disk.
     []
From 02717609200c2caebc31b7af61428fc30b301335 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Thu, 18 May 2023 19:21:03 +0200
Subject: [PATCH 041/222] reduce surface area
---
 src/Compiler/Service/BackgroundCompiler.fs    |  2 +-
 src/Compiler/Service/FSharpCheckerResults.fsi |  8 +--
 src/Compiler/Service/IncrementalBuild.fsi     |  2 +-
 ...ervice.SurfaceArea.netstandard20.debug.bsl | 57 -------------------
 ...vice.SurfaceArea.netstandard20.release.bsl | 57 -------------------
 5 files changed, 6 insertions(+), 120 deletions(-)
diff --git a/src/Compiler/Service/BackgroundCompiler.fs b/src/Compiler/Service/BackgroundCompiler.fs
index cc25ed2bed3..ed8675b41fb 100644
--- a/src/Compiler/Service/BackgroundCompiler.fs
+++ b/src/Compiler/Service/BackgroundCompiler.fs
@@ -184,7 +184,7 @@ module EnvMisc =
         GetEnvInteger "FCS_frameworkTcImportsCacheStrongSizeDefault" 8
 
 []
-module Helpers =
+module internal Helpers =
 
     /// Determine whether two (fileName,options) keys are identical w.r.t. affect on checking
     let AreSameForChecking2 ((fileName1: string, options1: FSharpProjectOptions), (fileName2, options2)) =
diff --git a/src/Compiler/Service/FSharpCheckerResults.fsi b/src/Compiler/Service/FSharpCheckerResults.fsi
index a84a9a7c3aa..6f77a0bcc99 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fsi
+++ b/src/Compiler/Service/FSharpCheckerResults.fsi
@@ -40,9 +40,9 @@ type internal DelayedILModuleReader =
 /// Unused in this API
 type public FSharpUnresolvedReferencesSet = internal FSharpUnresolvedReferencesSet of UnresolvedAssemblyReference list
 
-type FSharpFileKey = string * string
+type internal FSharpFileKey = string * string
 
-type FSharpProjectSnapshotKey =
+type internal FSharpProjectSnapshotKey =
     { ProjectFileName: string
       SourceFiles: FSharpFileKey list
       OtherOptions: string list
@@ -60,7 +60,7 @@ type FSharpFileSnapshot =
       Version: string
       GetSource: unit -> Task }
 
-    member Key: FSharpFileKey
+    member internal Key: FSharpFileKey
 
 []
 type FSharpProjectSnapshot =
@@ -131,7 +131,7 @@ type FSharpProjectSnapshot =
     /// A snapshot of the same project with file versions removed.
     member WithoutFileVersions: FSharpProjectSnapshot
 
-    member Key: FSharpProjectSnapshotKey
+    member internal Key: FSharpProjectSnapshotKey
 
 and [] public FSharpReferencedProjectSnapshot =
     internal
diff --git a/src/Compiler/Service/IncrementalBuild.fsi b/src/Compiler/Service/IncrementalBuild.fsi
index bd54cf4f3f5..50c7201195c 100644
--- a/src/Compiler/Service/IncrementalBuild.fsi
+++ b/src/Compiler/Service/IncrementalBuild.fsi
@@ -23,7 +23,7 @@ open FSharp.Compiler.Text
 open FSharp.Compiler.TypedTree
 open FSharp.Compiler.BuildGraph
 
-type FrameworkImportsCacheKey =
+type internal FrameworkImportsCacheKey =
     | FrameworkImportsCacheKey of
         resolvedpath: string list *
         assemblyName: string *
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 3fb4db8a604..db548f930f9 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
@@ -2098,8 +2098,6 @@ FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.String ToString()
 FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.String Version
 FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.String get_FileName()
 FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.String get_Version()
-FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.Tuple`2[System.String,System.String] Key
-FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.Tuple`2[System.String,System.String] get_Key()
 FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: Void .ctor(System.String, System.String, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.Threading.Tasks.Task`1[FSharp.Compiler.Text.ISourceText]])
 FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsBindingALambdaAtPosition(FSharp.Compiler.Text.Position)
 FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsPosContainedInApplication(FSharp.Compiler.Text.Position)
@@ -2206,8 +2204,6 @@ FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot UpTo(System.String)
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot WithoutFileVersions
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot get_WithoutFileVersions()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey Key
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey get_Key()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Int32 GetHashCode()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Int32 GetHashCode(System.Collections.IEqualityComparer)
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Int32 IndexOf(System.String)
@@ -2234,30 +2230,6 @@ FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: System.String ProjectFileNam
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: System.String ToString()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: System.String get_ProjectFileName()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Void .ctor(System.String, Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot], Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot], Boolean, Boolean, System.DateTime, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet], Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Text.Range,System.String,System.String]], Microsoft.FSharp.Core.FSharpOption`1[System.Int64])
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean Equals(FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey)
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean Equals(System.Object)
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean IsIncompleteTypeCheckEnvironment
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean UseScriptResolutionRules
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean get_IsIncompleteTypeCheckEnvironment()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean get_UseScriptResolutionRules()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 CompareTo(FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey)
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 CompareTo(System.Object)
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 CompareTo(System.Object, System.Collections.IComparer)
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 GetHashCode()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 GetHashCode(System.Collections.IEqualityComparer)
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey] ReferencedProjects
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey] get_ReferencedProjects()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] OtherOptions
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_OtherOptions()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.String,System.String]] SourceFiles
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.String,System.String]] get_SourceFiles()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.String ProjectFileName
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.String ToString()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.String get_ProjectFileName()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.Tuple`2[System.String,System.String] LastFile
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.Tuple`2[System.String,System.String] get_LastFile()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Void .ctor(System.String, Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.String,System.String]], Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey], Boolean, Boolean)
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: Boolean Equals(System.Object)
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: FSharp.Compiler.CodeAnalysis.FSharpReferencedProject CreateFSharp(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions)
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: FSharp.Compiler.CodeAnalysis.FSharpReferencedProject CreateFromILModuleReader(System.String, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.DateTime], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,FSharp.Compiler.AbstractIL.ILBinaryReader+ILModuleReader])
@@ -2309,35 +2281,6 @@ FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: Boolean Equals(Syste
 FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: Int32 GetHashCode()
 FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: Int32 GetHashCode(System.Collections.IEqualityComparer)
 FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: System.String ToString()
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Boolean Equals(FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey)
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Boolean Equals(System.Object)
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey NewFrameworkImportsCacheKey(Microsoft.FSharp.Collections.FSharpList`1[System.String], System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String], System.String, System.Decimal)
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 CompareTo(FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey)
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 CompareTo(System.Object)
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 CompareTo(System.Object, System.Collections.IComparer)
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 GetHashCode()
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 GetHashCode(System.Collections.IEqualityComparer)
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 Tag
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 get_Tag()
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_resolvedpath()
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_targetFrameworkDirectories()
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] resolvedpath
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] targetFrameworkDirectories
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.Decimal get_langVersion()
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.Decimal langVersion
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String ToString()
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String assemblyName
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String fsharpBinaries
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String get_assemblyName()
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String get_fsharpBinaries()
-FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSameForChecking2(System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions], System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions])
-FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSameForChecking3(System.Tuple`3[System.String,System.Int64,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions], System.Tuple`3[System.String,System.Int64,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions])
-FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSameForParsing[a](System.Tuple`3[System.String,System.Int64,a], System.Tuple`3[System.String,System.Int64,a])
-FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSimilarForParsing[a,b,c,d,e](System.Tuple`3[a,b,c], System.Tuple`3[a,d,e])
-FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSubsumable2(System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions], System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions])
-FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSubsumable3[a,b](System.Tuple`3[System.String,a,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions], System.Tuple`3[System.String,b,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions])
-FSharp.Compiler.CodeAnalysis.Helpers: Boolean NamesContainAttribute(FSharp.Compiler.Symbols.FSharpSymbol, Microsoft.FSharp.Collections.FSharpSet`1[System.String])
 FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver: FSharp.Compiler.CodeAnalysis.LegacyResolvedFile[] Resolve(FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment, System.Tuple`2[System.String,System.String][], System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String], System.String, System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String], System.String, Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Core.FSharpFunc`2[System.Boolean,Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Core.Unit]]])
 FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver: System.String DotNetFrameworkReferenceAssembliesRootDirectory
 FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver: System.String HighestInstalledNetFrameworkVersion()
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 3fb4db8a604..db548f930f9 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
@@ -2098,8 +2098,6 @@ FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.String ToString()
 FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.String Version
 FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.String get_FileName()
 FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.String get_Version()
-FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.Tuple`2[System.String,System.String] Key
-FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: System.Tuple`2[System.String,System.String] get_Key()
 FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot: Void .ctor(System.String, System.String, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.Threading.Tasks.Task`1[FSharp.Compiler.Text.ISourceText]])
 FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsBindingALambdaAtPosition(FSharp.Compiler.Text.Position)
 FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsPosContainedInApplication(FSharp.Compiler.Text.Position)
@@ -2206,8 +2204,6 @@ FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot UpTo(System.String)
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot WithoutFileVersions
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot get_WithoutFileVersions()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey Key
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey get_Key()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Int32 GetHashCode()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Int32 GetHashCode(System.Collections.IEqualityComparer)
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Int32 IndexOf(System.String)
@@ -2234,30 +2230,6 @@ FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: System.String ProjectFileNam
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: System.String ToString()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: System.String get_ProjectFileName()
 FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshot: Void .ctor(System.String, Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpFileSnapshot], Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpReferencedProjectSnapshot], Boolean, Boolean, System.DateTime, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet], Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Text.Range,System.String,System.String]], Microsoft.FSharp.Core.FSharpOption`1[System.Int64])
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean Equals(FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey)
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean Equals(System.Object)
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean IsIncompleteTypeCheckEnvironment
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean UseScriptResolutionRules
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean get_IsIncompleteTypeCheckEnvironment()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Boolean get_UseScriptResolutionRules()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 CompareTo(FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey)
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 CompareTo(System.Object)
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 CompareTo(System.Object, System.Collections.IComparer)
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 GetHashCode()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Int32 GetHashCode(System.Collections.IEqualityComparer)
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey] ReferencedProjects
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey] get_ReferencedProjects()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] OtherOptions
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_OtherOptions()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.String,System.String]] SourceFiles
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.String,System.String]] get_SourceFiles()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.String ProjectFileName
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.String ToString()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.String get_ProjectFileName()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.Tuple`2[System.String,System.String] LastFile
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: System.Tuple`2[System.String,System.String] get_LastFile()
-FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey: Void .ctor(System.String, Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.String,System.String]], Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpProjectSnapshotKey], Boolean, Boolean)
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: Boolean Equals(System.Object)
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: FSharp.Compiler.CodeAnalysis.FSharpReferencedProject CreateFSharp(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions)
 FSharp.Compiler.CodeAnalysis.FSharpReferencedProject: FSharp.Compiler.CodeAnalysis.FSharpReferencedProject CreateFromILModuleReader(System.String, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.DateTime], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,FSharp.Compiler.AbstractIL.ILBinaryReader+ILModuleReader])
@@ -2309,35 +2281,6 @@ FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: Boolean Equals(Syste
 FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: Int32 GetHashCode()
 FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: Int32 GetHashCode(System.Collections.IEqualityComparer)
 FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: System.String ToString()
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Boolean Equals(FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey)
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Boolean Equals(System.Object)
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey NewFrameworkImportsCacheKey(Microsoft.FSharp.Collections.FSharpList`1[System.String], System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String], System.String, System.Decimal)
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 CompareTo(FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey)
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 CompareTo(System.Object)
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 CompareTo(System.Object, System.Collections.IComparer)
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 GetHashCode()
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 GetHashCode(System.Collections.IEqualityComparer)
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 Tag
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Int32 get_Tag()
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_resolvedpath()
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_targetFrameworkDirectories()
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] resolvedpath
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: Microsoft.FSharp.Collections.FSharpList`1[System.String] targetFrameworkDirectories
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.Decimal get_langVersion()
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.Decimal langVersion
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String ToString()
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String assemblyName
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String fsharpBinaries
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String get_assemblyName()
-FSharp.Compiler.CodeAnalysis.FrameworkImportsCacheKey: System.String get_fsharpBinaries()
-FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSameForChecking2(System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions], System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions])
-FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSameForChecking3(System.Tuple`3[System.String,System.Int64,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions], System.Tuple`3[System.String,System.Int64,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions])
-FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSameForParsing[a](System.Tuple`3[System.String,System.Int64,a], System.Tuple`3[System.String,System.Int64,a])
-FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSimilarForParsing[a,b,c,d,e](System.Tuple`3[a,b,c], System.Tuple`3[a,d,e])
-FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSubsumable2(System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions], System.Tuple`2[System.String,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions])
-FSharp.Compiler.CodeAnalysis.Helpers: Boolean AreSubsumable3[a,b](System.Tuple`3[System.String,a,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions], System.Tuple`3[System.String,b,FSharp.Compiler.CodeAnalysis.FSharpProjectOptions])
-FSharp.Compiler.CodeAnalysis.Helpers: Boolean NamesContainAttribute(FSharp.Compiler.Symbols.FSharpSymbol, Microsoft.FSharp.Collections.FSharpSet`1[System.String])
 FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver: FSharp.Compiler.CodeAnalysis.LegacyResolvedFile[] Resolve(FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment, System.Tuple`2[System.String,System.String][], System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String], System.String, System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String], System.String, Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Core.FSharpFunc`2[System.Boolean,Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Core.Unit]]])
 FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver: System.String DotNetFrameworkReferenceAssembliesRootDirectory
 FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver: System.String HighestInstalledNetFrameworkVersion()
From b0758ed8d6260182848de78c65d1d8c9aa833fd3 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Fri, 19 May 2023 18:42:53 +0200
Subject: [PATCH 042/222] benchmark
---
 src/Compiler/Service/TransparentCompiler.fs   |  34 ++++--
 .../ProjectGeneration.fs                      |  28 +++--
 .../BackgroundCompilerBenchmarks.fs           | 112 ++++++++++++++++++
 3 files changed, 149 insertions(+), 25 deletions(-)
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 51be01b1d73..5f32e4325cf 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -690,10 +690,30 @@ type internal TransparentCompiler
                     |> fst
                     |> Graph.subGraphFor (sourceFiles |> Array.last).Idx
 
+
                 let fileIndexes =
                     graph.Values |> Seq.collect id |> Seq.append graph.Keys |> Seq.distinct |> Set
 
-                return TransformDependencyGraph(graph, filePairs), fileIndexes
+                let nodeGraph = TransformDependencyGraph(graph, filePairs)
+
+                let fileNames =
+                    parsedInputs
+                    |> Seq.mapi (fun idx input -> idx, Path.GetFileName input.FileName)
+                    |> Map.ofSeq
+
+                let debugGraph =
+                    nodeGraph
+                    |> Graph.map (function
+                        | NodeToTypeCheck.PhysicalFile i -> i, fileNames[i]
+                        | NodeToTypeCheck.ArtificialImplFile i -> -(i + 1), $"AIF : {fileNames[i]}")
+                    |> Graph.serialiseToMermaid
+
+                Trace.TraceInformation("\n" + debugGraph)
+
+                if Activity.Current <> null then
+                    Activity.Current.AddTag("graph", debugGraph) |> ignore
+
+                return nodeGraph, fileIndexes
             }
         )
 
@@ -815,18 +835,6 @@ type internal TransparentCompiler
 
                 let! graph, dependencyFiles = ComputeDependencyGraph priorSnapshot (parsedInputs |> Seq.map p13) bootstrapInfo.TcConfig
 
-                let fileNames =
-                    parsedInputs
-                    |> Seq.mapi (fun idx (input, _, _) -> idx, Path.GetFileName input.FileName)
-                    |> Map.ofSeq
-
-                let debugGraph =
-                    graph
-                    |> Graph.map (function
-                        | NodeToTypeCheck.PhysicalFile i -> i, fileNames[i]
-                        | NodeToTypeCheck.ArtificialImplFile i -> -(i + 1), $"AIF : {fileNames[i]}")
-
-                Trace.TraceInformation("\n" + (debugGraph |> Graph.serialiseToMermaid))
 
                 // layers that can be processed in parallel
                 let layers = Graph.leafSequence graph |> Seq.toList
diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
index 6861c256a26..0a001ec3b88 100644
--- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs
+++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
@@ -616,12 +616,13 @@ type ProjectWorkflowBuilder
         ?useGetSource,
         ?useChangeNotifications,
         ?useSyntaxTreeCache,
-        ?useTransparentCompiler
+        ?useTransparentCompiler,
+        ?runTimeout
     ) =
 
-    let useGetSource = defaultArg useGetSource false
-    let useChangeNotifications = defaultArg useChangeNotifications false
     let useTransparentCompiler = defaultArg useTransparentCompiler false
+    let useGetSource = not useTransparentCompiler && defaultArg useGetSource false
+    let useChangeNotifications = not useTransparentCompiler && defaultArg useChangeNotifications false
 
     let mutable latestProject = initialProject
     let mutable activity = None
@@ -652,26 +653,29 @@ type ProjectWorkflowBuilder
 
     let mapProject f = mapProjectAsync (f >> async.Return)
 
+    let getInitialContext() =
+        match initialContext with
+        | Some ctx -> async.Return ctx
+        | None -> SaveAndCheckProject initialProject checker
+
     /// Creates a ProjectWorkflowBuilder which will already have the project
     /// saved and checked so time won't be spent on that.
     /// Also the project won't be deleted after the computation expression is evaluated
     member this.CreateBenchmarkBuilder() =
-        let ctx = this.Yield() |> Async.RunSynchronously
+        let ctx = getInitialContext() |> Async.RunSynchronously
 
         ProjectWorkflowBuilder(
             ctx.Project,
             ctx,
             useGetSource = useGetSource,
-            useChangeNotifications = useChangeNotifications
-        )
+            useChangeNotifications = useChangeNotifications,
+            useTransparentCompiler = useTransparentCompiler,
+            ?runTimeout = runTimeout)
 
     member this.Checker = checker
 
     member this.Yield _ = async {
-        let! ctx =
-            match initialContext with
-            | Some ctx -> async.Return ctx
-            | _ -> SaveAndCheckProject initialProject checker
+        let! ctx = getInitialContext()
         tracerProvider <-
             Sdk.CreateTracerProviderBuilder()
                 .AddSource("fsc")
@@ -679,7 +683,7 @@ type ProjectWorkflowBuilder
                 .AddJaegerExporter()
                 .Build()
             |> Some
-        activity <- Activity.start ctx.Project.Name [ Activity.Tags.project, ctx.Project.Name ] |> Some
+        activity <- Activity.start ctx.Project.Name [ Activity.Tags.project, ctx.Project.Name; "UsingTransparentCompiler", useTransparentCompiler.ToString() ] |> Some
         return ctx
     }
 
@@ -689,7 +693,7 @@ type ProjectWorkflowBuilder
 
     member this.Run(workflow: Async) =
         try
-            Async.RunSynchronously workflow
+            Async.RunSynchronously(workflow, timeout = defaultArg runTimeout 60_000)
         finally
             if initialContext.IsNone then
                 this.DeleteProjectDir()
diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/BackgroundCompilerBenchmarks.fs b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/BackgroundCompilerBenchmarks.fs
index 3b44c1d37bf..b555ac27508 100644
--- a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/BackgroundCompilerBenchmarks.fs
+++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/BackgroundCompilerBenchmarks.fs
@@ -6,6 +6,7 @@ open FSharp.Compiler.CodeAnalysis
 open FSharp.Compiler.Text
 open FSharp.Compiler.Diagnostics
 open FSharp.Test.ProjectGeneration
+open BenchmarkDotNet.Engines
 
 
 []
@@ -221,3 +222,114 @@ type NoFileSystemCheckerBenchmark() =
     []
     member this.Cleanup() =
         benchmark.DeleteProjectDir()
+
+
+
+type TestProjectType =
+    | DependencyChain = 1
+    | DependentGroups = 2
+    | ParallelGroups = 3
+
+
+[]
+[]
+[]
+[]
+type TransparentCompilerBenchmark() =
+
+    let size = 30
+
+    let groups = 6
+    let filesPerGroup = size / groups
+    let somethingToCompile = File.ReadAllText (__SOURCE_DIRECTORY__ ++ "SomethingToCompileSmaller.fs")
+
+    let projects = Map [
+
+        TestProjectType.DependencyChain,
+            SyntheticProject.Create("SingleDependencyChain", [|
+                sourceFile $"File%03d{0}" []
+                for i in 1..size do
+                    { sourceFile $"File%03d{i}" [$"File%03d{i-1}"] with ExtraSource = somethingToCompile }
+            |])
+
+        TestProjectType.DependentGroups,
+            SyntheticProject.Create("GroupDependenciesProject", [|
+                for group in 1..groups do
+                    for i in 1..filesPerGroup do
+                        { sourceFile $"G{group}_F%03d{i}" [
+                            if group > 1 then $"G1_F%03d{1}"
+                            if i > 1 then $"G{group}_F%03d{i - 1}" ]
+                            with ExtraSource = somethingToCompile }
+            |])
+
+        TestProjectType.ParallelGroups,
+            SyntheticProject.Create("ParallelGroupsProject", [|
+                for group in 1..groups do
+                    for i in 1..filesPerGroup do
+                        { sourceFile $"G{group}_F%03d{i}" [
+                            if group > 1 then
+                                for i in 1..filesPerGroup do
+                                    $"G{group-1}_F%03d{i}" ]
+                            with ExtraSource = somethingToCompile }
+            |])
+    ]
+
+    let mutable benchmark : ProjectWorkflowBuilder = Unchecked.defaultof<_>
+
+    member val UseGetSource = true with get,set
+
+    member val UseChangeNotifications = true with get,set
+
+    //[]
+    member val EmptyCache = false with get,set
+
+    []
+    member val UseTransparentCompiler = true with get,set
+
+    []
+    member val ProjectType = TestProjectType.ParallelGroups with get,set
+
+    member this.Project = projects[this.ProjectType]
+
+    []
+    member this.Setup() =
+        benchmark <-
+            ProjectWorkflowBuilder(
+            this.Project,
+            useGetSource = this.UseGetSource,
+            useChangeNotifications = this.UseChangeNotifications,
+            useTransparentCompiler = this.UseTransparentCompiler,
+            runTimeout = 15_000).CreateBenchmarkBuilder()
+
+    []
+    member this.EditFirstFile_OnlyInternalChange() =
+        if this.EmptyCache then
+            benchmark.Checker.InvalidateAll()
+            benchmark.Checker.ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients()
+
+    []
+    member this.ExampleWorkflow() =
+
+        use _ = Activity.start "Benchmark" [
+            "UseTransparentCompiler", this.UseTransparentCompiler.ToString()
+        ]
+
+        let first = this.Project.SourceFiles[0].Id
+        let middle = this.Project.SourceFiles[size / 2].Id
+        let last = this.Project.SourceFiles |> List.last |> fun f -> f.Id
+
+        benchmark {
+            updateFile first updatePublicSurface
+            checkFile first expectSignatureChanged
+            checkFile last expectSignatureChanged
+            updateFile middle updatePublicSurface
+            checkFile last expectOk
+            addFileAbove middle (sourceFile "addedFile" [first])
+            updateFile middle (addDependency "addedFile")
+            checkFile middle expectSignatureChanged
+            checkFile last expectOk
+        }
+
+    []
+    member this.Cleanup() =
+        benchmark.DeleteProjectDir()
From 22b1c9bee775a9bfa3e37015d776561de14aeab2 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Fri, 19 May 2023 19:36:02 +0200
Subject: [PATCH 043/222] f
---
 src/Compiler/Service/TransparentCompiler.fs | 2 --
 1 file changed, 2 deletions(-)
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 5f32e4325cf..bab6a5a7c7b 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -690,7 +690,6 @@ type internal TransparentCompiler
                     |> fst
                     |> Graph.subGraphFor (sourceFiles |> Array.last).Idx
 
-
                 let fileIndexes =
                     graph.Values |> Seq.collect id |> Seq.append graph.Keys |> Seq.distinct |> Set
 
@@ -835,7 +834,6 @@ type internal TransparentCompiler
 
                 let! graph, dependencyFiles = ComputeDependencyGraph priorSnapshot (parsedInputs |> Seq.map p13) bootstrapInfo.TcConfig
 
-
                 // layers that can be processed in parallel
                 let layers = Graph.leafSequence graph |> Seq.toList
 
From 68df1f6c298ebf5ea3036f2761e3050b889604da Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Mon, 5 Jun 2023 15:44:45 +0200
Subject: [PATCH 044/222] in memory project references
---
 src/Compiler/Driver/GraphChecking/Graph.fs    |   3 +
 src/Compiler/Driver/GraphChecking/Graph.fsi   |   2 +
 src/Compiler/Service/BackgroundCompiler.fs    |   6 +
 src/Compiler/Service/FSharpCheckerResults.fs  |   1 +
 src/Compiler/Service/IncrementalBuild.fs      |   1 +
 src/Compiler/Service/IncrementalBuild.fsi     |  13 +
 src/Compiler/Service/TransparentCompiler.fs   | 500 ++++++++++++------
 .../FSharpChecker/TransparentCompiler.fs      |  52 +-
 8 files changed, 415 insertions(+), 163 deletions(-)
diff --git a/src/Compiler/Driver/GraphChecking/Graph.fs b/src/Compiler/Driver/GraphChecking/Graph.fs
index 9cbce0b4b9b..41e1ae4a47e 100644
--- a/src/Compiler/Driver/GraphChecking/Graph.fs
+++ b/src/Compiler/Driver/GraphChecking/Graph.fs
@@ -27,6 +27,9 @@ module internal Graph =
         |> Array.map (fun (KeyValue (k, v)) -> k, v)
         |> readOnlyDict
 
+    let nodes (graph: Graph<'Node>) : Set<'Node> =
+        graph.Values |> Seq.collect id |> Seq.append graph.Keys |> Seq.distinct |> Set
+
     /// Find transitive dependencies of a single node.
     let transitiveDeps (node: 'Node) (graph: Graph<'Node>) =
         let visited = HashSet<'Node>()
diff --git a/src/Compiler/Driver/GraphChecking/Graph.fsi b/src/Compiler/Driver/GraphChecking/Graph.fsi
index 7d885f5c96a..f92a2a58468 100644
--- a/src/Compiler/Driver/GraphChecking/Graph.fsi
+++ b/src/Compiler/Driver/GraphChecking/Graph.fsi
@@ -10,6 +10,8 @@ module internal Graph =
     /// Build the graph.
     val make: nodeDeps: seq<'Node * 'Node array> -> Graph<'Node> when 'Node: equality
     val map<'T, 'U when 'U: equality> : f: ('T -> 'U) -> graph: Graph<'T> -> Graph<'U>
+    /// Get all nodes of the graph.
+    val nodes: graph: Graph<'Node> -> Set<'Node>
     /// Create a transitive closure of the graph in O(n^2) time (but parallelize it).
     /// The resulting graph contains edge A -> C iff the input graph contains a (directed) non-zero length path from A to C.
     val transitive<'Node when 'Node: equality> : graph: Graph<'Node> -> Graph<'Node>
diff --git a/src/Compiler/Service/BackgroundCompiler.fs b/src/Compiler/Service/BackgroundCompiler.fs
index baad181612a..4de5d8f7972 100644
--- a/src/Compiler/Service/BackgroundCompiler.fs
+++ b/src/Compiler/Service/BackgroundCompiler.fs
@@ -87,6 +87,9 @@ type internal IBackgroundCompiler =
     abstract member GetAssemblyData:
         options: FSharpProjectOptions * userOpName: string -> NodeCode
 
+    abstract member GetAssemblyData:
+        projectSnapshot: FSharpProjectSnapshot * userOpName: string -> NodeCode
+
     /// Fetch the check information from the background compiler (which checks w.r.t. the FileSystem API)
     abstract member GetBackgroundCheckResultsForFileInProject:
         fileName: string * options: FSharpProjectOptions * userOpName: string -> NodeCode
@@ -1490,6 +1493,9 @@ type internal BackgroundCompiler
         member _.GetAssemblyData(options: FSharpProjectOptions, userOpName: string) : NodeCode =
             self.GetAssemblyData(options, userOpName)
 
+        member _.GetAssemblyData(projectSnapshot: FSharpProjectSnapshot, userOpName: string) : NodeCode =
+            self.GetAssemblyData(projectSnapshot.ToOptions(), userOpName)
+
         member _.GetBackgroundCheckResultsForFileInProject
             (
                 fileName: string,
diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs
index 408e758427c..5e43544cfe5 100644
--- a/src/Compiler/Service/FSharpCheckerResults.fs
+++ b/src/Compiler/Service/FSharpCheckerResults.fs
@@ -59,6 +59,7 @@ open Internal.Utilities
 open Internal.Utilities.Collections
 open FSharp.Compiler.AbstractIL.ILBinaryReader
 open System.Threading.Tasks
+open System.Runtime.CompilerServices
 
 type FSharpUnresolvedReferencesSet = FSharpUnresolvedReferencesSet of UnresolvedAssemblyReference list
 
diff --git a/src/Compiler/Service/IncrementalBuild.fs b/src/Compiler/Service/IncrementalBuild.fs
index 5403a37b86b..bee2e5df0ec 100644
--- a/src/Compiler/Service/IncrementalBuild.fs
+++ b/src/Compiler/Service/IncrementalBuild.fs
@@ -578,6 +578,7 @@ module Utilities =
 /// Constructs the build data (IRawFSharpAssemblyData) representing the assembly when used
 /// as a cross-assembly reference.  Note the assembly has not been generated on disk, so this is
 /// a virtualized view of the assembly contents as computed by background checking.
+[]
 type RawFSharpAssemblyDataBackedByLanguageService (tcConfig, tcGlobals, generatedCcu: CcuThunk, outfile, topAttrs, assemblyName, ilAssemRef) =
 
     let exportRemapping = MakeExportRemapping generatedCcu generatedCcu.Contents
diff --git a/src/Compiler/Service/IncrementalBuild.fsi b/src/Compiler/Service/IncrementalBuild.fsi
index 50c7201195c..d4fe402cce1 100644
--- a/src/Compiler/Service/IncrementalBuild.fsi
+++ b/src/Compiler/Service/IncrementalBuild.fsi
@@ -140,6 +140,19 @@ type internal PartialCheckResults =
 
     member TimeStamp: DateTime
 
+[]
+type internal RawFSharpAssemblyDataBackedByLanguageService =
+    new:
+        tcConfig: TcConfig *
+        tcGlobals: TcGlobals *
+        generatedCcu: CcuThunk *
+        outfile: string *
+        topAttrs: TopAttribs *
+        assemblyName: string *
+        ilAssemRef: FSharp.Compiler.AbstractIL.IL.ILAssemblyRef ->
+            RawFSharpAssemblyDataBackedByLanguageService
+    interface IRawFSharpAssemblyData
+
 /// Manages an incremental build graph for the build of an F# project
 []
 type internal IncrementalBuilder =
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 237c32027df..97b264ad663 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -2,6 +2,7 @@ namespace FSharp.Compiler.CodeAnalysis.TransparentCompiler
 
 open System
 open System.Collections.Generic
+open System.Runtime.CompilerServices
 open System.Diagnostics
 open System.IO
 
@@ -37,6 +38,8 @@ open FSharp.Compiler.TypedTree
 open FSharp.Compiler.CheckDeclarations
 open FSharp.Compiler.EditorServices
 open FSharp.Compiler.CodeAnalysis
+open FSharp.Compiler.CreateILModule
+open FSharp.Compiler.TypedTreeOps
 
 type internal FSharpFile =
     {
@@ -49,6 +52,8 @@ type internal FSharpFile =
 /// Things we need to start parsing and checking files for a given project snapshot
 type internal BootstrapInfo =
     {
+        AssemblyName: string
+        OutFile: string
         TcConfig: TcConfig
         TcImports: TcImports
         TcGlobals: TcGlobals
@@ -86,6 +91,19 @@ type internal TcIntermediate =
         sink: TcResultsSinkImpl
     }
 
+[]
+type internal DependencyGraphType =
+    /// A dependency graph for a single file - it will be missing files which this file does not depend on
+    | File
+    /// A dependency graph for a project - it will contain all files in the project
+    | Project
+
+[]
+type internal Extensions =
+    []
+    static member Key(fileSnapshots: FSharpFileSnapshot list) =
+        fileSnapshots |> List.map (fun f -> f.Key)
+
 type internal TransparentCompiler
     (
         legacyReferenceResolver,
@@ -102,7 +120,7 @@ type internal TransparentCompiler
         getSource: (string -> Async) option,
         useChangeNotifications,
         useSyntaxTreeCache
-    ) =
+    ) as self =
 
     // Is having just one of these ok?
     let lexResourceManager = Lexhelp.LexResourceManager()
@@ -115,6 +133,9 @@ type internal TransparentCompiler
     let ParseAndCheckFileInProjectCache =
         AsyncMemoize(triggerCacheEvent "ParseAndCheckFileInProject")
 
+    let ParseAndCheckFullProjectCache =
+        AsyncMemoize(triggerCacheEvent "ParseAndCheckFullProject")
+
     let FrameworkImportsCache = AsyncMemoize(triggerCacheEvent "FrameworkImports")
     let BootstrapInfoStaticCache = AsyncMemoize(triggerCacheEvent "BootstrapInfoStatic")
     let BootstrapInfoCache = AsyncMemoize(triggerCacheEvent "BootstrapInfo")
@@ -123,6 +144,8 @@ type internal TransparentCompiler
 
     let DependencyGraphCache = AsyncMemoize(triggerCacheEvent "DependencyGraph")
 
+    let AssemblyDataCache = AsyncMemoize(triggerCacheEvent "AssemblyData")
+
     let SemanticClassificationCache =
         AsyncMemoize(triggerCacheEvent "SemanticClassification")
 
@@ -156,44 +179,6 @@ type internal TransparentCompiler
         )
         :> IBackgroundCompiler
 
-    let getProjectReferences (project: FSharpProjectSnapshot) userOpName =
-        [
-            for r in project.ReferencedProjects do
-
-                match r with
-                | FSharpReferencedProjectSnapshot.FSharpReference (nm, opts) ->
-                    // Don't use cross-project references for FSharp.Core, since various bits of code
-                    // require a concrete FSharp.Core to exist on-disk. The only solutions that have
-                    // these cross-project references to FSharp.Core are VisualFSharp.sln and FSharp.sln. The ramification
-                    // of this is that you need to build FSharp.Core to get intellisense in those projects.
-
-                    if
-                        (try
-                            Path.GetFileNameWithoutExtension(nm)
-                         with _ ->
-                             "")
-                        <> GetFSharpCoreLibraryName()
-                    then
-                        { new IProjectReference with
-                            member x.EvaluateRawContents() =
-                                node {
-                                    Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "GetAssemblyData", nm)
-
-                                    return!
-                                        backgroundCompiler.GetAssemblyData(
-                                            opts.ToOptions(),
-                                            userOpName + ".CheckReferencedProject(" + nm + ")"
-                                        )
-                                }
-
-                            member x.TryGetLogicalTimeStamp(cache) =
-                                // TODO:
-                                None
-
-                            member x.FileName = nm
-                        }
-        ]
-
     let ComputeFrameworkImports (tcConfig: TcConfig) frameworkDLLs nonFrameworkResolutions =
         let frameworkDLLsKey =
             frameworkDLLs
@@ -322,6 +307,40 @@ type internal TransparentCompiler
             return tcImports, tcInfo
         }
 
+    let getProjectReferences (project: FSharpProjectSnapshot) userOpName =
+        [
+            for r in project.ReferencedProjects do
+
+                match r with
+                | FSharpReferencedProjectSnapshot.FSharpReference (nm, opts) ->
+                    // Don't use cross-project references for FSharp.Core, since various bits of code
+                    // require a concrete FSharp.Core to exist on-disk. The only solutions that have
+                    // these cross-project references to FSharp.Core are VisualFSharp.sln and FSharp.sln. The ramification
+                    // of this is that you need to build FSharp.Core to get intellisense in those projects.
+
+                    if
+                        (try
+                            Path.GetFileNameWithoutExtension(nm)
+                         with _ ->
+                             "")
+                        <> GetFSharpCoreLibraryName()
+                    then
+                        { new IProjectReference with
+                            member x.EvaluateRawContents() =
+                                node {
+                                    Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "GetAssemblyData", nm)
+
+                                    return! self.GetAssemblyData(opts, userOpName + ".CheckReferencedProject(" + nm + ")")
+                                }
+
+                            member x.TryGetLogicalTimeStamp(cache) =
+                                // TODO:
+                                None
+
+                            member x.FileName = nm
+                        }
+        ]
+
     /// Bootstrap info that does not depend on contents of the files
     let ComputeBootstrapInfoStatic (projectSnapshot: FSharpProjectSnapshot) =
 
@@ -457,7 +476,7 @@ type internal TransparentCompiler
                 setupConfigFromLoadClosure ()
 
                 let tcConfig = TcConfig.Create(tcConfigB, validate = true)
-                let _outfile, _, assemblyName = tcConfigB.DecideNames sourceFiles
+                let outfile, _, assemblyName = tcConfigB.DecideNames sourceFiles
 
                 // Resolve assemblies and create the framework TcImports. This caches a level of "system" references. No type providers are
                 // included in these references.
@@ -548,14 +567,30 @@ type internal TransparentCompiler
                         importsInvalidatedByTypeProvider
                     )
 
-                return sourceFiles, tcConfig, tcImports, tcGlobals, initialTcInfo, loadClosureOpt, importsInvalidatedByTypeProvider
+                return
+                    assemblyName,
+                    outfile,
+                    sourceFiles,
+                    tcConfig,
+                    tcImports,
+                    tcGlobals,
+                    initialTcInfo,
+                    loadClosureOpt,
+                    importsInvalidatedByTypeProvider
             }
         )
 
     let computeBootstrapInfoInner (projectSnapshot: FSharpProjectSnapshot) =
         node {
-            let! sourceFiles, tcConfig, tcImports, tcGlobals, initialTcInfo, loadClosureOpt, _importsInvalidatedByTypeProvider =
-                ComputeBootstrapInfoStatic projectSnapshot
+            let! assemblyName,
+                 outFile,
+                 sourceFiles,
+                 tcConfig,
+                 tcImports,
+                 tcGlobals,
+                 initialTcInfo,
+                 loadClosureOpt,
+                 _importsInvalidatedByTypeProvider = ComputeBootstrapInfoStatic projectSnapshot
 
             let fileSnapshots = Map [ for f in projectSnapshot.SourceFiles -> f.FileName, f ]
 
@@ -582,6 +617,8 @@ type internal TransparentCompiler
             return
                 Some
                     {
+                        AssemblyName = assemblyName
+                        OutFile = outFile
                         TcConfig = tcConfig
                         TcImports = tcImports
                         TcGlobals = tcGlobals
@@ -667,71 +704,73 @@ type internal TransparentCompiler
             }
         )
 
-    let ComputeDependencyGraph (priorSnapshot: FSharpProjectSnapshot) parsedInputs (tcConfig: TcConfig) =
-        let key = priorSnapshot.SourceFiles |> List.map (fun s -> s.Key)
-
-        DependencyGraphCache.Get(
-            key,
-            node {
+    let computeDependencyGraph parsedInputs (tcConfig: TcConfig) (processGraph: Graph -> Graph) =
+        node {
+            let sourceFiles: FileInProject array =
+                parsedInputs
+                |> Seq.toArray
+                |> Array.mapi (fun idx (input: ParsedInput) ->
+                    {
+                        Idx = idx
+                        FileName = input.FileName
+                        ParsedInput = input
+                    })
 
-                let sourceFiles: FileInProject array =
-                    parsedInputs
-                    |> Seq.toArray
-                    |> Array.mapi (fun idx (input: ParsedInput) ->
-                        {
-                            Idx = idx
-                            FileName = input.FileName
-                            ParsedInput = input
-                        })
+            use _ =
+                Activity.start "ComputeDependencyGraph" [| Activity.Tags.fileName, (sourceFiles |> Array.last).FileName |]
 
-                use _ =
-                    Activity.start "ComputeDependencyGraph" [| Activity.Tags.fileName, (sourceFiles |> Array.last).FileName |]
+            let filePairs = FilePairMap(sourceFiles)
 
-                let filePairs = FilePairMap(sourceFiles)
+            // TODO: we will probably want to cache and re-use larger graphs if available
+            let graph =
+                DependencyResolution.mkGraph tcConfig.compilingFSharpCore filePairs sourceFiles
+                |> fst
+                |> processGraph
 
-                // TODO: we will probably want to cache and re-use larger graphs if available
-                let graph =
-                    DependencyResolution.mkGraph tcConfig.compilingFSharpCore filePairs sourceFiles
-                    |> fst
-                    |> Graph.subGraphFor (sourceFiles |> Array.last).Idx
+            let nodeGraph = TransformDependencyGraph(graph, filePairs)
 
-                let fileIndexes =
-                    graph.Values |> Seq.collect id |> Seq.append graph.Keys |> Seq.distinct |> Set
+            let fileNames =
+                parsedInputs
+                |> Seq.mapi (fun idx input -> idx, Path.GetFileName input.FileName)
+                |> Map.ofSeq
 
-                let nodeGraph = TransformDependencyGraph(graph, filePairs)
+            let debugGraph =
+                nodeGraph
+                |> Graph.map (function
+                    | NodeToTypeCheck.PhysicalFile i -> i, fileNames[i]
+                    | NodeToTypeCheck.ArtificialImplFile i -> -(i + 1), $"AIF : {fileNames[i]}")
+                |> Graph.serialiseToMermaid
 
-                let fileNames =
-                    parsedInputs
-                    |> Seq.mapi (fun idx input -> idx, Path.GetFileName input.FileName)
-                    |> Map.ofSeq
+            Trace.TraceInformation("\n" + debugGraph)
 
-                let debugGraph =
-                    nodeGraph
-                    |> Graph.map (function
-                        | NodeToTypeCheck.PhysicalFile i -> i, fileNames[i]
-                        | NodeToTypeCheck.ArtificialImplFile i -> -(i + 1), $"AIF : {fileNames[i]}")
-                    |> Graph.serialiseToMermaid
+            if Activity.Current <> null then
+                Activity.Current.AddTag("graph", debugGraph) |> ignore
 
-                Trace.TraceInformation("\n" + debugGraph)
+            return nodeGraph, graph
+        }
 
-                if Activity.Current <> null then
-                    Activity.Current.AddTag("graph", debugGraph) |> ignore
+    let ComputeDependencyGraphForFile (priorSnapshot: FSharpProjectSnapshot) parsedInputs (tcConfig: TcConfig) =
+        let key = priorSnapshot.SourceFiles.Key(), DependencyGraphType.File
+        let lastFileIndex = (parsedInputs |> Array.length) - 1
+        DependencyGraphCache.Get(key, computeDependencyGraph parsedInputs tcConfig (Graph.subGraphFor lastFileIndex))
 
-                return nodeGraph, fileIndexes
-            }
-        )
+    let ComputeDependencyGraphForProject (projectSnapshot: FSharpProjectSnapshot) parsedInputs (tcConfig: TcConfig) =
+        let key = projectSnapshot.SourceFiles.Key(), DependencyGraphType.Project
+        DependencyGraphCache.Get(key, computeDependencyGraph parsedInputs tcConfig id)
 
     let ComputeTcIntermediate
         (projectSnapshot: FSharpProjectSnapshot)
-        (dependencyFiles: Set)
+        (dependencyGraph: Graph)
         (fileIndex: FileIndex)
         (parsedInput: ParsedInput, parseErrors)
         bootstrapInfo
         (prevTcInfo: TcInfo)
         =
 
+        let dependencyFiles = dependencyGraph |> Graph.subGraphFor fileIndex |> Graph.nodes
+
         TcIntermediateCache.Get(
-            projectSnapshot.UpTo(fileIndex).OnlyWith(dependencyFiles).Key,
+            projectSnapshot.OnlyWith(dependencyFiles).Key,
             node {
                 let input = parsedInput
                 let fileName = input.FileName
@@ -797,24 +836,79 @@ type internal TransparentCompiler
         )
 
     let mergeIntermediateResults =
-        Array.fold (fun (tcInfo: TcInfo) (tcIntermediate: TcIntermediate) ->
-            let (tcEnv, topAttribs, _checkImplFileOpt, ccuSigForFile), tcState =
-                tcInfo.tcState |> tcIntermediate.finisher.Invoke
-
-            let tcEnvAtEndOfFile =
-                if keepAllBackgroundResolutions then
-                    tcEnv
-                else
-                    tcState.TcEnvFromImpls
-
-            { tcInfo with
-                tcState = tcState
-                tcEnvAtEndOfFile = tcEnvAtEndOfFile
-                topAttribs = Some topAttribs
-                tcDiagnosticsRev = tcIntermediate.tcDiagnosticsRev @ tcInfo.tcDiagnosticsRev
-                tcDependencyFiles = tcIntermediate.tcDependencyFiles @ tcInfo.tcDependencyFiles
-                latestCcuSigForFile = Some ccuSigForFile
-            })
+        Array.fold (fun (tcInfos: TcInfo list) (tcIntermediate: TcIntermediate) ->
+            match tcInfos with
+            | [] -> failwith "need initial tcInfo"
+            | tcInfo :: rest ->
+                let (tcEnv, topAttribs, _checkImplFileOpt, ccuSigForFile), tcState =
+                    tcInfo.tcState |> tcIntermediate.finisher.Invoke
+
+                let tcEnvAtEndOfFile =
+                    if keepAllBackgroundResolutions then
+                        tcEnv
+                    else
+                        tcState.TcEnvFromImpls
+
+                { tcInfo with
+                    tcState = tcState
+                    tcEnvAtEndOfFile = tcEnvAtEndOfFile
+                    topAttribs = Some topAttribs
+                    tcDiagnosticsRev = tcIntermediate.tcDiagnosticsRev @ tcInfo.tcDiagnosticsRev
+                    tcDependencyFiles = tcIntermediate.tcDependencyFiles @ tcInfo.tcDependencyFiles
+                    latestCcuSigForFile = Some ccuSigForFile
+                }
+                :: tcInfo :: rest)
+
+    let typeCheckLayers bootstrapInfo projectSnapshot (parsedInputs: array<_>) graph layers =
+        let rec processLayer (layers: Set list) tcInfos =
+            node {
+                match layers, tcInfos with
+                | [], _ -> return tcInfos
+                | _, [] -> return failwith "need initial tcInfo"
+                | layer :: rest, tcInfo :: _ ->
+                    let! results =
+                        layer
+                        |> Seq.map (fun fileNode ->
+
+                            match fileNode with
+                            | NodeToTypeCheck.PhysicalFile fileIndex ->
+                                let parsedInput, parseErrors, _ = parsedInputs[fileIndex]
+
+                                ComputeTcIntermediate projectSnapshot graph fileIndex (parsedInput, parseErrors) bootstrapInfo tcInfo
+                            | NodeToTypeCheck.ArtificialImplFile fileIndex ->
+
+                                let finisher tcState =
+                                    let parsedInput, _parseErrors, _ = parsedInputs[fileIndex]
+                                    let prefixPathOpt = None
+                                    // Retrieve the type-checked signature information and add it to the TcEnvFromImpls.
+                                    AddSignatureResultToTcImplEnv
+                                        (bootstrapInfo.TcImports,
+                                         bootstrapInfo.TcGlobals,
+                                         prefixPathOpt,
+                                         TcResultsSink.NoSink,
+                                         tcState,
+                                         parsedInput)
+                                        tcState
+
+                                let tcIntermediate =
+                                    {
+                                        finisher = finisher
+                                        moduleNamesDict = tcInfo.moduleNamesDict
+                                        tcDiagnosticsRev = []
+                                        tcDependencyFiles = []
+                                        sink = Unchecked.defaultof<_> // TODO: something nicer
+                                    }
+
+                                node.Return(tcIntermediate))
+                        |> NodeCode.Parallel
+
+                    return! processLayer rest (mergeIntermediateResults tcInfos results)
+            }
+
+        node {
+            let! tcInfo = processLayer layers [ bootstrapInfo.InitialTcInfo ]
+            return tcInfo, graph
+        }
 
     // Type check everything that is needed to check given file
     let ComputeTcPrior (file: FSharpFile) (bootstrapInfo: BootstrapInfo) (projectSnapshot: FSharpProjectSnapshot) =
@@ -837,7 +931,8 @@ type internal TransparentCompiler
 
                 let! parsedInputs = files |> Seq.map (ComputeParseFile bootstrapInfo) |> NodeCode.Parallel
 
-                let! graph, dependencyFiles = ComputeDependencyGraph priorSnapshot (parsedInputs |> Seq.map p13) bootstrapInfo.TcConfig
+                let! graph, dependencyFiles =
+                    ComputeDependencyGraphForFile priorSnapshot (parsedInputs |> Array.map p13) bootstrapInfo.TcConfig
 
                 // layers that can be processed in parallel
                 let layers = Graph.leafSequence graph |> Seq.toList
@@ -845,58 +940,9 @@ type internal TransparentCompiler
                 // remove the final layer, which should be the target file
                 let layers = layers |> List.take (layers.Length - 1)
 
-                let rec processLayer (layers: Set list) tcInfo =
-                    node {
-                        match layers with
-                        | [] -> return tcInfo
-                        | layer :: rest ->
-                            let! results =
-                                layer
-                                |> Seq.map (fun fileNode ->
-
-                                    match fileNode with
-                                    | NodeToTypeCheck.PhysicalFile fileIndex ->
-                                        let parsedInput, parseErrors, _ = parsedInputs[fileIndex]
-
-                                        ComputeTcIntermediate
-                                            projectSnapshot
-                                            dependencyFiles
-                                            fileIndex
-                                            (parsedInput, parseErrors)
-                                            bootstrapInfo
-                                            tcInfo
-                                    | NodeToTypeCheck.ArtificialImplFile fileIndex ->
-
-                                        let finisher tcState =
-                                            let parsedInput, _parseErrors, _ = parsedInputs[fileIndex]
-                                            let prefixPathOpt = None
-                                            // Retrieve the type-checked signature information and add it to the TcEnvFromImpls.
-                                            AddSignatureResultToTcImplEnv
-                                                (bootstrapInfo.TcImports,
-                                                 bootstrapInfo.TcGlobals,
-                                                 prefixPathOpt,
-                                                 TcResultsSink.NoSink,
-                                                 tcState,
-                                                 parsedInput)
-                                                tcState
-
-                                        let tcIntermediate =
-                                            {
-                                                finisher = finisher
-                                                moduleNamesDict = tcInfo.moduleNamesDict
-                                                tcDiagnosticsRev = []
-                                                tcDependencyFiles = []
-                                                sink = Unchecked.defaultof<_>
-                                            }
-
-                                        node.Return(tcIntermediate))
-                                |> NodeCode.Parallel
-
-                            return! processLayer rest (mergeIntermediateResults tcInfo results)
-                    }
+                let! tcInfos, graph = typeCheckLayers bootstrapInfo priorSnapshot parsedInputs dependencyFiles layers
 
-                let! tcInfo = processLayer layers bootstrapInfo.InitialTcInfo
-                return tcInfo, dependencyFiles
+                return tcInfos.Head, graph
             }
         )
 
@@ -981,24 +1027,46 @@ type internal TransparentCompiler
             }
         )
 
+    let ComputeParseAndCheckFullProject (bootstrapInfo: BootstrapInfo) (projectSnapshot: FSharpProjectSnapshot) =
+        ParseAndCheckFullProjectCache.Get(
+            projectSnapshot.Key,
+            node {
+                use _ =
+                    Activity.start
+                        "ComputeParseAndCheckFullProject"
+                        [| Activity.Tags.project, projectSnapshot.ProjectFileName |> Path.GetFileName |]
+
+                let! parsedInputs =
+                    bootstrapInfo.SourceFiles
+                    |> Seq.map (ComputeParseFile bootstrapInfo)
+                    |> NodeCode.Parallel
+
+                let! graph, dependencyFiles =
+                    ComputeDependencyGraphForProject projectSnapshot (parsedInputs |> Array.map p13) bootstrapInfo.TcConfig
+
+                // layers that can be processed in parallel
+                let layers = Graph.leafSequence graph |> Seq.toList
+
+                let! tcInfos, _ = typeCheckLayers bootstrapInfo projectSnapshot parsedInputs dependencyFiles layers
+                return tcInfos |> List.rev
+            }
+        )
+
     let tryGetSink fileName (projectSnapshot: FSharpProjectSnapshot) =
         node {
-            use _ =
-                Activity.start "ComputeSemanticClassification" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
-
             match! ComputeBootstrapInfo projectSnapshot with
             | None, _ -> return None
             | Some bootstrapInfo, _creationDiags ->
 
                 let file = bootstrapInfo.GetFile fileName
 
-                let! tcInfo, dependencyFiles = ComputeTcPrior file bootstrapInfo projectSnapshot
+                let! tcInfo, graph = ComputeTcPrior file bootstrapInfo projectSnapshot
                 let! parseTree, parseDiagnostics, _sourceText = ComputeParseFile bootstrapInfo file
 
                 let fileIndex = projectSnapshot.IndexOf fileName
 
                 let! { sink = sink } =
-                    ComputeTcIntermediate projectSnapshot dependencyFiles fileIndex (parseTree, parseDiagnostics) bootstrapInfo tcInfo
+                    ComputeTcIntermediate projectSnapshot graph fileIndex (parseTree, parseDiagnostics) bootstrapInfo tcInfo
 
                 return Some(sink, bootstrapInfo)
         }
@@ -1099,6 +1167,111 @@ type internal TransparentCompiler
             | Some itemKeyStore -> return itemKeyStore.FindAll symbol.Item
         }
 
+    member _.GetAssemblyData(projectSnapshot: FSharpProjectSnapshot, _userOpName) =
+        AssemblyDataCache.Get(
+            projectSnapshot.Key,
+            node {
+
+                match! ComputeBootstrapInfo projectSnapshot with
+                | None, _ -> return ProjectAssemblyDataResult.Unavailable true
+                | Some bootstrapInfo, _creationDiags ->
+
+                    let! tcInfos = ComputeParseAndCheckFullProject bootstrapInfo projectSnapshot
+
+                    let assemblyName = bootstrapInfo.AssemblyName
+                    let tcConfig = bootstrapInfo.TcConfig
+                    let tcGlobals = bootstrapInfo.TcGlobals
+
+                    let results =
+                        [
+                            for tcInfo in tcInfos ->
+                                tcInfo.tcEnvAtEndOfFile, defaultArg tcInfo.topAttribs EmptyTopAttrs, None, tcInfo.latestCcuSigForFile
+                        ]
+
+                    // Get the state at the end of the type-checking of the last file
+                    let finalInfo = List.last tcInfos
+
+                    // Finish the checking
+                    let (_tcEnvAtEndOfLastFile, topAttrs, _mimpls, _), tcState =
+                        CheckMultipleInputsFinish(results, finalInfo.tcState)
+
+                    let tcState, _, ccuContents = CheckClosedInputSetFinish([], tcState)
+
+                    let generatedCcu = tcState.Ccu.CloneWithFinalizedContents(ccuContents)
+
+                    // Compute the identity of the generated assembly based on attributes, options etc.
+                    // Some of this is duplicated from fsc.fs
+                    let ilAssemRef =
+                        let publicKey =
+                            try
+                                let signingInfo = ValidateKeySigningAttributes(tcConfig, tcGlobals, topAttrs)
+
+                                match GetStrongNameSigner signingInfo with
+                                | None -> None
+                                | Some s -> Some(PublicKey.KeyAsToken(s.PublicKey))
+                            with exn ->
+                                errorRecoveryNoRange exn
+                                None
+
+                        let locale =
+                            TryFindFSharpStringAttribute
+                                tcGlobals
+                                (tcGlobals.FindSysAttrib "System.Reflection.AssemblyCultureAttribute")
+                                topAttrs.assemblyAttrs
+
+                        let assemVerFromAttrib =
+                            TryFindFSharpStringAttribute
+                                tcGlobals
+                                (tcGlobals.FindSysAttrib "System.Reflection.AssemblyVersionAttribute")
+                                topAttrs.assemblyAttrs
+                            |> Option.bind (fun v ->
+                                try
+                                    Some(parseILVersion v)
+                                with _ ->
+                                    None)
+
+                        let ver =
+                            match assemVerFromAttrib with
+                            | None -> tcConfig.version.GetVersionInfo(tcConfig.implicitIncludeDir)
+                            | Some v -> v
+
+                        ILAssemblyRef.Create(assemblyName, None, publicKey, false, Some ver, locale)
+
+                    let assemblyDataResult =
+                        try
+                            // Assemblies containing type provider components can not successfully be used via cross-assembly references.
+                            // We return 'None' for the assembly portion of the cross-assembly reference
+                            let hasTypeProviderAssemblyAttrib =
+                                topAttrs.assemblyAttrs
+                                |> List.exists (fun (Attrib (tcref, _, _, _, _, _, _)) ->
+                                    let nm = tcref.CompiledRepresentationForNamedType.BasicQualifiedName
+
+                                    nm = typeof
+                                        .FullName)
+
+                            if tcState.CreatesGeneratedProvidedTypes || hasTypeProviderAssemblyAttrib then
+                                ProjectAssemblyDataResult.Unavailable true
+                            else
+                                ProjectAssemblyDataResult.Available(
+                                    RawFSharpAssemblyDataBackedByLanguageService(
+                                        tcConfig,
+                                        tcGlobals,
+                                        generatedCcu,
+                                        bootstrapInfo.OutFile,
+                                        topAttrs,
+                                        assemblyName,
+                                        ilAssemRef
+                                    )
+                                    :> IRawFSharpAssemblyData
+                                )
+                        with exn ->
+                            errorRecoveryNoRange exn
+                            ProjectAssemblyDataResult.Unavailable true
+
+                    return assemblyDataResult
+            }
+        )
+
     interface IBackgroundCompiler with
 
         member _.CacheEvent = cacheEvent.Publish
@@ -1166,6 +1339,9 @@ type internal TransparentCompiler
         member _.GetAssemblyData(options: FSharpProjectOptions, userOpName: string) : NodeCode =
             backgroundCompiler.GetAssemblyData(options, userOpName)
 
+        member this.GetAssemblyData(projectSnapshot: FSharpProjectSnapshot, userOpName: string) : NodeCode =
+            this.GetAssemblyData(projectSnapshot, userOpName)
+
         member _.GetBackgroundCheckResultsForFileInProject
             (
                 fileName: string,
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
index 842dcefaf5c..4c626c89221 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
+++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
@@ -4,6 +4,7 @@ open System.Collections.Concurrent
 open System.Diagnostics
 open FSharp.Compiler.CodeAnalysis
 open Internal.Utilities.Collections
+open FSharp.Compiler.CodeAnalysis.TransparentCompiler
 
 open Xunit
 
@@ -173,9 +174,14 @@ let ``Changes in a referenced project`` () =
         |> updateFile "First" (addDependency "Library")
 
     ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
+
+        updateFile "First" updatePublicSurface
+        checkFile "Last" expectOk
+
         updateFile "Library" updatePublicSurface
         saveFile "Library"
         checkFile "Last" expectSignatureChanged
+
     }
 
 []
@@ -222,6 +228,7 @@ let ``Files that are not depended on don't invalidate cache`` () =
     let cacheEvents = ResizeArray()
 
     ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
+        updateFile "First" updatePublicSurface
         checkFile "Last" expectOk
         withChecker (fun checker -> checker.CacheEvent.Add cacheEvents.Add)
         updateFile "Second" updatePublicSurface
@@ -240,7 +247,7 @@ let ``Files that are not depended on don't invalidate cache`` () =
     let graphConstructions =
         cacheEvents
         |> Seq.choose (function
-            | ("DependencyGraph", e, k) -> Some ((k :?> FSharpFileKey list) |> List.last |> fst |> Path.GetFileName, e)
+            | ("DependencyGraph", e, k) -> Some ((k :?> (FSharpFileKey list * DependencyGraphType)) |> fst |> List.last |> fst |> Path.GetFileName, e)
             | _ -> None)
         |> Seq.groupBy fst
         |> Seq.map (fun (k, g) -> k, g |> Seq.map snd |> Seq.toList)
@@ -249,3 +256,46 @@ let ``Files that are not depended on don't invalidate cache`` () =
     Assert.Equal([Started; Finished], graphConstructions["FileLast.fs"])
 
     Assert.True intermediateTypeChecks.IsEmpty
+
+[]
+let ``Files that are not depended on don't invalidate cache part 2`` () =
+    let project = SyntheticProject.Create(
+        sourceFile "A" [],
+        sourceFile "B" ["A"],
+        sourceFile "C" ["A"],
+        sourceFile "D" ["B"; "C"],
+        sourceFile "E" ["C"])
+
+    let cacheEvents = ResizeArray()
+    let allEvents = ResizeArray()
+
+    ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
+        withChecker (fun checker -> checker.CacheEvent.Add allEvents.Add)
+        updateFile "A" updatePublicSurface
+        checkFile "D" expectOk
+        withChecker (fun checker -> checker.CacheEvent.Add cacheEvents.Add)
+        updateFile "B" updatePublicSurface
+        checkFile "E" expectOk
+    } |> ignore
+
+    let intermediateTypeChecks =
+        cacheEvents
+        |> Seq.choose (function
+            | ("TcIntermediate", e, k) -> Some ((k :?> FSharpProjectSnapshotKey).LastFile |> fst |> Path.GetFileName, e)
+            | _ -> None)
+        |> Seq.groupBy fst
+        |> Seq.map (fun (k, g) -> k, g |> Seq.map snd |> Seq.toList)
+        |> Map
+
+    let graphConstructions =
+        cacheEvents
+        |> Seq.choose (function
+            | ("DependencyGraph", e, k) -> Some ((k :?> (FSharpFileKey list * DependencyGraphType)) |> fst |> List.last |> fst |> Path.GetFileName, e)
+            | _ -> None)
+        |> Seq.groupBy fst
+        |> Seq.map (fun (k, g) -> k, g |> Seq.map snd |> Seq.toList)
+        |> Map
+
+    Assert.Equal([Started; Finished], graphConstructions["FileE.fs"])
+
+    Assert.True intermediateTypeChecks.IsEmpty
\ No newline at end of file
From faaf9fa11ce75a2b6321d45650badd8b7111e523 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Mon, 5 Jun 2023 16:58:30 +0200
Subject: [PATCH 045/222] try deflake test
---
 src/Compiler/Service/TransparentCompiler.fs            |  4 ++--
 .../FSharpChecker/TransparentCompiler.fs               | 10 ++++++----
 2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 97b264ad663..d30d38a6a2f 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -312,7 +312,7 @@ type internal TransparentCompiler
             for r in project.ReferencedProjects do
 
                 match r with
-                | FSharpReferencedProjectSnapshot.FSharpReference (nm, opts) ->
+                | FSharpReferencedProjectSnapshot.FSharpReference (nm, projectSnapshot) ->
                     // Don't use cross-project references for FSharp.Core, since various bits of code
                     // require a concrete FSharp.Core to exist on-disk. The only solutions that have
                     // these cross-project references to FSharp.Core are VisualFSharp.sln and FSharp.sln. The ramification
@@ -330,7 +330,7 @@ type internal TransparentCompiler
                                 node {
                                     Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "GetAssemblyData", nm)
 
-                                    return! self.GetAssemblyData(opts, userOpName + ".CheckReferencedProject(" + nm + ")")
+                                    return! self.GetAssemblyData(projectSnapshot, userOpName + ".CheckReferencedProject(" + nm + ")")
                                 }
 
                             member x.TryGetLogicalTimeStamp(cache) =
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
index 4c626c89221..4ded2fb2490 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
+++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
@@ -267,13 +267,15 @@ let ``Files that are not depended on don't invalidate cache part 2`` () =
         sourceFile "E" ["C"])
 
     let cacheEvents = ResizeArray()
-    let allEvents = ResizeArray()
 
     ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
-        withChecker (fun checker -> checker.CacheEvent.Add allEvents.Add)
         updateFile "A" updatePublicSurface
         checkFile "D" expectOk
-        withChecker (fun checker -> checker.CacheEvent.Add cacheEvents.Add)
+        withChecker (fun checker ->
+            async {
+                do! Async.Sleep 50 // wait for events from initial project check
+                checker.CacheEvent.Add cacheEvents.Add
+            })
         updateFile "B" updatePublicSurface
         checkFile "E" expectOk
     } |> ignore
@@ -298,4 +300,4 @@ let ``Files that are not depended on don't invalidate cache part 2`` () =
 
     Assert.Equal([Started; Finished], graphConstructions["FileE.fs"])
 
-    Assert.True intermediateTypeChecks.IsEmpty
\ No newline at end of file
+    Assert.Equal([], intermediateTypeChecks |> Map.toList)
\ No newline at end of file
From d244d7337ad26b76e01846c9f38b31dab801dc84 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Mon, 5 Jun 2023 17:32:53 +0200
Subject: [PATCH 046/222] remove distinct
---
 src/Compiler/Driver/GraphChecking/Graph.fs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Compiler/Driver/GraphChecking/Graph.fs b/src/Compiler/Driver/GraphChecking/Graph.fs
index 41e1ae4a47e..84d96422811 100644
--- a/src/Compiler/Driver/GraphChecking/Graph.fs
+++ b/src/Compiler/Driver/GraphChecking/Graph.fs
@@ -28,7 +28,7 @@ module internal Graph =
         |> readOnlyDict
 
     let nodes (graph: Graph<'Node>) : Set<'Node> =
-        graph.Values |> Seq.collect id |> Seq.append graph.Keys |> Seq.distinct |> Set
+        graph.Values |> Seq.collect id |> Seq.append graph.Keys |> Set
 
     /// Find transitive dependencies of a single node.
     let transitiveDeps (node: 'Node) (graph: Graph<'Node>) =
From 26c542670f2cbca547c740e27053a3a3f2226152 Mon Sep 17 00:00:00 2001
From: 0101 <0101@innit.cz>
Date: Mon, 5 Jun 2023 17:47:48 +0200
Subject: [PATCH 047/222] try deflake test
---
 .../FSharpChecker/TransparentCompiler.fs                  | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
index 4ded2fb2490..1dc0cea36f1 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
+++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs
@@ -230,7 +230,11 @@ let ``Files that are not depended on don't invalidate cache`` () =
     ProjectWorkflowBuilder(project, useTransparentCompiler = true) {
         updateFile "First" updatePublicSurface
         checkFile "Last" expectOk
-        withChecker (fun checker -> checker.CacheEvent.Add cacheEvents.Add)
+        withChecker (fun checker ->
+            async {
+                do! Async.Sleep 50 // wait for events from initial project check
+                checker.CacheEvent.Add cacheEvents.Add
+            })
         updateFile "Second" updatePublicSurface
         checkFile "Last" expectOk
     } |> ignore
@@ -255,7 +259,7 @@ let ``Files that are not depended on don't invalidate cache`` () =
 
     Assert.Equal([Started; Finished], graphConstructions["FileLast.fs"])
 
-    Assert.True intermediateTypeChecks.IsEmpty
+    Assert.Equal([], intermediateTypeChecks |> Map.toList)
 
 []
 let ``Files that are not depended on don't invalidate cache part 2`` () =
From 9d4642283094917c6dfff37174033a9e820e27cd Mon Sep 17 00:00:00 2001
From: Petr Pokorny 
Date: Thu, 8 Jun 2023 17:36:20 +0200
Subject: [PATCH 048/222] fix cache agent loop
---
 src/Compiler/Facilities/AsyncMemoize.fs       | 110 ++++++++++--------
 src/Compiler/Service/TransparentCompiler.fs   |  33 +++---
 .../CompilerService/AsyncMemoize.fs           |   6 +-
 .../FSharp.Editor/Common/CancellableTasks.fs  |  60 +++++++++-
 .../src/FSharp.Editor/FSharp.Editor.resx      |   1 +
 .../LanguageService/LanguageService.fs        |   2 +-
 .../FSharp.Editor/xlf/FSharp.Editor.cs.xlf    |   1 +
 .../FSharp.Editor/xlf/FSharp.Editor.de.xlf    |   2 +
 .../FSharp.Editor/xlf/FSharp.Editor.es.xlf    |   1 +
 .../FSharp.Editor/xlf/FSharp.Editor.fr.xlf    |   2 +
 .../FSharp.Editor/xlf/FSharp.Editor.it.xlf    |   2 +
 .../FSharp.Editor/xlf/FSharp.Editor.ja.xlf    |   1 +
 .../FSharp.Editor/xlf/FSharp.Editor.ko.xlf    |   2 +
 .../FSharp.Editor/xlf/FSharp.Editor.pl.xlf    |   2 +
 .../FSharp.Editor/xlf/FSharp.Editor.pt-BR.xlf |   1 +
 .../FSharp.Editor/xlf/FSharp.Editor.ru.xlf    |   1 +
 .../FSharp.Editor/xlf/FSharp.Editor.tr.xlf    |   2 +
 .../xlf/FSharp.Editor.zh-Hans.xlf             |   1 +
 .../xlf/FSharp.Editor.zh-Hant.xlf             |   2 +
 19 files changed, 163 insertions(+), 69 deletions(-)
diff --git a/src/Compiler/Facilities/AsyncMemoize.fs b/src/Compiler/Facilities/AsyncMemoize.fs
index 581e6201193..2b56024fbe0 100644
--- a/src/Compiler/Facilities/AsyncMemoize.fs
+++ b/src/Compiler/Facilities/AsyncMemoize.fs
@@ -1,13 +1,15 @@
 namespace Internal.Utilities.Collections
 
-open FSharp.Compiler.BuildGraph
-open System.Threading
+open System
 open System.Collections.Generic
+open System.Threading
+
+open FSharp.Compiler.BuildGraph
 
 type internal Action<'TKey, 'TValue> =
     | GetOrCompute of NodeCode<'TValue> * CancellationToken
     | CancelRequest
-    | JobCompleted
+    | JobCompleted of 'TValue
 
 type MemoizeRequest<'TKey, 'TValue> = 'TKey * Action<'TKey, 'TValue> * AsyncReplyChannel>
 
@@ -20,12 +22,13 @@ type internal JobEventType =
     | Finished
     | Canceled
 
-type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?logEvent: (JobEventType * 'TKey -> unit)) =
+type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?logEvent: (string -> JobEventType * 'TKey -> unit), ?name: string) =
 
+    let name = defaultArg name "N/A"
     let tok = obj ()
 
     let cache =
-        MruCache<_, 'TKey, Job<'TValue>>(keepStrongly = 10, areSame = (fun (x, y) -> x = y))
+        MruCache<_, 'TKey, Job<'TValue>>(keepStrongly = 30, areSame = (fun (x, y) -> x = y))
 
     let requestCounts = Dictionary<'TKey, int>()
 
@@ -39,7 +42,8 @@ type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?logEvent: (JobE
     let sendAsync (inbox: MailboxProcessor<_>) key msg =
         inbox.PostAndAsyncReply(fun rc -> key, msg, rc) |> Async.Ignore |> Async.Start
 
-    let log event = logEvent |> Option.iter ((|>) event)
+    let log event =
+        logEvent |> Option.iter (fun x -> x name event)
 
     let agent =
         MailboxProcessor.Start(fun (inbox: MailboxProcessor>) ->
@@ -48,66 +52,72 @@ type internal AsyncMemoize<'TKey, 'TValue when 'TKey: equality>(?logEvent: (JobE
 
             async {
                 while true do
+                    try
+                        let _name = name
 
-                    let! key, action, replyChannel = inbox.Receive()
-
-                    match action, cache.TryGet(tok, key) with
-                    | GetOrCompute _, Some (Completed job) -> replyChannel.Reply job
-                    | GetOrCompute (_, ct), Some (Running (job, _)) ->
+                        let! key, action, replyChannel = inbox.Receive()
 
-                        incrRequestCount key
-                        replyChannel.Reply job
-                        ct.Register(fun _ -> post key CancelRequest) |> ignore
+                        match action, cache.TryGet(tok, key) with
+                        | GetOrCompute _, Some (Completed job) -> replyChannel.Reply job
+                        | GetOrCompute (_, ct), Some (Running (job, _)) ->
+                            incrRequestCount key
+                            replyChannel.Reply job
+                            ct.Register(fun _ -> post key CancelRequest) |> ignore
 
-                    | GetOrCompute (computation, ct), None ->
+                        | GetOrCompute (computation, ct), None ->
 
-                        let cts = new CancellationTokenSource()
+                            let cts = new CancellationTokenSource()
 
-                        let startedComputation =
-                            Async.StartAsTask(
-                                Async.AwaitNodeCode(
-                                    node {
-                                        log (Started, key)
-                                        let! result = computation
-                                        post key JobCompleted
-                                        return result
-                                    }
-                                ),
-                                cancellationToken = cts.Token
-                            )
+                            let startedComputation =
+                                Async.StartAsTask(
+                                    Async.AwaitNodeCode(
+                                        node {
+                                            log (Started, key)
+                                            let! result = computation
+                                            post key (JobCompleted result)
+                                            return result
+                                        }
+                                    ),
+                                    cancellationToken = cts.Token
+                                )
 
-                        let job = NodeCode.AwaitTask startedComputation
+                            let job = NodeCode.AwaitTask startedComputation
 
-                        cache.Set(tok, key, (Running(job, cts)))
+                            cache.Set(tok, key, (Running(job, cts)))
 
-                        incrRequestCount key
+                            incrRequestCount key
 
-                        ct.Register(fun _ -> post key CancelRequest) |> ignore
+                            ct.Register(fun _ -> post key CancelRequest) |> ignore
 
-                        replyChannel.Reply job
+                            replyChannel.Reply job
 
-                    | CancelRequest, Some (Running (_, cts)) ->
-                        let requestCount = requestCounts.TryGetValue key |> snd
+                        | CancelRequest, Some (Running (_, cts)) ->
+                            let requestCount = requestCounts.TryGetValue key |> snd
 
-                        if requestCount > 1 then
-                            requestCounts.[key] <- requestCount - 1
+                            if requestCount > 1 then
+                                requestCounts.[key] <- requestCount - 1
 
-                        else
-                            cts.Cancel()
-                            cache.RemoveAnySimilar(tok, key)
-                            requestCounts.Remove key |> ignore
-                            log (Canceled, key)
+                            else
+                                cts.Cancel()
+                                cache.RemoveAnySimilar(tok, key)
+                                requestCounts.Remove key |> ignore
+                                log (Canceled, key)
 
-                    | CancelRequest, None
-                    | CancelRequest, Some (Completed _) -> ()
+                        | CancelRequest, None
+                        | CancelRequest, Some (Completed _) -> ()
 
-                    | JobCompleted, Some (Running (job, _)) ->
-                        // TODO: should we re-wrap the result?
-                        cache.Set(tok, key, (Completed job))
-                        requestCounts.Remove key |> ignore
-                        log (Finished, key)
+                        | JobCompleted result, Some (Running _)
+                        // Job could be evicted from cache while it's running
+                        | JobCompleted result, None ->
+                            cache.Set(tok, key, (Completed(node.Return result)))
+                            requestCounts.Remove key |> ignore
+                            log (Finished, key)
 
-                    | JobCompleted, _ -> failwith "If this happens there's a bug"
+                        | JobCompleted _, _ -> failwith "If this happens there's a bug"
+                    with
+                    | :? OperationCanceledException as e ->
+                        System.Diagnostics.Trace.TraceError($"AsyncMemoize OperationCanceledException: {e.Message}")
+                    | ex -> System.Diagnostics.Trace.TraceError($"AsyncMemoize Exception: %A{ex}")
             })
 
     member _.Get(key, computation) =
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index d30d38a6a2f..d783c63e359 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -128,28 +128,33 @@ type internal TransparentCompiler
     let cacheEvent = new Event()
     let triggerCacheEvent name (e, k) = cacheEvent.Trigger(name, e, k)
 
-    let ParseFileCache = AsyncMemoize(triggerCacheEvent "ParseFile")
+    let ParseFileCache = AsyncMemoize(triggerCacheEvent, "ParseFile")
 
     let ParseAndCheckFileInProjectCache =
-        AsyncMemoize(triggerCacheEvent "ParseAndCheckFileInProject")
+        AsyncMemoize(triggerCacheEvent, "ParseAndCheckFileInProject")
 
     let ParseAndCheckFullProjectCache =
-        AsyncMemoize(triggerCacheEvent "ParseAndCheckFullProject")
+        AsyncMemoize(triggerCacheEvent, "ParseAndCheckFullProject")
 
-    let FrameworkImportsCache = AsyncMemoize(triggerCacheEvent "FrameworkImports")
-    let BootstrapInfoStaticCache = AsyncMemoize(triggerCacheEvent "BootstrapInfoStatic")
-    let BootstrapInfoCache = AsyncMemoize(triggerCacheEvent "BootstrapInfo")
-    let TcPriorCache = AsyncMemoize(triggerCacheEvent "TcPrior")
-    let TcIntermediateCache = AsyncMemoize(triggerCacheEvent "TcIntermediate")
+    let FrameworkImportsCache = AsyncMemoize(triggerCacheEvent, "FrameworkImports")
 
-    let DependencyGraphCache = AsyncMemoize(triggerCacheEvent "DependencyGraph")
+    let BootstrapInfoStaticCache =
+        AsyncMemoize(triggerCacheEvent, "BootstrapInfoStatic")
 
-    let AssemblyDataCache = AsyncMemoize(triggerCacheEvent "AssemblyData")
+    let BootstrapInfoCache = AsyncMemoize(triggerCacheEvent, "BootstrapInfo")
+
+    let TcPriorCache = AsyncMemoize(triggerCacheEvent, "TcPrior")
+
+    let TcIntermediateCache = AsyncMemoize(triggerCacheEvent, "TcIntermediate")
+
+    let DependencyGraphCache = AsyncMemoize(triggerCacheEvent, "DependencyGraph")
+
+    let AssemblyDataCache = AsyncMemoize(triggerCacheEvent, "AssemblyData")
 
     let SemanticClassificationCache =
-        AsyncMemoize(triggerCacheEvent "SemanticClassification")
+        AsyncMemoize(triggerCacheEvent, "SemanticClassification")
 
-    let ItemKeyStoreCache = AsyncMemoize(triggerCacheEvent "ItemKeyStore")
+    let ItemKeyStoreCache = AsyncMemoize(triggerCacheEvent, "ItemKeyStore")
 
     // We currently share one global dependency provider for all scripts for the FSharpChecker.
     // For projects, one is used per project.
@@ -1144,8 +1149,8 @@ type internal TransparentCompiler
 
     member _.ParseFile(fileName, projectSnapshot: FSharpProjectSnapshot, _userOpName) =
         node {
-            use _ =
-                Activity.start "ParseFile" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
+            //use _ =
+            //    Activity.start "ParseFile" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
 
             match! ComputeBootstrapInfo projectSnapshot with
             | None, creationDiags -> return emptyParseResult fileName creationDiags
diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
index 80c137cc603..61fae5d2af3 100644
--- a/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
+++ b/tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs
@@ -18,7 +18,7 @@ let ``Basics``() =
 
     let eventLog = ResizeArray()
 
-    let memoize = AsyncMemoize(eventLog.Add)
+    let memoize = AsyncMemoize(fun _ -> eventLog.Add)
 
     let task =
         NodeCode.Parallel(seq {
@@ -53,7 +53,7 @@ let ``We can cancel a job`` () =
     }
 
     let eventLog = ResizeArray()
-    let memoize = AsyncMemoize(eventLog.Add)
+    let memoize = AsyncMemoize(fun _ -> eventLog.Add)
 
     use cts1 = new CancellationTokenSource()
     use cts2 = new CancellationTokenSource()
@@ -96,7 +96,7 @@ let ``Job keeps running even if first requestor cancels`` () =
     }
 
     let eventLog = ResizeArray()
-    let memoize = AsyncMemoize(eventLog.Add)
+    let memoize = AsyncMemoize(fun _ -> eventLog.Add)
 
     use cts1 = new CancellationTokenSource()
     use cts2 = new CancellationTokenSource()
diff --git a/vsintegration/src/FSharp.Editor/Common/CancellableTasks.fs b/vsintegration/src/FSharp.Editor/Common/CancellableTasks.fs
index 11ef1ebe152..6ff78a04d09 100644
--- a/vsintegration/src/FSharp.Editor/Common/CancellableTasks.fs
+++ b/vsintegration/src/FSharp.Editor/Common/CancellableTasks.fs
@@ -37,6 +37,14 @@ module CancellableTasks =
     open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators
     open Microsoft.FSharp.Collections
 
+    []
+    type VolatileBarrier() =
+        [