diff --git a/src/fsharp/CompilerConfig.fs b/src/fsharp/CompilerConfig.fs index c544b626f75..8751f92c834 100644 --- a/src/fsharp/CompilerConfig.fs +++ b/src/fsharp/CompilerConfig.fs @@ -316,7 +316,8 @@ type PackageManagerLine = [] type TcConfigBuilder = - { mutable primaryAssembly: PrimaryAssembly + { + mutable primaryAssembly: PrimaryAssembly mutable noFeedback: bool mutable stackReserveSize: int32 option mutable implicitIncludeDir: string (* normally "." *) @@ -400,7 +401,6 @@ type TcConfigBuilder = mutable includewin32manifest: bool mutable linkResources: string list mutable legacyReferenceResolver: LegacyReferenceResolver - mutable fxResolver: FxResolver mutable showFullPaths: bool mutable errorStyle: ErrorStyle @@ -464,7 +464,11 @@ type TcConfigBuilder = /// When false FSI will lock referenced assemblies requiring process restart, false = disable Shadow Copy false (*default*) mutable shadowCopyReferences: bool mutable useSdkRefs: bool - + mutable fxResolver: FxResolver + + /// specify the error range for FxResolver + mutable rangeForErrors: range + /// Override the SDK directory used by FxResolver, used for FCS only mutable sdkDirOverride: string option @@ -571,7 +575,6 @@ type TcConfigBuilder = includewin32manifest = true linkResources = [] legacyReferenceResolver = null - fxResolver = Unchecked.defaultof<_> showFullPaths = false errorStyle = ErrorStyle.DefaultErrors @@ -611,6 +614,8 @@ type TcConfigBuilder = copyFSharpCore = CopyFSharpCoreFlag.No shadowCopyReferences = false useSdkRefs = true + fxResolver = Unchecked.defaultof + rangeForErrors = range0 sdkDirOverride = None tryGetMetadataSnapshot = (fun _ -> None) internalTestSpanStackReferring = false @@ -638,8 +643,16 @@ type TcConfigBuilder = } |> Seq.distinct - static member CreateNew(legacyReferenceResolver, fxResolver, defaultFSharpBinariesDir, reduceMemoryUsage, implicitIncludeDir, - isInteractive, isInvalidationSupported, defaultCopyFSharpCore, tryGetMetadataSnapshot) = + static member CreateNew(legacyReferenceResolver, + defaultFSharpBinariesDir, + reduceMemoryUsage, + implicitIncludeDir, + isInteractive, + isInvalidationSupported, + defaultCopyFSharpCore, + tryGetMetadataSnapshot, + sdkDirOverride, + rangeForErrors) = Debug.Assert(FileSystem.IsPathRootedShim implicitIncludeDir, sprintf "implicitIncludeDir should be absolute: '%s'" implicitIncludeDir) @@ -647,20 +660,34 @@ type TcConfigBuilder = failwith "Expected a valid defaultFSharpBinariesDir" let tcConfigBuilder = - { TcConfigBuilder.Initial with + { TcConfigBuilder.Initial with implicitIncludeDir = implicitIncludeDir defaultFSharpBinariesDir = defaultFSharpBinariesDir reduceMemoryUsage = reduceMemoryUsage legacyReferenceResolver = legacyReferenceResolver - fxResolver = fxResolver isInteractive = isInteractive isInvalidationSupported = isInvalidationSupported copyFSharpCore = defaultCopyFSharpCore tryGetMetadataSnapshot = tryGetMetadataSnapshot useFsiAuxLib = isInteractive + rangeForErrors = rangeForErrors + sdkDirOverride = sdkDirOverride } tcConfigBuilder + member tcConfigB.FxResolver = + let resolver = + lazy (let assumeDotNetFramework = Some (tcConfigB.primaryAssembly = PrimaryAssembly.Mscorlib) + FxResolver(assumeDotNetFramework, tcConfigB.implicitIncludeDir, rangeForErrors=tcConfigB.rangeForErrors, useSdkRefs=tcConfigB.useSdkRefs, isInteractive=tcConfigB.isInteractive, sdkDirOverride=tcConfigB.sdkDirOverride)) + + if tcConfigB.fxResolver = Unchecked.defaultof then + lock tcConfigB (fun () -> + if tcConfigB.fxResolver = Unchecked.defaultof then + tcConfigB.fxResolver <- resolver.Force() + ) + + tcConfigB.fxResolver + member tcConfigB.ResolveSourceFile(m, nm, pathLoadedFrom) = use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parameter ResolveFileUsingPaths(tcConfigB.includes @ [pathLoadedFrom], m, nm) @@ -801,7 +828,7 @@ type TcConfigBuilder = member tcConfigB.AddPathMapping (oldPrefix, newPrefix) = tcConfigB.pathMap <- tcConfigB.pathMap |> PathMap.addMapping oldPrefix newPrefix - + static member SplitCommandLineResourceInfo (ri: string) = let p = ri.IndexOf ',' if p <> -1 then @@ -885,9 +912,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = #endif None, data.legacyReferenceResolver.Impl.HighestInstalledNetFrameworkVersion() - let systemAssemblies = data.fxResolver.GetSystemAssemblies() - - member x.FxResolver = data.fxResolver + member x.FxResolver = data.FxResolver member x.primaryAssembly = data.primaryAssembly member x.noFeedback = data.noFeedback member x.stackReserveSize = data.stackReserveSize @@ -1166,7 +1191,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = try FileSystem.SafeExists filename && ((tcConfig.GetTargetFrameworkDirectories() |> List.exists (fun clrRoot -> clrRoot = Path.GetDirectoryName filename)) || - (systemAssemblies.Contains (fileNameWithoutExtension filename)) || + (tcConfig.FxResolver.GetSystemAssemblies().Contains (fileNameWithoutExtension filename)) || tcConfig.FxResolver.IsInReferenceAssemblyPackDirectory filename) with _ -> false diff --git a/src/fsharp/CompilerConfig.fsi b/src/fsharp/CompilerConfig.fsi index dc7894c2c41..3a5c2b5a344 100644 --- a/src/fsharp/CompilerConfig.fsi +++ b/src/fsharp/CompilerConfig.fsi @@ -214,7 +214,6 @@ type TcConfigBuilder = mutable includewin32manifest: bool mutable linkResources: string list mutable legacyReferenceResolver: LegacyReferenceResolver - mutable fxResolver: FxResolver mutable showFullPaths: bool mutable errorStyle: ErrorStyle mutable utf8output: bool @@ -257,6 +256,8 @@ type TcConfigBuilder = mutable copyFSharpCore: CopyFSharpCoreFlag mutable shadowCopyReferences: bool mutable useSdkRefs: bool + mutable fxResolver: FxResolver + mutable rangeForErrors: range mutable sdkDirOverride: string option /// A function to call to try to get an object that acts as a snapshot of the metadata section of a .NET binary, @@ -276,16 +277,17 @@ type TcConfigBuilder = static member Initial: TcConfigBuilder - static member CreateNew: + static member CreateNew: legacyReferenceResolver: LegacyReferenceResolver * - fxResolver: FxResolver * defaultFSharpBinariesDir: string * reduceMemoryUsage: ReduceMemoryFlag * implicitIncludeDir: string * isInteractive: bool * isInvalidationSupported: bool * defaultCopyFSharpCore: CopyFSharpCoreFlag * - tryGetMetadataSnapshot: ILReaderTryGetMetadataSnapshot + tryGetMetadataSnapshot: ILReaderTryGetMetadataSnapshot * + sdkDirOverride: string option * + rangeForErrors: range -> TcConfigBuilder member DecideNames: string list -> outfile: string * pdbfile: string option * assemblyName: string @@ -317,6 +319,9 @@ type TcConfigBuilder = member AddLoadedSource: m: range * originalPath: string * pathLoadedFrom: string -> unit + member FxResolver: FxResolver + + /// Immutable TcConfig, modifications are made via a TcConfigBuilder [] type TcConfig = diff --git a/src/fsharp/FxResolver.fs b/src/fsharp/FxResolver.fs index f236fb31baf..665f142b4d0 100644 --- a/src/fsharp/FxResolver.fs +++ b/src/fsharp/FxResolver.fs @@ -119,7 +119,7 @@ type internal FxResolver(assumeDotNetFramework: bool option, projectDir: string, else -1, Array.empty, Array.empty - /// Find the relevant sdk version by running `dotnet --version` in the script/project location, + /// Find the relevant sdk version by running `dotnet --version` in the script/project location, /// taking into account any global.json let tryGetDesiredDotNetSdkVersionForDirectoryInfo() = desiredDotNetSdkVersionForDirectoryCache.GetOrAdd(projectDir, (fun _ -> @@ -763,38 +763,40 @@ type internal FxResolver(assumeDotNetFramework: bool option, projectDir: string, // The set of references entered into the TcConfigBuilder for scripts prior to computing the load closure. member _.GetDefaultReferences (useFsiAuxLib, assumeDotNetFramework) = - if assumeDotNetFramework then - getDotNetFrameworkDefaultReferences useFsiAuxLib, assumeDotNetFramework - else - if useSdkRefs then - // Go fetch references - match tryGetSdkRefsPackDirectory() with - | Some path -> - try - let sdkReferences = - [ yield! Directory.GetFiles(path, "*.dll") - yield getFSharpCoreImplementationReference() - if useFsiAuxLib then yield getFsiLibraryImplementationReference() - ] - sdkReferences, false - with _ -> + let defaultReferences = + if assumeDotNetFramework then + getDotNetFrameworkDefaultReferences useFsiAuxLib, assumeDotNetFramework + else + if useSdkRefs then + // Go fetch references + match tryGetSdkRefsPackDirectory() with + | Some path -> + try + let sdkReferences = + [ yield! Directory.GetFiles(path, "*.dll") + yield getFSharpCoreImplementationReference() + if useFsiAuxLib then yield getFsiLibraryImplementationReference() + ] + sdkReferences, false + with _ -> + if isRunningOnCoreClr then + // If running on .NET Core and something goes wrong with getting the + // .NET Core references then use .NET Core implementation assemblies for running process + getDotNetCoreImplementationReferences useFsiAuxLib, false + else + // If running on .NET Framework and something goes wrong with getting the + // .NET Core references then default back to .NET Framework and return a flag indicating this has been done + getDotNetFrameworkDefaultReferences useFsiAuxLib, true + | None -> if isRunningOnCoreClr then - // If running on .NET Core and something goes wrong with getting the - // .NET Core references then use .NET Core implementation assemblies for running process + // If running on .NET Core and there is no Sdk refs pack directory + // then use .NET Core implementation assemblies for running process getDotNetCoreImplementationReferences useFsiAuxLib, false else - // If running on .NET Framework and something goes wrong with getting the - // .NET Core references then default back to .NET Framework and return a flag indicating this has been done + // If running on .NET Framework and there is no Sdk refs pack directory + // then default back to .NET Framework and return a flag indicating this has been done getDotNetFrameworkDefaultReferences useFsiAuxLib, true - | None -> - if isRunningOnCoreClr then - // If running on .NET Core and there is no Sdk refs pack directory - // then use .NET Core implementation assemblies for running process - getDotNetCoreImplementationReferences useFsiAuxLib, false - else - // If running on .NET Framework and there is no Sdk refs pack directory - // then default back to .NET Framework and return a flag indicating this has been done - getDotNetFrameworkDefaultReferences useFsiAuxLib, true - else - getDotNetCoreImplementationReferences useFsiAuxLib, assumeDotNetFramework + else + getDotNetCoreImplementationReferences useFsiAuxLib, assumeDotNetFramework + defaultReferences diff --git a/src/fsharp/ScriptClosure.fs b/src/fsharp/ScriptClosure.fs index 9da309b4e66..27bc6ec6b12 100644 --- a/src/fsharp/ScriptClosure.fs +++ b/src/fsharp/ScriptClosure.fs @@ -123,20 +123,27 @@ module ScriptPreprocessClosure = useSimpleResolution, useFsiAuxLib, basicReferences, applyCommandLineArgs, assumeDotNetFramework, useSdkRefs, sdkDirOverride, - tryGetMetadataSnapshot, reduceMemoryUsage) = + tryGetMetadataSnapshot, reduceMemoryUsage) = let projectDir = Path.GetDirectoryName filename let isInteractive = (codeContext = CodeContext.CompilationAndEvaluation) let isInvalidationSupported = (codeContext = CodeContext.Editing) let rangeForErrors = mkFirstLineOfFile filename - let fxResolver = FxResolver(Some assumeDotNetFramework, projectDir, rangeForErrors=rangeForErrors, useSdkRefs=useSdkRefs, isInteractive=isInteractive, sdkDirOverride=sdkDirOverride) - - let tcConfigB = - TcConfigBuilder.CreateNew - (legacyReferenceResolver, fxResolver, defaultFSharpBinariesDir, reduceMemoryUsage, projectDir, - isInteractive, isInvalidationSupported, CopyFSharpCoreFlag.No, - tryGetMetadataSnapshot) + let tcConfigB = + let tcb = + TcConfigBuilder.CreateNew(legacyReferenceResolver, + defaultFSharpBinariesDir, + reduceMemoryUsage, + projectDir, + isInteractive, + isInvalidationSupported, + CopyFSharpCoreFlag.No, + tryGetMetadataSnapshot, + sdkDirOverride, + rangeForErrors) + tcb.useSdkRefs <- useSdkRefs + tcb applyCommandLineArgs tcConfigB @@ -147,7 +154,7 @@ module ScriptPreprocessClosure = | None -> let errorLogger = CapturingErrorLogger("ScriptDefaultReferences") use unwindEL = PushErrorLoggerPhaseUntilUnwind (fun _ -> errorLogger) - let references, assumeDotNetFramework = fxResolver.GetDefaultReferences (useFsiAuxLib, assumeDotNetFramework) + let references, assumeDotNetFramework = tcConfigB.FxResolver.GetDefaultReferences (useFsiAuxLib, assumeDotNetFramework) // Add script references for reference in references do tcConfigB.AddReferencedAssemblyByPath(range0, reference) diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index 82b45bb1d34..8247b48805d 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -445,16 +445,20 @@ let main1(ctok, argv, legacyReferenceResolver, bannerAlreadyPrinted, let tryGetMetadataSnapshot = (fun _ -> None) - let fxResolver = FxResolver(None, directoryBuildingFrom, rangeForErrors=range0, useSdkRefs=true, isInteractive=false, sdkDirOverride=None) - let defaultFSharpBinariesDir = FSharpEnvironment.BinFolderOfDefaultFSharpCompiler(FSharpEnvironment.tryCurrentDomain()).Value - let tcConfigB = - TcConfigBuilder.CreateNew(legacyReferenceResolver, fxResolver, defaultFSharpBinariesDir, - reduceMemoryUsage=reduceMemoryUsage, implicitIncludeDir=directoryBuildingFrom, - isInteractive=false, isInvalidationSupported=false, - defaultCopyFSharpCore=defaultCopyFSharpCore, - tryGetMetadataSnapshot=tryGetMetadataSnapshot) + let tcConfigB = + TcConfigBuilder.CreateNew(legacyReferenceResolver, + defaultFSharpBinariesDir, + reduceMemoryUsage=reduceMemoryUsage, + implicitIncludeDir=directoryBuildingFrom, + isInteractive=false, + isInvalidationSupported=false, + defaultCopyFSharpCore=defaultCopyFSharpCore, + tryGetMetadataSnapshot=tryGetMetadataSnapshot, + sdkDirOverride=None, + rangeForErrors=range0 + ) // Preset: --optimize+ -g --tailcalls+ (see 4505) SetOptimizeSwitch tcConfigB OptionSwitch.On @@ -464,8 +468,8 @@ let main1(ctok, argv, legacyReferenceResolver, bannerAlreadyPrinted, // Now install a delayed logger to hold all errors from flags until after all flags have been parsed (for example, --vserrors) let delayForFlagsLogger = errorLoggerProvider.CreateDelayAndForwardLogger exiter - let _unwindEL_1 = PushErrorLoggerPhaseUntilUnwind (fun _ -> delayForFlagsLogger) - + let _unwindEL_1 = PushErrorLoggerPhaseUntilUnwind (fun _ -> delayForFlagsLogger) + // Share intern'd strings across all lexing/parsing let lexResourceManager = new Lexhelp.LexResourceManager() @@ -482,10 +486,7 @@ let main1(ctok, argv, legacyReferenceResolver, bannerAlreadyPrinted, with e -> errorRecovery e rangeStartup delayForFlagsLogger.ForwardDelayedDiagnostics tcConfigB - exiter.Exit 1 - - let assumeDotNetFramework = (tcConfigB.primaryAssembly = PrimaryAssembly.Mscorlib) - tcConfigB.fxResolver <- FxResolver(Some assumeDotNetFramework, directoryBuildingFrom, rangeForErrors=range0, useSdkRefs=true, isInteractive=false, sdkDirOverride=None) + exiter.Exit 1 tcConfigB.conditionalCompilationDefines <- "COMPILED" :: tcConfigB.conditionalCompilationDefines @@ -633,16 +634,16 @@ let main1OfAst let directoryBuildingFrom = Directory.GetCurrentDirectory() - let fxResolver = FxResolver(None, directoryBuildingFrom, rangeForErrors=range0, useSdkRefs=true, isInteractive=false, sdkDirOverride=None) - let defaultFSharpBinariesDir = FSharpEnvironment.BinFolderOfDefaultFSharpCompiler(FSharpEnvironment.tryCurrentDomain()).Value let tcConfigB = - TcConfigBuilder.CreateNew(legacyReferenceResolver, fxResolver, defaultFSharpBinariesDir, + TcConfigBuilder.CreateNew(legacyReferenceResolver, defaultFSharpBinariesDir, reduceMemoryUsage=reduceMemoryUsage, implicitIncludeDir=directoryBuildingFrom, isInteractive=false, isInvalidationSupported=false, defaultCopyFSharpCore=CopyFSharpCoreFlag.No, - tryGetMetadataSnapshot=tryGetMetadataSnapshot) + tryGetMetadataSnapshot=tryGetMetadataSnapshot, + sdkDirOverride=None, + rangeForErrors=range0) let primaryAssembly = // temporary workaround until https://github.com/dotnet/fsharp/pull/8043 is merged: diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index aeb6522c730..2690d3e8da0 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -841,7 +841,7 @@ type internal FsiCommandLineOptions(fsi: FsiEvaluationSessionHostConfig, member _.WriteReferencesAndExit = writeReferencesAndExit member _.DependencyProvider = dependencyProvider - member _.FxResolver = tcConfigB.fxResolver + member _.FxResolver = tcConfigB.FxResolver /// Set the current ui culture for the current thread. let internal SetCurrentUICultureForThread (lcid : int option) = @@ -2757,21 +2757,17 @@ type FsiEvaluationSession (fsi: FsiEvaluationSessionHostConfig, argv:string[], i | None -> SimulatedMSBuildReferenceResolver.getResolver() | Some rr -> rr - // We know the target framework up front - let assumeDotNetFramework = not FSharpEnvironment.isRunningOnCoreClr - - let fxResolver = FxResolver(Some assumeDotNetFramework, currentDirectory, rangeForErrors=range0, useSdkRefs=true, isInteractive=true, sdkDirOverride=None) - let tcConfigB = - TcConfigBuilder.CreateNew(legacyReferenceResolver, - fxResolver, - defaultFSharpBinariesDir=defaultFSharpBinariesDir, - reduceMemoryUsage=ReduceMemoryFlag.Yes, - implicitIncludeDir=currentDirectory, - isInteractive=true, - isInvalidationSupported=false, - defaultCopyFSharpCore=CopyFSharpCoreFlag.No, - tryGetMetadataSnapshot=tryGetMetadataSnapshot) + TcConfigBuilder.CreateNew(legacyReferenceResolver, + defaultFSharpBinariesDir=defaultFSharpBinariesDir, + reduceMemoryUsage=ReduceMemoryFlag.Yes, + implicitIncludeDir=currentDirectory, + isInteractive=true, + isInvalidationSupported=false, + defaultCopyFSharpCore=CopyFSharpCoreFlag.No, + tryGetMetadataSnapshot=tryGetMetadataSnapshot, + sdkDirOverride=None, + rangeForErrors=range0) let tcConfigP = TcConfigProvider.BasedOnMutableBuilder(tcConfigB) do tcConfigB.resolutionEnvironment <- LegacyResolutionEnvironment.CompilationAndEvaluation // See Bug 3608 @@ -2803,7 +2799,7 @@ type FsiEvaluationSession (fsi: FsiEvaluationSessionHostConfig, argv:string[], i let updateBannerText() = tcConfigB.productNameForBannerText <- FSIstrings.SR.fsiProductName(FSharpEnvironment.FSharpBannerVersion) - + do updateBannerText() // setting the correct banner so that 'fsi -?' display the right thing let fsiOptions = FsiCommandLineOptions(fsi, argv, tcConfigB, fsiConsoleOutput) diff --git a/src/fsharp/service/IncrementalBuild.fs b/src/fsharp/service/IncrementalBuild.fs index 735e600b98a..5ef7abbc243 100755 --- a/src/fsharp/service/IncrementalBuild.fs +++ b/src/fsharp/service/IncrementalBuild.fs @@ -1303,29 +1303,32 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput | Some idx -> Some(commandLineArgs.[idx].Substring(switchString.Length)) | _ -> None - let assumeDotNetFramework = - match loadClosureOpt with - | None -> None - | Some loadClosure -> Some loadClosure.UseDesktopFramework - let sdkDirOverride = match loadClosureOpt with | None -> None | Some loadClosure -> loadClosure.SdkDirOverride - let fxResolver = FxResolver(assumeDotNetFramework, projectDirectory, rangeForErrors=range0, useSdkRefs=true, isInteractive=false, sdkDirOverride=sdkDirOverride) - // see also fsc.fs: runFromCommandLineToImportingAssemblies(), as there are many similarities to where the PS creates a tcConfigB - let tcConfigB = - TcConfigBuilder.CreateNew(legacyReferenceResolver, - fxResolver, - defaultFSharpBinariesDir, - implicitIncludeDir=projectDirectory, - reduceMemoryUsage=ReduceMemoryFlag.Yes, - isInteractive=useScriptResolutionRules, - isInvalidationSupported=true, - defaultCopyFSharpCore=CopyFSharpCoreFlag.No, - tryGetMetadataSnapshot=tryGetMetadataSnapshot) + let tcConfigB = + TcConfigBuilder.CreateNew(legacyReferenceResolver, + defaultFSharpBinariesDir, + implicitIncludeDir=projectDirectory, + reduceMemoryUsage=ReduceMemoryFlag.Yes, + isInteractive=useScriptResolutionRules, + isInvalidationSupported=true, + defaultCopyFSharpCore=CopyFSharpCoreFlag.No, + tryGetMetadataSnapshot=tryGetMetadataSnapshot, + sdkDirOverride=sdkDirOverride, + rangeForErrors=range0) + + tcConfigB.primaryAssembly <- + match loadClosureOpt with + | None -> PrimaryAssembly.Mscorlib + | Some loadClosure -> + if loadClosure.UseDesktopFramework then + PrimaryAssembly.Mscorlib + else + PrimaryAssembly.System_Runtime tcConfigB.resolutionEnvironment <- (LegacyResolutionEnvironment.EditingOrCompilation true)