diff --git a/src/Compiler/Driver/CompilerConfig.fs b/src/Compiler/Driver/CompilerConfig.fs index e945c9564a4..aac405088fe 100644 --- a/src/Compiler/Driver/CompilerConfig.fs +++ b/src/Compiler/Driver/CompilerConfig.fs @@ -588,6 +588,8 @@ type TcConfigBuilder = mutable exiter: Exiter mutable parallelReferenceResolution: ParallelReferenceResolution + + mutable captureIdentifiersWhenParsing: bool } // Directories to start probing in @@ -777,6 +779,7 @@ type TcConfigBuilder = xmlDocInfoLoader = None exiter = QuitProcessExiter parallelReferenceResolution = ParallelReferenceResolution.Off + captureIdentifiersWhenParsing = false } member tcConfigB.FxResolver = @@ -1322,6 +1325,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = member _.xmlDocInfoLoader = data.xmlDocInfoLoader member _.exiter = data.exiter member _.parallelReferenceResolution = data.parallelReferenceResolution + member _.captureIdentifiersWhenParsing = data.captureIdentifiersWhenParsing static member Create(builder, validate) = use _ = UseBuildPhase BuildPhase.Parameter diff --git a/src/Compiler/Driver/CompilerConfig.fsi b/src/Compiler/Driver/CompilerConfig.fsi index 95e26b637ef..069ae83fa5d 100644 --- a/src/Compiler/Driver/CompilerConfig.fsi +++ b/src/Compiler/Driver/CompilerConfig.fsi @@ -491,6 +491,8 @@ type TcConfigBuilder = mutable exiter: Exiter mutable parallelReferenceResolution: ParallelReferenceResolution + + mutable captureIdentifiersWhenParsing: bool } static member CreateNew: @@ -858,6 +860,8 @@ type TcConfig = member parallelReferenceResolution: ParallelReferenceResolution + member captureIdentifiersWhenParsing: bool + /// Represents a computation to return a TcConfig. Normally this is just a constant immutable TcConfig, /// but for F# Interactive it may be based on an underlying mutable TcConfigBuilder. [] diff --git a/src/Compiler/Driver/ParseAndCheckInputs.fs b/src/Compiler/Driver/ParseAndCheckInputs.fs index b384a93bf9e..45fb1ab34f7 100644 --- a/src/Compiler/Driver/ParseAndCheckInputs.fs +++ b/src/Compiler/Driver/ParseAndCheckInputs.fs @@ -413,7 +413,8 @@ let ParseInput lexbuf: UnicodeLexing.Lexbuf, defaultNamespace, fileName, - isLastCompiland + isLastCompiland, + identCapture ) = // The assert below is almost ok, but it fires in two cases: // - fsi.exe sometimes passes "stdin" as a dummy file name @@ -433,25 +434,29 @@ let ParseInput let input = let identStore = HashSet() - let identCaptureLexer x = - let token = lexer x - - match token with - | Parser.token.PERCENT_OP ident - | Parser.token.FUNKY_OPERATOR_NAME ident - | Parser.token.ADJACENT_PREFIX_OP ident - | Parser.token.PLUS_MINUS_OP ident - | Parser.token.INFIX_AMP_OP ident - | Parser.token.INFIX_STAR_DIV_MOD_OP ident - | Parser.token.PREFIX_OP ident - | Parser.token.INFIX_BAR_OP ident - | Parser.token.INFIX_AT_HAT_OP ident - | Parser.token.INFIX_COMPARE_OP ident - | Parser.token.INFIX_STAR_STAR_OP ident - | Parser.token.IDENT ident -> identStore.Add ident |> ignore - | _ -> () - - token + let lexer = + if identCapture then + (fun x -> + let token = lexer x + + match token with + | Parser.token.PERCENT_OP ident + | Parser.token.FUNKY_OPERATOR_NAME ident + | Parser.token.ADJACENT_PREFIX_OP ident + | Parser.token.PLUS_MINUS_OP ident + | Parser.token.INFIX_AMP_OP ident + | Parser.token.INFIX_STAR_DIV_MOD_OP ident + | Parser.token.PREFIX_OP ident + | Parser.token.INFIX_BAR_OP ident + | Parser.token.INFIX_AT_HAT_OP ident + | Parser.token.INFIX_COMPARE_OP ident + | Parser.token.INFIX_STAR_STAR_OP ident + | Parser.token.IDENT ident -> identStore.Add ident |> ignore + | _ -> () + + token) + else + lexer if FSharpMLCompatFileSuffixes |> List.exists (FileSystemUtils.checkSuffix fileName) then if lexbuf.SupportsFeature LanguageFeature.MLCompatRevisions then @@ -461,14 +466,14 @@ let ParseInput // Call the appropriate parser - for signature files or implementation files if FSharpImplFileSuffixes |> List.exists (FileSystemUtils.checkSuffix fileName) then - let impl = Parser.implementationFile identCaptureLexer lexbuf + let impl = Parser.implementationFile lexer lexbuf let tripleSlashComments = LexbufLocalXmlDocStore.ReportInvalidXmlDocPositions(lexbuf) PostParseModuleImpls(defaultNamespace, fileName, isLastCompiland, impl, lexbuf, tripleSlashComments, Set identStore) elif FSharpSigFileSuffixes |> List.exists (FileSystemUtils.checkSuffix fileName) then - let intfs = Parser.signatureFile identCaptureLexer lexbuf + let intfs = Parser.signatureFile lexer lexbuf let tripleSlashComments = LexbufLocalXmlDocStore.ReportInvalidXmlDocPositions(lexbuf) @@ -640,7 +645,8 @@ let ParseOneInputLexbuf (tcConfig: TcConfig, lexResourceManager, lexbuf, fileNam lexbuf, None, fileName, - isLastCompiland + isLastCompiland, + tcConfig.captureIdentifiersWhenParsing ) // Report the statistics for testing purposes diff --git a/src/Compiler/Driver/ParseAndCheckInputs.fsi b/src/Compiler/Driver/ParseAndCheckInputs.fsi index 166191d363e..13ed6801ad2 100644 --- a/src/Compiler/Driver/ParseAndCheckInputs.fsi +++ b/src/Compiler/Driver/ParseAndCheckInputs.fsi @@ -39,7 +39,8 @@ val ParseInput: lexbuf: Lexbuf * defaultNamespace: string option * fileName: string * - isLastCompiland: (bool * bool) -> + isLastCompiland: (bool * bool) * + identCapture: bool -> ParsedInput /// A general routine to process hash directives diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs index 25d1cbeba0b..61ba9c39c63 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fs +++ b/src/Compiler/Service/FSharpCheckerResults.fs @@ -2345,7 +2345,15 @@ module internal ParseAndCheckFile = matchingBraces.ToArray() - let parseFile (sourceText: ISourceText, fileName, options: FSharpParsingOptions, userOpName: string, suggestNamesForErrors: bool) = + let parseFile + ( + sourceText: ISourceText, + fileName, + options: FSharpParsingOptions, + userOpName: string, + suggestNamesForErrors: bool, + identCapture: bool + ) = Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "parseFile", fileName) use act = @@ -2377,7 +2385,8 @@ module internal ParseAndCheckFile = lexbuf, None, fileName, - (isLastCompiland, isExe) + (isLastCompiland, isExe), + identCapture ) with e -> errHandler.DiagnosticsLogger.StopProcessingRecovery e range0 // don't re-raise any exceptions, we must return None. @@ -3180,7 +3189,14 @@ type FsiInteractiveChecker(legacyReferenceResolver, tcConfig: TcConfig, tcGlobal FSharpParsingOptions.FromTcConfig(tcConfig, [| fileName |], true) let parseErrors, parsedInput, anyErrors = - ParseAndCheckFile.parseFile (sourceText, fileName, parsingOptions, userOpName, suggestNamesForErrors) + ParseAndCheckFile.parseFile ( + sourceText, + fileName, + parsingOptions, + userOpName, + suggestNamesForErrors, + tcConfig.captureIdentifiersWhenParsing + ) let dependencyFiles = [||] // interactions have no dependencies diff --git a/src/Compiler/Service/FSharpCheckerResults.fsi b/src/Compiler/Service/FSharpCheckerResults.fsi index bbf14830f39..444807b0117 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fsi +++ b/src/Compiler/Service/FSharpCheckerResults.fsi @@ -530,7 +530,8 @@ module internal ParseAndCheckFile = fileName: string * options: FSharpParsingOptions * userOpName: string * - suggestNamesForErrors: bool -> + suggestNamesForErrors: bool * + identCapture: bool -> FSharpDiagnostic[] * ParsedInput * bool val matchBraces: diff --git a/src/Compiler/Service/IncrementalBuild.fs b/src/Compiler/Service/IncrementalBuild.fs index a77ba8ff9ff..e1d59dc904b 100644 --- a/src/Compiler/Service/IncrementalBuild.fs +++ b/src/Compiler/Service/IncrementalBuild.fs @@ -1440,7 +1440,8 @@ type IncrementalBuilder(initialState: IncrementalBuilderInitialState, state: Inc enablePartialTypeChecking: bool, enableParallelCheckingWithSignatureFiles: bool, dependencyProvider, - parallelReferenceResolution + parallelReferenceResolution, + captureIdentifiersWhenParsing ) = let useSimpleResolutionSwitch = "--simpleresolution" @@ -1523,7 +1524,8 @@ type IncrementalBuilder(initialState: IncrementalBuilderInitialState, state: Inc tcConfigB.parallelCheckingWithSignatureFiles <- enableParallelCheckingWithSignatureFiles tcConfigB.parallelReferenceResolution <- parallelReferenceResolution - + tcConfigB.captureIdentifiersWhenParsing <- captureIdentifiersWhenParsing + tcConfigB, sourceFilesNew // If this is a builder for a script, re-apply the settings inferred from the diff --git a/src/Compiler/Service/IncrementalBuild.fsi b/src/Compiler/Service/IncrementalBuild.fsi index 481ed50689e..3a2e9554dd3 100755 --- a/src/Compiler/Service/IncrementalBuild.fsi +++ b/src/Compiler/Service/IncrementalBuild.fsi @@ -265,7 +265,8 @@ type internal IncrementalBuilder = enablePartialTypeChecking: bool * enableParallelCheckingWithSignatureFiles: bool * dependencyProvider: DependencyProvider option * - parallelReferenceResolution: ParallelReferenceResolution -> + parallelReferenceResolution: ParallelReferenceResolution * + captureIdentifiersWhenParsing: bool -> NodeCode /// Generalized Incremental Builder. This is exposed only for unit testing purposes. diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs index 9af88d75880..de261d0975e 100644 --- a/src/Compiler/Service/service.fs +++ b/src/Compiler/Service/service.fs @@ -188,7 +188,8 @@ type BackgroundCompiler enableBackgroundItemKeyStoreAndSemanticClassification, enablePartialTypeChecking, enableParallelCheckingWithSignatureFiles, - parallelReferenceResolution + parallelReferenceResolution, + captureIdentifiersWhenParsing ) as self = let beforeFileChecked = Event() @@ -320,7 +321,8 @@ type BackgroundCompiler enablePartialTypeChecking, enableParallelCheckingWithSignatureFiles, dependencyProvider, - parallelReferenceResolution + parallelReferenceResolution, + captureIdentifiersWhenParsing ) match builderOpt with @@ -496,14 +498,14 @@ type BackgroundCompiler Interlocked.Increment(&actualParseFileCount) |> ignore let parseDiagnostics, parseTree, anyErrors = - ParseAndCheckFile.parseFile (sourceText, fileName, options, userOpName, suggestNamesForErrors) + 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) + ParseAndCheckFile.parseFile (sourceText, fileName, options, userOpName, false, captureIdentifiersWhenParsing) return FSharpParseFileResults(parseDiagnostics, parseTree, anyErrors, options.SourceFiles) } @@ -750,7 +752,14 @@ type BackgroundCompiler GraphNode.SetPreferredUILang tcPrior.TcConfig.preferredUiLang let parseDiagnostics, parseTree, anyErrors = - ParseAndCheckFile.parseFile (sourceText, fileName, parsingOptions, userOpName, suggestNamesForErrors) + ParseAndCheckFile.parseFile ( + sourceText, + fileName, + parsingOptions, + userOpName, + suggestNamesForErrors, + captureIdentifiersWhenParsing + ) let parseResults = FSharpParseFileResults(parseDiagnostics, parseTree, anyErrors, builder.AllDependenciesDeprecated) @@ -1224,7 +1233,8 @@ type FSharpChecker enableBackgroundItemKeyStoreAndSemanticClassification, enablePartialTypeChecking, enableParallelCheckingWithSignatureFiles, - parallelReferenceResolution + parallelReferenceResolution, + captureIdentifiersWhenParsing ) = let backgroundCompiler = @@ -1239,7 +1249,8 @@ type FSharpChecker enableBackgroundItemKeyStoreAndSemanticClassification, enablePartialTypeChecking, enableParallelCheckingWithSignatureFiles, - parallelReferenceResolution + parallelReferenceResolution, + captureIdentifiersWhenParsing ) static let globalInstance = lazy FSharpChecker.Create() @@ -1282,7 +1293,8 @@ type FSharpChecker ?enableBackgroundItemKeyStoreAndSemanticClassification, ?enablePartialTypeChecking, ?enableParallelCheckingWithSignatureFiles, - ?parallelReferenceResolution + ?parallelReferenceResolution: bool, + ?captureIdentifiersWhenParsing: bool ) = use _ = Activity.startNoTags "FSharpChecker.Create" @@ -1304,6 +1316,7 @@ type FSharpChecker let enablePartialTypeChecking = defaultArg enablePartialTypeChecking false let enableParallelCheckingWithSignatureFiles = defaultArg enableParallelCheckingWithSignatureFiles false + let captureIdentifiersWhenParsing = defaultArg captureIdentifiersWhenParsing false if keepAssemblyContents && enablePartialTypeChecking then invalidArg "enablePartialTypeChecking" "'keepAssemblyContents' and 'enablePartialTypeChecking' cannot be both enabled." @@ -1321,7 +1334,8 @@ type FSharpChecker enableBackgroundItemKeyStoreAndSemanticClassification, enablePartialTypeChecking, enableParallelCheckingWithSignatureFiles, - parallelReferenceResolution + parallelReferenceResolution, + captureIdentifiersWhenParsing ) member _.ReferenceResolver = legacyReferenceResolver @@ -1499,7 +1513,7 @@ type FSharpChecker let userOpName = defaultArg userOpName "Unknown" node { - if fastCheck <> Some true then + if fastCheck <> Some true || not captureIdentifiersWhenParsing then return! backgroundCompiler.FindReferencesInFile(fileName, options, symbol, canInvalidateProject, userOpName) else let! parseResults = backgroundCompiler.GetBackgroundParseResultsForFileInProject(fileName, options, userOpName) diff --git a/src/Compiler/Service/service.fsi b/src/Compiler/Service/service.fsi index 697e6ae2cb8..b02a5668900 100644 --- a/src/Compiler/Service/service.fsi +++ b/src/Compiler/Service/service.fsi @@ -34,6 +34,7 @@ type public FSharpChecker = /// Indicates whether to perform partial type checking. Cannot be set to true if keepAssmeblyContents is true. If set to true, can cause duplicate type-checks when richer information on a file is needed, but can skip background type-checking entirely on implementation files with signature files. /// Type check implementation files that are backed by a signature file in parallel. /// Indicates whether to resolve references in parallel. + /// When set to true we create a set of all identifiers for each parsed file which can be used to speed up finding references. static member Create: ?projectCacheSize: int * ?keepAssemblyContents: bool * @@ -45,7 +46,8 @@ type public FSharpChecker = ?enableBackgroundItemKeyStoreAndSemanticClassification: bool * ?enablePartialTypeChecking: bool * ?enableParallelCheckingWithSignatureFiles: bool * - ?parallelReferenceResolution: bool -> + ?parallelReferenceResolution: bool * + ?captureIdentifiersWhenParsing: bool -> FSharpChecker /// @@ -300,14 +302,14 @@ type public FSharpChecker = /// The options for the project or script, used to determine active --define conditionals and other options relevant to parsing. /// The symbol to find all uses in the file. /// Default: true. If true, this call can invalidate the current state of project if the options have changed. If false, the current state of the project will be used. - /// Default: false. Experimental feature that makes the operation faster. + /// Default: false. Experimental feature that makes the operation faster. Requires FSharpChecker to be created with captureIdentifiersWhenParsing = true. /// An optional string used for tracing compiler operations associated with this request. member FindBackgroundReferencesInFile: fileName: string * options: FSharpProjectOptions * symbol: FSharpSymbol * ?canInvalidateProject: bool * - ?fastCheck: bool * + [] ?fastCheck: bool * ?userOpName: string -> Async diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fsi b/src/Compiler/SyntaxTree/SyntaxTree.fsi index f878e5fa21f..6caea468438 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTree.fsi @@ -1955,5 +1955,5 @@ type ParsedInput = /// Gets the #nowarn and other scoped pragmas member ScopedPragmas: ScopedPragma list - /// Gets a set of all identifiers used in this parsed input + /// Gets a set of all identifiers used in this parsed input. Only populated if captureIdentifiersWhenParsing option was used. member Identifiers: Set diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/FindReferences.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/FindReferences.fs index b421de62027..83131035443 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/FindReferences.fs +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/FindReferences.fs @@ -96,8 +96,12 @@ secondA.DoNothing(secondB) } -[] -let ``Finding references in project`` () = +[] +[] +[] +[] +[] +let ``Finding references in project`` (fastCheck, captureIdentifiersWhenParsing) = let size = 20 let project = @@ -111,10 +115,12 @@ let ``Finding references in project`` () = |> updateFile "File005" (addDependency "File000") |> updateFile "File010" (addDependency "File000") - let checker = FSharpChecker.Create(enableBackgroundItemKeyStoreAndSemanticClassification = true) + let checker = FSharpChecker.Create( + enableBackgroundItemKeyStoreAndSemanticClassification = true, + captureIdentifiersWhenParsing = captureIdentifiersWhenParsing) project.WorkflowWith checker { - findAllReferencesToModuleFromFile "File000" true (expectNumberOfResults 5) + findAllReferencesToModuleFromFile "File000" fastCheck (expectNumberOfResults 5) } [] @@ -189,4 +195,4 @@ let foo x = 5""" }) "FileSecond.fs", 8, 2, 4 "FileThird.fs", 8, 2, 13 ]) - } + } \ No newline at end of file diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected index 10aabc3dcc4..fbf5be3fb78 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -2009,7 +2009,7 @@ 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: 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]) +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[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]) diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs index 3d9c4f9f528..04870ad0892 100644 --- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs +++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs @@ -415,7 +415,8 @@ type ProjectWorkflowBuilder(initialProject: SyntheticProject, ?checker: FSharpCh (FSharpChecker.Create( keepAllBackgroundSymbolUses = false, enableBackgroundItemKeyStoreAndSemanticClassification = true, - enablePartialTypeChecking = true + enablePartialTypeChecking = true, + captureIdentifiersWhenParsing = true )) let mapProject f workflow = diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/BackgroundCompilerBenchmarks.fs b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/BackgroundCompilerBenchmarks.fs index 3062f194353..9033ffe3b1b 100644 --- a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/BackgroundCompilerBenchmarks.fs +++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/BackgroundCompilerBenchmarks.fs @@ -1,10 +1,10 @@ module FSharp.Benchmarks.BackgroundCompilerBenchmarks - open System.IO open BenchmarkDotNet.Attributes -open FSharp.Test.ProjectGeneration open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.Text +open FSharp.Test.ProjectGeneration [] @@ -29,7 +29,8 @@ type BackgroundCompilerBenchmarks () = member this.setup(project) = let checker = FSharpChecker.Create( - enableBackgroundItemKeyStoreAndSemanticClassification = true + enableBackgroundItemKeyStoreAndSemanticClassification = true, + captureIdentifiersWhenParsing = true ) this.Benchmark <- ProjectBenchmarkBuilder.Create(project, checker) |> Async.RunSynchronously @@ -99,3 +100,33 @@ type BackgroundCompilerBenchmarks () = [] member this.Cleanup() = this.Benchmark.DeleteProjectDir() + +[] +[] +type ParsingBenchmark() = + + let mutable checker: FSharpChecker = Unchecked.defaultof<_> + let mutable parsingOptions: FSharpParsingOptions = Unchecked.defaultof<_> + + let filePath = __SOURCE_DIRECTORY__ ++ ".." ++ ".." ++ ".." ++ ".." ++ "src" ++ "Compiler" ++ "Checking" ++ "CheckExpressions.fs" + let source = File.ReadAllText filePath |> SourceText.ofString + + [] + member val IdentCapture = true with get, set + + [] + member this.Setup() = + checker <- FSharpChecker.Create(captureIdentifiersWhenParsing = this.IdentCapture) + parsingOptions <- { (checker.GetParsingOptionsFromCommandLineArgs([]) |> fst) with SourceFiles = [| filePath |] } + + [] + member _.IterationSetup() = + checker.InvalidateAll() + checker.ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients() + + [] + member _.ParseBigFile() = + let result = checker.ParseFile(filePath, source, parsingOptions) |> Async.RunSynchronously + + if result.ParseHadErrors then + failwith "ParseHadErrors" diff --git a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs index 5a15a55db0f..166eb6fa4cc 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs @@ -122,7 +122,8 @@ type internal FSharpWorkspaceServiceFactory enableBackgroundItemKeyStoreAndSemanticClassification = true, enablePartialTypeChecking = true, enableParallelCheckingWithSignatureFiles = enableParallelCheckingWithSignatureFiles, - parallelReferenceResolution = enableParallelReferenceResolution) + parallelReferenceResolution = enableParallelReferenceResolution, + captureIdentifiersWhenParsing = true) checker checkerSingleton <- Some checker )