diff --git a/src/fsharp/service/service.fs b/src/fsharp/service/service.fs
index d170a7a5b2d..bfb074eede8 100644
--- a/src/fsharp/service/service.fs
+++ b/src/fsharp/service/service.fs
@@ -846,6 +846,12 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC
if startBackgroundCompileIfAlreadySeen then
bc.CheckProjectInBackground(options, userOpName + ".StartBackgroundCompile"))
+ member bc.ClearCache(options : FSharpProjectOptions seq, userOpName) =
+ // This operation can't currently be cancelled nor awaited
+ reactor.EnqueueOp(userOpName, "ClearCache", String.Empty, fun ctok ->
+ options
+ |> Seq.iter (fun options -> incrementalBuildersCache.RemoveAnySimilar(ctok, options)))
+
member __.NotifyProjectCleaned (options : FSharpProjectOptions, userOpName) =
reactor.EnqueueAndAwaitOpAsync(userOpName, "NotifyProjectCleaned", options.ProjectFileName, fun ctok ->
cancellable {
@@ -1142,6 +1148,11 @@ type FSharpChecker(legacyReferenceResolver,
let userOpName = defaultArg userOpName "Unknown"
backgroundCompiler.InvalidateConfiguration(options, startBackgroundCompile, userOpName)
+ /// Clear the internal cache of the given projects.
+ member __.ClearCache(options: FSharpProjectOptions seq, ?userOpName: string) =
+ let userOpName = defaultArg userOpName "Unknown"
+ backgroundCompiler.ClearCache(options, userOpName)
+
/// This function is called when a project has been cleaned, and thus type providers should be refreshed.
member __.NotifyProjectCleaned(options: FSharpProjectOptions, ?userOpName: string) =
let userOpName = defaultArg userOpName "Unknown"
diff --git a/src/fsharp/service/service.fsi b/src/fsharp/service/service.fsi
index 330a51adf38..365805ca8c6 100755
--- a/src/fsharp/service/service.fsi
+++ b/src/fsharp/service/service.fsi
@@ -358,6 +358,11 @@ type public FSharpChecker =
/// An optional string used for tracing compiler operations associated with this request.
member InvalidateConfiguration: options: FSharpProjectOptions * ?startBackgroundCompileIfAlreadySeen: bool * ?userOpName: string -> unit
+ /// Clear the internal cache of the given projects.
+ /// The given project options.
+ /// An optional string used for tracing compiler operations associated with this request.
+ member ClearCache: options: FSharpProjectOptions seq * ?userOpName: string -> unit
+
/// Set the project to be checked in the background. Overrides any previous call to CheckProjectInBackground
member CheckProjectInBackground: options: FSharpProjectOptions * ?userOpName: string -> unit
diff --git a/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs b/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs
index 085ccfcff9b..5818a5a1b16 100644
--- a/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs
+++ b/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs
@@ -81,7 +81,7 @@ type private FSharpProjectOptionsMessage =
| ClearSingleFileOptionsCache of DocumentId
[]
-type private FSharpProjectOptionsReactor (_workspace: VisualStudioWorkspace, settings: EditorOptions, _serviceProvider, checkerProvider: FSharpCheckerProvider) =
+type private FSharpProjectOptionsReactor (workspace: Workspace, settings: EditorOptions, _serviceProvider, checkerProvider: FSharpCheckerProvider) =
let cancellationTokenSource = new CancellationTokenSource()
// Hack to store command line options from HandleCommandLineChanges
@@ -208,6 +208,22 @@ type private FSharpProjectOptionsReactor (_workspace: VisualStudioWorkspace, set
if Array.isEmpty projectOptions.SourceFiles then
return None
else
+ // Clear any caches that need clearing and invalidate the project.
+ let currentSolution = workspace.CurrentSolution
+ let projectsToClearCache =
+ cache
+ |> Seq.filter (fun pair -> not (currentSolution.ContainsProject pair.Key))
+
+ if not (Seq.isEmpty projectsToClearCache) then
+ projectsToClearCache
+ |> Seq.iter (fun pair -> cache.Remove pair.Key |> ignore)
+ let options =
+ projectsToClearCache
+ |> Seq.map (fun pair ->
+ let _, _, projectOptions = pair.Value
+ projectOptions)
+ checkerProvider.Checker.ClearCache(options, userOpName = "tryComputeOptions")
+
checkerProvider.Checker.InvalidateConfiguration(projectOptions, startBackgroundCompileIfAlreadySeen = false, userOpName = "computeOptions")
let parsingOptions, _ = checkerProvider.Checker.GetParsingOptionsFromProjectOptions(projectOptions)