From c677e2e2373d01f2c8ebe7807cb2007be7bbb230 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 8 Apr 2022 15:34:59 +1000 Subject: [PATCH 01/11] cleanup --- src/fsharp/CheckDeclarations.fs | 6 +- src/fsharp/CheckDeclarations.fsi | 4 +- src/fsharp/CompilerConfig.fs | 35 +++--- src/fsharp/CompilerConfig.fsi | 16 ++- src/fsharp/CompilerOptions.fs | 5 +- src/fsharp/ParseAndCheckInputs.fs | 89 ++++++++------- src/fsharp/ParseAndCheckInputs.fsi | 106 ++++++++++++------ src/fsharp/fsc.fs | 9 +- src/fsharp/fsi/fsi.fs | 43 +++---- src/fsharp/lex.fsl | 96 ++++++++-------- src/fsharp/lexhelp.fs | 12 +- src/fsharp/lexhelp.fsi | 2 +- src/fsharp/service/FSharpCheckerResults.fs | 23 ++-- src/fsharp/service/FSharpCheckerResults.fsi | 2 +- src/fsharp/service/FSharpParseFileResults.fs | 2 +- src/fsharp/service/IncrementalBuild.fs | 58 ++++++---- src/fsharp/service/IncrementalBuild.fsi | 4 +- src/fsharp/service/ServiceLexing.fs | 14 +-- src/fsharp/service/ServiceLexing.fsi | 2 +- src/fsharp/service/ServiceParsedInputOps.fs | 2 +- src/fsharp/service/ServiceParsedInputOps.fsi | 2 +- src/fsharp/service/service.fs | 87 +++++++------- src/fsharp/service/service.fsi | 36 +++++- ...erService.SurfaceArea.netstandard.expected | 4 +- .../CompilerServiceBenchmarks/Benchmarks.fs | 2 +- .../Classification/ClassificationService.fs | 2 +- .../ImplementInterfaceCodeFixProvider.fs | 2 +- .../Formatting/EditorFormattingService.fs | 2 +- .../Formatting/IndentationService.fs | 2 +- .../FSharpProjectOptionsManager.fs | 64 +++++------ .../LanguageService/WorkspaceExtensions.fs | 6 +- .../ProjectSitesAndFiles.fs | 4 +- vsintegration/tests/UnitTests/Tests.Watson.fs | 2 +- 33 files changed, 429 insertions(+), 316 deletions(-) diff --git a/src/fsharp/CheckDeclarations.fs b/src/fsharp/CheckDeclarations.fs index af6411a5539..ed18577463e 100644 --- a/src/fsharp/CheckDeclarations.fs +++ b/src/fsharp/CheckDeclarations.fs @@ -5783,7 +5783,7 @@ and TcModuleOrNamespaceElements cenv parent endm env xml mutRecNSInfo openDecls0 //-------------------------------------------------------------------------- -// TypeCheckOneImplFile - Typecheck all the namespace fragments in a file. +// CheckOneImplFile - Typecheck all the namespace fragments in a file. //-------------------------------------------------------------------------- @@ -5966,7 +5966,7 @@ let MakeInitialEnv env = /// Check an entire implementation file /// Typecheck, then close the inference scope and then check the file meets its signature (if any) -let TypeCheckOneImplFile +let CheckOneImplFile // checkForErrors: A function to help us stop reporting cascading errors (g, niceNameGen, amap, topCcu, @@ -6100,7 +6100,7 @@ let TypeCheckOneImplFile /// Check an entire signature file -let TypeCheckOneSigFile (g, niceNameGen, amap, topCcu, checkForErrors, conditionalDefines, tcSink, isInternalTestSpanStackReferring) tcEnv (ParsedSigFileInput (qualifiedNameOfFile = qualNameOfFile; modules = sigFileFrags)) = +let CheckOneSigFile (g, niceNameGen, amap, topCcu, checkForErrors, conditionalDefines, tcSink, isInternalTestSpanStackReferring) tcEnv (ParsedSigFileInput (qualifiedNameOfFile = qualNameOfFile; modules = sigFileFrags)) = cancellable { let cenv = cenv.Create diff --git a/src/fsharp/CheckDeclarations.fsi b/src/fsharp/CheckDeclarations.fsi index 2878efca08b..6dc27155926 100644 --- a/src/fsharp/CheckDeclarations.fsi +++ b/src/fsharp/CheckDeclarations.fsi @@ -48,7 +48,7 @@ val TcOpenModuleOrNamespaceDecl: TcResultsSink -> TcGlobals -> ImportMap -> ran val AddLocalSubModule: g: TcGlobals -> amap: ImportMap -> m: range -> env: TcEnv -> modul: ModuleOrNamespace -> TcEnv -val TypeCheckOneImplFile: +val CheckOneImplFile: TcGlobals * NiceNameGenerator * ImportMap * @@ -63,7 +63,7 @@ val TypeCheckOneImplFile: ParsedImplFileInput -> Cancellable -val TypeCheckOneSigFile : +val CheckOneSigFile : TcGlobals * NiceNameGenerator * ImportMap * CcuThunk * (unit -> bool) * ConditionalDefines option * TcResultsSink * bool -> TcEnv -> ParsedSigFileInput diff --git a/src/fsharp/CompilerConfig.fs b/src/fsharp/CompilerConfig.fs index a130e7b2404..befa0e71a8d 100644 --- a/src/fsharp/CompilerConfig.fs +++ b/src/fsharp/CompilerConfig.fs @@ -343,7 +343,7 @@ type TcConfigBuilder = mutable resolutionEnvironment: LegacyResolutionEnvironment mutable implicitlyResolveAssemblies: bool mutable light: bool option - mutable conditionalCompilationDefines: string list + mutable conditionalDefines: string list mutable loadedSources: (range * string * string) list mutable compilerToolPaths: string list mutable referencedDLLs: AssemblyReference list @@ -413,6 +413,7 @@ type TcConfigBuilder = mutable win32manifest: string mutable includewin32manifest: bool mutable linkResources: string list + mutable legacyReferenceResolver: LegacyReferenceResolver mutable showFullPaths: bool @@ -526,16 +527,18 @@ type TcConfigBuilder = } |> Seq.distinct - static member CreateNew(legacyReferenceResolver, - defaultFSharpBinariesDir, - reduceMemoryUsage, - implicitIncludeDir, - isInteractive, - isInvalidationSupported, - defaultCopyFSharpCore, - tryGetMetadataSnapshot, - sdkDirOverride, - rangeForErrors) = + static member CreateNew( + legacyReferenceResolver, + defaultFSharpBinariesDir, + reduceMemoryUsage, + implicitIncludeDir, + isInteractive, + isInvalidationSupported, + defaultCopyFSharpCore, + tryGetMetadataSnapshot, + sdkDirOverride, + rangeForErrors + ) = if (String.IsNullOrEmpty defaultFSharpBinariesDir) then failwith "Expected a valid defaultFSharpBinariesDir" @@ -546,7 +549,7 @@ type TcConfigBuilder = light = None noFeedback = false stackReserveSize = None - conditionalCompilationDefines = [] + conditionalDefines = [] openDebugInformationForLaterStaticLinking = false compilingFslib = false useIncrementalBuilder = false @@ -947,7 +950,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = member x.implicitlyResolveAssemblies = data.implicitlyResolveAssemblies member x.resolutionEnvironment = data.resolutionEnvironment member x.light = data.light - member x.conditionalCompilationDefines = data.conditionalCompilationDefines + member x.conditionalDefines = data.conditionalDefines member x.loadedSources = data.loadedSources member x.compilerToolPaths = data.compilerToolPaths member x.referencedDLLs = data.referencedDLLs @@ -1064,10 +1067,10 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parameter TcConfig(builder, validate) - member x.legacyReferenceResolver = data.legacyReferenceResolver + member _.legacyReferenceResolver = data.legacyReferenceResolver - member tcConfig.CloneToBuilder() = - { data with conditionalCompilationDefines=data.conditionalCompilationDefines } + member _.CloneToBuilder() = + { data with conditionalDefines=data.conditionalDefines } member tcConfig.ComputeCanContainEntryPoint(sourceFiles: string list) = let n = sourceFiles.Length in diff --git a/src/fsharp/CompilerConfig.fsi b/src/fsharp/CompilerConfig.fsi index 11224395b92..1d0693afc7b 100644 --- a/src/fsharp/CompilerConfig.fsi +++ b/src/fsharp/CompilerConfig.fsi @@ -158,14 +158,21 @@ type TcConfigBuilder = mutable useFsiAuxLib: bool mutable framework: bool mutable resolutionEnvironment: LegacyResolutionEnvironment + mutable implicitlyResolveAssemblies: bool + /// Set if the user has explicitly turned indentation-aware syntax on/off mutable light: bool option - mutable conditionalCompilationDefines: string list + + mutable conditionalDefines: string list + /// Sources added into the build with #load mutable loadedSources: (range * string * string) list + mutable compilerToolPaths: string list + mutable referencedDLLs: AssemblyReference list + mutable packageManagerLines: Map mutable projectReferences: IProjectReference list mutable knownUnresolvedReferences: UnresolvedAssemblyReference list @@ -357,11 +364,16 @@ type TcConfig = member useFsiAuxLib: bool member framework: bool member implicitlyResolveAssemblies: bool + /// Set if the user has explicitly turned indentation-aware syntax on/off member light: bool option - member conditionalCompilationDefines: string list + + member conditionalDefines: string list + member subsystemVersion: int * int + member useHighEntropyVA: bool + member compilerToolPaths: string list member referencedDLLs: AssemblyReference list member reduceMemoryUsage: ReduceMemoryFlag diff --git a/src/fsharp/CompilerOptions.fs b/src/fsharp/CompilerOptions.fs index e076d7fdaf1..5a5720d87ae 100644 --- a/src/fsharp/CompilerOptions.fs +++ b/src/fsharp/CompilerOptions.fs @@ -827,7 +827,7 @@ let codeGenerationFlags isFsi (tcConfigB: TcConfigBuilder) = // OptionBlock: Language //---------------------- -let defineSymbol tcConfigB s = tcConfigB.conditionalCompilationDefines <- s :: tcConfigB.conditionalCompilationDefines +let defineSymbol tcConfigB s = tcConfigB.conditionalDefines <- s :: tcConfigB.conditionalDefines let mlCompatibilityFlag (tcConfigB: TcConfigBuilder) = CompilerOption @@ -1058,7 +1058,8 @@ let editorSpecificFlags (tcConfigB: TcConfigBuilder) = CompilerOption("gccerrors", tagNone, OptionUnit (fun () -> tcConfigB.errorStyle <- ErrorStyle.GccErrors), None, None) CompilerOption("exename", tagNone, OptionString (fun s -> tcConfigB.exename <- Some s), None, None) CompilerOption("maxerrors", tagInt, OptionInt (fun n -> tcConfigB.maxErrors <- n), None, None) - CompilerOption("noconditionalerasure", tagNone, OptionUnit (fun () -> tcConfigB.noConditionalErasure <- true), None, None) ] + CompilerOption("noconditionalerasure", tagNone, OptionUnit (fun () -> tcConfigB.noConditionalErasure <- true), None, None) + ] let internalFlags (tcConfigB:TcConfigBuilder) = [ diff --git a/src/fsharp/ParseAndCheckInputs.fs b/src/fsharp/ParseAndCheckInputs.fs index b4ffd4bb26b..087623088d0 100644 --- a/src/fsharp/ParseAndCheckInputs.fs +++ b/src/fsharp/ParseAndCheckInputs.fs @@ -377,7 +377,7 @@ let EmptyParsedInput(filename, isLastCompiland) = ) /// Parse an input, drawing tokens from the LexBuffer -let ParseOneInputLexbuf (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, lexbuf, filename, isLastCompiland, errorLogger) = +let ParseOneInputLexbuf (tcConfig: TcConfig, lexResourceManager, lexbuf, filename, isLastCompiland, errorLogger) = use unwindbuildphase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse try @@ -388,7 +388,7 @@ let ParseOneInputLexbuf (tcConfig: TcConfig, lexResourceManager, conditionalComp let lightStatus = LightSyntaxStatus (tcConfig.ComputeLightSyntaxInitialStatus filename, true) // Set up the initial lexer arguments - let lexargs = mkLexargs (conditionalCompilationDefines@tcConfig.conditionalCompilationDefines, lightStatus, lexResourceManager, [], errorLogger, tcConfig.pathMap) + let lexargs = mkLexargs (tcConfig.conditionalDefines, lightStatus, lexResourceManager, [], errorLogger, tcConfig.pathMap) // Set up the initial lexer arguments let shortFilename = SanitizeFileName filename tcConfig.implicitIncludeDir @@ -399,9 +399,12 @@ let ParseOneInputLexbuf (tcConfig: TcConfig, lexResourceManager, conditionalComp // Set up the LexFilter over the token stream let tokenizer,tokenizeOnly = match tcConfig.tokenize with - | Unfiltered -> (fun () -> Lexer.token lexargs skipWhitespaceTokens lexbuf), true - | Only -> LexFilter.LexFilter(lightStatus, tcConfig.compilingFslib, Lexer.token lexargs skipWhitespaceTokens, lexbuf).GetToken, true - | _ -> LexFilter.LexFilter(lightStatus, tcConfig.compilingFslib, Lexer.token lexargs skipWhitespaceTokens, lexbuf).GetToken, false + | TokenizeOption.Unfiltered -> + (fun () -> Lexer.token lexargs skipWhitespaceTokens lexbuf), true + | TokenizeOption.Only -> + LexFilter.LexFilter(lightStatus, tcConfig.compilingFslib, Lexer.token lexargs skipWhitespaceTokens, lexbuf).GetToken, true + | _ -> + LexFilter.LexFilter(lightStatus, tcConfig.compilingFslib, Lexer.token lexargs skipWhitespaceTokens, lexbuf).GetToken, false // If '--tokenize' then show the tokens now and exit if tokenizeOnly then @@ -437,23 +440,23 @@ let checkInputFile (tcConfig: TcConfig) filename = else error(Error(FSComp.SR.buildInvalidSourceFileExtension(SanitizeFileName filename tcConfig.implicitIncludeDir), rangeStartup)) -let parseInputStreamAux (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, errorLogger, retryLocked, stream: Stream) = +let parseInputStreamAux (tcConfig: TcConfig, lexResourceManager, filename, isLastCompiland, errorLogger, retryLocked, stream: Stream) = use reader = stream.GetReader(tcConfig.inputCodePage, retryLocked) // Set up the LexBuffer for the file let lexbuf = UnicodeLexing.StreamReaderAsLexbuf(not tcConfig.compilingFslib, tcConfig.langVersion, reader) // Parse the file drawing tokens from the lexbuf - ParseOneInputLexbuf(tcConfig, lexResourceManager, conditionalCompilationDefines, lexbuf, filename, isLastCompiland, errorLogger) + ParseOneInputLexbuf(tcConfig, lexResourceManager, lexbuf, filename, isLastCompiland, errorLogger) -let parseInputSourceTextAux (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, errorLogger, sourceText: ISourceText) = +let parseInputSourceTextAux (tcConfig: TcConfig, lexResourceManager, filename, isLastCompiland, errorLogger, sourceText: ISourceText) = // Set up the LexBuffer for the file let lexbuf = UnicodeLexing.SourceTextAsLexbuf(not tcConfig.compilingFslib, tcConfig.langVersion, sourceText) // Parse the file drawing tokens from the lexbuf - ParseOneInputLexbuf(tcConfig, lexResourceManager, conditionalCompilationDefines, lexbuf, filename, isLastCompiland, errorLogger) + ParseOneInputLexbuf(tcConfig, lexResourceManager, lexbuf, filename, isLastCompiland, errorLogger) -let parseInputFileAux (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, errorLogger, retryLocked) = +let parseInputFileAux (tcConfig: TcConfig, lexResourceManager, filename, isLastCompiland, errorLogger, retryLocked) = // Get a stream reader for the file use fileStream = FileSystem.OpenFileForReadShim(filename) use reader = fileStream.GetReader(tcConfig.inputCodePage, retryLocked) @@ -462,35 +465,35 @@ let parseInputFileAux (tcConfig: TcConfig, lexResourceManager, conditionalCompil let lexbuf = UnicodeLexing.StreamReaderAsLexbuf(not tcConfig.compilingFslib, tcConfig.langVersion, reader) // Parse the file drawing tokens from the lexbuf - ParseOneInputLexbuf(tcConfig, lexResourceManager, conditionalCompilationDefines, lexbuf, filename, isLastCompiland, errorLogger) + ParseOneInputLexbuf(tcConfig, lexResourceManager, lexbuf, filename, isLastCompiland, errorLogger) /// Parse an input from stream -let ParseOneInputStream (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, errorLogger, retryLocked, stream: Stream) = +let ParseOneInputStream (tcConfig: TcConfig, lexResourceManager, filename, isLastCompiland, errorLogger, retryLocked, stream: Stream) = try - parseInputStreamAux(tcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, errorLogger, retryLocked, stream) + parseInputStreamAux(tcConfig, lexResourceManager, filename, isLastCompiland, errorLogger, retryLocked, stream) with e -> errorRecovery e rangeStartup EmptyParsedInput(filename, isLastCompiland) /// Parse an input from source text -let ParseOneInputSourceText (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, errorLogger, sourceText: ISourceText) = +let ParseOneInputSourceText (tcConfig: TcConfig, lexResourceManager, filename, isLastCompiland, errorLogger, sourceText: ISourceText) = try - parseInputSourceTextAux(tcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, errorLogger, sourceText) + parseInputSourceTextAux(tcConfig, lexResourceManager, filename, isLastCompiland, errorLogger, sourceText) with e -> errorRecovery e rangeStartup EmptyParsedInput(filename, isLastCompiland) /// Parse an input from disk -let ParseOneInputFile (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, errorLogger, retryLocked) = +let ParseOneInputFile (tcConfig: TcConfig, lexResourceManager, filename, isLastCompiland, errorLogger, retryLocked) = try checkInputFile tcConfig filename - parseInputFileAux(tcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, errorLogger, retryLocked) + parseInputFileAux(tcConfig, lexResourceManager, filename, isLastCompiland, errorLogger, retryLocked) with e -> errorRecovery e rangeStartup EmptyParsedInput(filename, isLastCompiland) /// Parse multiple input files from disk -let ParseInputFiles (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, sourceFiles, errorLogger: ErrorLogger, exiter: Exiter, createErrorLogger: Exiter -> CapturingErrorLogger, retryLocked) = +let ParseInputFiles (tcConfig: TcConfig, lexResourceManager, sourceFiles, errorLogger: ErrorLogger, exiter: Exiter, createErrorLogger: Exiter -> CapturingErrorLogger, retryLocked) = try let isLastCompiland, isExe = sourceFiles |> tcConfig.ComputeCanContainEntryPoint let sourceFiles = isLastCompiland |> List.zip sourceFiles |> Array.ofList @@ -517,7 +520,7 @@ let ParseInputFiles (tcConfig: TcConfig, lexResourceManager, conditionalCompilat let delayedErrorLogger = delayedErrorLoggers.[i] let directoryName = Path.GetDirectoryName filename - let input = parseInputFileAux(tcConfig, lexResourceManager, conditionalCompilationDefines, filename, (isLastCompiland, isExe), delayedErrorLogger, retryLocked) + let input = parseInputFileAux(tcConfig, lexResourceManager, filename, (isLastCompiland, isExe), delayedErrorLogger, retryLocked) (input, directoryName) ) finally @@ -535,7 +538,7 @@ let ParseInputFiles (tcConfig: TcConfig, lexResourceManager, conditionalCompilat sourceFiles |> Array.map (fun (filename, isLastCompiland) -> let directoryName = Path.GetDirectoryName filename - let input = ParseOneInputFile(tcConfig, lexResourceManager, conditionalCompilationDefines, filename, (isLastCompiland, isExe), errorLogger, retryLocked) + let input = ParseOneInputFile(tcConfig, lexResourceManager, filename, (isLastCompiland, isExe), errorLogger, retryLocked) (input, directoryName)) |> List.ofArray @@ -832,15 +835,17 @@ let GetInitialTcState(m, ccuName, tcConfig: TcConfig, tcGlobals, tcImports: TcIm } /// Typecheck a single file (or interactive entry into F# Interactive) -let TypeCheckOneInput(checkForErrors, - tcConfig: TcConfig, - tcImports: TcImports, - tcGlobals, - prefixPathOpt, - tcSink, - tcState: TcState, - inp: ParsedInput, - skipImplIfSigExists: bool) = +let CheckOneInput( + checkForErrors, + tcConfig: TcConfig, + tcImports: TcImports, + tcGlobals, + prefixPathOpt, + tcSink, + tcState: TcState, + inp: ParsedInput, + skipImplIfSigExists: bool + ) = cancellable { try @@ -860,11 +865,11 @@ let TypeCheckOneInput(checkForErrors, errorR(Error(FSComp.SR.buildImplementationAlreadyGivenDetail(qualNameOfFile.Text), m)) let conditionalDefines = - if tcConfig.noConditionalErasure then None else Some tcConfig.conditionalCompilationDefines + if tcConfig.noConditionalErasure then None else Some tcConfig.conditionalDefines // Typecheck the signature file let! tcEnv, sigFileType, createsGeneratedProvidedTypes = - TypeCheckOneSigFile (tcGlobals, tcState.tcsNiceNameGen, amap, tcState.tcsCcu, checkForErrors, conditionalDefines, tcSink, tcConfig.internalTestSpanStackReferring) tcState.tcsTcSigEnv file + CheckOneSigFile (tcGlobals, tcState.tcsNiceNameGen, amap, tcState.tcsCcu, checkForErrors, conditionalDefines, tcSink, tcConfig.internalTestSpanStackReferring) tcState.tcsTcSigEnv file let rootSigs = Zmap.add qualNameOfFile sigFileType tcState.tcsRootSigs @@ -900,7 +905,7 @@ let TypeCheckOneInput(checkForErrors, let tcImplEnv = tcState.tcsTcImplEnv let conditionalDefines = - if tcConfig.noConditionalErasure then None else Some tcConfig.conditionalCompilationDefines + if tcConfig.noConditionalErasure then None else Some tcConfig.conditionalDefines let hadSig = rootSigOpt.IsSome @@ -913,7 +918,7 @@ let TypeCheckOneInput(checkForErrors, (EmptyTopAttrs, dummyImplFile, Unchecked.defaultof<_>, tcImplEnv, false) |> Cancellable.ret else - TypeCheckOneImplFile (tcGlobals, tcState.tcsNiceNameGen, amap, tcState.tcsCcu, tcState.tcsImplicitOpenDeclarations, checkForErrors, conditionalDefines, tcSink, tcConfig.internalTestSpanStackReferring, tcImplEnv, rootSigOpt, file) + CheckOneImplFile (tcGlobals, tcState.tcsNiceNameGen, amap, tcState.tcsCcu, tcState.tcsImplicitOpenDeclarations, checkForErrors, conditionalDefines, tcSink, tcConfig.internalTestSpanStackReferring, tcImplEnv, rootSigOpt, file) let! topAttrs, implFile, _implFileHiddenType, tcEnvAtEnd, createsGeneratedProvidedTypes = typeCheckOne @@ -969,11 +974,11 @@ let TypeCheckOneInputEntry (ctok, checkForErrors, tcConfig:TcConfig, tcImports, use unwindBP = PushThreadBuildPhaseUntilUnwind BuildPhase.TypeCheck RequireCompilationThread ctok - TypeCheckOneInput (checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt, TcResultsSink.NoSink, tcState, inp, false) + CheckOneInput (checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt, TcResultsSink.NoSink, tcState, inp, false) |> Cancellable.runWithoutCancellation /// Finish checking multiple files (or one interactive entry into F# Interactive) -let TypeCheckMultipleInputsFinish(results, tcState: TcState) = +let CheckMultipleInputsFinish(results, tcState: TcState) = let tcEnvsAtEndFile, topAttrs, implFiles, ccuSigsForFiles = List.unzip4 results let topAttrs = List.foldBack CombineTopAttrs topAttrs EmptyTopAttrs let implFiles = List.choose id implFiles @@ -981,16 +986,16 @@ let TypeCheckMultipleInputsFinish(results, tcState: TcState) = let tcEnvAtEndOfLastFile = (match tcEnvsAtEndFile with h :: _ -> h | _ -> tcState.TcEnvFromSignatures) (tcEnvAtEndOfLastFile, topAttrs, implFiles, ccuSigsForFiles), tcState -let TypeCheckOneInputAndFinish(checkForErrors, tcConfig: TcConfig, tcImports, tcGlobals, prefixPathOpt, tcSink, tcState, input) = +let CheckOneInputAndFinish(checkForErrors, tcConfig: TcConfig, tcImports, tcGlobals, prefixPathOpt, tcSink, tcState, input) = cancellable { Logger.LogBlockStart LogCompilerFunctionId.CompileOps_TypeCheckOneInputAndFinishEventually - let! results, tcState = TypeCheckOneInput(checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt, tcSink, tcState, input, false) - let result = TypeCheckMultipleInputsFinish([results], tcState) + let! results, tcState = CheckOneInput(checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt, tcSink, tcState, input, false) + let result = CheckMultipleInputsFinish([results], tcState) Logger.LogBlockStop LogCompilerFunctionId.CompileOps_TypeCheckOneInputAndFinishEventually return result } -let TypeCheckClosedInputSetFinish (declaredImpls: TypedImplFile list, tcState) = +let CheckClosedInputSetFinish (declaredImpls: TypedImplFile list, tcState) = // Latest contents to the CCU let ccuContents = Construct.NewCcuContents ILScopeRef.Local range0 tcState.tcsCcu.AssemblyName tcState.tcsCcuSig @@ -1001,10 +1006,10 @@ let TypeCheckClosedInputSetFinish (declaredImpls: TypedImplFile list, tcState) = tcState, declaredImpls, ccuContents -let TypeCheckClosedInputSet (ctok, checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt, tcState, inputs) = +let CheckClosedInputSet (ctok, checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt, tcState, inputs) = // tcEnvAtEndOfLastFile is the environment required by fsi.exe when incrementally adding definitions let results, tcState = (tcState, inputs) ||> List.mapFold (TypeCheckOneInputEntry (ctok, checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt)) - let (tcEnvAtEndOfLastFile, topAttrs, implFiles, _), tcState = TypeCheckMultipleInputsFinish(results, tcState) - let tcState, declaredImpls, ccuContents = TypeCheckClosedInputSetFinish (implFiles, tcState) + let (tcEnvAtEndOfLastFile, topAttrs, implFiles, _), tcState = CheckMultipleInputsFinish(results, tcState) + let tcState, declaredImpls, ccuContents = CheckClosedInputSetFinish (implFiles, tcState) tcState.Ccu.Deref.Contents <- ccuContents tcState, topAttrs, declaredImpls, tcEnvAtEndOfLastFile diff --git a/src/fsharp/ParseAndCheckInputs.fsi b/src/fsharp/ParseAndCheckInputs.fsi index ac6f992f3f7..2ba62e2b4f1 100644 --- a/src/fsharp/ParseAndCheckInputs.fsi +++ b/src/fsharp/ParseAndCheckInputs.fsi @@ -32,7 +32,15 @@ type ModuleNamesDict = Map> val DeduplicateParsedInputModuleName: ModuleNamesDict -> ParsedInput -> ParsedInput * ModuleNamesDict /// Parse a single input (A signature file or implementation file) -val ParseInput: (Lexbuf -> Parser.token) * FSharpDiagnosticOptions * ErrorLogger * Lexbuf * string option * string * isLastCompiland:(bool * bool) -> ParsedInput +val ParseInput: + lexer: (Lexbuf -> Parser.token) * + diagnosticOptions: FSharpDiagnosticOptions * + errorLogger: ErrorLogger * + lexbuf: Lexbuf * + defaultNamespace: string option * + filename: string * + isLastCompiland:(bool * bool) + -> ParsedInput /// A general routine to process hash directives val ProcessMetaCommandsFromInput : @@ -48,17 +56,65 @@ val ApplyMetaCommandsFromInputToTcConfig: TcConfig * ParsedInput * string * Depe /// Process the #nowarn in an input and integrate them into the TcConfig val ApplyNoWarnsToTcConfig: TcConfig * ParsedInput * string -> TcConfig +val GetScopedPragmasForInput: + input: ParsedInput + -> ScopedPragma list + /// Parse one input stream -val ParseOneInputStream: TcConfig * Lexhelp.LexResourceManager * conditionalCompilationDefines: string list * string * isLastCompiland: (bool * bool) * ErrorLogger * retryLocked: bool * stream: Stream -> ParsedInput +val ParseOneInputStream: + tcConfig: TcConfig * + lexResourceManager: Lexhelp.LexResourceManager * + filename: string * + isLastCompiland: (bool * bool) * + errorLogger: ErrorLogger * + retryLocked: bool * + stream: Stream + -> ParsedInput /// Parse one input source text -val ParseOneInputSourceText: TcConfig * Lexhelp.LexResourceManager * conditionalCompilationDefines: string list * string * isLastCompiland: (bool * bool) * ErrorLogger * sourceText: ISourceText -> ParsedInput +val ParseOneInputSourceText: + tcConfig: TcConfig * + lexResourceManager: Lexhelp.LexResourceManager * + filename: string * + isLastCompiland: (bool * bool) * + errorLogger: ErrorLogger * + sourceText: ISourceText + -> ParsedInput /// Parse one input file -val ParseOneInputFile: TcConfig * Lexhelp.LexResourceManager * conditionalCompilationDefines: string list * string * isLastCompiland: (bool * bool) * ErrorLogger * retryLocked: bool -> ParsedInput +val ParseOneInputFile: + tcConfig: TcConfig * + lexResourceManager: Lexhelp.LexResourceManager * + filename: string * + isLastCompiland: (bool * bool) * + errorLogger: ErrorLogger * + retryLocked: bool + -> ParsedInput + +val ParseOneInputLexbuf: + tcConfig: TcConfig * + lexResourceManager: Lexhelp.LexResourceManager * + lexbuf: Lexbuf * + filename: string * + isLastCompiland: (bool * bool) * + errorLogger: ErrorLogger + -> ParsedInput + +val EmptyParsedInput: + filename: string * + isLastCompiland: (bool * bool) + -> ParsedInput /// Parse multiple input files from disk -val ParseInputFiles: TcConfig * Lexhelp.LexResourceManager * conditionalCompilationDefines: string list * string list * ErrorLogger * Exiter * createErrorLogger: (Exiter -> CapturingErrorLogger) * retryLocked: bool -> (ParsedInput * string) list +val ParseInputFiles: + tcConfig: TcConfig * + lexResourceManager: Lexhelp.LexResourceManager * + sourceFiles: string list * + errorLogger: ErrorLogger * + exiter: Exiter * + createErrorLogger: (Exiter -> CapturingErrorLogger) * + retryLocked: bool + -> (ParsedInput * string) list /// Get the initial type checking environment including the loading of mscorlib/System.Core, FSharp.Core /// applying the InternalsVisibleTo in referenced assemblies and opening 'Checked' if requested. @@ -99,8 +155,8 @@ val GetInitialTcState: -> TcState /// Check one input, returned as an Eventually computation -val TypeCheckOneInput: - checkForErrors:(unit -> bool) * +val CheckOneInput: + checkForErrors: (unit -> bool) * TcConfig * TcImports * TcGlobals * @@ -109,19 +165,22 @@ val TypeCheckOneInput: TcState * ParsedInput * skipImplIfSigExists: bool - -> Cancellable<(TcEnv * TopAttribs * TypedImplFile option * ModuleOrNamespaceType) * TcState> + -> Cancellable<(TcEnv * TopAttribs * TypedImplFile option * ModuleOrNamespaceType) * TcState> /// Finish the checking of multiple inputs -val TypeCheckMultipleInputsFinish: (TcEnv * TopAttribs * 'T option * 'U) list * TcState -> (TcEnv * TopAttribs * 'T list * 'U list) * TcState +val CheckMultipleInputsFinish: + (TcEnv * TopAttribs * 'T option * 'U) list * + TcState + -> (TcEnv * TopAttribs * 'T list * 'U list) * TcState /// Finish the checking of a closed set of inputs -val TypeCheckClosedInputSetFinish: +val CheckClosedInputSetFinish: TypedImplFile list * TcState - -> TcState * TypedImplFile list * ModuleOrNamespace + -> TcState * TypedImplFile list * ModuleOrNamespace /// Check a closed set of inputs -val TypeCheckClosedInputSet: +val CheckClosedInputSet: CompilationThreadToken * checkForErrors: (unit -> bool) * TcConfig * @@ -130,10 +189,10 @@ val TypeCheckClosedInputSet: LongIdent option * TcState * ParsedInput list - -> TcState * TopAttribs * TypedImplFile list * TcEnv + -> TcState * TopAttribs * TypedImplFile list * TcEnv /// Check a single input and finish the checking -val TypeCheckOneInputAndFinish : +val CheckOneInputAndFinish : checkForErrors: (unit -> bool) * TcConfig * TcImports * @@ -142,21 +201,4 @@ val TypeCheckOneInputAndFinish : NameResolution.TcResultsSink * TcState * ParsedInput - -> Cancellable<(TcEnv * TopAttribs * TypedImplFile list * ModuleOrNamespaceType list) * TcState> - -val GetScopedPragmasForInput: input: ParsedInput -> ScopedPragma list - -val ParseOneInputLexbuf: - tcConfig: TcConfig * - lexResourceManager: Lexhelp.LexResourceManager * - conditionalCompilationDefines: string list * - lexbuf: Lexbuf * - filename: string * - isLastCompiland: (bool * bool) * - errorLogger: ErrorLogger - -> ParsedInput - -val EmptyParsedInput: - filename: string * - isLastCompiland: (bool * bool) - -> ParsedInput + -> Cancellable<(TcEnv * TopAttribs * TypedImplFile list * ModuleOrNamespaceType list) * TcState> diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index ea66b9a60e0..a2c585ee659 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -181,7 +181,7 @@ let TypeCheck (ctok, tcConfig, tcImports, tcGlobals, errorLogger: ErrorLogger, a if isNil inputs then error(Error(FSComp.SR.fscNoImplementationFiles(), rangeStartup)) let ccuName = assemblyName let tcInitialState = GetInitialTcState (rangeStartup, ccuName, tcConfig, tcGlobals, tcImports, niceNameGen, tcEnv0, openDecls0) - TypeCheckClosedInputSet (ctok, (fun () -> errorLogger.ErrorCount > 0), tcConfig, tcImports, tcGlobals, None, tcInitialState, inputs) + CheckClosedInputSet (ctok, (fun () -> errorLogger.ErrorCount > 0), tcConfig, tcImports, tcGlobals, None, tcInitialState, inputs) with e -> errorRecovery e rangeStartup exiter.Exit 1 @@ -474,7 +474,7 @@ let main1(ctok, argv, legacyReferenceResolver, bannerAlreadyPrinted, delayForFlagsLogger.ForwardDelayedDiagnostics tcConfigB exiter.Exit 1 - tcConfigB.conditionalCompilationDefines <- "COMPILED" :: tcConfigB.conditionalCompilationDefines + tcConfigB.conditionalDefines <- "COMPILED" :: tcConfigB.conditionalDefines // Display the banner text, if necessary if not bannerAlreadyPrinted then @@ -533,7 +533,8 @@ let main1(ctok, argv, legacyReferenceResolver, bannerAlreadyPrinted, use unwindParsePhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse let createErrorLogger = (fun exiter -> errorLoggerProvider.CreateDelayAndForwardLogger(exiter) :> CapturingErrorLogger) - let inputs = ParseInputFiles(tcConfig, lexResourceManager, ["COMPILED"], sourceFiles, errorLogger, exiter, createErrorLogger, (*retryLocked*)false) + + let inputs = ParseInputFiles(tcConfig, lexResourceManager, sourceFiles, errorLogger, exiter, createErrorLogger, (*retryLocked*)false) let inputs, _ = (Map.empty, inputs) ||> List.mapFold (fun state (input, x) -> @@ -646,7 +647,7 @@ let main1OfAst let delayForFlagsLogger = errorLoggerProvider.CreateDelayAndForwardLogger exiter let _unwindEL_1 = PushErrorLoggerPhaseUntilUnwind (fun _ -> delayForFlagsLogger) - tcConfigB.conditionalCompilationDefines <- "COMPILED" :: tcConfigB.conditionalCompilationDefines + tcConfigB.conditionalDefines <- "COMPILED" :: tcConfigB.conditionalDefines // append assembly dependencies dllReferences |> List.iter (fun ref -> tcConfigB.AddReferencedAssemblyByPath(rangeStartup,ref)) diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index c483a7f14f6..cda3868081c 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -1626,7 +1626,7 @@ type internal FsiDynamicCompiler // Typecheck. The lock stops the type checker running at the same time as the // server intellisense implementation (which is currently incomplete and #if disabled) let tcState, topCustomAttrs, declaredImpls, tcEnvAtEndOfLastInput = - lock tcLockObject (fun _ -> TypeCheckClosedInputSet(ctok, errorLogger.CheckForErrors, tcConfig, tcImports, tcGlobals, Some prefixPath, tcState, inputs)) + lock tcLockObject (fun _ -> CheckClosedInputSet(ctok, errorLogger.CheckForErrors, tcConfig, tcImports, tcGlobals, Some prefixPath, tcState, inputs)) let codegenResults, optEnv, fragName = ProcessTypedImpl(errorLogger, optEnv, tcState, tcConfig, isInteractiveItExpr, topCustomAttrs, prefixPath, isIncrementalFragment, declaredImpls, ilxGenerator) @@ -1988,7 +1988,7 @@ type internal FsiDynamicCompiler input.MetaCommandDiagnostics |> List.iter diagnosticSink let parsedInput = match input.SyntaxTree with - | None -> ParseOneInputFile(tcConfig,lexResourceManager,["INTERACTIVE"],input.FileName,(true,false),errorLogger,(*retryLocked*)false) + | None -> ParseOneInputFile(tcConfig, lexResourceManager, input.FileName, (true, false), errorLogger, (*retryLocked*)false) | Some parseTree -> parseTree input.FileName, parsedInput) |> List.unzip @@ -2393,12 +2393,13 @@ module internal MagicAssemblyResolution = // Reading stdin //---------------------------------------------------------------------------- -type internal FsiStdinLexerProvider - (tcConfigB, fsiStdinSyphon, - fsiConsoleInput : FsiConsoleInput, - fsiConsoleOutput : FsiConsoleOutput, - fsiOptions : FsiCommandLineOptions, - lexResourceManager : LexResourceManager) = +type FsiStdinLexerProvider ( + tcConfigB, fsiStdinSyphon, + fsiConsoleInput: FsiConsoleInput, + fsiConsoleOutput: FsiConsoleOutput, + fsiOptions: FsiCommandLineOptions, + lexResourceManager: LexResourceManager + ) = // #light is the default for FSI let interactiveInputLightSyntaxStatus = @@ -2439,7 +2440,7 @@ type internal FsiStdinLexerProvider resetLexbufPos sourceFileName lexbuf let skip = true // don't report whitespace from lexer - let defines = "INTERACTIVE"::tcConfigB.conditionalCompilationDefines + let defines = tcConfigB.conditionalDefines let lexargs = mkLexargs (defines, interactiveInputLightSyntaxStatus, lexResourceManager, [], errorLogger, PathMap.empty) let tokenizer = LexFilter.LexFilter(interactiveInputLightSyntaxStatus, tcConfigB.compilingFslib, Lexer.token lexargs skip, lexbuf) tokenizer @@ -2479,17 +2480,18 @@ type internal FsiStdinLexerProvider // It might be simpler if it ran on the parser thread. //---------------------------------------------------------------------------- -type internal FsiInteractionProcessor - (fsi: FsiEvaluationSessionHostConfig, - tcConfigB, - fsiOptions: FsiCommandLineOptions, - fsiDynamicCompiler: FsiDynamicCompiler, - fsiConsolePrompt : FsiConsolePrompt, - fsiConsoleOutput : FsiConsoleOutput, - fsiInterruptController : FsiInterruptController, - fsiStdinLexerProvider : FsiStdinLexerProvider, - lexResourceManager : LexResourceManager, - initialInteractiveState) = +type FsiInteractionProcessor ( + fsi: FsiEvaluationSessionHostConfig, + tcConfigB, + fsiOptions: FsiCommandLineOptions, + fsiDynamicCompiler: FsiDynamicCompiler, + fsiConsolePrompt : FsiConsolePrompt, + fsiConsoleOutput : FsiConsoleOutput, + fsiInterruptController : FsiInterruptController, + fsiStdinLexerProvider : FsiStdinLexerProvider, + lexResourceManager : LexResourceManager, + initialInteractiveState + ) = let referencedAssemblies = Dictionary() @@ -3187,6 +3189,7 @@ type FsiEvaluationSession (fsi: FsiEvaluationSessionHostConfig, argv:string[], i let tcConfigP = TcConfigProvider.BasedOnMutableBuilder(tcConfigB) do tcConfigB.resolutionEnvironment <- LegacyResolutionEnvironment.CompilationAndEvaluation // See Bug 3608 do tcConfigB.useFsiAuxLib <- fsi.UseFsiAuxLib + do tcConfigB.conditionalDefines <- "INTERACTIVE" :: tcConfigB.conditionalDefines #if NETSTANDARD do tcConfigB.SetUseSdkRefs true diff --git a/src/fsharp/lex.fsl b/src/fsharp/lex.fsl index ef21d16b45e..af11cf489c1 100644 --- a/src/fsharp/lex.fsl +++ b/src/fsharp/lex.fsl @@ -707,51 +707,59 @@ rule token args skip = parse | ('#' anywhite* | "#line" anywhite+ ) digit+ anywhite* ('@'? "\"" [^'\n''\r''"']+ '"')? anywhite* newline { let pos = lexbuf.EndPos if skip then - let s = lexeme lexbuf - let rec parseLeadingDirective n = - match s.[n] with - | c when c >= 'a' && c <= 'z' -> parseLeadingDirective (n+1) - | _ -> parseLeadingWhitespace n // goto the next state - - and parseLeadingWhitespace n = - match s.[n] with - | ' ' | '\t' -> parseLeadingWhitespace (n+1) - | _ -> parseLineNumber n n // goto the next state - - and parseLineNumber start n = - match s.[n] with - | c when c >= '0' && c <= '9' -> parseLineNumber start (n+1) - | _ -> let text = (String.sub s start (n-start)) - let lineNumber = - try int32 text - with err -> errorR(Error(FSComp.SR.lexInvalidLineNumber(text), lexbuf.LexemeRange)); 0 - lineNumber, parseWhitespaceBeforeFile n // goto the next state - - and parseWhitespaceBeforeFile n = - match s.[n] with - | ' ' | '\t' | '@' -> parseWhitespaceBeforeFile (n+1) - | '"' -> Some (parseFile (n+1) (n+1)) - | _ -> None - - and parseFile start n = - match s.[n] with - | '"' -> String.sub s start (n-start) - | _ -> parseFile start (n+1) - - // Call the parser - let line,file = parseLeadingDirective 1 - - // Construct the new position - if args.applyLineDirectives then - lexbuf.EndPos <- pos.ApplyLineDirective((match file with Some f -> FileIndex.fileIndexOfFile f | None -> pos.FileIndex), line) - else - // add a newline when we don't apply a directive since we consumed a newline getting here - newline lexbuf - token args skip lexbuf + let s = lexeme lexbuf + let rec parseLeadingDirective n = + match s.[n] with + | c when c >= 'a' && c <= 'z' -> parseLeadingDirective (n+1) + | _ -> parseLeadingWhitespace n // goto the next state + + and parseLeadingWhitespace n = + match s.[n] with + | ' ' | '\t' -> parseLeadingWhitespace (n+1) + | _ -> parseLineNumber n n // goto the next state + + and parseLineNumber start n = + match s.[n] with + | c when c >= '0' && c <= '9' -> parseLineNumber start (n+1) + | _ -> + let text = String.sub s start (n-start) + + let lineNumber = + try + int32 text + with err -> + errorR(Error(FSComp.SR.lexInvalidLineNumber(text), lexbuf.LexemeRange)) + 0 + + lineNumber, parseWhitespaceBeforeFile n // goto the next state + + and parseWhitespaceBeforeFile n = + match s.[n] with + | ' ' | '\t' | '@' -> parseWhitespaceBeforeFile (n+1) + | '"' -> Some (parseFile (n+1) (n+1)) + | _ -> None + + and parseFile start n = + match s.[n] with + | '"' -> String.sub s start (n-start) + | _ -> parseFile start (n+1) + + // Call the parser + let line, file = parseLeadingDirective 1 + + // Construct the new position + if args.applyLineDirectives then + lexbuf.EndPos <- pos.ApplyLineDirective((match file with Some f -> FileIndex.fileIndexOfFile f | None -> pos.FileIndex), line) + else + // add a newline when we don't apply a directive since we consumed a newline getting here + newline lexbuf + + token args skip lexbuf else - // add a newline when we don't apply a directive since we consumed a newline getting here - newline lexbuf - HASH_LINE (LexCont.Token (args.ifdefStack, args.stringNest)) } + // add a newline when we don't apply a directive since we consumed a newline getting here + newline lexbuf + HASH_LINE (LexCont.Token (args.ifdefStack, args.stringNest)) + } | "<@" { checkExprOp lexbuf; LQUOTE ("<@ @>", false) } diff --git a/src/fsharp/lexhelp.fs b/src/fsharp/lexhelp.fs index a23280166ea..e8bfff78a1e 100644 --- a/src/fsharp/lexhelp.fs +++ b/src/fsharp/lexhelp.fs @@ -70,13 +70,13 @@ type LongUnicodeLexResult = let mkLexargs (defines, lightStatus, resourceManager, ifdefStack, errorLogger, pathMap:PathMap) = { defines = defines - ifdefStack= ifdefStack - lightStatus=lightStatus - resourceManager=resourceManager - errorLogger=errorLogger - applyLineDirectives=true + ifdefStack = ifdefStack + lightStatus = lightStatus + resourceManager = resourceManager + errorLogger = errorLogger + applyLineDirectives = true stringNest = [] - pathMap=pathMap + pathMap = pathMap } /// Register the lexbuf and call the given function diff --git a/src/fsharp/lexhelp.fsi b/src/fsharp/lexhelp.fsi index 9f6981610b8..9f2cf62d12d 100644 --- a/src/fsharp/lexhelp.fsi +++ b/src/fsharp/lexhelp.fsi @@ -37,7 +37,7 @@ type LexArgs = applyLineDirectives: bool pathMap: PathMap mutable ifdefStack: LexerIfdefStack - mutable lightStatus : LightSyntaxStatus + mutable lightStatus: LightSyntaxStatus mutable stringNest: LexerInterpolatedStringNesting } diff --git a/src/fsharp/service/FSharpCheckerResults.fs b/src/fsharp/service/FSharpCheckerResults.fs index 9cbc7d48393..c4743c505f0 100644 --- a/src/fsharp/service/FSharpCheckerResults.fs +++ b/src/fsharp/service/FSharpCheckerResults.fs @@ -150,12 +150,12 @@ and FSharpProjectOptions = SourceFiles: string[] OtherOptions: string[] ReferencedProjects: FSharpReferencedProject[] - IsIncompleteTypeCheckEnvironment : bool - UseScriptResolutionRules : bool - LoadTime : DateTime - UnresolvedReferences : FSharpUnresolvedReferencesSet option + IsIncompleteTypeCheckEnvironment: bool + UseScriptResolutionRules: bool + LoadTime: DateTime + UnresolvedReferences: FSharpUnresolvedReferencesSet option OriginalLoadReferences: (range * string * string) list - Stamp : int64 option + Stamp: int64 option } static member UseSameProject(options1,options2) = @@ -1548,7 +1548,7 @@ type internal TypeCheckInfo type FSharpParsingOptions = { SourceFiles: string [] - ConditionalCompilationDefines: string list + ConditionalDefines: string list ErrorSeverityOptions: FSharpDiagnosticOptions LangVersionText: string IsInteractive: bool @@ -1562,7 +1562,7 @@ type FSharpParsingOptions = static member Default = { SourceFiles = Array.empty - ConditionalCompilationDefines = [] + ConditionalDefines = [] ErrorSeverityOptions = FSharpDiagnosticOptions.Default LangVersionText = LanguageVersion.Default.VersionText IsInteractive = false @@ -1572,7 +1572,7 @@ type FSharpParsingOptions = static member FromTcConfig(tcConfig: TcConfig, sourceFiles, isInteractive: bool) = { SourceFiles = sourceFiles - ConditionalCompilationDefines = tcConfig.conditionalCompilationDefines + ConditionalDefines = tcConfig.conditionalDefines ErrorSeverityOptions = tcConfig.errorSeverityOptions LangVersionText = tcConfig.langVersion.VersionText IsInteractive = isInteractive @@ -1583,7 +1583,7 @@ type FSharpParsingOptions = static member FromTcConfigBuilder(tcConfigB: TcConfigBuilder, sourceFiles, isInteractive: bool) = { SourceFiles = sourceFiles - ConditionalCompilationDefines = tcConfigB.conditionalCompilationDefines + ConditionalDefines = tcConfigB.conditionalDefines ErrorSeverityOptions = tcConfigB.errorSeverityOptions LangVersionText = tcConfigB.langVersion.VersionText IsInteractive = isInteractive @@ -1653,7 +1653,7 @@ module internal ParseAndCheckFile = // If we're editing a script then we define INTERACTIVE otherwise COMPILED. // Since this parsing for intellisense we always define EDITING. - let defines = (SourceFileImpl.AdditionalDefinesForUseInEditor options.IsInteractive) @ options.ConditionalCompilationDefines + let defines = (SourceFileImpl.GetImplicitConditionalDefinesForEditing options.IsInteractive) @ options.ConditionalDefines // Note: we don't really attempt to intern strings across a large scope. let lexResourceManager = LexResourceManager() @@ -1666,7 +1666,6 @@ module internal ParseAndCheckFile = let tokenizer = LexFilter.LexFilter(lightStatus, options.CompilingFsLib, Lexer.token lexargs true, lexbuf) (fun _ -> tokenizer.GetToken()) - let createLexbuf langVersion sourceText = UnicodeLexing.SourceTextAsLexbuf(true, LanguageVersion(langVersion), sourceText) @@ -1909,7 +1908,7 @@ module internal ParseAndCheckFile = use _unwind = new CompilationGlobalsScope (errHandler.ErrorLogger, BuildPhase.TypeCheck) let! result = - TypeCheckOneInputAndFinish(checkForErrors, tcConfig, tcImports, tcGlobals, None, TcResultsSink.WithSink sink, tcState, parsedMainInput) + CheckOneInputAndFinish(checkForErrors, tcConfig, tcImports, tcGlobals, None, TcResultsSink.WithSink sink, tcState, parsedMainInput) return result with e -> diff --git a/src/fsharp/service/FSharpCheckerResults.fsi b/src/fsharp/service/FSharpCheckerResults.fsi index 589df9226a0..5e3ec0fea69 100644 --- a/src/fsharp/service/FSharpCheckerResults.fsi +++ b/src/fsharp/service/FSharpCheckerResults.fsi @@ -193,7 +193,7 @@ type public FSharpProjectContext = type public FSharpParsingOptions = { SourceFiles: string[] - ConditionalCompilationDefines: string list + ConditionalDefines: string list ErrorSeverityOptions: FSharpDiagnosticOptions LangVersionText: string IsInteractive: bool diff --git a/src/fsharp/service/FSharpParseFileResults.fs b/src/fsharp/service/FSharpParseFileResults.fs index b559f3a2ca5..9c7e6695efb 100644 --- a/src/fsharp/service/FSharpParseFileResults.fs +++ b/src/fsharp/service/FSharpParseFileResults.fs @@ -21,7 +21,7 @@ module SourceFileImpl = 0 = String.Compare(".fsi", ext, StringComparison.OrdinalIgnoreCase) /// Additional #defines that should be in place when editing a file in a file editor such as VS. - let AdditionalDefinesForUseInEditor(isInteractive: bool) = + let GetImplicitConditionalDefinesForEditing(isInteractive: bool) = if isInteractive then ["INTERACTIVE";"EDITING"] // This is still used by the foreground parse else ["COMPILED";"EDITING"] diff --git a/src/fsharp/service/IncrementalBuild.fs b/src/fsharp/service/IncrementalBuild.fs index 6726c2f6b0a..f3edbc20920 100644 --- a/src/fsharp/service/IncrementalBuild.fs +++ b/src/fsharp/service/IncrementalBuild.fs @@ -96,7 +96,14 @@ module IncrementalBuildSyntaxTree = /// Information needed to lazily parse a file to get a ParsedInput. Internally uses a weak cache. [] - type SyntaxTree (tcConfig: TcConfig, fileParsed: Event, lexResourceManager, sourceRange: range, source: FSharpSource, isLastCompiland) = + type SyntaxTree ( + tcConfig: TcConfig, + fileParsed: Event, + lexResourceManager, + sourceRange: range, + source: FSharpSource, + isLastCompiland + ) = let filename = source.FilePath let mutable weakCache: WeakReference<_> option = None @@ -128,11 +135,11 @@ module IncrementalBuildSyntaxTree = use text = source.GetTextContainer() match text with | TextContainer.Stream(stream) -> - ParseOneInputStream(tcConfig, lexResourceManager, [], filename, isLastCompiland, errorLogger, (*retryLocked*)false, stream) + ParseOneInputStream(tcConfig, lexResourceManager, filename, isLastCompiland, errorLogger, (*retryLocked*)false, stream) | TextContainer.SourceText(sourceText) -> - ParseOneInputSourceText(tcConfig, lexResourceManager, [], filename, isLastCompiland, errorLogger, sourceText) + ParseOneInputSourceText(tcConfig, lexResourceManager, filename, isLastCompiland, errorLogger, sourceText) | TextContainer.OnDisk -> - ParseOneInputFile(tcConfig, lexResourceManager, [], filename, isLastCompiland, errorLogger, (*retryLocked*)true) + ParseOneInputFile(tcConfig, lexResourceManager, filename, isLastCompiland, errorLogger, (*retryLocked*)true) fileParsed.Trigger filename @@ -479,7 +486,7 @@ type BoundModel private (tcConfig: TcConfig, Logger.LogBlockMessageStart filename LogCompilerFunctionId.IncrementalBuild_TypeCheck let! (tcEnvAtEndOfFile, topAttribs, implFile, ccuSigForFile), tcState = - TypeCheckOneInput + CheckOneInput ((fun () -> hadParseErrors || errorLogger.ErrorCount > 0), tcConfig, tcImports, tcGlobals, @@ -863,11 +870,11 @@ module IncrementalBuilderHelpers = // Finish the checking let (_tcEnvAtEndOfLastFile, topAttrs, mimpls, _), tcState = - TypeCheckMultipleInputsFinish (results, finalInfo.tcState) + CheckMultipleInputsFinish (results, finalInfo.tcState) let ilAssemRef, tcAssemblyDataOpt, tcAssemblyExprOpt = try - let tcState, tcAssemblyExpr, ccuContents = TypeCheckClosedInputSetFinish (mimpls, tcState) + let tcState, tcAssemblyExpr, ccuContents = CheckClosedInputSetFinish (mimpls, tcState) let generatedCcu = tcState.Ccu.CloneWithFinalizedContents(ccuContents) @@ -1370,20 +1377,25 @@ type IncrementalBuilder(initialState: IncrementalBuilderInitialState, state: Inc /// CreateIncrementalBuilder (for background type checking). Note that fsc.fs also /// creates an incremental builder used by the command line compiler. - static member TryCreateIncrementalBuilderForProjectOptions - (legacyReferenceResolver, defaultFSharpBinariesDir, - frameworkTcImportsCache: FrameworkImportsCache, - loadClosureOpt: LoadClosure option, - sourceFiles: string list, - commandLineArgs: string list, - projectReferences, projectDirectory, - useScriptResolutionRules, keepAssemblyContents, - keepAllBackgroundResolutions, - tryGetMetadataSnapshot, suggestNamesForErrors, - keepAllBackgroundSymbolUses, - enableBackgroundItemKeyStoreAndSemanticClassification, - enablePartialTypeChecking: bool, - dependencyProvider) = + static member TryCreateIncrementalBuilderForProjectOptions( + legacyReferenceResolver, + defaultFSharpBinariesDir, + frameworkTcImportsCache: FrameworkImportsCache, + loadClosureOpt: LoadClosure option, + sourceFiles: string list, + commandLineArgs: string list, + projectReferences, + projectDirectory, + useScriptResolutionRules, + keepAssemblyContents, + keepAllBackgroundResolutions, + tryGetMetadataSnapshot, + suggestNamesForErrors, + keepAllBackgroundSymbolUses, + enableBackgroundItemKeyStoreAndSemanticClassification, + enablePartialTypeChecking: bool, + dependencyProvider + ) = let useSimpleResolutionSwitch = "--simpleresolution" @@ -1438,9 +1450,9 @@ type IncrementalBuilder(initialState: IncrementalBuilderInitialState, state: Inc tcConfigB.resolutionEnvironment <- (LegacyResolutionEnvironment.EditingOrCompilation true) - tcConfigB.conditionalCompilationDefines <- + tcConfigB.conditionalDefines <- let define = if useScriptResolutionRules then "INTERACTIVE" else "COMPILED" - define :: tcConfigB.conditionalCompilationDefines + define :: tcConfigB.conditionalDefines tcConfigB.projectReferences <- projectReferences diff --git a/src/fsharp/service/IncrementalBuild.fsi b/src/fsharp/service/IncrementalBuild.fsi index 7896197ba95..7da546ac879 100755 --- a/src/fsharp/service/IncrementalBuild.fsi +++ b/src/fsharp/service/IncrementalBuild.fsi @@ -237,9 +237,9 @@ type internal IncrementalBuilder = /// Create the incremental builder static member TryCreateIncrementalBuilderForProjectOptions: - LegacyReferenceResolver * + legacyReferenceResolver: LegacyReferenceResolver * defaultFSharpBinariesDir: string * - FrameworkImportsCache * + frameworkTcImportsCache: FrameworkImportsCache * loadClosureOpt:LoadClosure option * sourceFiles:string list * commandLineArgs:string list * diff --git a/src/fsharp/service/ServiceLexing.fs b/src/fsharp/service/ServiceLexing.fs index a902c63c795..4537a2f9402 100644 --- a/src/fsharp/service/ServiceLexing.fs +++ b/src/fsharp/service/ServiceLexing.fs @@ -1511,7 +1511,7 @@ type FSharpToken = [] module FSharpLexerImpl = - let lexWithErrorLogger (text: ISourceText) conditionalCompilationDefines (flags: FSharpLexerFlags) reportLibraryOnlyFeatures langVersion errorLogger onToken pathMap (ct: CancellationToken) = + let lexWithErrorLogger (text: ISourceText) conditionalDefines (flags: FSharpLexerFlags) reportLibraryOnlyFeatures langVersion errorLogger onToken pathMap (ct: CancellationToken) = let canSkipTrivia = (flags &&& FSharpLexerFlags.SkipTrivia) = FSharpLexerFlags.SkipTrivia let isLightSyntaxOn = (flags &&& FSharpLexerFlags.LightSyntaxOn) = FSharpLexerFlags.LightSyntaxOn let isCompiling = (flags &&& FSharpLexerFlags.Compiling) = FSharpLexerFlags.Compiling @@ -1520,7 +1520,7 @@ module FSharpLexerImpl = let lexbuf = UnicodeLexing.SourceTextAsLexbuf(reportLibraryOnlyFeatures, langVersion, text) let lightStatus = LightSyntaxStatus(isLightSyntaxOn, true) - let lexargs = mkLexargs (conditionalCompilationDefines, lightStatus, LexResourceManager(0), [], errorLogger, pathMap) + let lexargs = mkLexargs (conditionalDefines, lightStatus, LexResourceManager(0), [], errorLogger, pathMap) let lexargs = { lexargs with applyLineDirectives = isCompiling } let getNextToken = @@ -1540,18 +1540,18 @@ module FSharpLexerImpl = ct.ThrowIfCancellationRequested () onToken (getNextToken lexbuf) lexbuf.LexemeRange - let lex text conditionalCompilationDefines flags reportLibraryOnlyFeatures langVersion lexCallback pathMap ct = + let lex text conditionalDefines flags reportLibraryOnlyFeatures langVersion lexCallback pathMap ct = let errorLogger = CompilationErrorLogger("Lexer", FSharpDiagnosticOptions.Default) - lexWithErrorLogger text conditionalCompilationDefines flags reportLibraryOnlyFeatures langVersion errorLogger lexCallback pathMap ct + lexWithErrorLogger text conditionalDefines flags reportLibraryOnlyFeatures langVersion errorLogger lexCallback pathMap ct [] type FSharpLexer = - static member Tokenize(text: ISourceText, tokenCallback, ?langVersion, ?filePath: string, ?conditionalCompilationDefines, ?flags, ?pathMap, ?ct) = + static member Tokenize(text: ISourceText, tokenCallback, ?langVersion, ?filePath: string, ?conditionalDefines, ?flags, ?pathMap, ?ct) = let langVersion = defaultArg langVersion "latestmajor" |> LanguageVersion let flags = defaultArg flags FSharpLexerFlags.Default ignore filePath // can be removed at later point - let conditionalCompilationDefines = defaultArg conditionalCompilationDefines [] + let conditionalDefines = defaultArg conditionalDefines [] let pathMap = defaultArg pathMap Map.Empty let ct = defaultArg ct CancellationToken.None @@ -1566,4 +1566,4 @@ type FSharpLexer = | _ -> tokenCallback fsTok let reportLibraryOnlyFeatures = true - lex text conditionalCompilationDefines flags reportLibraryOnlyFeatures langVersion onToken pathMap ct + lex text conditionalDefines flags reportLibraryOnlyFeatures langVersion onToken pathMap ct diff --git a/src/fsharp/service/ServiceLexing.fsi b/src/fsharp/service/ServiceLexing.fsi index 49f1e6cc177..9637a6bb0dd 100755 --- a/src/fsharp/service/ServiceLexing.fsi +++ b/src/fsharp/service/ServiceLexing.fsi @@ -578,4 +578,4 @@ type public FSharpToken = type public FSharpLexer = [] - static member Tokenize: text: ISourceText * tokenCallback: (FSharpToken -> unit) * ?langVersion: string * ?filePath: string * ?conditionalCompilationDefines: string list * ?flags: FSharpLexerFlags * ?pathMap: Map * ?ct: CancellationToken -> unit + static member Tokenize: text: ISourceText * tokenCallback: (FSharpToken -> unit) * ?langVersion: string * ?filePath: string * ?conditionalDefines: string list * ?flags: FSharpLexerFlags * ?pathMap: Map * ?ct: CancellationToken -> unit diff --git a/src/fsharp/service/ServiceParsedInputOps.fs b/src/fsharp/service/ServiceParsedInputOps.fs index 1dc3c049dbe..2ec41f66f4c 100644 --- a/src/fsharp/service/ServiceParsedInputOps.fs +++ b/src/fsharp/service/ServiceParsedInputOps.fs @@ -21,7 +21,7 @@ module SourceFileImpl = 0 = String.Compare(".fsi", ext, StringComparison.OrdinalIgnoreCase) /// Additional #defines that should be in place when editing a file in a file editor such as VS. - let AdditionalDefinesForUseInEditor(isInteractive: bool) = + let GetImplicitConditionalDefinesForEditing(isInteractive: bool) = if isInteractive then ["INTERACTIVE";"EDITING"] // This is still used by the foreground parse else ["COMPILED";"EDITING"] diff --git a/src/fsharp/service/ServiceParsedInputOps.fsi b/src/fsharp/service/ServiceParsedInputOps.fsi index 2180b700416..0aa0bbcc590 100644 --- a/src/fsharp/service/ServiceParsedInputOps.fsi +++ b/src/fsharp/service/ServiceParsedInputOps.fsi @@ -154,5 +154,5 @@ module internal SourceFileImpl = val IsInterfaceFile: string -> bool - val AdditionalDefinesForUseInEditor: isInteractive: bool -> string list + val GetImplicitConditionalDefinesForEditing: isInteractive: bool -> string list diff --git a/src/fsharp/service/service.fs b/src/fsharp/service/service.fs index e009bc23c61..8a3eae0ad79 100644 --- a/src/fsharp/service/service.fs +++ b/src/fsharp/service/service.fs @@ -255,8 +255,6 @@ type BackgroundCompiler( // of this is that you need to build FSharp.Core to get intellisense in those projects. if (try Path.GetFileNameWithoutExtension(nm) with _ -> "") <> GetFSharpCoreLibraryName() then - - yield { new IProjectReference with member x.EvaluateRawContents() = node { @@ -268,7 +266,6 @@ type BackgroundCompiler( member x.FileName = nm } | FSharpReferencedProject.PEReference(nm,getStamp,delayedReader) -> - yield { new IProjectReference with member x.EvaluateRawContents() = node { @@ -287,7 +284,6 @@ type BackgroundCompiler( member x.FileName = nm } | FSharpReferencedProject.ILModuleReference(nm,getStamp,getReader) -> - yield { new IProjectReference with member x.EvaluateRawContents() = node { @@ -303,14 +299,24 @@ type BackgroundCompiler( let loadClosure = scriptClosureCache.TryGet(AnyCallerThread, options) 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, - (if options.UseScriptResolutionRules then Some dependencyProviderForScripts else None)) + 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, + (if options.UseScriptResolutionRules then Some dependencyProviderForScripts else None)) match builderOpt with | None -> () @@ -539,7 +545,7 @@ type BackgroundCompiler( return None } - member private bc.CheckOneFileImplAux + member private _.CheckOneFileImplAux (parseResults: FSharpParseFileResults, sourceText: ISourceText, fileName: string, @@ -556,26 +562,27 @@ type BackgroundCompiler( 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.TcErrors, - options.IsIncompleteTypeCheckEnvironment, - options, - builder, - Array.ofList tcInfo.tcDependencyFiles, - creationDiags, - parseResults.Diagnostics, - keepAssemblyContents, - suggestNamesForErrors) |> NodeCode.FromCancellable + FSharpCheckFileResults.CheckOneFile ( + parseResults, + sourceText, + fileName, + options.ProjectFileName, + tcConfig, + tcPrior.TcGlobals, + tcPrior.TcImports, + tcInfo.tcState, + tcInfo.moduleNamesDict, + loadClosure, + tcInfo.TcErrors, + 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.TimeStamp) } @@ -1082,7 +1089,7 @@ type FSharpChecker(legacyReferenceResolver, let argv = List.ofArray options.OtherOptions ic.GetParsingOptionsFromCommandLineArgs(sourceFiles, argv, options.UseScriptResolutionRules) - member ic.ParseFile(filename, sourceText, options, ?cache, ?userOpName: string) = + member _.ParseFile(filename, sourceText, options, ?cache, ?userOpName: string) = let cache = defaultArg cache true let userOpName = defaultArg userOpName "Unknown" backgroundCompiler.ParseFile(filename, sourceText, options, cache, userOpName) @@ -1295,11 +1302,11 @@ type FSharpChecker(legacyReferenceResolver, rangeForErrors=range0) // These defines are implied by the F# compiler - tcConfigB.conditionalCompilationDefines <- + tcConfigB.conditionalDefines <- let define = if isInteractive then "INTERACTIVE" else "COMPILED" - define :: tcConfigB.conditionalCompilationDefines + define :: tcConfigB.conditionalDefines if isEditing then - tcConfigB.conditionalCompilationDefines <- "EDITING":: tcConfigB.conditionalCompilationDefines + tcConfigB.conditionalDefines <- "EDITING":: tcConfigB.conditionalDefines // Apply command-line arguments and collect more source files if they are in the arguments let sourceFilesNew = ApplyCommandLineArgs(tcConfigB, sourceFiles, argv) @@ -1374,9 +1381,9 @@ type CompilerEnvironment() = references /// Publish compiler-flags parsing logic. Must be fast because its used by the colorizer. - static member GetCompilationDefinesForEditing (parsingOptions: FSharpParsingOptions) = - SourceFileImpl.AdditionalDefinesForUseInEditor(parsingOptions.IsInteractive) @ - parsingOptions.ConditionalCompilationDefines + static member GetConditionalDefinesForEditing (parsingOptions: FSharpParsingOptions) = + SourceFileImpl.GetImplicitConditionalDefinesForEditing(parsingOptions.IsInteractive) @ + parsingOptions.ConditionalDefines /// Return true if this is a subcategory of error or warning message that the language service can emit static member IsCheckerSupportedSubcategory(subcategory:string) = diff --git a/src/fsharp/service/service.fsi b/src/fsharp/service/service.fsi index c27fc86ca3f..8ce4dc09fc0 100644 --- a/src/fsharp/service/service.fsi +++ b/src/fsharp/service/service.fsi @@ -69,7 +69,13 @@ type public FSharpChecker = /// Parsing options for the project or script. /// Store the parse in a size-limited cache assocaited with the FSharpChecker. Default: true /// An optional string used for tracing compiler operations associated with this request. - member ParseFile: filename: string * sourceText: ISourceText * options: FSharpParsingOptions * ?cache: bool * ?userOpName: string -> Async + member ParseFile: + filename: string * + sourceText: ISourceText * + options: FSharpParsingOptions * + ?cache: bool * + ?userOpName: string + -> Async /// /// Parses a source code for a file. Returns an AST that can be traversed for various features. @@ -81,7 +87,13 @@ type public FSharpChecker = /// Store the parse in a size-limited cache assocaited with the FSharpChecker. Default: true /// An optional string used for tracing compiler operations associated with this request. [] - member ParseFileInProject: filename: string * source: string * options: FSharpProjectOptions * ?cache: bool * ?userOpName: string -> Async + member ParseFileInProject: + filename: string * + source: string * + options: FSharpProjectOptions * + ?cache: bool * + ?userOpName: string + -> Async /// /// Check a source code file, returning a handle to the results of the parse including @@ -101,7 +113,14 @@ type public FSharpChecker = /// The options for the project or script. /// An optional string used for tracing compiler operations associated with this request. [] - member CheckFileInProjectAllowingStaleCachedResults: parseResults: FSharpParseFileResults * filename: string * fileVersion: int * source: string * options: FSharpProjectOptions * ?userOpName: string -> Async + member CheckFileInProjectAllowingStaleCachedResults: + parseResults: FSharpParseFileResults * + filename: string * + fileVersion: int * + source: string * + options: FSharpProjectOptions * + ?userOpName: string + -> Async /// /// @@ -121,7 +140,14 @@ type public FSharpChecker = /// The full source for the file. /// The options for the project or script. /// An optional string used for tracing compiler operations associated with this request. - member CheckFileInProject: parseResults: FSharpParseFileResults * filename: string * fileVersion: int * sourceText: ISourceText * options: FSharpProjectOptions * ?userOpName: string -> Async + member CheckFileInProject: + parseResults: FSharpParseFileResults * + filename: string * + fileVersion: int * + sourceText: ISourceText * + options: FSharpProjectOptions * + ?userOpName: string + -> Async /// /// @@ -434,7 +460,7 @@ type public CompilerEnvironment = static member DefaultReferencesForOrphanSources: assumeDotNetFramework: bool -> string list /// Return the compilation defines that should be used when editing the given file. - static member GetCompilationDefinesForEditing: parsingOptions: FSharpParsingOptions -> string list + static member GetConditionalDefinesForEditing: parsingOptions: FSharpParsingOptions -> string list /// Return true if this is a subcategory of error or warning message that the language service can emit static member IsCheckerSupportedSubcategory: string -> bool 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 51f2f425da7..a2ccc8be5c6 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -2097,7 +2097,7 @@ FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Int32 CompareTo(System.Object FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Int32 CompareTo(System.Object, System.Collections.IComparer) FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Int32 GetHashCode() FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Int32 GetHashCode(System.Collections.IEqualityComparer) -FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Microsoft.FSharp.Collections.FSharpList`1[System.String] ConditionalCompilationDefines +FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Microsoft.FSharp.Collections.FSharpList`1[System.String] ConditionalDefines FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_ConditionalCompilationDefines() FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Microsoft.FSharp.Core.FSharpOption`1[System.Boolean] LightSyntax FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Microsoft.FSharp.Core.FSharpOption`1[System.Boolean] get_LightSyntax() @@ -2196,7 +2196,7 @@ FSharp.Compiler.CompilerEnvironment: Boolean IsCompilable(System.String) FSharp.Compiler.CompilerEnvironment: Boolean IsScriptFile(System.String) FSharp.Compiler.CompilerEnvironment: Boolean MustBeSingleFileProject(System.String) FSharp.Compiler.CompilerEnvironment: Microsoft.FSharp.Collections.FSharpList`1[System.String] DefaultReferencesForOrphanSources(Boolean) -FSharp.Compiler.CompilerEnvironment: Microsoft.FSharp.Collections.FSharpList`1[System.String] GetCompilationDefinesForEditing(FSharp.Compiler.CodeAnalysis.FSharpParsingOptions) +FSharp.Compiler.CompilerEnvironment: Microsoft.FSharp.Collections.FSharpList`1[System.String] GetConditionalDefinesForEditing(FSharp.Compiler.CodeAnalysis.FSharpParsingOptions) FSharp.Compiler.CompilerEnvironment: Microsoft.FSharp.Core.FSharpOption`1[System.String] BinFolderOfDefaultFSharpCompiler(Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CompilerEnvironment: System.Guid GetDebuggerLanguageID() FSharp.Compiler.DependencyManager.AssemblyResolutionProbe diff --git a/tests/benchmarks/CompilerServiceBenchmarks/Benchmarks.fs b/tests/benchmarks/CompilerServiceBenchmarks/Benchmarks.fs index 2a8ff70a862..a77024a3e06 100644 --- a/tests/benchmarks/CompilerServiceBenchmarks/Benchmarks.fs +++ b/tests/benchmarks/CompilerServiceBenchmarks/Benchmarks.fs @@ -132,7 +132,7 @@ type CompilerService() = let parsingOptions = { SourceFiles = [|"CheckExpressions.fs"|] - ConditionalCompilationDefines = [] + ConditionalDefines = [] ErrorSeverityOptions = FSharpDiagnosticOptions.Default LangVersionText = "default" IsInteractive = false diff --git a/vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs b/vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs index bb16634ff28..8d46f40ad76 100644 --- a/vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs +++ b/vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs @@ -91,7 +91,7 @@ type internal FSharpClassificationService | _ -> () let flags = FSharpLexerFlags.Default &&& ~~~FSharpLexerFlags.Compiling &&& ~~~FSharpLexerFlags.UseLexFilter - FSharpLexer.Tokenize(text.ToFSharpSourceText(), tokenCallback, filePath = filePath, conditionalCompilationDefines = defines, flags = flags, ct = ct) + FSharpLexer.Tokenize(text.ToFSharpSourceText(), tokenCallback, filePath = filePath, conditionalDefines = defines, flags = flags, ct = ct) result.ToImmutable() diff --git a/vsintegration/src/FSharp.Editor/CodeFix/ImplementInterfaceCodeFixProvider.fs b/vsintegration/src/FSharp.Editor/CodeFix/ImplementInterfaceCodeFixProvider.fs index 93d2686c5c9..0e6c6b5b577 100644 --- a/vsintegration/src/FSharp.Editor/CodeFix/ImplementInterfaceCodeFixProvider.fs +++ b/vsintegration/src/FSharp.Editor/CodeFix/ImplementInterfaceCodeFixProvider.fs @@ -143,7 +143,7 @@ type internal FSharpImplementInterfaceCodeFixProvider let! sourceText = context.Document.GetTextAsync(cancellationToken) let textLine = sourceText.Lines.GetLineFromPosition context.Span.Start let! _, _, parsingOptions, _ = context.Document.GetFSharpCompilationOptionsAsync(nameof(FSharpImplementInterfaceCodeFixProvider)) |> liftAsync - let defines = CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions + let defines = CompilerEnvironment.GetConditionalDefinesForEditing parsingOptions // Notice that context.Span doesn't return reliable ranges to find tokens at exact positions. // That's why we tokenize the line and try to find the last successive identifier token let tokens = Tokenizer.tokenizeLine(context.Document.Id, sourceText, context.Span.Start, context.Document.FilePath, defines) diff --git a/vsintegration/src/FSharp.Editor/Formatting/EditorFormattingService.fs b/vsintegration/src/FSharp.Editor/Formatting/EditorFormattingService.fs index b35d122d04b..778dc22b0dd 100644 --- a/vsintegration/src/FSharp.Editor/Formatting/EditorFormattingService.fs +++ b/vsintegration/src/FSharp.Editor/Formatting/EditorFormattingService.fs @@ -40,7 +40,7 @@ type internal FSharpEditorFormattingService let line = sourceText.Lines.[sourceText.Lines.IndexOf position] - let defines = CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions + let defines = CompilerEnvironment.GetConditionalDefinesForEditing parsingOptions let tokens = Tokenizer.tokenizeLine(documentId, sourceText, line.Start, filePath, defines) diff --git a/vsintegration/src/FSharp.Editor/Formatting/IndentationService.fs b/vsintegration/src/FSharp.Editor/Formatting/IndentationService.fs index 1a87ac9d89d..ec73168c1f7 100644 --- a/vsintegration/src/FSharp.Editor/Formatting/IndentationService.fs +++ b/vsintegration/src/FSharp.Editor/Formatting/IndentationService.fs @@ -28,7 +28,7 @@ type internal FSharpIndentationService static member IndentShouldFollow (documentId: DocumentId, sourceText: SourceText, filePath: string, position: int, parsingOptions: FSharpParsingOptions) = let lastTokenOpt = - let defines = CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions + let defines = CompilerEnvironment.GetConditionalDefinesForEditing parsingOptions let tokens = Tokenizer.tokenizeLine(documentId, sourceText, position, filePath, defines) tokens diff --git a/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs b/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs index 1b953dc7872..cb8c6e71b82 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs @@ -276,20 +276,20 @@ type private FSharpProjectOptionsReactor (checker: FSharpChecker) = | Some projectSite -> let otherOptions = - project.ProjectReferences - |> Seq.map (fun x -> "-r:" + project.Solution.GetProject(x.ProjectId).OutputFilePath) - |> Array.ofSeq - |> Array.append ( - project.MetadataReferences.OfType() - |> Seq.map (fun x -> "-r:" + x.FilePath) - |> Array.ofSeq - |> Array.append ( - // Clear any references from CompilationOptions. - // We get the references from Project.ProjectReferences/Project.MetadataReferences. - projectSite.CompilationOptions - |> Array.filter (fun x -> not (x.Contains("-r:"))) - ) - ) + [| + // Clear any references from CompilationOptions. + // We get the references from Project.ProjectReferences/Project.MetadataReferences. + for x in projectSite.CompilationOptions do + if not (x.Contains("-r:")) then + x + + for x in project.MetadataReferences.OfType() do + "-r:" + x.FilePath + + for x in project.ProjectReferences do + "-r:" + project.Solution.GetProject(x.ProjectId).OutputFilePath + + |] let! ver = project.GetDependentVersionAsync(ct) |> Async.AwaitTask @@ -494,53 +494,47 @@ type internal FSharpProjectOptionsManager reactor.SetLegacyProjectSite (projectId, projectSite) /// Clear a project from the project table - member this.ClearInfoForProject(projectId:ProjectId) = + member _.ClearInfoForProject(projectId:ProjectId) = reactor.ClearOptionsByProjectId(projectId) - member this.ClearSingleFileOptionsCache(documentId) = + member _.ClearSingleFileOptionsCache(documentId) = reactor.ClearSingleFileOptionsCache(documentId) /// Get compilation defines relevant for syntax processing. /// Quicker then TryGetOptionsForDocumentOrProject as it doesn't need to recompute the exact project /// options for a script. - member this.GetCompilationDefinesForEditingDocument(document:Document) = + member _.GetCompilationDefinesForEditingDocument(document:Document) = let parsingOptions = match reactor.TryGetCachedOptionsByProjectId(document.Project.Id) with | Some (_, parsingOptions, _) -> parsingOptions - | _ -> { FSharpParsingOptions.Default with IsInteractive = CompilerEnvironment.IsScriptFile document.Name } - CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions + | _ -> + { FSharpParsingOptions.Default with + IsInteractive = CompilerEnvironment.IsScriptFile document.Name + } + CompilerEnvironment.GetConditionalDefinesForEditing parsingOptions - member this.TryGetOptionsByProject(project) = + member _.TryGetOptionsByProject(project) = reactor.TryGetOptionsByProjectAsync(project) /// Get the exact options for a document or project - member this.TryGetOptionsForDocumentOrProject(document: Document, cancellationToken, userOpName) = - async { - match! reactor.TryGetOptionsByDocumentAsync(document, cancellationToken, userOpName) with - | Some(parsingOptions, projectOptions) -> - return Some(parsingOptions, None, projectOptions) - | _ -> - return None - } + member _.TryGetOptionsForDocumentOrProject(document: Document, cancellationToken, userOpName) = + reactor.TryGetOptionsByDocumentAsync(document, cancellationToken, userOpName) /// Get the exact options for a document or project relevant for syntax processing. member this.TryGetOptionsForEditingDocumentOrProject(document:Document, cancellationToken, userOpName) = - async { - let! result = this.TryGetOptionsForDocumentOrProject(document, cancellationToken, userOpName) - return result |> Option.map(fun (parsingOptions, _, projectOptions) -> parsingOptions, projectOptions) - } + this.TryGetOptionsForDocumentOrProject(document, cancellationToken, userOpName) /// Get the options for a document or project relevant for syntax processing. /// Quicker it doesn't need to recompute the exact project options for a script. - member this.TryGetQuickParsingOptionsForEditingDocumentOrProject(document:Document) = + member _.TryGetQuickParsingOptionsForEditingDocumentOrProject(document:Document) = match reactor.TryGetCachedOptionsByProjectId(document.Project.Id) with | Some (_, parsingOptions, _) -> parsingOptions | _ -> { FSharpParsingOptions.Default with IsInteractive = CompilerEnvironment.IsScriptFile document.Name } - member this.SetCommandLineOptions(projectId, sourcePaths, options: ImmutableArray) = + member _.SetCommandLineOptions(projectId, sourcePaths, options: ImmutableArray) = reactor.SetCommandLineOptions(projectId, sourcePaths, options.ToArray()) - member this.ClearAllCaches() = + member _.ClearAllCaches() = reactor.ClearAllCaches() member _.Checker = checker diff --git a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs index b64c7ed3e7f..21f566ef88e 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs @@ -116,7 +116,7 @@ type Document with let! ct = Async.CancellationToken match! projectOptionsManager.TryGetOptionsForDocumentOrProject(this, ct, userOpName) with | None -> return raise(System.OperationCanceledException("FSharp project options not found.")) - | Some(parsingOptions, _, projectOptions) -> + | Some(parsingOptions, projectOptions) -> let result = (service.Checker, projectOptionsManager, parsingOptions, projectOptions) return ProjectCache.Projects.GetValue(this.Project, Runtime.CompilerServices.ConditionalWeakTable<_,_>.CreateValueCallback(fun _ -> result)) else @@ -127,7 +127,7 @@ type Document with member this.GetFSharpCompilationDefinesAsync(userOpName) = async { let! _, _, parsingOptions, _ = this.GetFSharpCompilationOptionsAsync(userOpName) - return CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions + return CompilerEnvironment.GetConditionalDefinesForEditing parsingOptions } /// Get the instance of the FSharpChecker from the workspace by the given F# document. @@ -206,7 +206,7 @@ type Document with /// This is only used for testing purposes. It sets the ProjectCache.Projects with the given FSharpProjectOptions and F# document's project. member this.SetFSharpProjectOptionsForTesting(projectOptions: FSharpProjectOptions) = let workspaceService = this.Project.Solution.GetFSharpWorkspaceService() - let parsingOptions, _, _ = + let parsingOptions, _ = workspaceService.FSharpProjectOptionsManager.TryGetOptionsForDocumentOrProject(this, CancellationToken.None, nameof(this.SetFSharpProjectOptionsForTesting)) |> Async.RunImmediateExceptOnUI |> Option.get diff --git a/vsintegration/src/FSharp.LanguageService/ProjectSitesAndFiles.fs b/vsintegration/src/FSharp.LanguageService/ProjectSitesAndFiles.fs index 25f21b93006..1204f3d3ce3 100644 --- a/vsintegration/src/FSharp.LanguageService/ProjectSitesAndFiles.fs +++ b/vsintegration/src/FSharp.LanguageService/ProjectSitesAndFiles.fs @@ -253,7 +253,7 @@ type internal ProjectSitesAndFiles() = // The only caller of this function calls it each time it needs to colorize a line, so this call must execute very fast. if CompilerEnvironment.MustBeSingleFileProject(filename) then let parsingOptions = { FSharpParsingOptions.Default with IsInteractive = true} - CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions + CompilerEnvironment.GetConditionalDefinesForEditing parsingOptions else let siteOpt = match VsRunningDocumentTable.FindDocumentWithoutLocking(rdt,filename) with @@ -266,7 +266,7 @@ type internal ProjectSitesAndFiles() = | None -> ProjectSitesAndFiles.ProjectSiteOfSingleFile(filename) let parsingOptions,_ = checker.GetParsingOptionsFromCommandLineArgs(site.CompilationOptions |> Array.toList) - CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions + CompilerEnvironment.GetConditionalDefinesForEditing parsingOptions member art.TryFindOwningProject_DEPRECATED(rdt:IVsRunningDocumentTable, filename) = if CompilerEnvironment.MustBeSingleFileProject(filename) then None diff --git a/vsintegration/tests/UnitTests/Tests.Watson.fs b/vsintegration/tests/UnitTests/Tests.Watson.fs index d843fa38339..e0e44503b47 100644 --- a/vsintegration/tests/UnitTests/Tests.Watson.fs +++ b/vsintegration/tests/UnitTests/Tests.Watson.fs @@ -36,7 +36,7 @@ type Check = with | :? 'TException as e -> let msg = e.ToString(); - if msg.Contains("ReportTime") || msg.Contains("TypeCheckOneInput") then () + if msg.Contains("ReportTime") || msg.Contains("CheckOneInput") then () else printfn "%s" msg Assert.Fail("The correct callstack was not reported to watson.") From 514744c6a7a8550bd523fe8ead9da589aad75dfe Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 8 Apr 2022 15:42:08 +1000 Subject: [PATCH 02/11] cleanup --- release-notes.md | 1 + src/fsharp/CompilerConfig.fs | 3 +- src/fsharp/ParseAndCheckInputs.fs | 3 +- src/fsharp/fsi/fsi.fs | 6 ++-- src/fsharp/service/IncrementalBuild.fs | 39 +++++++++++++------------- 5 files changed, 29 insertions(+), 23 deletions(-) diff --git a/release-notes.md b/release-notes.md index 7a699441d55..28f788b806a 100644 --- a/release-notes.md +++ b/release-notes.md @@ -16,6 +16,7 @@ These release notes track our current efforts to document changes to the F# proj ### FSharp Compiler Service (main) +* In FSharpParsingOptions, rename ConditionalCompilationDefines --> ConditionalDefines * Some syntax tree nodes have changed, e.g. introduction of SyntaxTree trivia * Resolved expressions (FSharpExpr) now reveal debug points, you must match them explicitly using `DebugPoint(dp, expr)` * Some node types in FSharpExpr (e.g. Let, While, TryFinally, TryWith) reveal additional debug points diff --git a/src/fsharp/CompilerConfig.fs b/src/fsharp/CompilerConfig.fs index befa0e71a8d..cd429708efe 100644 --- a/src/fsharp/CompilerConfig.fs +++ b/src/fsharp/CompilerConfig.fs @@ -527,7 +527,8 @@ type TcConfigBuilder = } |> Seq.distinct - static member CreateNew( + static member CreateNew + ( legacyReferenceResolver, defaultFSharpBinariesDir, reduceMemoryUsage, diff --git a/src/fsharp/ParseAndCheckInputs.fs b/src/fsharp/ParseAndCheckInputs.fs index 087623088d0..e2eceb24230 100644 --- a/src/fsharp/ParseAndCheckInputs.fs +++ b/src/fsharp/ParseAndCheckInputs.fs @@ -835,7 +835,8 @@ let GetInitialTcState(m, ccuName, tcConfig: TcConfig, tcGlobals, tcImports: TcIm } /// Typecheck a single file (or interactive entry into F# Interactive) -let CheckOneInput( +let CheckOneInput + ( checkForErrors, tcConfig: TcConfig, tcImports: TcImports, diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index cda3868081c..15366d9eac1 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -2393,7 +2393,8 @@ module internal MagicAssemblyResolution = // Reading stdin //---------------------------------------------------------------------------- -type FsiStdinLexerProvider ( +type FsiStdinLexerProvider + ( tcConfigB, fsiStdinSyphon, fsiConsoleInput: FsiConsoleInput, fsiConsoleOutput: FsiConsoleOutput, @@ -2480,7 +2481,8 @@ type FsiStdinLexerProvider ( // It might be simpler if it ran on the parser thread. //---------------------------------------------------------------------------- -type FsiInteractionProcessor ( +type FsiInteractionProcessor + ( fsi: FsiEvaluationSessionHostConfig, tcConfigB, fsiOptions: FsiCommandLineOptions, diff --git a/src/fsharp/service/IncrementalBuild.fs b/src/fsharp/service/IncrementalBuild.fs index f3edbc20920..50ea61a27cf 100644 --- a/src/fsharp/service/IncrementalBuild.fs +++ b/src/fsharp/service/IncrementalBuild.fs @@ -1377,25 +1377,26 @@ type IncrementalBuilder(initialState: IncrementalBuilderInitialState, state: Inc /// CreateIncrementalBuilder (for background type checking). Note that fsc.fs also /// creates an incremental builder used by the command line compiler. - static member TryCreateIncrementalBuilderForProjectOptions( - legacyReferenceResolver, - defaultFSharpBinariesDir, - frameworkTcImportsCache: FrameworkImportsCache, - loadClosureOpt: LoadClosure option, - sourceFiles: string list, - commandLineArgs: string list, - projectReferences, - projectDirectory, - useScriptResolutionRules, - keepAssemblyContents, - keepAllBackgroundResolutions, - tryGetMetadataSnapshot, - suggestNamesForErrors, - keepAllBackgroundSymbolUses, - enableBackgroundItemKeyStoreAndSemanticClassification, - enablePartialTypeChecking: bool, - dependencyProvider - ) = + static member TryCreateIncrementalBuilderForProjectOptions + ( + legacyReferenceResolver, + defaultFSharpBinariesDir, + frameworkTcImportsCache: FrameworkImportsCache, + loadClosureOpt: LoadClosure option, + sourceFiles: string list, + commandLineArgs: string list, + projectReferences, + projectDirectory, + useScriptResolutionRules, + keepAssemblyContents, + keepAllBackgroundResolutions, + tryGetMetadataSnapshot, + suggestNamesForErrors, + keepAllBackgroundSymbolUses, + enableBackgroundItemKeyStoreAndSemanticClassification, + enablePartialTypeChecking: bool, + dependencyProvider + ) = let useSimpleResolutionSwitch = "--simpleresolution" From 8108b50764ff585d87f891fd8e181a396f597dfd Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 8 Apr 2022 16:06:25 +1000 Subject: [PATCH 03/11] cleanup --- src/fsharp/ScriptClosure.fs | 214 +++++++++++++++++++++++++----------- 1 file changed, 148 insertions(+), 66 deletions(-) diff --git a/src/fsharp/ScriptClosure.fs b/src/fsharp/ScriptClosure.fs index 23b299abf2c..5f2951d9206 100644 --- a/src/fsharp/ScriptClosure.fs +++ b/src/fsharp/ScriptClosure.fs @@ -26,48 +26,51 @@ open FSharp.Compiler.Text.Range [] type LoadClosureInput = - { FileName: string - SyntaxTree: ParsedInput option - ParseDiagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity) list - MetaCommandDiagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity) list } + { + FileName: string + SyntaxTree: ParsedInput option + ParseDiagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity) list + MetaCommandDiagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity) list + } [] type LoadClosure = - { /// The source files along with the ranges of the #load positions in each file. - SourceFiles: (string * range list) list + { + /// The source files along with the ranges of the #load positions in each file. + SourceFiles: (string * range list) list - /// The resolved references along with the ranges of the #r positions in each file. - References: (string * AssemblyResolution list) list + /// The resolved references along with the ranges of the #r positions in each file. + References: (string * AssemblyResolution list) list - /// The resolved pacakge references along with the ranges of the #r positions in each file. - PackageReferences: (range * string list)[] + /// The resolved pacakge references along with the ranges of the #r positions in each file. + PackageReferences: (range * string list)[] - /// Whether we're decided to use .NET Framework analysis for this script - UseDesktopFramework: bool + /// Whether we're decided to use .NET Framework analysis for this script + UseDesktopFramework: bool - /// Was the SDK directory override given? - SdkDirOverride: string option + /// Was the SDK directory override given? + SdkDirOverride: string option - /// The list of references that were not resolved during load closure. These may still be extension references. - UnresolvedReferences: UnresolvedAssemblyReference list + /// The list of references that were not resolved during load closure. These may still be extension references. + UnresolvedReferences: UnresolvedAssemblyReference list - /// The list of all sources in the closure with inputs when available - Inputs: LoadClosureInput list + /// The list of all sources in the closure with inputs when available + Inputs: LoadClosureInput list - /// The #load, including those that didn't resolve - OriginalLoadReferences: (range * string * string) list + /// The #load, including those that didn't resolve + OriginalLoadReferences: (range * string * string) list - /// The #nowarns - NoWarns: (string * range list) list + /// The #nowarns + NoWarns: (string * range list) list - /// Diagnostics seen while processing resolutions - ResolutionDiagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity) list + /// Diagnostics seen while processing resolutions + ResolutionDiagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity) list - /// Diagnostics seen while parsing root of closure - AllRootFileDiagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity) list + /// Diagnostics seen while parsing root of closure + AllRootFileDiagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity) list - /// Diagnostics seen while processing the compiler options implied root of closure - LoadClosureRootFileDiagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity) list + /// Diagnostics seen while processing the compiler options implied root of closure + LoadClosureRootFileDiagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity) list } @@ -80,24 +83,42 @@ type CodeContext = module ScriptPreprocessClosure = /// Represents an input to the closure finding process - type ClosureSource = ClosureSource of filename: string * referenceRange: range * sourceText: ISourceText * parseRequired: bool + type ClosureSource = + ClosureSource of + filename: string * + referenceRange: range * + sourceText: ISourceText * + parseRequired: bool /// Represents an output of the closure finding process - type ClosureFile = ClosureFile of string * range * ParsedInput option * (PhasedDiagnostic * FSharpDiagnosticSeverity) list * (PhasedDiagnostic * FSharpDiagnosticSeverity) list * (string * range) list // filename, range, errors, warnings, nowarns + type ClosureFile = + ClosureFile of + filename: string * + range: range * + parsedInput: ParsedInput option * + parseDiagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity) list * + metaDiagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity) list * + nowarns: (string * range) list type Observed() = let seen = Dictionary<_, bool>() - member ob.SetSeen check = + member _.SetSeen check = if not(seen.ContainsKey check) then seen.Add(check, true) - member ob.HaveSeen check = + member _.HaveSeen check = seen.ContainsKey check - /// Parse a script from source. - let ParseScriptText - (filename: string, sourceText: ISourceText, tcConfig: TcConfig, codeContext, - lexResourceManager: Lexhelp.LexResourceManager, errorLogger: ErrorLogger) = + /// Parse a script file (or any input file referenced by '#load') + let ParseScriptClosureInput + ( + filename: string, + sourceText: ISourceText, + tcConfig: TcConfig, + codeContext, + lexResourceManager: Lexhelp.LexResourceManager, + errorLogger: ErrorLogger + ) = // fsc.exe -- COMPILED\!INTERACTIVE // fsi.exe -- !COMPILED\INTERACTIVE @@ -110,19 +131,33 @@ module ScriptPreprocessClosure = | CodeContext.Compilation -> ["COMPILED"] | CodeContext.Editing -> "EDITING" :: (if IsScript filename then ["INTERACTIVE"] else ["COMPILED"]) + let tcConfigB = tcConfig.CloneToBuilder() + tcConfigB.conditionalDefines <- defines @ tcConfig.conditionalDefines + let tcConfig = TcConfig.Create(tcConfigB, false) + let lexbuf = UnicodeLexing.SourceTextAsLexbuf(true, tcConfig.langVersion, sourceText) - let isLastCompiland = (IsScript filename), tcConfig.target.IsExe // The root compiland is last in the list of compilands. - ParseOneInputLexbuf (tcConfig, lexResourceManager, defines, lexbuf, filename, isLastCompiland, errorLogger) + // The root compiland is last in the list of compilands. + let isLastCompiland = (IsScript filename, tcConfig.target.IsExe) + ParseOneInputLexbuf (tcConfig, lexResourceManager, lexbuf, filename, isLastCompiland, errorLogger) /// Create a TcConfig for load closure starting from a single .fsx file let CreateScriptTextTcConfig - (legacyReferenceResolver, defaultFSharpBinariesDir, - filename: string, codeContext, - useSimpleResolution, useFsiAuxLib, - basicReferences, applyCommandLineArgs, - assumeDotNetFramework, useSdkRefs, sdkDirOverride, - tryGetMetadataSnapshot, reduceMemoryUsage) = + ( + legacyReferenceResolver, + defaultFSharpBinariesDir, + filename: string, + codeContext, + useSimpleResolution, + useFsiAuxLib, + basicReferences, + applyCommandLineArgs, + assumeDotNetFramework, + useSdkRefs, + sdkDirOverride, + tryGetMetadataSnapshot, + reduceMemoryUsage + ) = let projectDir = Path.GetDirectoryName filename let isInteractive = (codeContext = CodeContext.CompilationAndEvaluation) @@ -175,11 +210,15 @@ module ScriptPreprocessClosure = | CodeContext.Editing -> LegacyResolutionEnvironment.EditingOrCompilation true | CodeContext.Compilation -> LegacyResolutionEnvironment.EditingOrCompilation false | CodeContext.CompilationAndEvaluation -> LegacyResolutionEnvironment.CompilationAndEvaluation + tcConfigB.framework <- false + tcConfigB.useSimpleResolution <- useSimpleResolution + // Indicates that there are some references not in basicReferencesForScriptLoadClosure which should // be added conditionally once the relevant version of mscorlib.dll has been detected. tcConfigB.implicitlyResolveAssemblies <- false + tcConfigB.SetUseSdkRefs useSdkRefs TcConfig.Create(tcConfigB, validate=true), scriptDefaultReferencesDiagnostics @@ -199,8 +238,12 @@ module ScriptPreprocessClosure = [] let ApplyMetaCommandsFromInputToTcConfigAndGatherNoWarn - (tcConfig: TcConfig, inp: ParsedInput, - pathOfMetaCommandSource, dependencyProvider) = + ( + tcConfig: TcConfig, + inp: ParsedInput, + pathOfMetaCommandSource, + dependencyProvider + ) = let tcConfigB = tcConfig.CloneToBuilder() let mutable nowarns = [] @@ -221,8 +264,14 @@ module ScriptPreprocessClosure = TcConfig.Create(tcConfigB, validate=false), nowarns let FindClosureFiles - (mainFile, _m, closureSources, origTcConfig:TcConfig, - codeContext, lexResourceManager: Lexhelp.LexResourceManager, dependencyProvider: DependencyProvider) = + ( + mainFile, + closureSources, + origTcConfig:TcConfig, + codeContext, + lexResourceManager: Lexhelp.LexResourceManager, + dependencyProvider: DependencyProvider + ) = let mutable tcConfig = origTcConfig @@ -310,7 +359,7 @@ module ScriptPreprocessClosure = let parseResult, parseDiagnostics = let errorLogger = CapturingErrorLogger("FindClosureParse") use _unwindEL = PushErrorLoggerPhaseUntilUnwind (fun _ -> errorLogger) - let result = ParseScriptText (filename, sourceText, tcConfig, codeContext, lexResourceManager, errorLogger) + let result = ParseScriptClosureInput (filename, sourceText, tcConfig, codeContext, lexResourceManager, errorLogger) result, errorLogger.Diagnostics let errorLogger = CapturingErrorLogger("FindClosureMetaCommands") @@ -425,12 +474,23 @@ module ScriptPreprocessClosure = /// Given source text, find the full load closure. Used from service.fs, when editing a script file let GetFullClosureOfScriptText - (legacyReferenceResolver, defaultFSharpBinariesDir, - filename, sourceText, codeContext, - useSimpleResolution, useFsiAuxLib, useSdkRefs, sdkDirOverride, + ( + legacyReferenceResolver, + defaultFSharpBinariesDir, + filename, + sourceText, + codeContext, + useSimpleResolution, + useFsiAuxLib, + useSdkRefs, + sdkDirOverride, lexResourceManager: Lexhelp.LexResourceManager, - applyCommandLineArgs, assumeDotNetFramework, - tryGetMetadataSnapshot, reduceMemoryUsage, dependencyProvider) = + applyCommandLineArgs, + assumeDotNetFramework, + tryGetMetadataSnapshot, + reduceMemoryUsage, + dependencyProvider + ) = // Resolve the basic references such as FSharp.Core.dll first, before processing any #I directives in the script // @@ -454,18 +514,23 @@ module ScriptPreprocessClosure = tryGetMetadataSnapshot, reduceMemoryUsage) let closureSources = [ClosureSource(filename, range0, sourceText, true)] - let closureFiles, tcConfig, packageReferences = FindClosureFiles(filename, range0, closureSources, tcConfig, codeContext, lexResourceManager, dependencyProvider) + let closureFiles, tcConfig, packageReferences = FindClosureFiles(filename, closureSources, tcConfig, codeContext, lexResourceManager, dependencyProvider) GetLoadClosure(filename, closureFiles, tcConfig, codeContext, packageReferences, scriptDefaultReferencesDiagnostics) /// Given source filename, find the full load closure /// Used from fsi.fs and fsc.fs, for #load and command line let GetFullClosureOfScriptFiles - (tcConfig:TcConfig, files:(string*range) list, codeContext, - lexResourceManager: Lexhelp.LexResourceManager, dependencyProvider) = + ( + tcConfig:TcConfig, + files:(string*range) list, + codeContext, + lexResourceManager: Lexhelp.LexResourceManager, + dependencyProvider + ) = - let mainFile, mainFileRange = List.last files + let mainFile, _mainFileRange = List.last files let closureSources = files |> List.collect (fun (filename, m) -> ClosureSourceOfFilename(filename, m,tcConfig.inputCodePage,true)) - let closureFiles, tcConfig, packageReferences = FindClosureFiles(mainFile, mainFileRange, closureSources, tcConfig, codeContext, lexResourceManager, dependencyProvider) + let closureFiles, tcConfig, packageReferences = FindClosureFiles(mainFile, closureSources, tcConfig, codeContext, lexResourceManager, dependencyProvider) GetLoadClosure(mainFile, closureFiles, tcConfig, codeContext, packageReferences, []) type LoadClosure with @@ -475,11 +540,23 @@ type LoadClosure with /// A temporary TcConfig is created along the way, is why this routine takes so many arguments. We want to be sure to use exactly the /// same arguments as the rest of the application. static member ComputeClosureOfScriptText - (legacyReferenceResolver, defaultFSharpBinariesDir, - filename: string, sourceText: ISourceText, implicitDefines, useSimpleResolution: bool, - useFsiAuxLib, useSdkRefs, sdkDir, lexResourceManager: Lexhelp.LexResourceManager, - applyCompilerOptions, assumeDotNetFramework, tryGetMetadataSnapshot, - reduceMemoryUsage, dependencyProvider) = + ( + legacyReferenceResolver, + defaultFSharpBinariesDir, + filename: string, + sourceText: ISourceText, + implicitDefines, + useSimpleResolution: bool, + useFsiAuxLib, + useSdkRefs, + sdkDir, + lexResourceManager: Lexhelp.LexResourceManager, + applyCompilerOptions, + assumeDotNetFramework, + tryGetMetadataSnapshot, + reduceMemoryUsage, + dependencyProvider + ) = use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse ScriptPreprocessClosure.GetFullClosureOfScriptText @@ -489,8 +566,13 @@ type LoadClosure with /// Analyze a set of script files and find the closure of their references. static member ComputeClosureOfScriptFiles - (tcConfig: TcConfig, files:(string*range) list, implicitDefines, - lexResourceManager: Lexhelp.LexResourceManager, dependencyProvider) = + ( + tcConfig: TcConfig, + files:(string*range) list, + implicitDefines, + lexResourceManager: Lexhelp.LexResourceManager, + dependencyProvider + ) = use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse ScriptPreprocessClosure.GetFullClosureOfScriptFiles (tcConfig, files, implicitDefines, lexResourceManager, dependencyProvider) From 1baf5f519aa3203c494d31644487cb2191954d8b Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 8 Apr 2022 16:53:04 +1000 Subject: [PATCH 04/11] ignore '#line' in the IDE --- src/fsharp/CompilerConfig.fs | 4 ++++ src/fsharp/CompilerConfig.fsi | 6 ++++++ src/fsharp/CompilerOptions.fs | 1 + src/fsharp/ParseAndCheckInputs.fs | 2 +- src/fsharp/fsi/fsi.fs | 7 ++++--- src/fsharp/lex.fsl | 4 ++-- src/fsharp/lexhelp.fs | 8 ++++---- src/fsharp/lexhelp.fsi | 12 ++++++++++-- src/fsharp/service/FSharpCheckerResults.fs | 11 ++++++++--- src/fsharp/service/FSharpCheckerResults.fsi | 14 ++++++++++++++ src/fsharp/service/ServiceLexing.fs | 8 +++++--- .../FSharp.Compiler.UnitTests/HashIfExpression.fs | 5 +++-- .../LanguageService/FSharpProjectOptionsManager.fs | 6 ++++++ 13 files changed, 68 insertions(+), 20 deletions(-) diff --git a/src/fsharp/CompilerConfig.fs b/src/fsharp/CompilerConfig.fs index cd429708efe..a6cef44414d 100644 --- a/src/fsharp/CompilerConfig.fs +++ b/src/fsharp/CompilerConfig.fs @@ -500,6 +500,8 @@ type TcConfigBuilder = mutable noConditionalErasure: bool + mutable applyLineDirectives: bool + mutable pathMap: PathMap mutable langVersion: LanguageVersion @@ -672,6 +674,7 @@ type TcConfigBuilder = fsiMultiAssemblyEmit = true internalTestSpanStackReferring = false noConditionalErasure = false + applyLineDirectives = true pathMap = PathMap.empty langVersion = LanguageVersion.Default implicitIncludeDir = implicitIncludeDir @@ -1062,6 +1065,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = member x.tryGetMetadataSnapshot = data.tryGetMetadataSnapshot member x.internalTestSpanStackReferring = data.internalTestSpanStackReferring member x.noConditionalErasure = data.noConditionalErasure + member _.applyLineDirectives = data.applyLineDirectives member x.xmlDocInfoLoader = data.xmlDocInfoLoader static member Create(builder, validate) = diff --git a/src/fsharp/CompilerConfig.fsi b/src/fsharp/CompilerConfig.fsi index 1d0693afc7b..a3e1dbfed39 100644 --- a/src/fsharp/CompilerConfig.fsi +++ b/src/fsharp/CompilerConfig.fsi @@ -293,6 +293,9 @@ type TcConfigBuilder = /// Prevent erasure of conditional attributes and methods so tooling is able analyse them. mutable noConditionalErasure: bool + /// Take '#line' into account? Defaults to true + mutable applyLineDirectives: bool + mutable pathMap : PathMap mutable langVersion : LanguageVersion @@ -524,6 +527,9 @@ type TcConfig = /// Prevent erasure of conditional attributes and methods so tooling is able analyse them. member noConditionalErasure: bool + /// Take '#line' into account? Defaults to true + member applyLineDirectives: bool + /// if true - 'let mutable x = Span.Empty', the value 'x' is a stack referring span. Used for internal testing purposes only until we get true stack spans. member internalTestSpanStackReferring : bool diff --git a/src/fsharp/CompilerOptions.fs b/src/fsharp/CompilerOptions.fs index 5a5720d87ae..04722254412 100644 --- a/src/fsharp/CompilerOptions.fs +++ b/src/fsharp/CompilerOptions.fs @@ -1059,6 +1059,7 @@ let editorSpecificFlags (tcConfigB: TcConfigBuilder) = CompilerOption("exename", tagNone, OptionString (fun s -> tcConfigB.exename <- Some s), None, None) CompilerOption("maxerrors", tagInt, OptionInt (fun n -> tcConfigB.maxErrors <- n), None, None) CompilerOption("noconditionalerasure", tagNone, OptionUnit (fun () -> tcConfigB.noConditionalErasure <- true), None, None) + CompilerOption("ignorelinedirectives", tagNone, OptionUnit (fun () -> tcConfigB.applyLineDirectives <- false), None, None) ] let internalFlags (tcConfigB:TcConfigBuilder) = diff --git a/src/fsharp/ParseAndCheckInputs.fs b/src/fsharp/ParseAndCheckInputs.fs index e2eceb24230..a995dbd57d7 100644 --- a/src/fsharp/ParseAndCheckInputs.fs +++ b/src/fsharp/ParseAndCheckInputs.fs @@ -388,7 +388,7 @@ let ParseOneInputLexbuf (tcConfig: TcConfig, lexResourceManager, lexbuf, filenam let lightStatus = LightSyntaxStatus (tcConfig.ComputeLightSyntaxInitialStatus filename, true) // Set up the initial lexer arguments - let lexargs = mkLexargs (tcConfig.conditionalDefines, lightStatus, lexResourceManager, [], errorLogger, tcConfig.pathMap) + let lexargs = mkLexargs (tcConfig.conditionalDefines, lightStatus, lexResourceManager, [], errorLogger, tcConfig.pathMap, tcConfig.applyLineDirectives) // Set up the initial lexer arguments let shortFilename = SanitizeFileName filename tcConfig.implicitIncludeDir diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 15366d9eac1..c2513e62462 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -2403,7 +2403,7 @@ type FsiStdinLexerProvider ) = // #light is the default for FSI - let interactiveInputLightSyntaxStatus = + let lightStatus = let initialLightSyntaxStatus = tcConfigB.light <> Some false LightSyntaxStatus (initialLightSyntaxStatus, false (* no warnings *)) @@ -2442,8 +2442,9 @@ type FsiStdinLexerProvider resetLexbufPos sourceFileName lexbuf let skip = true // don't report whitespace from lexer let defines = tcConfigB.conditionalDefines - let lexargs = mkLexargs (defines, interactiveInputLightSyntaxStatus, lexResourceManager, [], errorLogger, PathMap.empty) - let tokenizer = LexFilter.LexFilter(interactiveInputLightSyntaxStatus, tcConfigB.compilingFslib, Lexer.token lexargs skip, lexbuf) + let applyLineDirectives = true + let lexargs = mkLexargs (defines, lightStatus, lexResourceManager, [], errorLogger, PathMap.empty, applyLineDirectives) + let tokenizer = LexFilter.LexFilter(lightStatus, tcConfigB.compilingFslib, Lexer.token lexargs skip, lexbuf) tokenizer // Create a new lexer to read stdin diff --git a/src/fsharp/lex.fsl b/src/fsharp/lex.fsl index af11cf489c1..be194d99cc2 100644 --- a/src/fsharp/lex.fsl +++ b/src/fsharp/lex.fsl @@ -949,7 +949,7 @@ rule token args skip = parse | anywhite* "#if" anywhite+ anystring { let m = lexbuf.LexemeRange - let lookup id = List.contains id args.defines + let lookup id = List.contains id args.conditionalDefines let lexed = lexeme lexbuf let isTrue, expr = evalIfDefExpression lexbuf.StartPos lexbuf.ReportLibraryOnlyFeatures lexbuf.LanguageVersion args lookup lexed args.ifdefStack <- (IfDefIf,m) :: args.ifdefStack @@ -1027,7 +1027,7 @@ and ifdefSkip n m args skip = parse else ifdefSkip n m args skip lexbuf else let lexed = lexeme lexbuf - let lookup id = List.contains id args.defines + let lookup id = List.contains id args.conditionalDefines let _, expr = evalIfDefExpression lexbuf.StartPos lexbuf.ReportLibraryOnlyFeatures lexbuf.LanguageVersion args lookup lexed LexbufIfdefStore.SaveIfHash(lexbuf, lexed, expr, m) let tok = INACTIVECODE(LexCont.EndLine(args.ifdefStack, args.stringNest, LexerEndlineContinuation.Skip(n+1, m))) diff --git a/src/fsharp/lexhelp.fs b/src/fsharp/lexhelp.fs index e8bfff78a1e..17472df4a6e 100644 --- a/src/fsharp/lexhelp.fs +++ b/src/fsharp/lexhelp.fs @@ -50,7 +50,7 @@ type LexResourceManager(?capacity: int) = /// Lexer parameters type LexArgs = { - defines: string list + conditionalDefines: string list resourceManager: LexResourceManager errorLogger: ErrorLogger applyLineDirectives: bool @@ -67,14 +67,14 @@ type LongUnicodeLexResult = | SingleChar of uint16 | Invalid -let mkLexargs (defines, lightStatus, resourceManager, ifdefStack, errorLogger, pathMap:PathMap) = +let mkLexargs (conditionalDefines, lightStatus, resourceManager, ifdefStack, errorLogger, pathMap:PathMap, applyLineDirectives) = { - defines = defines + conditionalDefines = conditionalDefines ifdefStack = ifdefStack lightStatus = lightStatus resourceManager = resourceManager errorLogger = errorLogger - applyLineDirectives = true + applyLineDirectives = applyLineDirectives stringNest = [] pathMap = pathMap } diff --git a/src/fsharp/lexhelp.fsi b/src/fsharp/lexhelp.fsi index 9f2cf62d12d..e72c2579780 100644 --- a/src/fsharp/lexhelp.fsi +++ b/src/fsharp/lexhelp.fsi @@ -31,7 +31,7 @@ type LexResourceManager = /// The context applicable to all lexing functions (tokens, strings etc.) type LexArgs = { - defines: string list + conditionalDefines: string list resourceManager: LexResourceManager errorLogger: ErrorLogger applyLineDirectives: bool @@ -48,7 +48,15 @@ type LongUnicodeLexResult = val resetLexbufPos: string -> Lexbuf -> unit -val mkLexargs: string list * LightSyntaxStatus * LexResourceManager * LexerIfdefStack * ErrorLogger * PathMap -> LexArgs +val mkLexargs: + conditionalDefines: string list * + lightStatus: LightSyntaxStatus * + resourceManager: LexResourceManager * + ifdefStack: LexerIfdefStack * + errorLogger: ErrorLogger * + pathMap: PathMap * + applyLineDirectives: bool + -> LexArgs val reusingLexbufForParsing: Lexbuf -> (unit -> 'a) -> 'a diff --git a/src/fsharp/service/FSharpCheckerResults.fs b/src/fsharp/service/FSharpCheckerResults.fs index c4743c505f0..d1847ae1988 100644 --- a/src/fsharp/service/FSharpCheckerResults.fs +++ b/src/fsharp/service/FSharpCheckerResults.fs @@ -1548,6 +1548,7 @@ type internal TypeCheckInfo type FSharpParsingOptions = { SourceFiles: string [] + ApplyLineDirectives: bool ConditionalDefines: string list ErrorSeverityOptions: FSharpDiagnosticOptions LangVersionText: string @@ -1562,6 +1563,7 @@ type FSharpParsingOptions = static member Default = { SourceFiles = Array.empty + ApplyLineDirectives = false ConditionalDefines = [] ErrorSeverityOptions = FSharpDiagnosticOptions.Default LangVersionText = LanguageVersion.Default.VersionText @@ -1572,6 +1574,7 @@ type FSharpParsingOptions = static member FromTcConfig(tcConfig: TcConfig, sourceFiles, isInteractive: bool) = { SourceFiles = sourceFiles + ApplyLineDirectives = tcConfig.applyLineDirectives ConditionalDefines = tcConfig.conditionalDefines ErrorSeverityOptions = tcConfig.errorSeverityOptions LangVersionText = tcConfig.langVersion.VersionText @@ -1583,6 +1586,7 @@ type FSharpParsingOptions = static member FromTcConfigBuilder(tcConfigB: TcConfigBuilder, sourceFiles, isInteractive: bool) = { SourceFiles = sourceFiles + ApplyLineDirectives = tcConfigB.applyLineDirectives ConditionalDefines = tcConfigB.conditionalDefines ErrorSeverityOptions = tcConfigB.errorSeverityOptions LangVersionText = tcConfigB.langVersion.VersionText @@ -1653,15 +1657,16 @@ module internal ParseAndCheckFile = // If we're editing a script then we define INTERACTIVE otherwise COMPILED. // Since this parsing for intellisense we always define EDITING. - let defines = (SourceFileImpl.GetImplicitConditionalDefinesForEditing options.IsInteractive) @ options.ConditionalDefines + let conditionalDefines = + SourceFileImpl.GetImplicitConditionalDefinesForEditing options.IsInteractive + @ options.ConditionalDefines // Note: we don't really attempt to intern strings across a large scope. let lexResourceManager = LexResourceManager() // When analyzing files using ParseOneFile, i.e. for the use of editing clients, we do not apply line directives. // TODO(pathmap): expose PathMap on the service API, and thread it through here - let lexargs = mkLexargs(defines, lightStatus, lexResourceManager, [], errHandler.ErrorLogger, PathMap.empty) - let lexargs = { lexargs with applyLineDirectives = false } + let lexargs = mkLexargs(conditionalDefines, lightStatus, lexResourceManager, [], errHandler.ErrorLogger, PathMap.empty, options.ApplyLineDirectives) let tokenizer = LexFilter.LexFilter(lightStatus, options.CompilingFsLib, Lexer.token lexargs true, lexbuf) (fun _ -> tokenizer.GetToken()) diff --git a/src/fsharp/service/FSharpCheckerResults.fsi b/src/fsharp/service/FSharpCheckerResults.fsi index 5e3ec0fea69..95bac1b2487 100644 --- a/src/fsharp/service/FSharpCheckerResults.fsi +++ b/src/fsharp/service/FSharpCheckerResults.fsi @@ -193,12 +193,26 @@ type public FSharpProjectContext = type public FSharpParsingOptions = { SourceFiles: string[] + + /// Indicates if the ranges returned by parsing should have '#line' directives applied to them. + /// When compiling code, this should usually be 'true'. For editing tools, this is usually 'false. + /// The default for FSharpParsingOptions.ApplyLineDirectives is 'false'. The default for + /// FSharpParsingOptions arising from FSharpProjectOptions will be 'true' unless '--ignorelinedirectives' is used in the + /// parameters from which these are derived. + ApplyLineDirectives: bool + ConditionalDefines: string list + ErrorSeverityOptions: FSharpDiagnosticOptions + LangVersionText: string + IsInteractive: bool + LightSyntax: bool option + CompilingFsLib: bool + IsExe: bool } static member Default: FSharpParsingOptions diff --git a/src/fsharp/service/ServiceLexing.fs b/src/fsharp/service/ServiceLexing.fs index 4537a2f9402..ebfa414b2d9 100644 --- a/src/fsharp/service/ServiceLexing.fs +++ b/src/fsharp/service/ServiceLexing.fs @@ -926,7 +926,9 @@ type FSharpSourceTokenizer(conditionalDefines: string list, filename: string opt let lexResourceManager = LexResourceManager() - let lexargs = mkLexargs(conditionalDefines, LightSyntaxStatus(true, false), lexResourceManager, [], DiscardErrorsLogger, PathMap.empty) + let applyLineDirectives = false + let lightStatus = LightSyntaxStatus(true, false) + let lexargs = mkLexargs(conditionalDefines, lightStatus, lexResourceManager, [], DiscardErrorsLogger, PathMap.empty, applyLineDirectives) member _.CreateLineTokenizer(lineText: string) = let lexbuf = UnicodeLexing.StringAsLexbuf(reportLibraryOnlyFeatures, langVersion, lineText) @@ -1520,8 +1522,8 @@ module FSharpLexerImpl = let lexbuf = UnicodeLexing.SourceTextAsLexbuf(reportLibraryOnlyFeatures, langVersion, text) let lightStatus = LightSyntaxStatus(isLightSyntaxOn, true) - let lexargs = mkLexargs (conditionalDefines, lightStatus, LexResourceManager(0), [], errorLogger, pathMap) - let lexargs = { lexargs with applyLineDirectives = isCompiling } + let applyLineDirectives = isCompiling + let lexargs = mkLexargs (conditionalDefines, lightStatus, LexResourceManager(0), [], errorLogger, pathMap, applyLineDirectives) let getNextToken = let lexer = Lexer.token lexargs canSkipTrivia diff --git a/tests/FSharp.Compiler.UnitTests/HashIfExpression.fs b/tests/FSharp.Compiler.UnitTests/HashIfExpression.fs index bf0d2d1a9e9..10a48d8414e 100644 --- a/tests/FSharp.Compiler.UnitTests/HashIfExpression.fs +++ b/tests/FSharp.Compiler.UnitTests/HashIfExpression.fs @@ -62,9 +62,10 @@ type public HashIfExpression() = let lightSyntax = LightSyntaxStatus(true, false) let resourceManager = LexResourceManager () - let defines= [] + let defines = [] + let applyLineDirectives = true let startPos = Position.Empty - let args = mkLexargs (defines, lightSyntax, resourceManager, [], errorLogger, PathMap.empty) + let args = mkLexargs (defines, lightSyntax, resourceManager, [], errorLogger, PathMap.empty, applyLineDirectives) CompileThreadStatic.ErrorLogger <- errorLogger diff --git a/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs b/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs index cb8c6e71b82..53dbbad2338 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs @@ -289,6 +289,11 @@ type private FSharpProjectOptionsReactor (checker: FSharpChecker) = for x in project.ProjectReferences do "-r:" + project.Solution.GetProject(x.ProjectId).OutputFilePath + // In the IDE we always ignore all #line directives for all purposes. This means + // IDE features work correctly within generated source files, but diagnostics are + // reported in the IDE with respect to the generated source, and will not unify with + // diagnostics from the build. + "--ignorelinedirectives" |] let! ver = project.GetDependentVersionAsync(ct) |> Async.AwaitTask @@ -509,6 +514,7 @@ type internal FSharpProjectOptionsManager | Some (_, parsingOptions, _) -> parsingOptions | _ -> { FSharpParsingOptions.Default with + ApplyLineDirectives = false IsInteractive = CompilerEnvironment.IsScriptFile document.Name } CompilerEnvironment.GetConditionalDefinesForEditing parsingOptions From 48e2115fb8e8b64e34fb42f8f7bf8d889b5f9d2a Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 8 Apr 2022 17:53:23 +1000 Subject: [PATCH 05/11] more cleanup --- src/fsharp/fsi/fsi.fs | 6 +++--- src/fsharp/lex.fsl | 4 ++-- src/fsharp/lexhelp.fs | 6 +++--- src/fsharp/lexhelp.fsi | 12 ++++++++++-- src/fsharp/service/FSharpCheckerResults.fs | 6 ++++-- ....CompilerService.SurfaceArea.netstandard.expected | 2 +- 6 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 15366d9eac1..f5d8d01fcf6 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -2403,7 +2403,7 @@ type FsiStdinLexerProvider ) = // #light is the default for FSI - let interactiveInputLightSyntaxStatus = + let lightStatus = let initialLightSyntaxStatus = tcConfigB.light <> Some false LightSyntaxStatus (initialLightSyntaxStatus, false (* no warnings *)) @@ -2442,8 +2442,8 @@ type FsiStdinLexerProvider resetLexbufPos sourceFileName lexbuf let skip = true // don't report whitespace from lexer let defines = tcConfigB.conditionalDefines - let lexargs = mkLexargs (defines, interactiveInputLightSyntaxStatus, lexResourceManager, [], errorLogger, PathMap.empty) - let tokenizer = LexFilter.LexFilter(interactiveInputLightSyntaxStatus, tcConfigB.compilingFslib, Lexer.token lexargs skip, lexbuf) + let lexargs = mkLexargs (defines, lightStatus, lexResourceManager, [], errorLogger, PathMap.empty) + let tokenizer = LexFilter.LexFilter(lightStatus, tcConfigB.compilingFslib, Lexer.token lexargs skip, lexbuf) tokenizer // Create a new lexer to read stdin diff --git a/src/fsharp/lex.fsl b/src/fsharp/lex.fsl index af11cf489c1..be194d99cc2 100644 --- a/src/fsharp/lex.fsl +++ b/src/fsharp/lex.fsl @@ -949,7 +949,7 @@ rule token args skip = parse | anywhite* "#if" anywhite+ anystring { let m = lexbuf.LexemeRange - let lookup id = List.contains id args.defines + let lookup id = List.contains id args.conditionalDefines let lexed = lexeme lexbuf let isTrue, expr = evalIfDefExpression lexbuf.StartPos lexbuf.ReportLibraryOnlyFeatures lexbuf.LanguageVersion args lookup lexed args.ifdefStack <- (IfDefIf,m) :: args.ifdefStack @@ -1027,7 +1027,7 @@ and ifdefSkip n m args skip = parse else ifdefSkip n m args skip lexbuf else let lexed = lexeme lexbuf - let lookup id = List.contains id args.defines + let lookup id = List.contains id args.conditionalDefines let _, expr = evalIfDefExpression lexbuf.StartPos lexbuf.ReportLibraryOnlyFeatures lexbuf.LanguageVersion args lookup lexed LexbufIfdefStore.SaveIfHash(lexbuf, lexed, expr, m) let tok = INACTIVECODE(LexCont.EndLine(args.ifdefStack, args.stringNest, LexerEndlineContinuation.Skip(n+1, m))) diff --git a/src/fsharp/lexhelp.fs b/src/fsharp/lexhelp.fs index e8bfff78a1e..c18d8d25558 100644 --- a/src/fsharp/lexhelp.fs +++ b/src/fsharp/lexhelp.fs @@ -50,7 +50,7 @@ type LexResourceManager(?capacity: int) = /// Lexer parameters type LexArgs = { - defines: string list + conditionalDefines: string list resourceManager: LexResourceManager errorLogger: ErrorLogger applyLineDirectives: bool @@ -67,9 +67,9 @@ type LongUnicodeLexResult = | SingleChar of uint16 | Invalid -let mkLexargs (defines, lightStatus, resourceManager, ifdefStack, errorLogger, pathMap:PathMap) = +let mkLexargs (conditionalDefines, lightStatus, resourceManager, ifdefStack, errorLogger, pathMap:PathMap) = { - defines = defines + conditionalDefines = conditionalDefines ifdefStack = ifdefStack lightStatus = lightStatus resourceManager = resourceManager diff --git a/src/fsharp/lexhelp.fsi b/src/fsharp/lexhelp.fsi index 9f2cf62d12d..e72c2579780 100644 --- a/src/fsharp/lexhelp.fsi +++ b/src/fsharp/lexhelp.fsi @@ -31,7 +31,7 @@ type LexResourceManager = /// The context applicable to all lexing functions (tokens, strings etc.) type LexArgs = { - defines: string list + conditionalDefines: string list resourceManager: LexResourceManager errorLogger: ErrorLogger applyLineDirectives: bool @@ -48,7 +48,15 @@ type LongUnicodeLexResult = val resetLexbufPos: string -> Lexbuf -> unit -val mkLexargs: string list * LightSyntaxStatus * LexResourceManager * LexerIfdefStack * ErrorLogger * PathMap -> LexArgs +val mkLexargs: + conditionalDefines: string list * + lightStatus: LightSyntaxStatus * + resourceManager: LexResourceManager * + ifdefStack: LexerIfdefStack * + errorLogger: ErrorLogger * + pathMap: PathMap * + applyLineDirectives: bool + -> LexArgs val reusingLexbufForParsing: Lexbuf -> (unit -> 'a) -> 'a diff --git a/src/fsharp/service/FSharpCheckerResults.fs b/src/fsharp/service/FSharpCheckerResults.fs index c4743c505f0..b1ccd46bc86 100644 --- a/src/fsharp/service/FSharpCheckerResults.fs +++ b/src/fsharp/service/FSharpCheckerResults.fs @@ -1653,14 +1653,16 @@ module internal ParseAndCheckFile = // If we're editing a script then we define INTERACTIVE otherwise COMPILED. // Since this parsing for intellisense we always define EDITING. - let defines = (SourceFileImpl.GetImplicitConditionalDefinesForEditing options.IsInteractive) @ options.ConditionalDefines + let conditionalDefines = + SourceFileImpl.GetImplicitConditionalDefinesForEditing options.IsInteractive + @ options.ConditionalDefines // Note: we don't really attempt to intern strings across a large scope. let lexResourceManager = LexResourceManager() // When analyzing files using ParseOneFile, i.e. for the use of editing clients, we do not apply line directives. // TODO(pathmap): expose PathMap on the service API, and thread it through here - let lexargs = mkLexargs(defines, lightStatus, lexResourceManager, [], errHandler.ErrorLogger, PathMap.empty) + let lexargs = mkLexargs(conditionalDefines, lightStatus, lexResourceManager, [], errHandler.ErrorLogger, PathMap.empty) let lexargs = { lexargs with applyLineDirectives = false } let tokenizer = LexFilter.LexFilter(lightStatus, options.CompilingFsLib, Lexer.token lexargs true, lexbuf) 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 a2ccc8be5c6..dc585930c99 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -2098,7 +2098,7 @@ FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Int32 CompareTo(System.Object FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Int32 GetHashCode() FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Int32 GetHashCode(System.Collections.IEqualityComparer) FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Microsoft.FSharp.Collections.FSharpList`1[System.String] ConditionalDefines -FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_ConditionalCompilationDefines() +FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_ConditionalDefines() FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Microsoft.FSharp.Core.FSharpOption`1[System.Boolean] LightSyntax FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Microsoft.FSharp.Core.FSharpOption`1[System.Boolean] get_LightSyntax() FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: System.String LangVersionText From 51673bafd661a6604420420bc04bff583809db84 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sun, 10 Apr 2022 12:53:31 +1000 Subject: [PATCH 06/11] fix build --- src/fsharp/lexhelp.fs | 2 +- src/fsharp/lexhelp.fsi | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/fsharp/lexhelp.fs b/src/fsharp/lexhelp.fs index c18d8d25558..5d18aa23a1e 100644 --- a/src/fsharp/lexhelp.fs +++ b/src/fsharp/lexhelp.fs @@ -67,7 +67,7 @@ type LongUnicodeLexResult = | SingleChar of uint16 | Invalid -let mkLexargs (conditionalDefines, lightStatus, resourceManager, ifdefStack, errorLogger, pathMap:PathMap) = +let mkLexargs (conditionalDefines, lightStatus, resourceManager, ifdefStack, errorLogger, pathMap: PathMap) = { conditionalDefines = conditionalDefines ifdefStack = ifdefStack diff --git a/src/fsharp/lexhelp.fsi b/src/fsharp/lexhelp.fsi index e72c2579780..06e43cf9e95 100644 --- a/src/fsharp/lexhelp.fsi +++ b/src/fsharp/lexhelp.fsi @@ -54,8 +54,7 @@ val mkLexargs: resourceManager: LexResourceManager * ifdefStack: LexerIfdefStack * errorLogger: ErrorLogger * - pathMap: PathMap * - applyLineDirectives: bool + pathMap: PathMap -> LexArgs val reusingLexbufForParsing: Lexbuf -> (unit -> 'a) -> 'a From fb6d7a1fadb4fec4a00c73f0109e708c52b7c77c Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sat, 7 May 2022 12:23:42 +0100 Subject: [PATCH 07/11] reformat --- src/fsharp/CheckDeclarations.fsi | 19 ++++++--- src/fsharp/CompilerConfig.fsi | 2 +- src/fsharp/ParseAndCheckInputs.fsi | 66 +++++++++++++----------------- 3 files changed, 42 insertions(+), 45 deletions(-) diff --git a/src/fsharp/CheckDeclarations.fsi b/src/fsharp/CheckDeclarations.fsi index 06acdfad5fb..4d31b04abdf 100644 --- a/src/fsharp/CheckDeclarations.fsi +++ b/src/fsharp/CheckDeclarations.fsi @@ -46,7 +46,7 @@ val TcOpenModuleOrNamespaceDecl: val AddLocalSubModule: g: TcGlobals -> amap: ImportMap -> m: range -> env: TcEnv -> modul: ModuleOrNamespace -> TcEnv -val CheckOneImplFile: +val CheckOneImplFile: TcGlobals * NiceNameGenerator * ImportMap * @@ -61,11 +61,18 @@ val CheckOneImplFile: ParsedImplFileInput -> Cancellable -val CheckOneSigFile : - TcGlobals * NiceNameGenerator * ImportMap * CcuThunk * (unit -> bool) * ConditionalDefines option * TcResultsSink * bool - -> TcEnv - -> ParsedSigFileInput - -> Cancellable +val CheckOneSigFile: + TcGlobals * + NiceNameGenerator * + ImportMap * + CcuThunk * + (unit -> bool) * + ConditionalDefines option * + TcResultsSink * + bool -> + TcEnv -> + ParsedSigFileInput -> + Cancellable exception ParameterlessStructCtor of range diff --git a/src/fsharp/CompilerConfig.fsi b/src/fsharp/CompilerConfig.fsi index 4e039bd2755..e90a95e22b8 100644 --- a/src/fsharp/CompilerConfig.fsi +++ b/src/fsharp/CompilerConfig.fsi @@ -466,7 +466,7 @@ type TcConfigBuilder = /// Take '#line' into account? Defaults to true mutable applyLineDirectives: bool - mutable pathMap : PathMap + mutable pathMap: PathMap mutable langVersion: LanguageVersion diff --git a/src/fsharp/ParseAndCheckInputs.fsi b/src/fsharp/ParseAndCheckInputs.fsi index e1ba0d0e9fc..2b438899ad7 100644 --- a/src/fsharp/ParseAndCheckInputs.fsi +++ b/src/fsharp/ParseAndCheckInputs.fsi @@ -39,8 +39,8 @@ val ParseInput: lexbuf: Lexbuf * defaultNamespace: string option * fileName: string * - isLastCompiland:(bool * bool) - -> ParsedInput + isLastCompiland: (bool * bool) -> + ParsedInput /// A general routine to process hash directives val ProcessMetaCommandsFromInput: @@ -54,9 +54,7 @@ val ApplyMetaCommandsFromInputToTcConfig: TcConfig * ParsedInput * string * Depe /// Process the #nowarn in an input and integrate them into the TcConfig val ApplyNoWarnsToTcConfig: TcConfig * ParsedInput * string -> TcConfig -val GetScopedPragmasForInput: - input: ParsedInput - -> ScopedPragma list +val GetScopedPragmasForInput: input: ParsedInput -> ScopedPragma list /// Parse one input stream val ParseOneInputStream: @@ -66,8 +64,8 @@ val ParseOneInputStream: isLastCompiland: (bool * bool) * errorLogger: ErrorLogger * retryLocked: bool * - stream: Stream - -> ParsedInput + stream: Stream -> + ParsedInput /// Parse one input source text val ParseOneInputSourceText: @@ -76,8 +74,8 @@ val ParseOneInputSourceText: fileName: string * isLastCompiland: (bool * bool) * errorLogger: ErrorLogger * - sourceText: ISourceText - -> ParsedInput + sourceText: ISourceText -> + ParsedInput /// Parse one input file val ParseOneInputFile: @@ -86,8 +84,8 @@ val ParseOneInputFile: fileName: string * isLastCompiland: (bool * bool) * errorLogger: ErrorLogger * - retryLocked: bool - -> ParsedInput + retryLocked: bool -> + ParsedInput val ParseOneInputLexbuf: tcConfig: TcConfig * @@ -95,13 +93,10 @@ val ParseOneInputLexbuf: lexbuf: Lexbuf * fileName: string * isLastCompiland: (bool * bool) * - errorLogger: ErrorLogger - -> ParsedInput + errorLogger: ErrorLogger -> + ParsedInput -val EmptyParsedInput: - fileName: string * - isLastCompiland: (bool * bool) - -> ParsedInput +val EmptyParsedInput: fileName: string * isLastCompiland: (bool * bool) -> ParsedInput /// Parse multiple input files from disk val ParseInputFiles: @@ -111,8 +106,8 @@ val ParseInputFiles: errorLogger: ErrorLogger * exiter: Exiter * createErrorLogger: (Exiter -> CapturingErrorLogger) * - retryLocked: bool - -> (ParsedInput * string) list + retryLocked: bool -> + (ParsedInput * string) list /// Get the initial type checking environment including the loading of mscorlib/System.Core, FSharp.Core /// applying the InternalsVisibleTo in referenced assemblies and opening 'Checked' if requested. @@ -154,22 +149,17 @@ val CheckOneInput: NameResolution.TcResultsSink * TcState * ParsedInput * - skipImplIfSigExists: bool - -> Cancellable<(TcEnv * TopAttribs * TypedImplFile option * ModuleOrNamespaceType) * TcState> + skipImplIfSigExists: bool -> + Cancellable<(TcEnv * TopAttribs * TypedImplFile option * ModuleOrNamespaceType) * TcState> -/// Finish the checking of multiple inputs +/// Finish the checking of multiple inputs val CheckMultipleInputsFinish: - (TcEnv * TopAttribs * 'T option * 'U) list * - TcState - -> (TcEnv * TopAttribs * 'T list * 'U list) * TcState - -/// Finish the checking of a closed set of inputs -val CheckClosedInputSetFinish: - TypedImplFile list * - TcState - -> TcState * TypedImplFile list * ModuleOrNamespace - -/// Check a closed set of inputs + (TcEnv * TopAttribs * 'T option * 'U) list * TcState -> (TcEnv * TopAttribs * 'T list * 'U list) * TcState + +/// Finish the checking of a closed set of inputs +val CheckClosedInputSetFinish: TypedImplFile list * TcState -> TcState * TypedImplFile list * ModuleOrNamespace + +/// Check a closed set of inputs val CheckClosedInputSet: CompilationThreadToken * checkForErrors: (unit -> bool) * @@ -178,11 +168,11 @@ val CheckClosedInputSet: TcGlobals * LongIdent option * TcState * - ParsedInput list - -> TcState * TopAttribs * TypedImplFile list * TcEnv + ParsedInput list -> + TcState * TopAttribs * TypedImplFile list * TcEnv /// Check a single input and finish the checking -val CheckOneInputAndFinish : +val CheckOneInputAndFinish: checkForErrors: (unit -> bool) * TcConfig * TcImports * @@ -190,5 +180,5 @@ val CheckOneInputAndFinish : LongIdent option * NameResolution.TcResultsSink * TcState * - ParsedInput - -> Cancellable<(TcEnv * TopAttribs * TypedImplFile list * ModuleOrNamespaceType list) * TcState> + ParsedInput -> + Cancellable<(TcEnv * TopAttribs * TypedImplFile list * ModuleOrNamespaceType list) * TcState> From dbfb796af989d65d3c8ee7e37afe3686c3b0f381 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Mon, 11 Jul 2022 23:12:10 +0100 Subject: [PATCH 08/11] format code --- src/Compiler/Service/FSharpCheckerResults.fs | 10 ++++++- src/Compiler/Service/ServiceLexing.fs | 24 ++++++++++++++-- src/Compiler/SyntaxTree/LexHelpers.fs | 29 +++++++++++++------- 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs index c44542ca9df..6f84923f6c7 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fs +++ b/src/Compiler/Service/FSharpCheckerResults.fs @@ -2187,7 +2187,15 @@ module internal ParseAndCheckFile = // When analyzing files using ParseOneFile, i.e. for the use of editing clients, we do not apply line directives. // TODO(pathmap): expose PathMap on the service API, and thread it through here let lexargs = - mkLexargs(conditionalDefines, indentationSyntaxStatus, lexResourceManager, [], errHandler.DiagnosticsLogger, PathMap.empty, options.ApplyLineDirectives) + mkLexargs ( + conditionalDefines, + indentationSyntaxStatus, + lexResourceManager, + [], + errHandler.DiagnosticsLogger, + PathMap.empty, + options.ApplyLineDirectives + ) let tokenizer = LexFilter.LexFilter(indentationSyntaxStatus, options.CompilingFSharpCore, Lexer.token lexargs true, lexbuf) diff --git a/src/Compiler/Service/ServiceLexing.fs b/src/Compiler/Service/ServiceLexing.fs index ef354d97581..ba2490c3f9d 100644 --- a/src/Compiler/Service/ServiceLexing.fs +++ b/src/Compiler/Service/ServiceLexing.fs @@ -1185,7 +1185,17 @@ type FSharpSourceTokenizer(conditionalDefines: string list, fileName: string opt let applyLineDirectives = false let indentationSyntaxStatus = IndentationAwareSyntaxStatus(true, false) - let lexargs = mkLexargs(conditionalDefines, indentationSyntaxStatus, lexResourceManager, [], DiscardErrorsLogger, PathMap.empty, applyLineDirectives) + + let lexargs = + mkLexargs ( + conditionalDefines, + indentationSyntaxStatus, + lexResourceManager, + [], + DiscardErrorsLogger, + PathMap.empty, + applyLineDirectives + ) member _.CreateLineTokenizer(lineText: string) = let lexbuf = @@ -1808,7 +1818,17 @@ module FSharpLexerImpl = let indentationSyntaxStatus = IndentationAwareSyntaxStatus(isLightSyntaxOn, true) let applyLineDirectives = isCompiling - let lexargs = mkLexargs (conditionalDefines, indentationSyntaxStatus, LexResourceManager(0), [], diagnosticsLogger, pathMap, applyLineDirectives) + + let lexargs = + mkLexargs ( + conditionalDefines, + indentationSyntaxStatus, + LexResourceManager(0), + [], + diagnosticsLogger, + pathMap, + applyLineDirectives + ) let getNextToken = let lexer = Lexer.token lexargs canSkipTrivia diff --git a/src/Compiler/SyntaxTree/LexHelpers.fs b/src/Compiler/SyntaxTree/LexHelpers.fs index a701a0987ea..80fc0c21246 100644 --- a/src/Compiler/SyntaxTree/LexHelpers.fs +++ b/src/Compiler/SyntaxTree/LexHelpers.fs @@ -74,16 +74,25 @@ type LongUnicodeLexResult = | SingleChar of uint16 | Invalid -let mkLexargs (conditionalDefines, indentationSyntaxStatus, resourceManager, ifdefStack, diagnosticsLogger, pathMap: PathMap, applyLineDirectives) = - { - conditionalDefines = conditionalDefines - ifdefStack = ifdefStack - indentationSyntaxStatus = indentationSyntaxStatus - resourceManager = resourceManager - diagnosticsLogger = diagnosticsLogger - applyLineDirectives = applyLineDirectives - stringNest = [] - pathMap = pathMap +let mkLexargs + ( + conditionalDefines, + indentationSyntaxStatus, + resourceManager, + ifdefStack, + diagnosticsLogger, + pathMap: PathMap, + applyLineDirectives + ) = + { + conditionalDefines = conditionalDefines + ifdefStack = ifdefStack + indentationSyntaxStatus = indentationSyntaxStatus + resourceManager = resourceManager + diagnosticsLogger = diagnosticsLogger + applyLineDirectives = applyLineDirectives + stringNest = [] + pathMap = pathMap } /// Register the lexbuf and call the given function From a6236d69765b0420fc2081a89d1fd486df1517a4 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 12 Jul 2022 00:32:46 +0100 Subject: [PATCH 09/11] fix build --- .../FSharp.CompilerService.SurfaceArea.netstandard.expected | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 090d64e02c7..d35d8849d33 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -2108,7 +2108,9 @@ FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: System.String ToString() FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: System.String get_LangVersionText() FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: System.String[] SourceFiles FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: System.String[] get_SourceFiles() -FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Void .ctor(System.String[], Microsoft.FSharp.Collections.FSharpList`1[System.String], FSharp.Compiler.Diagnostics.FSharpDiagnosticOptions, System.String, Boolean, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Boolean, Boolean) +FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Boolean ApplyLineDirectives +FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Boolean get_ApplyLineDirectives() +FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Void .ctor(System.String[], Boolean, Microsoft.FSharp.Collections.FSharpList`1[System.String], FSharp.Compiler.Diagnostics.FSharpDiagnosticOptions, System.String, Boolean, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Boolean, Boolean) FSharp.Compiler.CodeAnalysis.FSharpProjectContext FSharp.Compiler.CodeAnalysis.FSharpProjectContext: FSharp.Compiler.CodeAnalysis.FSharpProjectOptions ProjectOptions FSharp.Compiler.CodeAnalysis.FSharpProjectContext: FSharp.Compiler.CodeAnalysis.FSharpProjectOptions get_ProjectOptions() From 7e281d555bae548252455fc3a084b54e2f2f5cf3 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 12 Jul 2022 01:22:58 +0100 Subject: [PATCH 10/11] add tests --- tests/service/ProjectAnalysisTests.fs | 34 ++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs index 3318cf40cf4..d552caf10aa 100644 --- a/tests/service/ProjectAnalysisTests.fs +++ b/tests/service/ProjectAnalysisTests.fs @@ -5333,7 +5333,7 @@ let x = (1 = 3.0) let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args) [] -let ``Test line directives in foreground analysis`` () = // see https://github.com/dotnet/fsharp/issues/3317 +let ``Test diagnostics with line directives active`` () = // In background analysis and normal compiler checking, the errors are reported w.r.t. the line directives let wholeProjectResults = checker.ParseAndCheckProject(ProjectLineDirectives.options) |> Async.RunImmediate @@ -5342,17 +5342,39 @@ let ``Test line directives in foreground analysis`` () = // see https://github.c [ for e in wholeProjectResults.Diagnostics -> e.Range.StartLine, e.Range.EndLine, e.Range.FileName ] |> shouldEqual [(10, 10, "Test.fsy")] - // In foreground analysis routines, used by visual editing tools, the errors are reported w.r.t. the source - // file, which is assumed to be in the editor, not the other files referred to by line directives. - let checkResults1 = + let checkResults = checker.ParseAndCheckFileInProject(ProjectLineDirectives.fileName1, 0, ProjectLineDirectives.fileSource1, ProjectLineDirectives.options) |> Async.RunImmediate |> function _,FSharpCheckFileAnswer.Succeeded x -> x | _ -> failwith "unexpected aborted" - for e in checkResults1.Diagnostics do + for e in checkResults.Diagnostics do printfn "ProjectLineDirectives checkResults1 error file: <<<%s>>>" e.Range.FileName - [ for e in checkResults1.Diagnostics -> e.Range.StartLine, e.Range.EndLine, e.Range.FileName ] |> shouldEqual [(5, 5, ProjectLineDirectives.fileName1)] + // No diagnostics for logical location "Test.fsy" are reported when checking the source since the filenames don't match. You need to pass --ignorelinedirectives to get them + [ for e in checkResults.Diagnostics -> e.Range.StartLine, e.Range.EndLine, e.Range.FileName ] |> shouldEqual [ ] + +[] +let ``Test diagnostics with line directives ignored`` () = + + // If you pass hidden IDE flag --ignorelinedirectives, the diagnostics are reported w.r.t. the source + // file, not the files referred to by line directives. + let options = { ProjectLineDirectives.options with OtherOptions = (Array.append ProjectLineDirectives.options.OtherOptions [| "--ignorelinedirectives" |]) } + + let wholeProjectResults = checker.ParseAndCheckProject(options) |> Async.RunImmediate + for e in wholeProjectResults.Diagnostics do + printfn "ProjectLineDirectives wholeProjectResults error file: <<<%s>>>" e.Range.FileName + + [ for e in wholeProjectResults.Diagnostics -> e.Range.StartLine, e.Range.EndLine, e.Range.FileName ] |> shouldEqual [(5, 5, ProjectLineDirectives.fileName1)] + + let checkResults = + checker.ParseAndCheckFileInProject(ProjectLineDirectives.fileName1, 0, ProjectLineDirectives.fileSource1, options) + |> Async.RunImmediate + |> function _,FSharpCheckFileAnswer.Succeeded x -> x | _ -> failwith "unexpected aborted" + + for e in checkResults.Diagnostics do + printfn "ProjectLineDirectives checkResults error file: <<<%s>>>" e.Range.FileName + + [ for e in checkResults.Diagnostics -> e.Range.StartLine, e.Range.EndLine, e.Range.FileName ] |> shouldEqual [(5, 5, ProjectLineDirectives.fileName1)] //------------------------------------------------------ From d94d27e9c4252392b6ea355925e389f795cfd8e4 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 12 Jul 2022 09:17:17 +0100 Subject: [PATCH 11/11] fix build --- .../FCSBenchmarks/CompilerServiceBenchmarks/Benchmarks.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/Benchmarks.fs b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/Benchmarks.fs index 5b244d4481a..6a48e688b4e 100644 --- a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/Benchmarks.fs +++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/Benchmarks.fs @@ -136,6 +136,7 @@ type CompilerService() = DiagnosticOptions = FSharpDiagnosticOptions.Default LangVersionText = "default" IsInteractive = false + ApplyLineDirectives = false IndentationAwareSyntax = None CompilingFSharpCore = false IsExe = false