diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/DocumentDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/DocumentDiagnosticAnalyzer.fs index a8534353c65..43e6efec1fb 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/DocumentDiagnosticAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/DocumentDiagnosticAnalyzer.fs @@ -10,29 +10,25 @@ open System.Threading open System.Threading.Tasks open Microsoft.CodeAnalysis -open Microsoft.CodeAnalysis.Diagnostics open Microsoft.CodeAnalysis.Text -open Microsoft.CodeAnalysis.Host.Mef open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Diagnostics -open FSharp.Compiler open FSharp.Compiler.SourceCodeServices - [] type internal DiagnosticsType = | Syntax | Semantic [)>] -type internal FSharpDocumentDiagnosticAnalyzer [] () = +type internal FSharpDocumentDiagnosticAnalyzer + [] + ( + checkerProvider: FSharpCheckerProvider, + projectInfoManager: FSharpProjectOptionsManager + ) = static let userOpName = "DocumentDiagnosticAnalyzer" - let getChecker(document: Document) = - document.Project.Solution.Workspace.Services.GetService().Checker - - let getProjectInfoManager(document: Document) = - document.Project.Solution.Workspace.Services.GetService().FSharpProjectOptionsManager static let errorInfoEqualityComparer = { new IEqualityComparer with @@ -110,27 +106,25 @@ type internal FSharpDocumentDiagnosticAnalyzer [] () = interface IFSharpDocumentDiagnosticAnalyzer with member this.AnalyzeSyntaxAsync(document: Document, cancellationToken: CancellationToken): Task> = - let projectInfoManager = getProjectInfoManager document asyncMaybe { let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) let! sourceText = document.GetTextAsync(cancellationToken) let! textVersion = document.GetTextVersionAsync(cancellationToken) return! - FSharpDocumentDiagnosticAnalyzer.GetDiagnostics(getChecker document, document.FilePath, sourceText, textVersion.GetHashCode(), parsingOptions, projectOptions, DiagnosticsType.Syntax) + FSharpDocumentDiagnosticAnalyzer.GetDiagnostics(checkerProvider.Checker, document.FilePath, sourceText, textVersion.GetHashCode(), parsingOptions, projectOptions, DiagnosticsType.Syntax) |> liftAsync } |> Async.map (Option.defaultValue ImmutableArray.Empty) |> RoslynHelpers.StartAsyncAsTask cancellationToken member this.AnalyzeSemanticsAsync(document: Document, cancellationToken: CancellationToken): Task> = - let projectInfoManager = getProjectInfoManager document asyncMaybe { let! parsingOptions, _, projectOptions = projectInfoManager.TryGetOptionsForDocumentOrProject(document, cancellationToken, userOpName) let! sourceText = document.GetTextAsync(cancellationToken) let! textVersion = document.GetTextVersionAsync(cancellationToken) if document.Project.Name <> FSharpConstants.FSharpMiscellaneousFilesName || isScriptFile document.FilePath then return! - FSharpDocumentDiagnosticAnalyzer.GetDiagnostics(getChecker document, document.FilePath, sourceText, textVersion.GetHashCode(), parsingOptions, projectOptions, DiagnosticsType.Semantic) + FSharpDocumentDiagnosticAnalyzer.GetDiagnostics(checkerProvider.Checker, document.FilePath, sourceText, textVersion.GetHashCode(), parsingOptions, projectOptions, DiagnosticsType.Semantic) |> liftAsync else return ImmutableArray.Empty diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs index 43641cc957b..50ac17d7bc4 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs @@ -17,12 +17,14 @@ open FSharp.Compiler.SourceCodeServices type private PerDocumentSavedData = { Hash: int; Diagnostics: ImmutableArray } [)>] -type internal SimplifyNameDiagnosticAnalyzer [] () = +type internal SimplifyNameDiagnosticAnalyzer + [] + ( + checkerProvider: FSharpCheckerProvider, + projectInfoManager: FSharpProjectOptionsManager + ) = static let userOpName = "SimplifyNameDiagnosticAnalyzer" - let getProjectInfoManager (document: Document) = document.Project.Solution.Workspace.Services.GetService().FSharpProjectOptionsManager - let getChecker (document: Document) = document.Project.Solution.Workspace.Services.GetService().Checker - static let cache = new MemoryCache("FSharp.Editor." + userOpName) // Make sure only one document is being analyzed at a time, to be nice static let guard = new SemaphoreSlim(1) @@ -36,7 +38,7 @@ type internal SimplifyNameDiagnosticAnalyzer [] () = do! Option.guard document.FSharpOptions.CodeFixes.SimplifyName do Trace.TraceInformation("{0:n3} (start) SimplifyName", DateTime.Now.TimeOfDay.TotalSeconds) do! Async.Sleep DefaultTuning.SimplifyNameInitialDelay |> liftAsync - let! _parsingOptions, projectOptions = getProjectInfoManager(document).TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) + let! _parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) let! textVersion = document.GetTextVersionAsync(cancellationToken) let textVersionHash = textVersion.GetHashCode() let! _ = guard.WaitAsync(cancellationToken) |> Async.AwaitTask |> liftAsync @@ -46,7 +48,7 @@ type internal SimplifyNameDiagnosticAnalyzer [] () = | :? PerDocumentSavedData as data when data.Hash = textVersionHash -> return data.Diagnostics | _ -> let! sourceText = document.GetTextAsync() - let checker = getChecker document + let checker = checkerProvider.Checker let! _, _, checkResults = checker.ParseAndCheckDocument(document, projectOptions, sourceText = sourceText, userOpName=userOpName) let! result = SimplifyNames.getSimplifiableNames(checkResults, fun lineNumber -> sourceText.Lines.[Line.toZ lineNumber].ToString()) |> liftAsync let mutable diag = ResizeArray() diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs index 62b556cb0bb..ce979c4e0e1 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs @@ -4,24 +4,22 @@ namespace rec Microsoft.VisualStudio.FSharp.Editor open System open System.Composition -open System.Collections.Generic open System.Collections.Immutable open System.Diagnostics -open System.Threading.Tasks open Microsoft.CodeAnalysis -open Microsoft.CodeAnalysis.Diagnostics -open Microsoft.CodeAnalysis.Host.Mef open FSharp.Compiler.SourceCodeServices open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Diagnostics [)>] -type internal UnusedDeclarationsAnalyzer [] () = +type internal UnusedDeclarationsAnalyzer + [] + ( + checkerProvider: FSharpCheckerProvider, + projectInfoManager: FSharpProjectOptionsManager + ) = static let userOpName = "UnusedDeclarationsAnalyzer" - let getProjectInfoManager (document: Document) = document.Project.Solution.Workspace.Services.GetService().FSharpProjectOptionsManager - let getChecker (document: Document) = document.Project.Solution.Workspace.Services.GetService().Checker - interface IFSharpUnusedDeclarationsDiagnosticAnalyzer with @@ -31,10 +29,10 @@ type internal UnusedDeclarationsAnalyzer [] () = do Trace.TraceInformation("{0:n3} (start) UnusedDeclarationsAnalyzer", DateTime.Now.TimeOfDay.TotalSeconds) do! Async.Sleep DefaultTuning.UnusedDeclarationsAnalyzerInitialDelay |> liftAsync // be less intrusive, give other work priority most of the time - match! getProjectInfoManager(document).TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) with + match! projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) with | (_parsingOptions, projectOptions) -> let! sourceText = document.GetTextAsync() - let checker = getChecker document + let checker = checkerProvider.Checker let! _, _, checkResults = checker.ParseAndCheckDocument(document, projectOptions, sourceText = sourceText, userOpName = userOpName) let! unusedRanges = UnusedDeclarations.getUnusedDeclarations( checkResults, (isScriptFile document.FilePath)) |> liftAsync return diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/UnusedOpensDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/UnusedOpensDiagnosticAnalyzer.fs index a16a66e43eb..f7ef3160b88 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/UnusedOpensDiagnosticAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/UnusedOpensDiagnosticAnalyzer.fs @@ -16,10 +16,12 @@ open FSharp.Compiler.SourceCodeServices open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Diagnostics [)>] -type internal UnusedOpensDiagnosticAnalyzer [] () = - - let getProjectInfoManager (document: Document) = document.Project.Solution.Workspace.Services.GetService().FSharpProjectOptionsManager - let getChecker (document: Document) = document.Project.Solution.Workspace.Services.GetService().Checker +type internal UnusedOpensDiagnosticAnalyzer + [] + ( + checkerProvider: FSharpCheckerProvider, + projectInfoManager: FSharpProjectOptionsManager + ) = static let userOpName = "UnusedOpensAnalyzer" @@ -28,13 +30,7 @@ type internal UnusedOpensDiagnosticAnalyzer [] () = do! Option.guard document.FSharpOptions.CodeFixes.UnusedOpens let! sourceText = document.GetTextAsync() let! _, _, checkResults = checker.ParseAndCheckDocument(document, options, sourceText = sourceText, userOpName = userOpName) -#if DEBUG - let sw = Stopwatch.StartNew() -#endif let! unusedOpens = UnusedOpens.getUnusedOpens(checkResults, fun lineNumber -> sourceText.Lines.[Line.toZ lineNumber].ToString()) |> liftAsync -#if DEBUG - Logging.Logging.logInfof "*** Got %d unused opens in %O" unusedOpens.Length sw.Elapsed -#endif return unusedOpens } @@ -44,9 +40,9 @@ type internal UnusedOpensDiagnosticAnalyzer [] () = asyncMaybe { do Trace.TraceInformation("{0:n3} (start) UnusedOpensAnalyzer", DateTime.Now.TimeOfDay.TotalSeconds) do! Async.Sleep DefaultTuning.UnusedOpensAnalyzerInitialDelay |> liftAsync // be less intrusive, give other work priority most of the time - let! _parsingOptions, projectOptions = getProjectInfoManager(document).TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) + let! _parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) let! sourceText = document.GetTextAsync() - let checker = getChecker document + let checker = checkerProvider.Checker let! unusedOpens = UnusedOpensDiagnosticAnalyzer.GetUnusedOpenRanges(document, projectOptions, checker) return