diff --git a/FSharp.Compiler.Service.sln b/FSharp.Compiler.Service.sln index ed82699919d..405a3f4a6d4 100644 --- a/FSharp.Compiler.Service.sln +++ b/FSharp.Compiler.Service.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.30503.244 MinimumVisualStudioVersion = 10.0.40219.1 Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Service", "src\fsharp\FSharp.Compiler.Service\FSharp.Compiler.Service.fsproj", "{A59DB8AE-8044-41A5-848A-800A7FF31C93}" EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Service.Tests", "tests\FSharp.Compiler.Service.Tests\FSharp.Compiler.Service.Tests.fsproj", "{8D9C9683-5041-48AB-8FA9-0939D2D27D33}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {A59DB8AE-8044-41A5-848A-800A7FF31C93}.Debug|Any CPU.Build.0 = Debug|Any CPU {A59DB8AE-8044-41A5-848A-800A7FF31C93}.Release|Any CPU.ActiveCfg = Release|Any CPU {A59DB8AE-8044-41A5-848A-800A7FF31C93}.Release|Any CPU.Build.0 = Release|Any CPU + {8D9C9683-5041-48AB-8FA9-0939D2D27D33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8D9C9683-5041-48AB-8FA9-0939D2D27D33}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8D9C9683-5041-48AB-8FA9-0939D2D27D33}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8D9C9683-5041-48AB-8FA9-0939D2D27D33}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/INTERNAL.md b/INTERNAL.md index 3497fa588c8..81d5c2ae199 100644 --- a/INTERNAL.md +++ b/INTERNAL.md @@ -17,6 +17,10 @@ navigating through an existing PR. [VS 15.0 to 15.5](https://dev.azure.com/devdiv/DevDiv/_build?definitionId=5037) +## Branch auto-merge definitions + +Branch auto-merge definitions are specified [here](https://github.com/dotnet/roslyn-tools/blob/master/src/GitHubCreateMergePRs/config.xml). + ## VS Insertion Generators VS 16.4 to current - part of the build definition. [See below](#vs-insertions-as-part-of-the-build-definition). diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 63dba3fed83..0759d5899fa 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -2308,8 +2308,6 @@ type TcConfigBuilder = mutable pathMap: PathMap mutable langVersion: LanguageVersion - - mutable dependencyProvider: DependencyProvider } static member Initial = @@ -2449,7 +2447,6 @@ type TcConfigBuilder = noConditionalErasure = false pathMap = PathMap.empty langVersion = LanguageVersion("default") - dependencyProvider = Unchecked.defaultof } // Directories to start probing in @@ -2459,13 +2456,17 @@ type TcConfigBuilder = // 2. compilerToolPath directories // 3. reference dll's // 4. The implicit include directory - member private tcConfigB.nativeProbingRoots () = + // + // NOTE: it is important this is a delayed IEnumerable sequence. It is recomputed + // each time a resolution happens and additional paths may be added as a result. + member tcConfigB.GetNativeProbingRoots () = seq { yield! tcConfigB.includes yield! tcConfigB.compilerToolPaths yield! (tcConfigB.referencedDLLs |> Seq.map(fun ref -> Path.GetDirectoryName(ref.Text))) yield tcConfigB.implicitIncludeDir - } |> Seq.distinct + } + |> Seq.distinct static member CreateNew(legacyReferenceResolver, defaultFSharpBinariesDir, reduceMemoryUsage, implicitIncludeDir, isInteractive, isInvalidationSupported, defaultCopyFSharpCore, tryGetMetadataSnapshot) = @@ -2487,7 +2488,6 @@ type TcConfigBuilder = tryGetMetadataSnapshot = tryGetMetadataSnapshot useFsiAuxLib = isInteractive } - tcConfigBuilder.dependencyProvider <- new DependencyProvider(NativeResolutionProbe(tcConfigBuilder.nativeProbingRoots)) tcConfigBuilder member tcConfigB.ResolveSourceFile(m, nm, pathLoadedFrom) = @@ -2599,6 +2599,32 @@ type TcConfigBuilder = member tcConfigB.AddDependencyManagerText (packageManager: IDependencyManagerProvider, lt, m, path: string) = tcConfigB.packageManagerLines <- PackageManagerLine.AddLineWithKey packageManager.Key lt path m tcConfigB.packageManagerLines + member tcConfigB.AddReferenceDirective (dependencyProvider: DependencyProvider, m, path: string, directive) = + let output = tcConfigB.outputDir |> Option.defaultValue "" + + let reportError = + ResolvingErrorReport (fun errorType err msg -> + let error = err, msg + match errorType with + | ErrorReportType.Warning -> warning(Error(error, m)) + | ErrorReportType.Error -> errorR(Error(error, m))) + + let dm = dependencyProvider.TryFindDependencyManagerInPath(tcConfigB.compilerToolPaths, output , reportError, path) + + match dm with + | _, dependencyManager when not(isNull dependencyManager) -> + if tcConfigB.langVersion.SupportsFeature(LanguageFeature.PackageManagement) then + tcConfigB.AddDependencyManagerText (dependencyManager, directive, m, path) + else + errorR(Error(FSComp.SR.packageManagementRequiresVFive(), m)) + + | _, _ when directive = Directive.Include -> + errorR(Error(FSComp.SR.poundiNotSupportedByRegisteredDependencyManagers(), m)) + + // #r "Assembly" + | path, _ -> + tcConfigB.AddReferencedAssemblyByPath (m, path) + member tcConfigB.RemoveReferencedAssemblyByPath (m, path) = tcConfigB.referencedDLLs <- tcConfigB.referencedDLLs |> List.filter (fun ar -> not (Range.equals ar.Range m) || ar.Text <> path) @@ -2920,8 +2946,6 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = member x.legacyReferenceResolver = data.legacyReferenceResolver - member x.dependencyProvider = data.dependencyProvider - member tcConfig.CloneOfOriginalBuilder = { data with conditionalCompilationDefines=data.conditionalCompilationDefines } @@ -3290,6 +3314,8 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = member tcConfig.CoreLibraryDllReference() = fslibReference + member tcConfig.GetNativeProbingRoots() = data.GetNativeProbingRoots() + let ReportWarning options err = warningOn err (options.WarnLevel) (options.WarnOn) && not (List.contains (GetDiagnosticNumber err) (options.WarnOff)) @@ -3999,7 +4025,9 @@ and TcImportsWeakHack (tcImports: WeakReference) = /// Represents a table of imported assemblies with their resolutions. /// Is a disposable object, but it is recommended not to explicitly call Dispose unless you absolutely know nothing will be using its contents after the disposal. /// Otherwise, simply allow the GC to collect this and it will properly call Dispose from the finalizer. -and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAssemblyResolutions, importsBase: TcImports option, ilGlobalsOpt, compilationThread: ICompilationThread) as this = +and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAssemblyResolutions, importsBase: TcImports option, + ilGlobalsOpt, compilationThread: ICompilationThread, + dependencyProviderOpt: DependencyProvider option) as this = let mutable resolutions = initialResolutions let mutable importsBase: TcImports option = importsBase @@ -4330,6 +4358,14 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse | ILScopeRef.Assembly a -> a.Name = nm | _ -> false) + member tcImports.DependencyProvider = + CheckDisposed() + match dependencyProviderOpt with + | None -> + Debug.Assert(false, "this should never be called on FrameworkTcImports") + new DependencyProvider(null, null) + | Some dependencyProvider -> dependencyProvider + member tcImports.GetImportMap() = CheckDisposed() let loaderInterface = @@ -4893,7 +4929,7 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse let tcResolutions = TcAssemblyResolutions.BuildFromPriorResolutions(ctok, tcConfig, frameworkDLLs, []) let tcAltResolutions = TcAssemblyResolutions.BuildFromPriorResolutions(ctok, tcConfig, nonFrameworkDLLs, []) - let frameworkTcImports = new TcImports(tcConfigP, tcResolutions, None, None, tcConfig.compilationThread) + let frameworkTcImports = new TcImports(tcConfigP, tcResolutions, None, None, tcConfig.compilationThread, None) // Fetch the primaryAssembly from the referenced assemblies otherwise let primaryAssemblyReference = @@ -5019,24 +5055,27 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse |> List.map (function UnresolvedAssemblyReference(file, originalReferences) -> file, originalReferences) |> List.iter reportAssemblyNotResolved - static member BuildNonFrameworkTcImports (ctok, tcConfigP: TcConfigProvider, tcGlobals: TcGlobals, baseTcImports, nonFrameworkReferences, knownUnresolved) = + static member BuildNonFrameworkTcImports + (ctok, tcConfigP: TcConfigProvider, tcGlobals: TcGlobals, baseTcImports, + nonFrameworkReferences, knownUnresolved, dependencyProvider) = + cancellable { let tcConfig = tcConfigP.Get ctok let tcResolutions = TcAssemblyResolutions.BuildFromPriorResolutions(ctok, tcConfig, nonFrameworkReferences, knownUnresolved) let references = tcResolutions.GetAssemblyResolutions() - let tcImports = new TcImports(tcConfigP, tcResolutions, Some baseTcImports, Some tcGlobals.ilg, tcConfig.compilationThread) + let tcImports = new TcImports(tcConfigP, tcResolutions, Some baseTcImports, Some tcGlobals.ilg, tcConfig.compilationThread, Some dependencyProvider) let! _assemblies = tcImports.RegisterAndImportReferencedAssemblies(ctok, references) tcImports.ReportUnresolvedAssemblyReferences knownUnresolved return tcImports } - static member BuildTcImports(ctok, tcConfigP: TcConfigProvider) = + static member BuildTcImports(ctok, tcConfigP: TcConfigProvider, dependencyProvider) = cancellable { let tcConfig = tcConfigP.Get ctok //let foundationalTcImports, tcGlobals = TcImports.BuildFoundationalTcImports tcConfigP let frameworkDLLs, nonFrameworkReferences, knownUnresolved = TcAssemblyResolutions.SplitNonFoundationalResolutions(ctok, tcConfig) let! tcGlobals, frameworkTcImports = TcImports.BuildFrameworkTcImports (ctok, tcConfigP, frameworkDLLs, nonFrameworkReferences) - let! tcImports = TcImports.BuildNonFrameworkTcImports(ctok, tcConfigP, tcGlobals, frameworkTcImports, nonFrameworkReferences, knownUnresolved) + let! tcImports = TcImports.BuildNonFrameworkTcImports(ctok, tcConfigP, tcGlobals, frameworkTcImports, nonFrameworkReferences, knownUnresolved, dependencyProvider) return tcGlobals, tcImports } @@ -5066,10 +5105,12 @@ let RequireDLL (ctok, tcImports: TcImports, tcEnv, thisAssemblyName, m, file) = let ProcessMetaCommandsFromInput (nowarnF: 'state -> range * string -> 'state, - dllRequireF: 'state -> range * string -> 'state, - packageRequireF: 'state -> IDependencyManagerProvider * Directive * range * string -> 'state, + hashReferenceF: 'state -> range * string * Directive -> 'state, loadSourceF: 'state -> range * string -> unit) - (tcConfig:TcConfigBuilder, inp, pathOfMetaCommandSource, state0) = + (tcConfig:TcConfigBuilder, + inp: ParsedInput, + pathOfMetaCommandSource, + state0) = use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse @@ -5078,50 +5119,25 @@ let ProcessMetaCommandsFromInput | ParsedInput.SigFile (_) -> false | ParsedInput.ImplFile (ParsedImplFileInput (isScript = isScript)) -> isScript - let ProcessMetaCommand state hash = - let mutable matchedm = range0 - try - let processDependencyManagerDirectives directive args m = - if not canHaveScriptMetaCommands then - errorR(HashReferenceNotAllowedInNonScript m) - - let reportError = - let report errorType err msg = - let error = err, msg - match errorType with - | ErrorReportType.Warning -> warning(Error(error, m)) - | ErrorReportType.Error -> errorR(Error(error, m)) - ResolvingErrorReport (report) - - match args with - | [path] -> - matchedm <- m - let output = tcConfig.outputDir |> Option.defaultValue "" - let dm = tcConfig.dependencyProvider.TryFindDependencyManagerInPath(tcConfig.compilerToolPaths, output , reportError, path) - match dm with - | _, dependencyManager when not(isNull dependencyManager) -> - if tcConfig.langVersion.SupportsFeature(LanguageFeature.PackageManagement) then - packageRequireF state (dependencyManager, directive, m, path) - else - errorR(Error(FSComp.SR.packageManagementRequiresVFive(), m)) - state + let ProcessDependencyManagerDirective directive args m state = + if not canHaveScriptMetaCommands then + errorR(HashReferenceNotAllowedInNonScript m) - | _, _ when directive = Directive.Include -> - errorR(Error(FSComp.SR.poundiNotSupportedByRegisteredDependencyManagers(), m)) - state + match args with + | [path] -> + let p = + if String.IsNullOrWhiteSpace(path) then "" + else path - // #r "Assembly" - | path, _ -> - let p = - if String.IsNullOrWhiteSpace(path) then "" - else path + hashReferenceF state (m, p, directive) - dllRequireF state (m, p) - - | _ -> - errorR(Error(FSComp.SR.buildInvalidHashrDirective(), m)) - state + | _ -> + errorR(Error(FSComp.SR.buildInvalidHashrDirective(), m)) + state + let ProcessMetaCommand state hash = + let mutable matchedm = range0 + try match hash with | ParsedHashDirective("I", args, m) -> if not canHaveScriptMetaCommands then @@ -5138,10 +5154,12 @@ let ProcessMetaCommandsFromInput List.fold (fun state d -> nowarnF state (m,d)) state numbers | ParsedHashDirective(("reference" | "r"), args, m) -> - processDependencyManagerDirectives Directive.Resolution args m + matchedm<-m + ProcessDependencyManagerDirective Directive.Resolution args m state | ParsedHashDirective(("i"), args, m) -> - processDependencyManagerDirectives Directive.Include args m + matchedm<-m + ProcessDependencyManagerDirective Directive.Include args m state | ParsedHashDirective("load", args, m) -> if not canHaveScriptMetaCommands then @@ -5217,20 +5235,22 @@ let ApplyNoWarnsToTcConfig (tcConfig: TcConfig, inp: ParsedInput, pathOfMetaComm // Clone let tcConfigB = tcConfig.CloneOfOriginalBuilder let addNoWarn = fun () (m,s) -> tcConfigB.TurnWarningOff(m, s) - let addReferencedAssemblyByPath = fun () (_m,_s) -> () - let addDependencyManagerText = fun () (_prefix, _lt, _m, _s) -> () - let addLoadedSource = fun () (_m,_s) -> () - ProcessMetaCommandsFromInput (addNoWarn, addReferencedAssemblyByPath, addDependencyManagerText, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ()) + let addReference = fun () (_m, _s, _) -> () + let addLoadedSource = fun () (_m, _s) -> () + ProcessMetaCommandsFromInput + (addNoWarn, addReference, addLoadedSource) + (tcConfigB, inp, pathOfMetaCommandSource, ()) TcConfig.Create(tcConfigB, validate=false) -let ApplyMetaCommandsFromInputToTcConfig (tcConfig: TcConfig, inp: ParsedInput, pathOfMetaCommandSource) = +let ApplyMetaCommandsFromInputToTcConfig (tcConfig: TcConfig, inp: ParsedInput, pathOfMetaCommandSource, dependencyProvider) = // Clone let tcConfigB = tcConfig.CloneOfOriginalBuilder let getWarningNumber = fun () _ -> () - let addReferencedAssemblyByPath = fun () (m,s) -> tcConfigB.AddReferencedAssemblyByPath(m,s) - let addDependencyManagerText = fun () (packageManager, lt, m,s) -> tcConfigB.AddDependencyManagerText(packageManager, lt, m, s) + let addReferenceDirective = fun () (m, path, directive) -> tcConfigB.AddReferenceDirective(dependencyProvider, m, path, directive) let addLoadedSource = fun () (m,s) -> tcConfigB.AddLoadedSource(m,s,pathOfMetaCommandSource) - ProcessMetaCommandsFromInput (getWarningNumber, addReferencedAssemblyByPath, addDependencyManagerText, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ()) + ProcessMetaCommandsFromInput + (getWarningNumber, addReferenceDirective, addLoadedSource) + (tcConfigB, inp, pathOfMetaCommandSource, ()) TcConfig.Create(tcConfigB, validate=false) //---------------------------------------------------------------------------- @@ -5254,22 +5274,34 @@ type LoadClosureInput = type LoadClosure = { /// 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 pacakge references along with the ranges of the #r positions in each file. + PackageReferences: (range * string 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 #load, including those that didn't resolve OriginalLoadReferences: (range * string * string) list + /// The #nowarns NoWarns: (string * range list) list + /// Diagnostics seen while processing resolutions ResolutionDiagnostics: (PhasedDiagnostic * bool) list + /// Diagnostics seen while parsing root of closure AllRootFileDiagnostics: (PhasedDiagnostic * bool) list + /// Diagnostics seen while processing the compiler options implied root of closure - LoadClosureRootFileDiagnostics: (PhasedDiagnostic * bool) list } + LoadClosureRootFileDiagnostics: (PhasedDiagnostic * bool) list + } [] @@ -5334,8 +5366,8 @@ module ScriptPreprocessClosure = let tcConfigB = TcConfigBuilder.CreateNew (legacyReferenceResolver, defaultFSharpBinariesDir, reduceMemoryUsage, projectDir, - isInteractive, isInvalidationSupported, defaultCopyFSharpCore=CopyFSharpCoreFlag.No, - tryGetMetadataSnapshot=tryGetMetadataSnapshot) + isInteractive, isInvalidationSupported, CopyFSharpCoreFlag.No, + tryGetMetadataSnapshot) applyCommandLineArgs tcConfigB @@ -5372,16 +5404,16 @@ module ScriptPreprocessClosure = [] let ApplyMetaCommandsFromInputToTcConfigAndGatherNoWarn - (tcConfig: TcConfig, inp: ParsedInput, pathOfMetaCommandSource) = + (tcConfig: TcConfig, inp: ParsedInput, + pathOfMetaCommandSource, dependencyProvider) = let tcConfigB = tcConfig.CloneOfOriginalBuilder let mutable nowarns = [] let getWarningNumber = fun () (m, s) -> nowarns <- (s, m) :: nowarns - let addReferencedAssemblyByPath = fun () (m, s) -> tcConfigB.AddReferencedAssemblyByPath(m, s) - let addDependencyManagerText = fun () (packageManagerPrefix, lt, m, s) -> tcConfigB.AddDependencyManagerText(packageManagerPrefix, lt, m, s) + let addReferenceDirective = fun () (m, s, directive) -> tcConfigB.AddReferenceDirective(dependencyProvider, m, s, directive) let addLoadedSource = fun () (m, s) -> tcConfigB.AddLoadedSource(m, s, pathOfMetaCommandSource) try - ProcessMetaCommandsFromInput (getWarningNumber, addReferencedAssemblyByPath, addDependencyManagerText, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ()) + ProcessMetaCommandsFromInput (getWarningNumber, addReferenceDirective, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ()) with ReportedError _ -> // Recover by using whatever did end up in the tcConfig () @@ -5393,11 +5425,15 @@ module ScriptPreprocessClosure = let tcConfigB = tcConfig.CloneOfOriginalBuilder TcConfig.Create(tcConfigB, validate=false), nowarns - let FindClosureFiles(mainFile, _m, closureSources, origTcConfig:TcConfig, codeContext, lexResourceManager: Lexhelp.LexResourceManager) = + let FindClosureFiles + (mainFile, _m, closureSources, origTcConfig:TcConfig, + codeContext, lexResourceManager: Lexhelp.LexResourceManager, dependencyProvider: DependencyProvider) = + let mutable tcConfig = origTcConfig let observedSources = Observed() let loadScripts = HashSet<_>() + let packageReferences = Dictionary(HashIdentity.Structural) // Resolve the packages let rec resolveDependencyManagerSources scriptName = @@ -5408,20 +5444,19 @@ module ScriptPreprocessClosure = | [] -> () | { Directive=_; LineStatus=_; Line=_; Range=m } :: _ -> let reportError = - let report errorType err msg = + ResolvingErrorReport (fun errorType err msg -> let error = err, msg match errorType with | ErrorReportType.Warning -> warning(Error(error, m)) - | ErrorReportType.Error -> errorR(Error(error, m)) - ResolvingErrorReport (report) + | ErrorReportType.Error -> errorR(Error(error, m))) match origTcConfig.packageManagerLines |> Map.tryFind packageManagerKey with | Some oldDependencyManagerLines when oldDependencyManagerLines = packageManagerLines -> () | _ -> let outputDir = tcConfig.outputDir |> Option.defaultValue "" - match tcConfig.dependencyProvider.TryFindDependencyManagerByKey(tcConfig.compilerToolPaths, outputDir, reportError, packageManagerKey) with + match dependencyProvider.TryFindDependencyManagerByKey(tcConfig.compilerToolPaths, outputDir, reportError, packageManagerKey) with | null -> - errorR(Error(tcConfig.dependencyProvider.CreatePackageManagerUnknownError(tcConfig.compilerToolPaths, outputDir, packageManagerKey, reportError), m)) + errorR(Error(dependencyProvider.CreatePackageManagerUnknownError(tcConfig.compilerToolPaths, outputDir, packageManagerKey, reportError), m)) | dependencyManager -> let directive d = @@ -5430,10 +5465,15 @@ module ScriptPreprocessClosure = | Directive.Include -> "i" let packageManagerTextLines = packageManagerLines |> List.map(fun l -> directive l.Directive, l.Line) - let result = tcConfig.dependencyProvider.Resolve(dependencyManager, ".fsx", packageManagerTextLines, reportError, executionTfm, executionRid, tcConfig.implicitIncludeDir, mainFile, scriptName) - match result.Success with - | true -> + let result = dependencyProvider.Resolve(dependencyManager, ".fsx", packageManagerTextLines, reportError, executionTfm, executionRid, tcConfig.implicitIncludeDir, mainFile, scriptName) + if result.Success then // Resolution produced no errors + //Write outputs in F# Interactive and compiler + if codeContext <> CodeContext.Editing then + for line in result.StdOut do Console.Out.WriteLine(line) + for line in result.StdError do Console.Error.WriteLine(line) + + packageReferences.[m] <- [ for script in result.SourceFiles do yield! File.ReadAllLines script ] if not (Seq.isEmpty result.Roots) then let tcConfigB = tcConfig.CloneOfOriginalBuilder for folder in result.Roots do @@ -5446,7 +5486,11 @@ module ScriptPreprocessClosure = let iSourceText = SourceText.ofString scriptText yield! loop (ClosureSource(script, m, iSourceText, true)) - | false -> + else + // Send outputs via diagnostics + if (result.StdOut.Length > 0 || result.StdError.Length > 0) then + for line in Array.append result.StdOut result.StdError do + errorR(Error(FSComp.SR.packageManagerError(line), m)) // Resolution produced errors update packagerManagerLines entries to note these failure // failed resolutions will no longer be considered let tcConfigB = tcConfig.CloneOfOriginalBuilder @@ -5472,7 +5516,7 @@ module ScriptPreprocessClosure = let pathOfMetaCommandSource = Path.GetDirectoryName filename let preSources = tcConfig.GetAvailableLoadedSources() - let tcConfigResult, noWarns = ApplyMetaCommandsFromInputToTcConfigAndGatherNoWarn (tcConfig, parsedScriptAst, pathOfMetaCommandSource) + let tcConfigResult, noWarns = ApplyMetaCommandsFromInputToTcConfigAndGatherNoWarn (tcConfig, parsedScriptAst, pathOfMetaCommandSource, dependencyProvider) tcConfig <- tcConfigResult // We accumulate the tcConfig in order to collect assembly references yield! resolveDependencyManagerSources filename @@ -5497,10 +5541,13 @@ module ScriptPreprocessClosure = printfn "yielding non-script source %s" filename yield ClosureFile(filename, m, None, [], [], []) ] - closureSources |> List.collect loop, tcConfig + let sources = closureSources |> List.collect loop + let packageReferences = packageReferences |> Seq.map (fun kvp -> kvp.Key, kvp.Value) |> Seq.toArray + sources, tcConfig, packageReferences + /// Reduce the full directive closure into LoadClosure - let GetLoadClosure(ctok, rootFilename, closureFiles, tcConfig: TcConfig, codeContext) = + let GetLoadClosure(ctok, rootFilename, closureFiles, tcConfig: TcConfig, codeContext, packageReferences) = // Mark the last file as isLastCompiland. let closureFiles = @@ -5565,6 +5612,7 @@ module ScriptPreprocessClosure = let result: LoadClosure = { SourceFiles = List.groupBy fst sourceFiles |> List.map (map2Of2 (List.map snd)) References = List.groupBy fst references |> List.map (map2Of2 (List.map snd)) + PackageReferences = packageReferences UnresolvedReferences = unresolvedReferences Inputs = sourceInputs NoWarns = List.groupBy fst globalNoWarns |> List.map (map2Of2 (List.map snd)) @@ -5582,7 +5630,7 @@ module ScriptPreprocessClosure = useSimpleResolution, useFsiAuxLib, useSdkRefs, lexResourceManager: Lexhelp.LexResourceManager, applyCommandLineArgs, assumeDotNetFramework, - tryGetMetadataSnapshot, reduceMemoryUsage) = + tryGetMetadataSnapshot, reduceMemoryUsage, dependencyProvider) = // Resolve the basic references such as FSharp.Core.dll first, before processing any #I directives in the script // @@ -5606,16 +5654,19 @@ module ScriptPreprocessClosure = tryGetMetadataSnapshot, reduceMemoryUsage) let closureSources = [ClosureSource(filename, range0, sourceText, true)] - let closureFiles, tcConfig = FindClosureFiles(filename, range0, closureSources, tcConfig, codeContext, lexResourceManager) - GetLoadClosure(ctok, filename, closureFiles, tcConfig, codeContext) + let closureFiles, tcConfig, packageReferences = FindClosureFiles(filename, range0, closureSources, tcConfig, codeContext, lexResourceManager, dependencyProvider) + GetLoadClosure(ctok, filename, closureFiles, tcConfig, codeContext, packageReferences) /// Given source filename, find the full load closure /// Used from fsi.fs and fsc.fs, for #load and command line - let GetFullClosureOfScriptFiles(ctok, tcConfig:TcConfig, files:(string*range) list,codeContext,lexResourceManager: Lexhelp.LexResourceManager) = + let GetFullClosureOfScriptFiles + (ctok, tcConfig:TcConfig, files:(string*range) list, codeContext, + lexResourceManager: Lexhelp.LexResourceManager, dependencyProvider) = + let mainFile, mainFileRange = List.last files let closureSources = files |> List.collect (fun (filename, m) -> ClosureSourceOfFilename(filename, m,tcConfig.inputCodePage,true)) - let closureFiles,tcConfig = FindClosureFiles(mainFile, mainFileRange, closureSources, tcConfig, codeContext, lexResourceManager) - GetLoadClosure(ctok, mainFile, closureFiles, tcConfig, codeContext) + let closureFiles, tcConfig, packageReferences = FindClosureFiles(mainFile, mainFileRange, closureSources, tcConfig, codeContext, lexResourceManager, dependencyProvider) + GetLoadClosure(ctok, mainFile, closureFiles, tcConfig, codeContext, packageReferences) type LoadClosure with /// Analyze a script text and find the closure of its references. @@ -5627,20 +5678,22 @@ type LoadClosure with (ctok, legacyReferenceResolver, defaultFSharpBinariesDir, filename: string, sourceText: ISourceText, codeContext, useSimpleResolution: bool, useFsiAuxLib, useSdkRefs, lexResourceManager: Lexhelp.LexResourceManager, - applyCommandLineArgs, assumeDotNetFramework, tryGetMetadataSnapshot, reduceMemoryUsage) = + applyCommandLineArgs, assumeDotNetFramework, tryGetMetadataSnapshot, + reduceMemoryUsage, dependencyProvider) = use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse ScriptPreprocessClosure.GetFullClosureOfScriptText (ctok, legacyReferenceResolver, defaultFSharpBinariesDir, filename, sourceText, codeContext, useSimpleResolution, useFsiAuxLib, useSdkRefs, lexResourceManager, - applyCommandLineArgs, assumeDotNetFramework, tryGetMetadataSnapshot, reduceMemoryUsage) + applyCommandLineArgs, assumeDotNetFramework, tryGetMetadataSnapshot, reduceMemoryUsage, dependencyProvider) /// Analyze a set of script files and find the closure of their references. static member ComputeClosureOfScriptFiles (ctok, tcConfig: TcConfig, files:(string*range) list, codeContext, - lexResourceManager: Lexhelp.LexResourceManager) = + lexResourceManager: Lexhelp.LexResourceManager, dependencyProvider) = + use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse - ScriptPreprocessClosure.GetFullClosureOfScriptFiles (ctok, tcConfig, files, codeContext, lexResourceManager) + ScriptPreprocessClosure.GetFullClosureOfScriptFiles (ctok, tcConfig, files, codeContext, lexResourceManager, dependencyProvider) //---------------------------------------------------------------------------- // Initial type checking environment diff --git a/src/fsharp/CompileOps.fsi b/src/fsharp/CompileOps.fsi index ebedf48153d..6d138c411a6 100644 --- a/src/fsharp/CompileOps.fsi +++ b/src/fsharp/CompileOps.fsi @@ -413,8 +413,6 @@ type TcConfigBuilder = mutable pathMap : PathMap mutable langVersion : LanguageVersion - - mutable dependencyProvider: DependencyProvider } static member Initial: TcConfigBuilder @@ -443,6 +441,9 @@ type TcConfigBuilder = static member SplitCommandLineResourceInfo: string -> string * string * ILResourceAccess + // Directories to start probing in for native DLLs for FSI dynamic loading + member GetNativeProbingRoots: unit -> seq + [] // Immutable TcConfig type TcConfig = @@ -559,8 +560,8 @@ type TcConfig = member isInteractive: bool member isInvalidationSupported: bool - member ComputeLightSyntaxInitialStatus: string -> bool + member GetTargetFrameworkDirectories: unit -> string list /// Get the loaded sources that exist and issue a warning for the ones that don't @@ -575,8 +576,11 @@ type TcConfig = member MakePathAbsolute: string -> string member copyFSharpCore: CopyFSharpCoreFlag + member shadowCopyReferences: bool + member useSdkRefs: bool + member langVersion: LanguageVersion static member Create: TcConfigBuilder * validate: bool -> TcConfig @@ -640,18 +644,28 @@ type TcImports = interface System.IDisposable //new: TcImports option -> TcImports member DllTable: NameMap with get + member GetImportedAssemblies: unit -> ImportedAssembly list + member GetCcusInDeclOrder: unit -> CcuThunk list + /// This excludes any framework imports (which may be shared between multiple builds) member GetCcusExcludingBase: unit -> CcuThunk list + member FindDllInfo: CompilationThreadToken * range * string -> ImportedBinary + member TryFindDllInfo: CompilationThreadToken * range * string * lookupOnly: bool -> option + member FindCcuFromAssemblyRef: CompilationThreadToken * range * ILAssemblyRef -> CcuResolutionResult + #if !NO_EXTENSIONTYPING member ProviderGeneratedTypeRoots: ProviderGeneratedType list #endif + member GetImportMap: unit -> Import.ImportMap + member DependencyProvider: DependencyProvider + /// Try to resolve a referenced assembly based on TcConfig settings. member TryResolveAssemblyReference: CompilationThreadToken * AssemblyReference * ResolveAssemblyReferenceMode -> OperationResult @@ -671,13 +685,33 @@ type TcImports = #endif /// Report unresolved references that also weren't consumed by any type providers. member ReportUnresolvedAssemblyReferences: UnresolvedAssemblyReference list -> unit + member SystemRuntimeContainsType: string -> bool member internal Base: TcImports option - static member BuildFrameworkTcImports : CompilationThreadToken * TcConfigProvider * AssemblyResolution list * AssemblyResolution list -> Cancellable - static member BuildNonFrameworkTcImports : CompilationThreadToken * TcConfigProvider * TcGlobals * TcImports * AssemblyResolution list * UnresolvedAssemblyReference list -> Cancellable - static member BuildTcImports : CompilationThreadToken * TcConfigProvider -> Cancellable + static member BuildFrameworkTcImports: + CompilationThreadToken * + TcConfigProvider * + AssemblyResolution list * + AssemblyResolution list + -> Cancellable + + static member BuildNonFrameworkTcImports: + CompilationThreadToken * + TcConfigProvider * + TcGlobals * + TcImports * + AssemblyResolution list * + UnresolvedAssemblyReference list * + DependencyProvider + -> Cancellable + + static member BuildTcImports: + CompilationThreadToken * + TcConfigProvider * + DependencyProvider + -> Cancellable //---------------------------------------------------------------------------- // Special resources in DLLs @@ -703,24 +737,22 @@ val WriteOptimizationData: TcGlobals * filename: string * inMem: bool * CcuThunk // #r and other directives //-------------------------------------------------------------------------- -//---------------------------------------------------------------------------- -// #r and other directives -//-------------------------------------------------------------------------- - /// Process #r in F# Interactive. /// Adds the reference to the tcImports and add the ccu to the type checking environment. val RequireDLL: CompilationThreadToken * TcImports * TcEnv * thisAssemblyName: string * referenceRange: range * file: string -> TcEnv * (ImportedBinary list * ImportedAssembly list) -/// Processing # commands +/// A general routine to process hash directives val ProcessMetaCommandsFromInput : - (('T -> range * string -> 'T) * ('T -> range * string -> 'T) * ('T -> IDependencyManagerProvider * Directive * range * string -> 'T) * ('T -> range * string -> unit)) - -> TcConfigBuilder * ParsedInput * string * 'T - -> 'T + (('T -> range * string -> 'T) * + ('T -> range * string * Directive -> 'T) * + ('T -> range * string -> unit)) + -> TcConfigBuilder * ParsedInput * string * 'T + -> 'T -/// Process all the #r, #I etc. in an input -val ApplyMetaCommandsFromInputToTcConfig: TcConfig * ParsedInput * string -> TcConfig +/// Process all the #r, #I etc. in an input. For non-scripts report warnings about ignored directives. +val ApplyMetaCommandsFromInputToTcConfig: TcConfig * ParsedInput * string * DependencyProvider -> TcConfig -/// Process the #nowarn in an input +/// Process the #nowarn in an input and integrate them into the TcConfig val ApplyNoWarnsToTcConfig: TcConfig * ParsedInput * string -> TcConfig //---------------------------------------------------------------------------- @@ -827,6 +859,9 @@ type LoadClosure = /// 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 list of references that were not resolved during load closure. UnresolvedReferences: UnresolvedAssemblyReference list @@ -853,8 +888,31 @@ type LoadClosure = // /// 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: CompilationThreadToken * legacyReferenceResolver: ReferenceResolver.Resolver * defaultFSharpBinariesDir: string * filename: string * sourceText: ISourceText * implicitDefines:CodeContext * useSimpleResolution: bool * useFsiAuxLib: bool * useSdkRefs: bool * lexResourceManager: Lexhelp.LexResourceManager * applyCompilerOptions: (TcConfigBuilder -> unit) * assumeDotNetFramework: bool * tryGetMetadataSnapshot: ILReaderTryGetMetadataSnapshot * reduceMemoryUsage: ReduceMemoryFlag -> LoadClosure + static member ComputeClosureOfScriptText: + CompilationThreadToken * + legacyReferenceResolver: ReferenceResolver.Resolver * + defaultFSharpBinariesDir: string * + filename: string * + sourceText: ISourceText * + implicitDefines:CodeContext * + useSimpleResolution: bool * + useFsiAuxLib: bool * + useSdkRefs: bool * + lexResourceManager: Lexhelp.LexResourceManager * + applyCompilerOptions: (TcConfigBuilder -> unit) * + assumeDotNetFramework: bool * + tryGetMetadataSnapshot: ILReaderTryGetMetadataSnapshot * + reduceMemoryUsage: ReduceMemoryFlag * + dependencyProvider: DependencyProvider + -> LoadClosure /// Analyze a set of script files and find the closure of their references. The resulting references are then added to the given TcConfig. /// Used from fsi.fs and fsc.fs, for #load and command line. - static member ComputeClosureOfScriptFiles: CompilationThreadToken * tcConfig:TcConfig * (string * range) list * implicitDefines:CodeContext * lexResourceManager: Lexhelp.LexResourceManager -> LoadClosure + static member ComputeClosureOfScriptFiles: + CompilationThreadToken * + tcConfig:TcConfig * + (string * range) list * + implicitDefines:CodeContext * + lexResourceManager: Lexhelp.LexResourceManager * + dependencyProvider: DependencyProvider + -> LoadClosure diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 7914b2e6919..358fb27c46b 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1378,6 +1378,7 @@ keywordDescriptionAssert,"Used to verify code during debugging." keywordDescriptionBase,"Used as the name of the base class object." keywordDescriptionBegin,"In verbose syntax, indicates the start of a code block." keywordDescriptionClass,"In verbose syntax, indicates the start of a class definition." +keywordDescriptionConst,"Keyword to specify a constant literal as a type parameter argument in Type Providers." keywordDescriptionDefault,"Indicates an implementation of an abstract method; used together with an abstract method declaration to create a virtual method." keywordDescriptionDelegate,"Used to declare a delegate." keywordDescriptionDo,"Used in looping constructs or to execute imperative code." diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index aa0b3e9edbc..78ebbfc4fca 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -58,12 +58,6 @@ FSStrings.resx - - Logger.fsi - - - Logger.fs - ErrorText\sformat.fsi @@ -76,11 +70,17 @@ ErrorText\sr.fs + + Facilities\Logger.fsi + + + Facilities\Logger.fs + - Driver\LanguageFeatures.fsi + Facilities\LanguageFeatures.fsi - Driver\LanguageFeatures.fs + Facilities\LanguageFeatures.fs LexYaccRuntime\prim-lexing.fsi diff --git a/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index 9d1b6851ac0..b1f2c20fc07 100644 --- a/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -58,12 +58,6 @@ FSStrings.resx FSStrings.resources - - Logger.fsi - - - Logger.fs - ErrorText\sformat.fsi @@ -76,11 +70,17 @@ ErrorText\sr.fs + + Facilities\Logger.fsi + + + Facilities\Logger.fs + - Driver\LanguageFeatures.fsi + Facilities\LanguageFeatures.fsi - Driver\LanguageFeatures.fs + Facilities\LanguageFeatures.fs LexYaccRuntime\prim-lexing.fsi diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs b/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs index 7a8946d1e59..d6c2f2f303d 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs +++ b/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs @@ -183,11 +183,6 @@ module internal Utilities = p.WaitForExit() - if p.ExitCode <> 0 then - //Write StandardError.txt to err stream - for line in stdOut do Console.Out.WriteLine(line) - for line in stdErr do Console.Error.WriteLine(line) - p.ExitCode = 0, stdOut, stdErr | None -> false, Array.empty, Array.empty @@ -203,7 +198,7 @@ module internal Utilities = | None -> "" let arguments prefix = - sprintf "%s -restore %s %c%s%c /t:InteractivePackageManagement" prefix binLoggingArguments '\"' projectPath '\"' + sprintf "%s -restore %s %c%s%c /nologo /t:InteractivePackageManagement" prefix binLoggingArguments '\"' projectPath '\"' let workingDir = Path.GetDirectoryName projectPath diff --git a/src/fsharp/MethodCalls.fs b/src/fsharp/MethodCalls.fs index 492e3af96a6..77fa96efaa6 100644 --- a/src/fsharp/MethodCalls.fs +++ b/src/fsharp/MethodCalls.fs @@ -619,7 +619,7 @@ type ArgumentAnalysis = let InferLambdaArgsForLambdaPropagation origRhsExpr = let rec loop e = match e with - | SynExpr.Lambda (_, _, _, rest, _) -> 1 + loop rest + | SynExpr.Lambda (_, _, _, rest, _, _) -> 1 + loop rest | SynExpr.MatchLambda _ -> 1 | _ -> 0 loop origRhsExpr diff --git a/src/fsharp/Microsoft.DotNet.DependencyManager/DependencyProvider.fs b/src/fsharp/Microsoft.DotNet.DependencyManager/DependencyProvider.fs index 2146c10b750..522be2a40a5 100644 --- a/src/fsharp/Microsoft.DotNet.DependencyManager/DependencyProvider.fs +++ b/src/fsharp/Microsoft.DotNet.DependencyManager/DependencyProvider.fs @@ -8,6 +8,7 @@ open System.Reflection open System.Runtime.InteropServices open Internal.Utilities.FSharpEnvironment open Microsoft.FSharp.Reflection +open System.Collections.Concurrent [] module ReflectionHelper = @@ -67,19 +68,14 @@ module ReflectionHelper = e.InnerException | _ -> e -open ReflectionHelper -open RidHelpers - /// Indicate the type of error to report [] type ErrorReportType = | Warning | Error - type ResolvingErrorReport = delegate of ErrorReportType * int * string -> unit - (* Shape of Dependency Manager contract, resolved using reflection *) /// The results of ResolveDependencies type IResolveDependenciesResult = @@ -88,19 +84,19 @@ type IResolveDependenciesResult = abstract Success: bool /// The resolution output log - abstract StdOut: string array + abstract StdOut: string[] /// The resolution error log (* process stderror *) - abstract StdError: string array + abstract StdError: string[] /// The resolution paths - abstract Resolutions: string seq + abstract Resolutions: seq /// The source code file paths - abstract SourceFiles: string seq + abstract SourceFiles: seq /// The roots to package directories - abstract Roots: string seq + abstract Roots: seq [] @@ -267,9 +263,17 @@ type ReflectionDependencyManagerProvider(theType: Type, /// Class is IDisposable type DependencyProvider (assemblyProbingPaths: AssemblyResolutionProbe, nativeProbingRoots: NativeResolutionProbe) = - let dllResolveHandler = new NativeDllResolveHandler(nativeProbingRoots) :> IDisposable + // Note: creating a NativeDllResolveHandler currently installs process-wide handlers + let dllResolveHandler = + match nativeProbingRoots with + | null -> { new IDisposable with member _.Dispose() = () } + | _ -> new NativeDllResolveHandler(nativeProbingRoots) :> IDisposable - let assemblyResolveHandler = new AssemblyResolveHandler(assemblyProbingPaths) :> IDisposable + // Note: creating a AssemblyResolveHandler currently installs process-wide handlers + let assemblyResolveHandler = + match assemblyProbingPaths with + | null -> { new IDisposable with member _.Dispose() = () } + | _ -> new AssemblyResolveHandler(assemblyProbingPaths) :> IDisposable // Resolution Path = Location of FSharp.Compiler.Private.dll let assemblySearchPaths = lazy ( @@ -326,9 +330,11 @@ type DependencyProvider (assemblyProbingPaths: AssemblyResolutionProbe, nativePr None managers - /// Returns a formatted error message for the host to presentconstruct with just nativeProbing handler - new (nativeProbingRoots: NativeResolutionProbe) = - new DependencyProvider(Unchecked.defaultof, nativeProbingRoots) + let cache = ConcurrentDictionary<_,Result>(HashIdentity.Structural) + + new (nativeProbingRoots: NativeResolutionProbe) = new DependencyProvider(null, nativeProbingRoots) + + new () = new DependencyProvider(null, null) /// Returns a formatted help messages for registered dependencymanagers for the host to present member _.GetRegisteredDependencyManagerHelpText (compilerTools, outputDir, errorReport) = [| @@ -390,19 +396,27 @@ type DependencyProvider (assemblyProbingPaths: AssemblyResolutionProbe, nativePr []implicitIncludeDir: string, []mainScriptName: string, []fileName: string): IResolveDependenciesResult = - - try - let executionRid = - if isNull executionRid then - RidHelpers.platformRid - else - executionRid - packageManager.ResolveDependencies(implicitIncludeDir, mainScriptName, fileName, scriptExt, packageManagerTextLines, executionTfm, executionRid) - - with e -> - let e = stripTieWrapper e - let err, msg = (DependencyManager.SR.packageManagerError(e.Message)) - reportError.Invoke(ErrorReportType.Error, err, msg) + + let key = (packageManager.Key, scriptExt, Seq.toArray packageManagerTextLines, executionTfm, executionRid, implicitIncludeDir, mainScriptName, fileName) + + let result = + cache.GetOrAdd(key, System.Func<_,_>(fun _ -> + try + let executionRid = + if isNull executionRid then + RidHelpers.platformRid + else + executionRid + Ok (packageManager.ResolveDependencies(implicitIncludeDir, mainScriptName, fileName, scriptExt, packageManagerTextLines, executionTfm, executionRid)) + + with e -> + let e = stripTieWrapper e + Error (DependencyManager.SR.packageManagerError(e.Message)) + )) + match result with + | Ok res -> res + | Error (errorNumber, errorData) -> + reportError.Invoke(ErrorReportType.Error, errorNumber, errorData) ReflectionDependencyManagerProvider.MakeResultFromFields(false, arrEmpty, arrEmpty, seqEmpty, seqEmpty, seqEmpty) interface IDisposable with diff --git a/src/fsharp/Microsoft.DotNet.DependencyManager/DependencyProvider.fsi b/src/fsharp/Microsoft.DotNet.DependencyManager/DependencyProvider.fsi index 2f16b59fd99..aa9b38f88ba 100644 --- a/src/fsharp/Microsoft.DotNet.DependencyManager/DependencyProvider.fsi +++ b/src/fsharp/Microsoft.DotNet.DependencyManager/DependencyProvider.fsi @@ -56,16 +56,23 @@ type ErrorReportType = type ResolvingErrorReport = delegate of ErrorReportType * int * string -> unit /// Provides DependencyManagement functions. -/// Class is IDisposable +/// +/// The class incrementally collects IDependencyManagerProvider, indexed by key, and +/// queries them. These are found and instantiated with respect to the compilerTools and outputDir +/// provided each time the TryFindDependencyManagerByKey and TryFindDependencyManagerInPath are +/// executed, which are assumed to be invariant over the lifetime of the DependencyProvider. type DependencyProvider = interface System.IDisposable - /// Construct a new DependencyProvider - new: assemblyProbingPaths: AssemblyResolutionProbe * nativeProbingRoots: NativeResolutionProbe -> DependencyProvider + /// Construct a new DependencyProvider with no dynamic load handlers (only for compilation/analysis) + new: unit -> DependencyProvider - /// Construct a new DependencyProvider + /// Construct a new DependencyProvider with only native resolution new: nativeProbingRoots: NativeResolutionProbe -> DependencyProvider + /// Construct a new DependencyProvider with managed and native resolution + new: assemblyProbingPaths: AssemblyResolutionProbe * nativeProbingRoots: NativeResolutionProbe -> DependencyProvider + /// Returns a formatted help messages for registered dependencymanagers for the host to present member GetRegisteredDependencyManagerHelpText: string seq * string * ResolvingErrorReport -> string[] diff --git a/src/fsharp/Microsoft.DotNet.DependencyManager/NativeDllResolveHandler.fs b/src/fsharp/Microsoft.DotNet.DependencyManager/NativeDllResolveHandler.fs index 60b52982cc5..6a4477631c0 100644 --- a/src/fsharp/Microsoft.DotNet.DependencyManager/NativeDllResolveHandler.fs +++ b/src/fsharp/Microsoft.DotNet.DependencyManager/NativeDllResolveHandler.fs @@ -101,8 +101,9 @@ type NativeDllResolveHandlerCoreClr (_nativeProbingRoots: NativeResolutionProbe) let probe = match _nativeProbingRoots with | null -> None - | _ -> _nativeProbingRoots.Invoke() - |> Seq.tryPick(fun root -> + | _ -> + _nativeProbingRoots.Invoke() + |> Seq.tryPick(fun root -> probingFileNames name |> Seq.tryPick(fun name -> let path = Path.Combine(root, name) if File.Exists(path) then diff --git a/src/fsharp/Microsoft.DotNet.DependencyManager/NativeDllResolveHandler.fsi b/src/fsharp/Microsoft.DotNet.DependencyManager/NativeDllResolveHandler.fsi index c98b5f142e7..d1aa22fe49c 100644 --- a/src/fsharp/Microsoft.DotNet.DependencyManager/NativeDllResolveHandler.fsi +++ b/src/fsharp/Microsoft.DotNet.DependencyManager/NativeDllResolveHandler.fsi @@ -18,7 +18,7 @@ type NativeResolutionProbe = delegate of Unit -> seq // Cut down AssemblyLoadContext, for loading native libraries type NativeDllResolveHandler = - /// Construct a new DependencyProvider + /// Construct a new NativeDllResolveHandler new: nativeProbingRoots: NativeResolutionProbe -> NativeDllResolveHandler interface IDisposable diff --git a/src/fsharp/SyntaxTree.fs b/src/fsharp/SyntaxTree.fs index df5d2b7726b..ac2574e4eaf 100644 --- a/src/fsharp/SyntaxTree.fs +++ b/src/fsharp/SyntaxTree.fs @@ -665,6 +665,8 @@ type SynExpr = /// First bool indicates if lambda originates from a method. Patterns here are always "simple" /// Second bool indicates if this is a "later" part of an iterated sequence of lambdas + /// parsedData keeps original parsed patterns and expression, + /// prior to transforming to "simple" patterns and iterated lambdas /// /// F# syntax: fun pat -> expr | Lambda of @@ -672,6 +674,7 @@ type SynExpr = inLambdaSeq: bool * args: SynSimplePats * body: SynExpr * + parsedData: (SynPat list * SynExpr) option * range: range /// F# syntax: function pat1 -> expr | ... | patN -> exprN diff --git a/src/fsharp/SyntaxTreeOps.fs b/src/fsharp/SyntaxTreeOps.fs index a2b1949a3e6..5f83ce8fc86 100644 --- a/src/fsharp/SyntaxTreeOps.fs +++ b/src/fsharp/SyntaxTreeOps.fs @@ -200,7 +200,7 @@ let rec SimplePatsOfPat synArgNameGenerator p = | SynPat.Tuple (false, ps, m) - | SynPat.Paren(SynPat.Tuple (false, ps, m), _) -> + | SynPat.Paren(SynPat.Tuple (false, ps, _), m) -> let ps2, laterF = List.foldBack (fun (p', rhsf) (ps', rhsf') -> @@ -224,7 +224,7 @@ let rec SimplePatsOfPat synArgNameGenerator p = let PushPatternToExpr synArgNameGenerator isMember pat (rhs: SynExpr) = let nowPats, laterF = SimplePatsOfPat synArgNameGenerator pat - nowPats, SynExpr.Lambda (isMember, false, nowPats, appFunOpt laterF rhs, rhs.Range) + nowPats, SynExpr.Lambda (isMember, false, nowPats, appFunOpt laterF rhs, None, rhs.Range) let private isSimplePattern pat = let _nowPats, laterF = SimplePatsOfPat (SynArgNameGenerator()) pat @@ -253,8 +253,8 @@ let PushCurriedPatternsToExpr synArgNameGenerator wholem isMember pats rhs = match spatsl with | [] -> rhs | h :: t -> - let expr = List.foldBack (fun spats e -> SynExpr.Lambda (isMember, true, spats, e, wholem)) t rhs - let expr = SynExpr.Lambda (isMember, false, h, expr, wholem) + let expr = List.foldBack (fun spats e -> SynExpr.Lambda (isMember, true, spats, e, None, wholem)) t rhs + let expr = SynExpr.Lambda (isMember, false, h, expr, Some (pats, rhs), wholem) expr spatsl, expr @@ -330,7 +330,7 @@ let mkSynUnit m = SynExpr.Const (SynConst.Unit, m) let mkSynUnitPat m = SynPat.Const(SynConst.Unit, m) let mkSynDelay m e = - SynExpr.Lambda (false, false, SynSimplePats.SimplePats ([mkSynCompGenSimplePatVar (mkSynId m "unitVar")], m), e, m) + SynExpr.Lambda (false, false, SynSimplePats.SimplePats ([mkSynCompGenSimplePatVar (mkSynId m "unitVar")], m), e, None, m) let mkSynAssign (l: SynExpr) (r: SynExpr) = let m = unionRanges l.Range r.Range @@ -498,7 +498,7 @@ module SynInfo = let InferLambdaArgs origRhsExpr = let rec loop e = match e with - | SynExpr.Lambda (false, _, spats, rest, _) -> + | SynExpr.Lambda (false, _, spats, rest, _, _) -> InferSynArgInfoFromSimplePats spats :: loop rest | _ -> [] loop origRhsExpr @@ -692,7 +692,7 @@ let rec synExprContainsError inpExpr = | SynExpr.MatchLambda (_, _, cl, _, _) -> walkMatchClauses cl - | SynExpr.Lambda (_, _, _, e, _) -> + | SynExpr.Lambda (_, _, _, e, _, _) -> walkExpr e | SynExpr.Match (_, e, cl, _) -> diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 50dfa1b36f5..7a22f367b54 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -2670,7 +2670,7 @@ module EventDeclarationNormalization = match rhsExpr with // Detect 'fun () -> e' which results from the compilation of a property getter - | SynExpr.Lambda (_, _, SynSimplePats.SimplePats([], _), trueRhsExpr, m) -> + | SynExpr.Lambda (_, _, SynSimplePats.SimplePats([], _), trueRhsExpr, _, m) -> let rhsExpr = mkSynApp1 (SynExpr.DotGet (SynExpr.Paren (trueRhsExpr, range0, None, m), range0, LongIdentWithDots([ident(target, m)], []), m)) (SynExpr.Ident (ident(argName, m))) m // reconstitute rhsExpr @@ -6414,7 +6414,7 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) = /// Check lambdas as a group, to catch duplicate names in patterns and TcIteratedLambdas cenv isFirst (env: TcEnv) overallTy takenNames tpenv e = match e with - | SynExpr.Lambda (isMember, isSubsequent, spats, bodyExpr, m) when isMember || isFirst || isSubsequent -> + | SynExpr.Lambda (isMember, isSubsequent, spats, bodyExpr, _, m) when isMember || isFirst || isSubsequent -> let domainTy, resultTy = UnifyFunctionType None cenv env.DisplayEnv m overallTy let vs, (tpenv, names, takenNames) = TcSimplePats cenv isMember CheckCxs domainTy env (tpenv, Map.empty, takenNames) spats let envinner, _, vspecMap = MakeAndPublishSimpleValsForMergedScope cenv env m names @@ -8241,7 +8241,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder Some (nm, Option.get (tryGetDataForCustomOperation nm), core, core.Range, optIntoInfo) | _ -> None - let mkSynLambda p e m = SynExpr.Lambda (false, false, p, e, m) + let mkSynLambda p e m = SynExpr.Lambda (false, false, p, e, None, m) let mkExprForVarSpace m (patvs: Val list) = match patvs with @@ -8940,7 +8940,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder // Check for the [] attribute on each argument position let args = args |> List.mapi (fun i arg -> if isCustomOperationProjectionParameter (i+1) nm then - SynExpr.Lambda (false, false, varSpaceSimplePat, arg, arg.Range.MakeSynthetic()) + SynExpr.Lambda (false, false, varSpaceSimplePat, arg, None, arg.Range.MakeSynthetic()) else arg) mkSynCall methInfo.DisplayName mClause (dataCompPrior :: args) else @@ -9180,7 +9180,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder let lambdaExpr = let mBuilderVal = mBuilderVal.MakeSynthetic() - SynExpr.Lambda (false, false, SynSimplePats.SimplePats ([mkSynSimplePatVar false (mkSynId mBuilderVal builderValName)], mBuilderVal), runExpr, mBuilderVal) + SynExpr.Lambda (false, false, SynSimplePats.SimplePats ([mkSynSimplePatVar false (mkSynId mBuilderVal builderValName)], mBuilderVal), runExpr, None, mBuilderVal) let env = match comp with @@ -9550,6 +9550,16 @@ and TcNameOfExpr cenv env tpenv (synArg: SynExpr) = let ad = env.eAccessRights let result = defaultArg resultOpt (List.last longId) + // Demangle back to source operator name if the lengths in the ranges indicate the + // original source range matches exactly + let result = + if IsMangledOpName result.idText then + let demangled = DecompileOpName result.idText + if demangled.Length = result.idRange.EndColumn - result.idRange.StartColumn then + ident(demangled, result.idRange) + else result + else result + // Nameof resolution resolves to a symbol and in general we make that the same symbol as // would resolve if the long ident was used as an expression at the given location. // @@ -10564,7 +10574,7 @@ and GetNewInferenceTypeForMethodArg cenv env tpenv x = match x with | SynExprParen(a, _, _, _) -> GetNewInferenceTypeForMethodArg cenv env tpenv a | SynExpr.AddressOf (true, a, _, m) -> mkByrefTyWithInference cenv.g (GetNewInferenceTypeForMethodArg cenv env tpenv a) (NewByRefKindInferenceType cenv.g m) - | SynExpr.Lambda (_, _, _, a, _) -> mkFunTy (NewInferenceType ()) (GetNewInferenceTypeForMethodArg cenv env tpenv a) + | SynExpr.Lambda (_, _, _, a, _, _) -> mkFunTy (NewInferenceType ()) (GetNewInferenceTypeForMethodArg cenv env tpenv a) | SynExpr.Quote (_, raw, a, _, _) -> if raw then mkRawQuotedExprTy cenv.g else mkQuotedExprTy cenv.g (GetNewInferenceTypeForMethodArg cenv env tpenv a) diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index 4892c4a07fb..f30e913a7a4 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -50,6 +50,7 @@ open FSharp.Compiler.TypedTreeOps open FSharp.Compiler.TcGlobals open FSharp.Compiler.TypeChecker open FSharp.Compiler.XmlDoc +open Microsoft.DotNet.DependencyManager open FSharp.Compiler.AbstractIL.Internal.StrongNameSign @@ -202,7 +203,7 @@ let TypeCheck (ctok, tcConfig, tcImports, tcGlobals, errorLogger: ErrorLogger, a exiter.Exit 1 /// Check for .fsx and, if present, compute the load closure for of #loaded files. -let AdjustForScriptCompile(ctok, tcConfigB: TcConfigBuilder, commandLineSourceFiles, lexResourceManager) = +let AdjustForScriptCompile(ctok, tcConfigB: TcConfigBuilder, commandLineSourceFiles, lexResourceManager, dependencyProvider) = let combineFilePath file = try @@ -227,7 +228,8 @@ let AdjustForScriptCompile(ctok, tcConfigB: TcConfigBuilder, commandLineSourceFi if IsScript filename then let closure = LoadClosure.ComputeClosureOfScriptFiles - (ctok, tcConfig, [filename, rangeStartup], CodeContext.Compilation, lexResourceManager=lexResourceManager) + (ctok, tcConfig, [filename, rangeStartup], CodeContext.Compilation, + lexResourceManager, dependencyProvider) // Record the references from the analysis of the script. The full resolutions are recorded as the corresponding #I paths used to resolve them // are local to the scripts and not added to the tcConfigB (they are added to localized clones of the tcConfigB). @@ -1763,6 +1765,8 @@ let main0(ctok, argv, legacyReferenceResolver, bannerAlreadyPrinted, // Share intern'd strings across all lexing/parsing let lexResourceManager = new Lexhelp.LexResourceManager() + let dependencyProvider = new DependencyProvider() + // process command line, flags and collect filenames let sourceFiles = @@ -1771,7 +1775,7 @@ let main0(ctok, argv, legacyReferenceResolver, bannerAlreadyPrinted, try let sourceFiles = let files = ProcessCommandLineFlags (tcConfigB, setProcessThreadLocals, lcidFromCodePage, argv) - AdjustForScriptCompile(ctok, tcConfigB, files, lexResourceManager) + AdjustForScriptCompile(ctok, tcConfigB, files, lexResourceManager, dependencyProvider) sourceFiles with e -> @@ -1855,12 +1859,12 @@ let main0(ctok, argv, legacyReferenceResolver, bannerAlreadyPrinted, if tcConfig.printAst then inputs |> List.iter (fun (input, _filename) -> printf "AST:\n"; printfn "%+A" input; printf "\n") - let tcConfig = (tcConfig, inputs) ||> List.fold (fun z (x, m) -> ApplyMetaCommandsFromInputToTcConfig(z, x, m)) + let tcConfig = (tcConfig, inputs) ||> List.fold (fun z (x, m) -> ApplyMetaCommandsFromInputToTcConfig(z, x, m, dependencyProvider)) let tcConfigP = TcConfigProvider.Constant tcConfig // Import other assemblies ReportTime tcConfig "Import non-system references" - let tcImports = TcImports.BuildNonFrameworkTcImports(ctok, tcConfigP, tcGlobals, frameworkTcImports, otherRes, knownUnresolved) |> Cancellable.runWithoutCancellation + let tcImports = TcImports.BuildNonFrameworkTcImports(ctok, tcConfigP, tcGlobals, frameworkTcImports, otherRes, knownUnresolved, dependencyProvider) |> Cancellable.runWithoutCancellation // register tcImports to be disposed in future disposables.Register tcImports @@ -1988,6 +1992,7 @@ let main0OfAst (ctok, legacyReferenceResolver, reduceMemoryUsage, assemblyName, delayForFlagsLogger.ForwardDelayedDiagnostics tcConfigB exiter.Exit 1 + let dependencyProvider = new DependencyProvider() let errorLogger = errorLoggerProvider.CreateErrorLoggerUpToMaxErrors(tcConfigB, exiter) // Install the global error logger and never remove it. This logger does have all command-line flags considered. @@ -2010,12 +2015,12 @@ let main0OfAst (ctok, legacyReferenceResolver, reduceMemoryUsage, assemblyName, use unwindParsePhase = PushThreadBuildPhaseUntilUnwind (BuildPhase.Parse) let meta = Directory.GetCurrentDirectory() - let tcConfig = (tcConfig,inputs) ||> List.fold (fun tcc inp -> ApplyMetaCommandsFromInputToTcConfig (tcc, inp,meta)) + let tcConfig = (tcConfig,inputs) ||> List.fold (fun tcc inp -> ApplyMetaCommandsFromInputToTcConfig (tcc, inp, meta, dependencyProvider)) let tcConfigP = TcConfigProvider.Constant tcConfig // Import other assemblies ReportTime tcConfig "Import non-system references" - let tcImports = TcImports.BuildNonFrameworkTcImports(ctok, tcConfigP, tcGlobals, frameworkTcImports, otherRes, knownUnresolved) |> Cancellable.runWithoutCancellation + let tcImports = TcImports.BuildNonFrameworkTcImports(ctok, tcConfigP, tcGlobals, frameworkTcImports, otherRes, knownUnresolved, dependencyProvider) |> Cancellable.runWithoutCancellation // register tcImports to be disposed in future disposables.Register tcImports diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 8e714f71dd1..40850bd7749 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -601,7 +601,11 @@ let internal directoryName (s:string) = //---------------------------------------------------------------------------- /// Process the command line options -type internal FsiCommandLineOptions(fsi: FsiEvaluationSessionHostConfig, argv: string[], tcConfigB, fsiConsoleOutput: FsiConsoleOutput) = +type internal FsiCommandLineOptions(fsi: FsiEvaluationSessionHostConfig, + argv: string[], + tcConfigB, + fsiConsoleOutput: FsiConsoleOutput) = + let mutable enableConsoleKeyProcessing = // Mono on Win32 doesn't implement correct console processing not (runningOnMono && System.Environment.OSVersion.Platform = System.PlatformID.Win32NT) @@ -757,6 +761,9 @@ type internal FsiCommandLineOptions(fsi: FsiEvaluationSessionHostConfig, argv: s stopProcessingRecovery e range0; failwithf "Error creating evaluation session: %A" e inputFilesAcc + // We need a dependency provider with native resolution. Managed resolution is handled by generated `#r` + let dependencyProvider = new DependencyProvider(NativeResolutionProbe(tcConfigB.GetNativeProbingRoots)) + do if tcConfigB.utf8output then let prev = Console.OutputEncoding @@ -797,7 +804,7 @@ type internal FsiCommandLineOptions(fsi: FsiEvaluationSessionHostConfig, argv: s fsiConsoleOutput.uprintfn """ #help;; // %s""" (FSIstrings.SR.fsiIntroTextHashhelpInfo()) if tcConfigB.langVersion.SupportsFeature(LanguageFeature.PackageManagement) then - for msg in tcConfigB.dependencyProvider.GetRegisteredDependencyManagerHelpText(tcConfigB.compilerToolPaths, getOutputDir tcConfigB, reportError m) do + for msg in dependencyProvider.GetRegisteredDependencyManagerHelpText(tcConfigB.compilerToolPaths, getOutputDir tcConfigB, reportError m) do fsiConsoleOutput.uprintfn "%s" msg fsiConsoleOutput.uprintfn """ #quit;; // %s""" (FSIstrings.SR.fsiIntroTextHashquitInfo()) (* last thing you want to do, last thing in the list - stands out more *) @@ -824,6 +831,8 @@ type internal FsiCommandLineOptions(fsi: FsiEvaluationSessionHostConfig, argv: s member __.SourceFiles = sourceFiles member __.Gui = gui + member _.DependencyProvider = dependencyProvider + /// Set the current ui culture for the current thread. let internal SetCurrentUICultureForThread (lcid : int option) = let culture = Thread.CurrentThread.CurrentUICulture @@ -1461,9 +1470,9 @@ type internal FsiDynamicCompiler | { Directive=_; LineStatus=_; Line=_; Range=m } :: _ -> let outputDir = tcConfigB.outputDir |> Option.defaultValue "" - match tcConfigB.dependencyProvider.TryFindDependencyManagerByKey(tcConfigB.compilerToolPaths, getOutputDir tcConfigB, reportError m, packageManagerKey) with + match fsiOptions.DependencyProvider.TryFindDependencyManagerByKey(tcConfigB.compilerToolPaths, getOutputDir tcConfigB, reportError m, packageManagerKey) with | null -> - errorR(Error(tcConfigB.dependencyProvider.CreatePackageManagerUnknownError(tcConfigB.compilerToolPaths, outputDir, packageManagerKey, reportError m), m)) + errorR(Error(fsiOptions.DependencyProvider.CreatePackageManagerUnknownError(tcConfigB.compilerToolPaths, outputDir, packageManagerKey, reportError m), m)) istate | dependencyManager -> let directive d = @@ -1475,13 +1484,10 @@ type internal FsiDynamicCompiler packageManagerLines |> List.map (fun line -> directive line.Directive, line.Line) try - let result = tcConfigB.dependencyProvider.Resolve(dependencyManager, ".fsx", packageManagerTextLines, reportError m, executionTfm, executionRid, tcConfigB.implicitIncludeDir, "stdin.fsx", "stdin.fsx") - match result.Success with - | false -> - tcConfigB.packageManagerLines <- PackageManagerLine.RemoveUnprocessedLines packageManagerKey tcConfigB.packageManagerLines - istate // error already reported - - | true -> + let result = fsiOptions.DependencyProvider.Resolve(dependencyManager, ".fsx", packageManagerTextLines, reportError m, executionTfm, executionRid, tcConfigB.implicitIncludeDir, "stdin.fsx", "stdin.fsx") + if result.Success then + for line in result.StdOut do Console.Out.WriteLine(line) + for line in result.StdError do Console.Error.WriteLine(line) tcConfigB.packageManagerLines <- PackageManagerLine.SetLinesAsProcessed packageManagerKey tcConfigB.packageManagerLines for folder in result.Roots do tcConfigB.AddIncludePath(m, folder, "") @@ -1489,6 +1495,15 @@ type internal FsiDynamicCompiler if not (isNil scripts) then fsiDynamicCompiler.EvalSourceFiles(ctok, istate, m, scripts, lexResourceManager, errorLogger) else istate + else + // Send outputs via diagnostics + if (result.StdOut.Length > 0 || result.StdError.Length > 0) then + for line in Array.append result.StdOut result.StdError do + errorR(Error(FSComp.SR.packageManagerError(line), m)) + //Write outputs in F# Interactive and compiler + tcConfigB.packageManagerLines <- PackageManagerLine.RemoveUnprocessedLines packageManagerKey tcConfigB.packageManagerLines + istate // error already reported + with _ -> // An exception occured during processing, so remove the lines causing the error from the package manager list. @@ -1502,8 +1517,27 @@ type internal FsiDynamicCompiler (fun () -> ProcessMetaCommandsFromInput ((fun st (m,nm) -> tcConfigB.TurnWarningOff(m,nm); st), - (fun st (m,nm) -> snd (fsiDynamicCompiler.EvalRequireReference (ctok, st, m, nm))), - (fun st (packageManagerPrefix, lt, m, nm) -> fsiDynamicCompiler.EvalDependencyManagerTextFragment (packageManagerPrefix, lt, m, nm); st), + (fun st (m, path, directive) -> + + let dm = tcImports.DependencyProvider.TryFindDependencyManagerInPath(tcConfigB.compilerToolPaths, getOutputDir tcConfigB, reportError m, path) + + match dm with + | _, dependencyManager when not(isNull dependencyManager) -> + if tcConfigB.langVersion.SupportsFeature(LanguageFeature.PackageManagement) then + fsiDynamicCompiler.EvalDependencyManagerTextFragment (dependencyManager, directive, m, path) + st + else + errorR(Error(FSComp.SR.packageManagementRequiresVFive(), m)) + st + + | _, _ when directive = Directive.Include -> + errorR(Error(FSComp.SR.poundiNotSupportedByRegisteredDependencyManagers(), m)) + st + + // #r "Assembly" + | path, _ -> + snd (fsiDynamicCompiler.EvalRequireReference (ctok, st, m, path)) + ), (fun _ _ -> ())) (tcConfigB, inp, Path.GetDirectoryName sourceFile, istate)) @@ -1517,7 +1551,11 @@ type internal FsiDynamicCompiler // Close the #load graph on each file and gather the inputs from the scripts. let tcConfig = TcConfig.Create(tcConfigB,validate=false) - let closure = LoadClosure.ComputeClosureOfScriptFiles(ctok, tcConfig, sourceFiles, CodeContext.CompilationAndEvaluation, lexResourceManager=lexResourceManager) + + let closure = + LoadClosure.ComputeClosureOfScriptFiles(ctok, tcConfig, + sourceFiles, CodeContext.CompilationAndEvaluation, + lexResourceManager, fsiOptions.DependencyProvider) // Intent "[Loading %s]\n" (String.concat "\n and " sourceFiles) fsiConsoleOutput.uprintf "[%s " (FSIstrings.SR.fsiLoadingFilesPrefixText()) @@ -2106,7 +2144,7 @@ type internal FsiInteractionProcessor /// Execute a single parsed interaction. Called on the GUI/execute/main thread. let ExecInteraction (ctok, tcConfig:TcConfig, istate, action:ParsedFsiInteraction, errorLogger: ErrorLogger) = let packageManagerDirective directive path m = - let dm = tcConfigB.dependencyProvider.TryFindDependencyManagerInPath(tcConfigB.compilerToolPaths, getOutputDir tcConfigB, reportError m, path) + let dm = fsiOptions.DependencyProvider.TryFindDependencyManagerInPath(tcConfigB.compilerToolPaths, getOutputDir tcConfigB, reportError m, path) match dm with | null, null -> // error already reported @@ -2749,7 +2787,8 @@ type FsiEvaluationSession (fsi: FsiEvaluationSessionHostConfig, argv:string[], i do updateBannerText() // setting the correct banner so that 'fsi -?' display the right thing - let fsiOptions = FsiCommandLineOptions(fsi, argv, tcConfigB, fsiConsoleOutput) + let fsiOptions = FsiCommandLineOptions(fsi, argv, tcConfigB, fsiConsoleOutput) + let fsiConsolePrompt = FsiConsolePrompt(fsiOptions, fsiConsoleOutput) do @@ -2791,7 +2830,7 @@ type FsiEvaluationSession (fsi: FsiEvaluationSessionHostConfig, argv:string[], i let tcImports = try - TcImports.BuildNonFrameworkTcImports(ctokStartup, tcConfigP, tcGlobals, frameworkTcImports, nonFrameworkResolutions, unresolvedReferences) |> Cancellable.runWithoutCancellation + TcImports.BuildNonFrameworkTcImports(ctokStartup, tcConfigP, tcGlobals, frameworkTcImports, nonFrameworkResolutions, unresolvedReferences, fsiOptions.DependencyProvider) |> Cancellable.runWithoutCancellation with e -> stopProcessingRecovery e range0; failwithf "Error creating evaluation session: %A" e diff --git a/src/fsharp/lexhelp.fs b/src/fsharp/lexhelp.fs index d4936792ec7..26a50de6f28 100644 --- a/src/fsharp/lexhelp.fs +++ b/src/fsharp/lexhelp.fs @@ -410,6 +410,7 @@ module Keywords = "base", FSComp.SR.keywordDescriptionBase() "begin", FSComp.SR.keywordDescriptionBegin() "class", FSComp.SR.keywordDescriptionClass() + "const", FSComp.SR.keywordDescriptionConst() "default", FSComp.SR.keywordDescriptionDefault() "delegate", FSComp.SR.keywordDescriptionDelegate() "do", FSComp.SR.keywordDescriptionDo() diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index 2f1bcf56641..c9b4a5861bf 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -5044,7 +5044,7 @@ atomType: | CONST atomicExpr { let e, _ = $2 - SynType.StaticConstantExpr(e, e.Range) } + SynType.StaticConstantExpr(e, lhs parseState) } | FALSE { SynType.StaticConstant(SynConst.Bool false, lhs parseState) } diff --git a/src/fsharp/service/FSharpCheckerResults.fs b/src/fsharp/service/FSharpCheckerResults.fs index f3c78473b27..4835516ef03 100644 --- a/src/fsharp/service/FSharpCheckerResults.fs +++ b/src/fsharp/service/FSharpCheckerResults.fs @@ -1051,7 +1051,21 @@ type internal TypeCheckInfo let tip = wordL (TaggedTextOps.tagStringLiteral((resolved.prepareToolTip ()).TrimEnd([|'\n'|]))) FSharpStructuredToolTipText.FSharpToolTipText [FSharpStructuredToolTipElement.Single(tip, FSharpXmlDoc.None)] - | [] -> FSharpStructuredToolTipText.FSharpToolTipText [] + | [] -> + let matches = + match loadClosure with + | None -> None + | Some(loadClosure) -> + loadClosure.PackageReferences + |> Array.tryFind (fun (m, _) -> Range.rangeContainsPos m pos) + match matches with + | None -> FSharpStructuredToolTipText.FSharpToolTipText [] + | Some (_, lines) -> + let lines = lines |> List.filter (fun line -> not (line.StartsWith("//")) && not (String.IsNullOrEmpty line)) + FSharpStructuredToolTipText.FSharpToolTipText + [ for line in lines -> + let tip = wordL (TaggedTextOps.tagStringLiteral line) + FSharpStructuredToolTipElement.Single(tip, FSharpXmlDoc.None)] ErrorScope.Protect Range.range0 dataTipOfReferences @@ -1621,7 +1635,7 @@ module internal ParseAndCheckFile = | None -> // For non-scripts, check for disallow #r and #load. - ApplyMetaCommandsFromInputToTcConfig (tcConfig, parsedMainInput,Path.GetDirectoryName mainInputFileName) |> ignore + ApplyMetaCommandsFromInputToTcConfig (tcConfig, parsedMainInput, Path.GetDirectoryName mainInputFileName, tcImports.DependencyProvider) |> ignore // Type check a single file against an initial context, gleaning both errors and intellisense information. let CheckOneFile @@ -2161,8 +2175,8 @@ type FSharpCheckProjectResults type FsiInteractiveChecker(legacyReferenceResolver, reactorOps: IReactorOperations, tcConfig: TcConfig, - tcGlobals, - tcImports, + tcGlobals: TcGlobals, + tcImports: TcImports, tcState) = let keepAssemblyContents = false @@ -2192,7 +2206,9 @@ type FsiInteractiveChecker(legacyReferenceResolver, tcConfig.useSimpleResolution, tcConfig.useFsiAuxLib, tcConfig.useSdkRefs, new Lexhelp.LexResourceManager(), applyCompilerOptions, assumeDotNetFramework, - tryGetMetadataSnapshot=(fun _ -> None), reduceMemoryUsage=reduceMemoryUsage) + tryGetMetadataSnapshot=(fun _ -> None), + reduceMemoryUsage=reduceMemoryUsage, + dependencyProvider=tcImports.DependencyProvider) let! tcErrors, tcFileInfo = ParseAndCheckFile.CheckOneFile diff --git a/src/fsharp/service/IncrementalBuild.fs b/src/fsharp/service/IncrementalBuild.fs index f60d85adfc1..107f381364d 100755 --- a/src/fsharp/service/IncrementalBuild.fs +++ b/src/fsharp/service/IncrementalBuild.fs @@ -26,6 +26,8 @@ open FSharp.Compiler.TypeChecker open FSharp.Compiler.TypedTree open FSharp.Compiler.TypedTreeOps +open Microsoft.DotNet.DependencyManager + open Internal.Utilities.Collections [] @@ -1220,9 +1222,12 @@ type RawFSharpAssemblyDataBackedByLanguageService (tcConfig, tcGlobals, tcState: /// Manages an incremental build graph for the build of a single F# project type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInputs, nonFrameworkResolutions, unresolvedReferences, tcConfig: TcConfig, projectDirectory, outfile, - assemblyName, niceNameGen: NiceNameGenerator, lexResourceManager, - sourceFiles, loadClosureOpt: LoadClosure option, - keepAssemblyContents, keepAllBackgroundResolutions, maxTimeShareMilliseconds, keepAllBackgroundSymbolUses, enableBackgroundItemKeyStoreAndSemanticClassification) = + assemblyName, niceNameGen: NiceNameGenerator, lexResourceManager, + sourceFiles, loadClosureOpt: LoadClosure option, + keepAssemblyContents, keepAllBackgroundResolutions, + maxTimeShareMilliseconds, keepAllBackgroundSymbolUses, + enableBackgroundItemKeyStoreAndSemanticClassification, + dependencyProviderOpt: DependencyProvider option) = let tcConfigP = TcConfigProvider.Constant tcConfig let fileParsed = new Event() @@ -1259,6 +1264,13 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput for (_, f, _) in sourceFiles do yield f |] + // For scripts, the dependency provider is already available. + // For projects create a fresh one for the project. + let dependencyProvider = + match dependencyProviderOpt with + | None -> new DependencyProvider() + | Some dependencyProvider -> dependencyProvider + //---------------------------------------------------- // START OF BUILD TASK FUNCTIONS @@ -1309,7 +1321,7 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput let! tcImports = cancellable { try - let! tcImports = TcImports.BuildNonFrameworkTcImports(ctok, tcConfigP, tcGlobals, frameworkTcImports, nonFrameworkResolutions, unresolvedReferences) + let! tcImports = TcImports.BuildNonFrameworkTcImports(ctok, tcConfigP, tcGlobals, frameworkTcImports, nonFrameworkResolutions, unresolvedReferences, dependencyProvider) #if !NO_EXTENSIONTYPING tcImports.GetCcusExcludingBase() |> Seq.iter (fun ccu -> // When a CCU reports an invalidation, merge them together and just report a @@ -1383,7 +1395,7 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput eventually { beforeFileChecked.Trigger filename - ApplyMetaCommandsFromInputToTcConfig (tcConfig, input, Path.GetDirectoryName filename) |> ignore + ApplyMetaCommandsFromInputToTcConfig (tcConfig, input, Path.GetDirectoryName filename, tcAcc.tcImports.DependencyProvider) |> ignore let sink = TcResultsSinkImpl(tcAcc.tcGlobals) let hadParseErrors = not (Array.isEmpty parseErrors) @@ -1740,7 +1752,7 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput /// CreateIncrementalBuilder (for background type checking). Note that fsc.fs also /// creates an incremental builder used by the command line compiler. - static member TryCreateBackgroundBuilderForProjectOptions + static member TryCreateIncrementalBuilderForProjectOptions (ctok, legacyReferenceResolver, defaultFSharpBinariesDir, frameworkTcImportsCache: FrameworkImportsCache, loadClosureOpt: LoadClosure option, @@ -1749,7 +1761,11 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput projectReferences, projectDirectory, useScriptResolutionRules, keepAssemblyContents, keepAllBackgroundResolutions, maxTimeShareMilliseconds, - tryGetMetadataSnapshot, suggestNamesForErrors, keepAllBackgroundSymbolUses, enableBackgroundItemKeyStoreAndSemanticClassification) = + tryGetMetadataSnapshot, suggestNamesForErrors, + keepAllBackgroundSymbolUses, + enableBackgroundItemKeyStoreAndSemanticClassification, + dependencyProviderOpt) = + let useSimpleResolutionSwitch = "--simpleresolution" cancellable { @@ -1864,14 +1880,16 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput yield Choice2Of2 pr, (fun (cache: TimeStampCache) ctok -> cache.GetProjectReferenceTimeStamp (pr, ctok)) ] let builder = - new IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInputs, nonFrameworkResolutions, unresolvedReferences, - tcConfig, projectDirectory, outfile, assemblyName, niceNameGen, - resourceManager, sourceFilesNew, loadClosureOpt, - keepAssemblyContents=keepAssemblyContents, - keepAllBackgroundResolutions=keepAllBackgroundResolutions, - maxTimeShareMilliseconds=maxTimeShareMilliseconds, - keepAllBackgroundSymbolUses=keepAllBackgroundSymbolUses, - enableBackgroundItemKeyStoreAndSemanticClassification=enableBackgroundItemKeyStoreAndSemanticClassification) + new IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInputs, + nonFrameworkResolutions, unresolvedReferences, + tcConfig, projectDirectory, outfile, assemblyName, niceNameGen, + resourceManager, sourceFilesNew, loadClosureOpt, + keepAssemblyContents, + keepAllBackgroundResolutions, + maxTimeShareMilliseconds, + keepAllBackgroundSymbolUses, + enableBackgroundItemKeyStoreAndSemanticClassification, + dependencyProviderOpt) return Some builder with e -> errorRecoveryNoRange e diff --git a/src/fsharp/service/IncrementalBuild.fsi b/src/fsharp/service/IncrementalBuild.fsi index e9f945cd970..c6bfe1e1f5a 100755 --- a/src/fsharp/service/IncrementalBuild.fsi +++ b/src/fsharp/service/IncrementalBuild.fsi @@ -16,6 +16,8 @@ open FSharp.Compiler.SyntaxTree open FSharp.Compiler.TcGlobals open FSharp.Compiler.TypedTree +open Microsoft.DotNet.DependencyManager + /// Lookup the global static cache for building the FrameworkTcImports type internal FrameworkImportsCache = new : size: int -> FrameworkImportsCache @@ -178,9 +180,29 @@ type internal IncrementalBuilder = /// Await the untyped parse results for a particular slot in the vector of parse results. /// /// This may be a marginally long-running operation (parses are relatively quick, only one file needs to be parsed) - member GetParseResultsForFile : CompilationThreadToken * filename:string -> Cancellable - - static member TryCreateBackgroundBuilderForProjectOptions : CompilationThreadToken * ReferenceResolver.Resolver * defaultFSharpBinariesDir: string * FrameworkImportsCache * scriptClosureOptions:LoadClosure option * sourceFiles:string list * commandLineArgs:string list * projectReferences: IProjectReference list * projectDirectory:string * useScriptResolutionRules:bool * keepAssemblyContents: bool * keepAllBackgroundResolutions: bool * maxTimeShareMilliseconds: int64 * tryGetMetadataSnapshot: ILBinaryReader.ILReaderTryGetMetadataSnapshot * suggestNamesForErrors: bool * keepAllBackgroundSymbolUses: bool * enableBackgroundItemKeyStoreAndSemanticClassification: bool -> Cancellable + member GetParseResultsForFile: CompilationThreadToken * filename:string -> Cancellable + + /// Create the incremental builder + static member TryCreateIncrementalBuilderForProjectOptions: + CompilationThreadToken * + ReferenceResolver.Resolver * + defaultFSharpBinariesDir: string * + FrameworkImportsCache * + scriptClosureOptions:LoadClosure option * + sourceFiles:string list * + commandLineArgs:string list * + projectReferences: IProjectReference list * + projectDirectory:string * + useScriptResolutionRules:bool * + keepAssemblyContents: bool * + keepAllBackgroundResolutions: bool * + maxTimeShareMilliseconds: int64 * + tryGetMetadataSnapshot: ILBinaryReader.ILReaderTryGetMetadataSnapshot * + suggestNamesForErrors: bool * + keepAllBackgroundSymbolUses: bool * + enableBackgroundItemKeyStoreAndSemanticClassification: bool * + dependencyProvider: DependencyProvider option + -> Cancellable /// Generalized Incremental Builder. This is exposed only for unit testing purposes. module internal IncrementalBuild = diff --git a/src/fsharp/service/ServiceAssemblyContent.fs b/src/fsharp/service/ServiceAssemblyContent.fs index b1406baadae..53a313baeb6 100644 --- a/src/fsharp/service/ServiceAssemblyContent.fs +++ b/src/fsharp/service/ServiceAssemblyContent.fs @@ -636,7 +636,7 @@ module ParsedInput = | SynExpr.Assert (e, _) | SynExpr.Lazy (e, _) | SynExpr.YieldOrReturnFrom (_, e, _) -> walkExpr e - | SynExpr.Lambda (_, _, pats, e, _) -> + | SynExpr.Lambda (_, _, pats, e, _, _) -> walkSimplePats pats walkExpr e | SynExpr.New (_, t, e, _) diff --git a/src/fsharp/service/ServiceInterfaceStubGenerator.fs b/src/fsharp/service/ServiceInterfaceStubGenerator.fs index 21ba5f77eb0..be58d530de8 100644 --- a/src/fsharp/service/ServiceInterfaceStubGenerator.fs +++ b/src/fsharp/service/ServiceInterfaceStubGenerator.fs @@ -802,7 +802,7 @@ module InterfaceStubGenerator = walkExpr synExpr | SynExpr.CompExpr (_, _, synExpr, _range) -> walkExpr synExpr - | SynExpr.Lambda (_, _, _synSimplePats, synExpr, _range) -> + | SynExpr.Lambda (_, _, _synSimplePats, synExpr, _, _range) -> walkExpr synExpr | SynExpr.MatchLambda (_isExnMatch, _argm, synMatchClauseList, _spBind, _wholem) -> diff --git a/src/fsharp/service/ServiceParseTreeWalk.fs b/src/fsharp/service/ServiceParseTreeWalk.fs index 7c2db37b98f..dc2d8a64220 100755 --- a/src/fsharp/service/ServiceParseTreeWalk.fs +++ b/src/fsharp/service/ServiceParseTreeWalk.fs @@ -391,7 +391,7 @@ module public AstTraversal = else traverseSynExpr synExpr - | SynExpr.Lambda (_, _, synSimplePats, synExpr, _range) -> + | SynExpr.Lambda (_, _, synSimplePats, synExpr, _, _range) -> match synSimplePats with | SynSimplePats.SimplePats(pats,_) -> match visitor.VisitSimplePats(pats) with diff --git a/src/fsharp/service/ServiceStructure.fs b/src/fsharp/service/ServiceStructure.fs index 2de95ace338..bd6cf90273a 100644 --- a/src/fsharp/service/ServiceStructure.fs +++ b/src/fsharp/service/ServiceStructure.fs @@ -376,7 +376,7 @@ module Structure = | SynExpr.While (_, _, e, r) -> rcheck Scope.While Collapse.Below r r parseExpr e - | SynExpr.Lambda (_, _, pats, e, r) -> + | SynExpr.Lambda (_, _, pats, e, _, r) -> match pats with | SynSimplePats.SimplePats (_, pr) | SynSimplePats.Typed (_, _, pr) -> diff --git a/src/fsharp/service/ServiceUntypedParse.fs b/src/fsharp/service/ServiceUntypedParse.fs index 3342650b5ae..22cfac1c674 100755 --- a/src/fsharp/service/ServiceUntypedParse.fs +++ b/src/fsharp/service/ServiceUntypedParse.fs @@ -278,7 +278,7 @@ type FSharpParseFileResults(errors: FSharpErrorInfo[], input: ParsedInput option yield! walkExprOpt false whenExpr yield! walkExpr true e - | SynExpr.Lambda (_, _, _, e, _) -> + | SynExpr.Lambda (_, _, _, e, _, _) -> yield! walkExpr true e | SynExpr.Match (spBind, e, cl, _) -> @@ -853,7 +853,7 @@ module UntypedParseImpl = | SynExpr.ForEach (_, _, _, _, e1, e2, _) -> List.tryPick (walkExprWithKind parentKind) [e1; e2] | SynExpr.ArrayOrListOfSeqExpr (_, e, _) -> walkExprWithKind parentKind e | SynExpr.CompExpr (_, _, e, _) -> walkExprWithKind parentKind e - | SynExpr.Lambda (_, _, _, e, _) -> walkExprWithKind parentKind e + | SynExpr.Lambda (_, _, _, e, _, _) -> walkExprWithKind parentKind e | SynExpr.MatchLambda (_, _, synMatchClauseList, _, _) -> List.tryPick walkClause synMatchClauseList | SynExpr.Match (_, e, synMatchClauseList, _) -> diff --git a/src/fsharp/service/service.fs b/src/fsharp/service/service.fs index 246f6d7440e..463e57a52d9 100644 --- a/src/fsharp/service/service.fs +++ b/src/fsharp/service/service.fs @@ -24,6 +24,8 @@ open FSharp.Compiler.SyntaxTree open FSharp.Compiler.TcGlobals open FSharp.Compiler.Text +open Microsoft.DotNet.DependencyManager + open Internal.Utilities open Internal.Utilities.Collections @@ -274,6 +276,14 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC let scriptClosureCacheLock = Lock() let frameworkTcImportsCache = FrameworkImportsCache(frameworkTcImportsCacheStrongSize) + // We currently share one global dependency provider for all scripts for the FSharpChecker. + // For projects, one is used per project. + // + // Sharing one for all scripts is necessary for good performance from GetProjectOptionsFromScript, + // which requires a dependency provider to process through the project options prior to working out + // if the cached incremental builder can be used for the project. + let dependencyProviderForScripts = new DependencyProvider() + /// CreateOneIncrementalBuilder (for background type checking). Note that fsc.fs also /// creates an incremental builder used by the command line compiler. let CreateOneIncrementalBuilder (ctok, options:FSharpProjectOptions, userOpName) = @@ -301,12 +311,15 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC member x.FileName = nm } ] let loadClosure = scriptClosureCacheLock.AcquireLock (fun ltok -> scriptClosureCache.TryGet (ltok, options)) + let! builderOpt, diagnostics = - IncrementalBuilder.TryCreateBackgroundBuilderForProjectOptions + IncrementalBuilder.TryCreateIncrementalBuilderForProjectOptions (ctok, legacyReferenceResolver, FSharpCheckerResultsSettings.defaultFSharpBinariesDir, frameworkTcImportsCache, loadClosure, Array.toList options.SourceFiles, Array.toList options.OtherOptions, projectReferences, options.ProjectDirectory, options.UseScriptResolutionRules, keepAssemblyContents, keepAllBackgroundResolutions, FSharpCheckerResultsSettings.maxTimeShareMilliseconds, - tryGetMetadataSnapshot, suggestNamesForErrors, keepAllBackgroundSymbolUses, enableBackgroundItemKeyStoreAndSemanticClassification) + tryGetMetadataSnapshot, suggestNamesForErrors, keepAllBackgroundSymbolUses, + enableBackgroundItemKeyStoreAndSemanticClassification, + (if options.UseScriptResolutionRules then Some dependencyProviderForScripts else None)) match builderOpt with | None -> () @@ -817,8 +830,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC FSharpCheckerResultsSettings.defaultFSharpBinariesDir, filename, sourceText, CodeContext.Editing, useSimpleResolution, useFsiAuxLib, useSdkRefs, new Lexhelp.LexResourceManager(), applyCompilerOptions, assumeDotNetFramework, - tryGetMetadataSnapshot=tryGetMetadataSnapshot, - reduceMemoryUsage=reduceMemoryUsage) + tryGetMetadataSnapshot, reduceMemoryUsage, dependencyProviderForScripts) let otherFlags = [| yield "--noframework"; yield "--warn:3"; diff --git a/src/fsharp/xlf/FSComp.txt.cs.xlf b/src/fsharp/xlf/FSComp.txt.cs.xlf index 9839f7d0bca..ffddf66f7ce 100644 --- a/src/fsharp/xlf/FSComp.txt.cs.xlf +++ b/src/fsharp/xlf/FSComp.txt.cs.xlf @@ -197,6 +197,11 @@ Invalid directive '#{0} {1}' + + Keyword to specify a constant literal as a type parameter argument in Type Providers. + Keyword to specify a constant literal as a type parameter argument in Type Providers. + + a byte string may not be interpolated a byte string may not be interpolated diff --git a/src/fsharp/xlf/FSComp.txt.de.xlf b/src/fsharp/xlf/FSComp.txt.de.xlf index f0ddc681111..229ddc47488 100644 --- a/src/fsharp/xlf/FSComp.txt.de.xlf +++ b/src/fsharp/xlf/FSComp.txt.de.xlf @@ -197,6 +197,11 @@ Invalid directive '#{0} {1}' + + Keyword to specify a constant literal as a type parameter argument in Type Providers. + Keyword to specify a constant literal as a type parameter argument in Type Providers. + + a byte string may not be interpolated a byte string may not be interpolated diff --git a/src/fsharp/xlf/FSComp.txt.es.xlf b/src/fsharp/xlf/FSComp.txt.es.xlf index 24077dfabb0..e54ea1b0e7e 100644 --- a/src/fsharp/xlf/FSComp.txt.es.xlf +++ b/src/fsharp/xlf/FSComp.txt.es.xlf @@ -197,6 +197,11 @@ Invalid directive '#{0} {1}' + + Keyword to specify a constant literal as a type parameter argument in Type Providers. + Keyword to specify a constant literal as a type parameter argument in Type Providers. + + a byte string may not be interpolated a byte string may not be interpolated diff --git a/src/fsharp/xlf/FSComp.txt.fr.xlf b/src/fsharp/xlf/FSComp.txt.fr.xlf index 505de283f8c..31fd1c7095e 100644 --- a/src/fsharp/xlf/FSComp.txt.fr.xlf +++ b/src/fsharp/xlf/FSComp.txt.fr.xlf @@ -197,6 +197,11 @@ Invalid directive '#{0} {1}' + + Keyword to specify a constant literal as a type parameter argument in Type Providers. + Keyword to specify a constant literal as a type parameter argument in Type Providers. + + a byte string may not be interpolated a byte string may not be interpolated diff --git a/src/fsharp/xlf/FSComp.txt.it.xlf b/src/fsharp/xlf/FSComp.txt.it.xlf index b6527118704..aacd17bbf27 100644 --- a/src/fsharp/xlf/FSComp.txt.it.xlf +++ b/src/fsharp/xlf/FSComp.txt.it.xlf @@ -197,6 +197,11 @@ Invalid directive '#{0} {1}' + + Keyword to specify a constant literal as a type parameter argument in Type Providers. + Keyword to specify a constant literal as a type parameter argument in Type Providers. + + a byte string may not be interpolated a byte string may not be interpolated diff --git a/src/fsharp/xlf/FSComp.txt.ja.xlf b/src/fsharp/xlf/FSComp.txt.ja.xlf index a361c41ff6b..88ab50b3ace 100644 --- a/src/fsharp/xlf/FSComp.txt.ja.xlf +++ b/src/fsharp/xlf/FSComp.txt.ja.xlf @@ -2607,6 +2607,11 @@ In verbose syntax, indicates the start of a class definition. + + Keyword to specify a constant literal as a type parameter argument in Type Providers. + Keyword to specify a constant literal as a type parameter argument in Type Providers. + + Indicates an implementation of an abstract method; used together with an abstract method declaration to create a virtual method. Indicates an implementation of an abstract method; used together with an abstract method declaration to create a virtual method. diff --git a/src/fsharp/xlf/FSComp.txt.ko.xlf b/src/fsharp/xlf/FSComp.txt.ko.xlf index a6fcf98469d..a17642876f9 100644 --- a/src/fsharp/xlf/FSComp.txt.ko.xlf +++ b/src/fsharp/xlf/FSComp.txt.ko.xlf @@ -197,6 +197,11 @@ Invalid directive '#{0} {1}' + + Keyword to specify a constant literal as a type parameter argument in Type Providers. + Keyword to specify a constant literal as a type parameter argument in Type Providers. + + a byte string may not be interpolated a byte string may not be interpolated diff --git a/src/fsharp/xlf/FSComp.txt.pl.xlf b/src/fsharp/xlf/FSComp.txt.pl.xlf index 3727ead1dac..699f1f2e755 100644 --- a/src/fsharp/xlf/FSComp.txt.pl.xlf +++ b/src/fsharp/xlf/FSComp.txt.pl.xlf @@ -197,6 +197,11 @@ Invalid directive '#{0} {1}' + + Keyword to specify a constant literal as a type parameter argument in Type Providers. + Keyword to specify a constant literal as a type parameter argument in Type Providers. + + a byte string may not be interpolated a byte string may not be interpolated diff --git a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf index c6281378ea8..884d70b372e 100644 --- a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf +++ b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf @@ -197,6 +197,11 @@ Invalid directive '#{0} {1}' + + Keyword to specify a constant literal as a type parameter argument in Type Providers. + Keyword to specify a constant literal as a type parameter argument in Type Providers. + + a byte string may not be interpolated a byte string may not be interpolated diff --git a/src/fsharp/xlf/FSComp.txt.ru.xlf b/src/fsharp/xlf/FSComp.txt.ru.xlf index afe00bca155..864e9e9b9ce 100644 --- a/src/fsharp/xlf/FSComp.txt.ru.xlf +++ b/src/fsharp/xlf/FSComp.txt.ru.xlf @@ -197,6 +197,11 @@ Invalid directive '#{0} {1}' + + Keyword to specify a constant literal as a type parameter argument in Type Providers. + Keyword to specify a constant literal as a type parameter argument in Type Providers. + + a byte string may not be interpolated a byte string may not be interpolated diff --git a/src/fsharp/xlf/FSComp.txt.tr.xlf b/src/fsharp/xlf/FSComp.txt.tr.xlf index bc142bfc6a0..7fd449a1959 100644 --- a/src/fsharp/xlf/FSComp.txt.tr.xlf +++ b/src/fsharp/xlf/FSComp.txt.tr.xlf @@ -197,6 +197,11 @@ Invalid directive '#{0} {1}' + + Keyword to specify a constant literal as a type parameter argument in Type Providers. + Keyword to specify a constant literal as a type parameter argument in Type Providers. + + a byte string may not be interpolated a byte string may not be interpolated diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf index 8df687974e5..8459be70851 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf @@ -197,6 +197,11 @@ Invalid directive '#{0} {1}' + + Keyword to specify a constant literal as a type parameter argument in Type Providers. + Keyword to specify a constant literal as a type parameter argument in Type Providers. + + a byte string may not be interpolated a byte string may not be interpolated diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf index 035bd7f69dc..0388f6c5814 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf @@ -197,6 +197,11 @@ Invalid directive '#{0} {1}' + + Keyword to specify a constant literal as a type parameter argument in Type Providers. + Keyword to specify a constant literal as a type parameter argument in Type Providers. + + a byte string may not be interpolated a byte string may not be interpolated diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs index a62667f01b2..68628e106aa 100644 --- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs +++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs @@ -54,10 +54,8 @@ type DependencyManagerInteractiveTests() = #r @"nuget:System.Collections.Immutable.DoesNotExist, version=1.5.0" 0""" use script = new scriptHost() - let opt = script.Eval(text) |> getValue - let value = opt.Value - Assert.Equal(typeof, value.ReflectionType) - Assert.Equal(0, value.ReflectionValue :?> int) + let opt, errors = script.Eval(text) + Assert.Equal(errors.Length, 1) (* [] @@ -232,7 +230,7 @@ type DependencyManagerInteractiveTests() = /// Native dll resolution is not implemented on desktop #if NETCOREAPP - [] + [] member __.``Script using TorchSharp``() = let text = """ #r "nuget:RestoreSources=https://donsyme.pkgs.visualstudio.com/TorchSharp/_packaging/packages2/nuget/v3/index.json" diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs index 3ab48c5d46e..151f376ad53 100644 --- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs +++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs @@ -249,21 +249,26 @@ printfn ""%A"" result if line.Contains("error NU1101:") && line.Contains("FSharp.Really.Not.A.Package") then found <- found + 1 outp.Add(line)) - let _result, _errors = script.Eval("""#r "nuget:FSharp.Really.Not.A.Package" """) - Assert.True( (found = 1), "Expected to see output contains 'error NU1101:' and 'FSharp.Really.Not.A.Package'") + let result, errors = script.Eval("""#r "nuget:FSharp.Really.Not.A.Package" """) + Assert.True( (found = 0), "Did not expect to see output contains 'error NU1101:' and 'FSharp.Really.Not.A.Package'") + Assert.True( errors |> Seq.exists (fun error -> error.Message.Contains("error NU1101:")), "Expect to error containing 'error NU1101:'") + Assert.True( errors |> Seq.exists (fun error -> error.Message.Contains("FSharp.Really.Not.A.Package")), "Expect to error containing 'FSharp.Really.Not.A.Package'") [] member __.``Eval script with invalid PackageName should fail immediately and resolve one time only``() = use output = new RedirectConsoleOutput() use script = new FSharpScript(additionalArgs=[|"/langversion:preview"|]) let mutable foundResolve = 0 - output.OutputProduced.Add (fun line -> if line.Contains("Microsoft (R) Build Engine version") then foundResolve <- foundResolve + 1) - let _result, _errors = + output.OutputProduced.Add (fun line -> if line.Contains("error NU1101:") then foundResolve <- foundResolve + 1) + let result, errors = script.Eval(""" #r "nuget:FSharp.Really.Not.A.Package" #r "nuget:FSharp.Really.Not.Another.Package" """) - Assert.True( (foundResolve = 1), (sprintf "Expected to see 'Microsoft (R) Build Engine version' only once actually resolved %d times" foundResolve)) + Assert.True( (foundResolve = 0), (sprintf "Did not expected to see 'error NU1101:' in output" )) + Assert.Equal(2, (errors |> Seq.filter (fun error -> error.Message.Contains("error NU1101:")) |> Seq.length)) + Assert.Equal(1, (errors |> Seq.filter (fun error -> error.Message.Contains("FSharp.Really.Not.A.Package")) |> Seq.length)) + Assert.Equal(1, (errors |> Seq.filter (fun error -> error.Message.Contains("FSharp.Really.Not.Another.Package")) |> Seq.length)) [] member __.``ML - use assembly with ref dependencies``() = diff --git a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs index 3a26973ad29..a200c265924 100644 --- a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs +++ b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs @@ -31673,6 +31673,8 @@ FSharp.Compiler.SyntaxTree+SynExpr+Lambda: SynExpr body FSharp.Compiler.SyntaxTree+SynExpr+Lambda: SynExpr get_body() FSharp.Compiler.SyntaxTree+SynExpr+Lambda: SynSimplePats args FSharp.Compiler.SyntaxTree+SynExpr+Lambda: SynSimplePats get_args() +FSharp.Compiler.SyntaxTree+SynExpr+Lambda: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTree+SynPat],FSharp.Compiler.SyntaxTree+SynExpr]] parsedData +FSharp.Compiler.SyntaxTree+SynExpr+Lambda: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTree+SynPat],FSharp.Compiler.SyntaxTree+SynExpr]] get_parsedData() FSharp.Compiler.SyntaxTree+SynExpr+Lambda: System.String ToString() FSharp.Compiler.SyntaxTree+SynExpr+Lambda: range Range FSharp.Compiler.SyntaxTree+SynExpr+Lambda: range RangeOfFirstPortion @@ -36769,7 +36771,7 @@ FSharp.Compiler.SyntaxTree+SynExpr: SynExpr NewInferredDowncast(SynExpr, range) FSharp.Compiler.SyntaxTree+SynExpr: SynExpr NewInferredUpcast(SynExpr, range) FSharp.Compiler.SyntaxTree+SynExpr: SynExpr NewInterpolatedString(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTree+SynInterpolatedStringPart], range) FSharp.Compiler.SyntaxTree+SynExpr: SynExpr NewJoinIn(SynExpr, range, SynExpr, range) -FSharp.Compiler.SyntaxTree+SynExpr: SynExpr NewLambda(Boolean, Boolean, SynSimplePats, SynExpr, range) +FSharp.Compiler.SyntaxTree+SynExpr: SynExpr NewLambda(Boolean, Boolean, SynSimplePats, SynExpr, Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTree+SynPat],FSharp.Compiler.SyntaxTree+SynExpr]], range) FSharp.Compiler.SyntaxTree+SynExpr: SynExpr NewLazy(SynExpr, range) FSharp.Compiler.SyntaxTree+SynExpr: SynExpr NewLetOrUse(Boolean, Boolean, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTree+SynBinding], SynExpr, range) FSharp.Compiler.SyntaxTree+SynExpr: SynExpr NewLetOrUseBang(DebugPointForBinding, Boolean, Boolean, SynPat, SynExpr, Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`6[FSharp.Compiler.SyntaxTree+DebugPointForBinding,System.Boolean,System.Boolean,FSharp.Compiler.SyntaxTree+SynPat,FSharp.Compiler.SyntaxTree+SynExpr,FSharp.Compiler.Range+range]], SynExpr, range) @@ -42401,6 +42403,7 @@ Microsoft.DotNet.DependencyManager.DependencyProvider: System.Tuple`2[System.Int Microsoft.DotNet.DependencyManager.DependencyProvider: System.Tuple`2[System.String,Microsoft.DotNet.DependencyManager.IDependencyManagerProvider] TryFindDependencyManagerInPath(System.Collections.Generic.IEnumerable`1[System.String], System.String, Microsoft.DotNet.DependencyManager.ResolvingErrorReport, System.String) Microsoft.DotNet.DependencyManager.DependencyProvider: Void .ctor(Microsoft.DotNet.DependencyManager.AssemblyResolutionProbe, Microsoft.DotNet.DependencyManager.NativeResolutionProbe) Microsoft.DotNet.DependencyManager.DependencyProvider: Void .ctor(Microsoft.DotNet.DependencyManager.NativeResolutionProbe) +Microsoft.DotNet.DependencyManager.DependencyProvider: Void .ctor() Microsoft.DotNet.DependencyManager.ErrorReportType+Tags: Int32 Error Microsoft.DotNet.DependencyManager.ErrorReportType+Tags: Int32 Warning Microsoft.DotNet.DependencyManager.ErrorReportType: Boolean Equals(Microsoft.DotNet.DependencyManager.ErrorReportType) diff --git a/tests/fsharp/core/nameof/preview/test.fsx b/tests/fsharp/core/nameof/preview/test.fsx index 3f69e973cfa..0a952ab823f 100644 --- a/tests/fsharp/core/nameof/preview/test.fsx +++ b/tests/fsharp/core/nameof/preview/test.fsx @@ -9,10 +9,6 @@ open System exception ABC -type Assert = - static member AreEqual (a, b) = a=b - static member Fail = raise (Exception("Fail")) - let failures = ref [] let report_failure (s : string) = @@ -27,6 +23,9 @@ let test (s : string) b = let check s b1 b2 = test s (b1 = b2) +type Assert = + static member AreEqual msg (a, b) = check msg a b; (a = b) + type BasicNameOfTests() = static let staticConstant = 23 @@ -47,34 +46,34 @@ type BasicNameOfTests() = static member ``local variable name lookup`` () = let a = 0 let b = nameof a - let result = Assert.AreEqual("a", b) + let result = Assert.AreEqual ("line " + string __LINE__) ("a", b) let c = nameof b - result || Assert.AreEqual("b", c) + result || Assert.AreEqual ("line " + string __LINE__) ("b", c) static member ``local int function name`` () = let myFunction x = 0 * x let result = nameof myFunction - Assert.AreEqual("myFunction", result) + Assert.AreEqual ("line " + string __LINE__) ("myFunction", result) static member ``local curried function name`` () = let curriedFunction x y = x * y let result = nameof curriedFunction - Assert.AreEqual("curriedFunction", result) + Assert.AreEqual ("line " + string __LINE__) ("curriedFunction", result) static member ``local tupled function name`` () = let tupledFunction(x,y) = x * y let result = nameof tupledFunction - Assert.AreEqual("tupledFunction", result) + Assert.AreEqual ("line " + string __LINE__) ("tupledFunction", result) static member ``local unit function name`` () = let myFunction() = 1 let result = nameof(myFunction) - Assert.AreEqual("myFunction", result) + Assert.AreEqual ("line " + string __LINE__) ("myFunction", result) static member ``local function parameter name`` () = let myFunction parameter1 = nameof parameter1 let result = myFunction "x" - Assert.AreEqual("parameter1", result) + Assert.AreEqual ("line " + string __LINE__) ("parameter1", result) static member ``can get name from inside a local function (needs to be let rec)`` () = let rec myLocalFunction x = @@ -82,91 +81,91 @@ type BasicNameOfTests() = nameof myLocalFunction + " " + z.ToString() let a = myLocalFunction 23 - let result = Assert.AreEqual("myLocalFunction 46", a) + let result = Assert.AreEqual ("line " + string __LINE__) ("myLocalFunction 46", a) let b = myLocalFunction 25 - result || Assert.AreEqual("myLocalFunction 50", b) + result || Assert.AreEqual ("line " + string __LINE__) ("myLocalFunction 50", b) static member ``can get name from inside static member`` () = let b = nameof(BasicNameOfTests.``can get name from inside static member``) - Assert.AreEqual("can get name from inside static member", b) + Assert.AreEqual ("line " + string __LINE__) ("can get name from inside static member", b) member this.``can get name from inside instance member`` () = let b = nameof(this.``can get name from inside instance member``) - Assert.AreEqual("can get name from inside instance member", b) + Assert.AreEqual ("line " + string __LINE__) ("can get name from inside instance member", b) static member ``can get name of static member`` () = let b = nameof(BasicNameOfTests.``can get name of static member``) - Assert.AreEqual("can get name of static member", b) + Assert.AreEqual ("line " + string __LINE__) ("can get name of static member", b) member this.``can get name of instance member`` () = let b = nameof(this.MemberMethod) - Assert.AreEqual("MemberMethod", b) + Assert.AreEqual ("line " + string __LINE__) ("MemberMethod", b) member this.``can get name of instance member via unchecked`` () = let b = nameof(Unchecked.defaultof.MemberMethod) - Assert.AreEqual("MemberMethod", b) + Assert.AreEqual ("line " + string __LINE__) ("MemberMethod", b) member this.``can get name of method type parameter``<'TTT> () = let b = nameof<'TTT> - Assert.AreEqual("TTT", b) + Assert.AreEqual ("line " + string __LINE__) ("TTT", b) static member ``namespace name`` () = let b = nameof(FSharp.Core) - Assert.AreEqual("Core",b) + Assert.AreEqual ("line " + string __LINE__) ("Core",b) static member ``module name`` () = let b = nameof(FSharp.Core.Operators) - Assert.AreEqual("Operators",b) + Assert.AreEqual ("line " + string __LINE__) ("Operators",b) static member ``exception name`` () = let b = nameof(ABC) - Assert.AreEqual("ABC",b) + Assert.AreEqual ("line " + string __LINE__) ("ABC",b) static member ``nested type name 1`` () = let b = nameof(System.Collections.Generic.List.Enumerator<_>) - Assert.AreEqual("Enumerator",b) + Assert.AreEqual ("line " + string __LINE__) ("Enumerator",b) static member ``type name 2`` () = let b = nameof(System.Action<_>) - Assert.AreEqual("Action",b) + Assert.AreEqual ("line " + string __LINE__) ("Action",b) static member ``member function which is defined below`` () = let x = BasicNameOfTests() let b = nameof(x.MemberMethodDefinedBelow) - Assert.AreEqual("MemberMethodDefinedBelow",b) + Assert.AreEqual ("line " + string __LINE__) ("MemberMethodDefinedBelow",b) member this.MemberMethodDefinedBelow(x,y) = x * y static member ``static member function name`` () = let b = nameof(BasicNameOfTests.StaticMethod) - Assert.AreEqual("StaticMethod",b) + Assert.AreEqual ("line " + string __LINE__) ("StaticMethod",b) member this.``class member lookup`` () = let b = nameof(localConstant) - Assert.AreEqual("localConstant",b) + Assert.AreEqual ("line " + string __LINE__) ("localConstant",b) static member ``static property name`` () = let b = nameof(BasicNameOfTests.StaticProperty) - Assert.AreEqual("StaticProperty",b) + Assert.AreEqual ("line " + string __LINE__) ("StaticProperty",b) member this.get_XYZ() = 1 static member ``member method starting with get_`` () = let x = BasicNameOfTests() let b = nameof(x.get_XYZ) - Assert.AreEqual("get_XYZ",b) + Assert.AreEqual ("line " + string __LINE__) ("get_XYZ",b) static member get_SXYZ() = 1 static member ``static method starting with get_`` () = let b = nameof(BasicNameOfTests.get_SXYZ) - Assert.AreEqual("get_SXYZ",b) + Assert.AreEqual ("line " + string __LINE__) ("get_SXYZ",b) static member ``nameof local property with encapsulated name`` () = let ``local property with encapsulated name and %.f`` = 0 let b = nameof(``local property with encapsulated name and %.f``) - Assert.AreEqual("local property with encapsulated name and %.f",b) + Assert.AreEqual ("line " + string __LINE__) ("local property with encapsulated name and %.f",b) type MethodGroupNameOfTests() = member this.MethodGroup() = () @@ -178,20 +177,20 @@ type MethodGroupNameOfTests() = member this.``single argument method group name lookup`` () = let b = nameof(this.MethodGroup) - Assert.AreEqual("MethodGroup",b) + Assert.AreEqual ("line " + string __LINE__) ("MethodGroup",b) member this.``multiple argument method group name lookup`` () = let b = nameof(this.MethodGroup1 : (float * int64 -> _)) - Assert.AreEqual("MethodGroup1",b) + Assert.AreEqual ("line " + string __LINE__) ("MethodGroup1",b) type FrameworkMethodTests() = member this.``library function name`` () = let b = nameof(List.map) - Assert.AreEqual("map",b) + Assert.AreEqual ("line " + string __LINE__) ("map",b) member this.``static class function name`` () = let b = nameof(System.Tuple.Create) - Assert.AreEqual("Create",b) + Assert.AreEqual ("line " + string __LINE__) ("Create",b) type CustomUnionType = | OptionA @@ -206,22 +205,22 @@ type UnionAndRecordNameOfTests() = member this.``measure 1`` () = let b = nameof(Milliquacks) - Assert.AreEqual("Milliquacks",b) + Assert.AreEqual ("line " + string __LINE__) ("Milliquacks",b) member this.``record case 1`` () = let sample = Unchecked.defaultof let b = nameof(sample.X) - let result = Assert.AreEqual("X",b) + let result = Assert.AreEqual ("line " + string __LINE__) ("X",b) let b = nameof(sample.Y) - result || Assert.AreEqual("Y",b) + result || Assert.AreEqual ("line " + string __LINE__) ("Y",b) member this.``union case 1`` () = let b = nameof(OptionA) - Assert.AreEqual("OptionA",b) + Assert.AreEqual ("line " + string __LINE__) ("OptionA",b) member this.``union case 2`` () = let b = nameof(OptionB) - Assert.AreEqual("OptionB",b) + Assert.AreEqual ("line " + string __LINE__) ("OptionB",b) type AttributeNameOfTests() = @@ -230,33 +229,33 @@ type AttributeNameOfTests() = let t = typeof.GetMethod("ok in attribute") let attrs = t.GetCustomAttributes(typeof, false) let attr = attrs.[0] :?> ObsoleteAttribute - Assert.AreEqual(attr.Message, "test string") + Assert.AreEqual ("line " + string __LINE__) (attr.Message, "test string") type OperatorNameOfTests() = member this.``lookup name of typeof operator`` () = let b = nameof(typeof) - Assert.AreEqual("typeof",b) + Assert.AreEqual ("line " + string __LINE__) ("typeof",b) member this.``lookup name of + operator`` () = let b = nameof(+) - Assert.AreEqual("+",b) + Assert.AreEqual ("line " + string __LINE__) ("+",b) let b2 = nameof(op_Addition) - Assert.AreEqual("op_Addition",b2) + Assert.AreEqual ("line " + string __LINE__) ("op_Addition",b2) let b3 = nameof(FSharp.Core.Operators.(+)) - Assert.AreEqual("+",b3) + Assert.AreEqual ("line " + string __LINE__) ("+",b3) let b4 = nameof(FSharp.Core.Operators.op_Addition) - Assert.AreEqual("op_Addition",b4) + Assert.AreEqual ("line " + string __LINE__) ("op_Addition",b4) member this.``lookup name of |> operator`` () = let a = nameof(|>) - let result = Assert.AreEqual("|>",a) + let result = Assert.AreEqual ("line " + string __LINE__) ("|>",a) let b = nameof(op_PipeRight) - result || Assert.AreEqual("op_PipeRight",b) + result || Assert.AreEqual ("line " + string __LINE__) ("op_PipeRight",b) member this.``lookup name of nameof operator`` () = let b = nameof(nameof) - Assert.AreEqual("nameof",b) + Assert.AreEqual ("line " + string __LINE__) ("nameof",b) type PatternMatchingOfOperatorNameTests() = member this.Method1(i:int) = () @@ -279,17 +278,17 @@ type NameOfOperatorForGenerics() = member this.``use it in a generic function`` () = let fullyGeneric x = x let b = nameof(fullyGeneric) - Assert.AreEqual("fullyGeneric",b) + Assert.AreEqual ("line " + string __LINE__) ("fullyGeneric",b) member this.``lookup name of a generic class`` () = let b = nameof System.Collections.Generic.List - Assert.AreEqual("List",b) + Assert.AreEqual ("line " + string __LINE__) ("List",b) type UserDefinedNameOfTests() = static member ``user defined nameof should shadow the operator`` () = let nameof x = "test" + x.ToString() let y = nameof 1 - Assert.AreEqual("test1",y) + Assert.AreEqual ("line " + string __LINE__) ("test1",y) type Person = { Name : string @@ -304,25 +303,25 @@ type GenericClassNameOfTests<'TTT>() = static member ``can get name of class type parameter`` () = let b = nameof<'TTT> - Assert.AreEqual("TTT", b) + Assert.AreEqual ("line " + string __LINE__) ("TTT", b) type GenericClassNameOfTests2<[] 'TTT>() = static member ``can get name of class unit of measure type parameter`` () = let b = nameof<'TTT> - Assert.AreEqual("TTT", b) + Assert.AreEqual ("line " + string __LINE__) ("TTT", b) module RecTest = let rec [] two = 2 and twoName = nameof(two) let ``can get name of recursive literal`` () = - Assert.AreEqual("two", twoName) + Assert.AreEqual ("line " + string __LINE__) ("two", twoName) module rec RecTest2 = let [] two = 2 let twoName = nameof(two) let ``can get name of literal in recursive module`` () = - Assert.AreEqual("two", twoName) + Assert.AreEqual ("line " + string __LINE__) ("two", twoName) do test "local variable name lookup" (BasicNameOfTests.``local variable name lookup`` ()) do test "local int function name" (BasicNameOfTests.``local int function name`` ()) diff --git a/tests/fsharp/typeProviders/negTests/neg1.bsl b/tests/fsharp/typeProviders/negTests/neg1.bsl index 20720a9f087..8572d60442e 100644 --- a/tests/fsharp/typeProviders/negTests/neg1.bsl +++ b/tests/fsharp/typeProviders/negTests/neg1.bsl @@ -1358,7 +1358,7 @@ neg1.fsx(341,110,341,114): typecheck error FS0001: This expression was expected but here has type 'bool' -neg1.fsx(342,110,342,114): typecheck error FS3045: Invalid static argument to provided type. Expected an argument of kind 'string'. +neg1.fsx(342,104,342,114): typecheck error FS3045: Invalid static argument to provided type. Expected an argument of kind 'string'. neg1.fsx(345,104,345,106): typecheck error FS3045: Invalid static argument to provided type. Expected an argument of kind 'float'. diff --git a/vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs b/vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs index 77d349e091e..916ad1e2f29 100644 --- a/vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs +++ b/vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs @@ -158,7 +158,7 @@ type internal FSharpClassificationService asyncMaybe { use _logBlock = Logger.LogBlock(LogEditorFunctionId.Classification_Semantic) - let! _, _, projectOptions = projectInfoManager.TryGetOptionsForDocumentOrProject(document, cancellationToken) + let! _, _, projectOptions = projectInfoManager.TryGetOptionsForDocumentOrProject(document, cancellationToken, userOpName) let! sourceText = document.GetTextAsync(cancellationToken) // If we are trying to get semantic classification for a document that is not open, get the results from the background and cache it. diff --git a/vsintegration/src/FSharp.Editor/CodeFix/AddOpenCodeFixProvider.fs b/vsintegration/src/FSharp.Editor/CodeFix/AddOpenCodeFixProvider.fs index 902d32357f0..387caea14d9 100644 --- a/vsintegration/src/FSharp.Editor/CodeFix/AddOpenCodeFixProvider.fs +++ b/vsintegration/src/FSharp.Editor/CodeFix/AddOpenCodeFixProvider.fs @@ -96,7 +96,7 @@ type internal FSharpAddOpenCodeFixProvider override __.RegisterCodeFixesAsync context : Task = asyncMaybe { let document = context.Document - let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, context.CancellationToken) + let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, context.CancellationToken, userOpName) let! sourceText = context.Document.GetTextAsync(context.CancellationToken) let! _, parsedInput, checkResults = checker.ParseAndCheckDocument(document, projectOptions, sourceText = sourceText, userOpName = userOpName) let line = sourceText.Lines.GetLineFromPosition(context.Span.End) @@ -105,7 +105,7 @@ type internal FSharpAddOpenCodeFixProvider let! symbol = asyncMaybe { - let! lexerSymbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, context.Span.End, document.FilePath, defines, SymbolLookupKind.Greedy, false) + let! lexerSymbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, context.Span.End, document.FilePath, defines, SymbolLookupKind.Greedy, false, false) return! checkResults.GetSymbolUseAtLocation(Line.fromZ linePos.Line, lexerSymbol.Ident.idRange.EndColumn, line.ToString(), lexerSymbol.FullIsland, userOpName=userOpName) } |> liftAsync diff --git a/vsintegration/src/FSharp.Editor/CodeFix/ImplementInterfaceCodeFixProvider.fs b/vsintegration/src/FSharp.Editor/CodeFix/ImplementInterfaceCodeFixProvider.fs index d50fce766fa..2415fa3baca 100644 --- a/vsintegration/src/FSharp.Editor/CodeFix/ImplementInterfaceCodeFixProvider.fs +++ b/vsintegration/src/FSharp.Editor/CodeFix/ImplementInterfaceCodeFixProvider.fs @@ -138,7 +138,7 @@ type internal FSharpImplementInterfaceCodeFixProvider override __.RegisterCodeFixesAsync context : Task = asyncMaybe { - let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(context.Document, context.CancellationToken) + let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(context.Document, context.CancellationToken, userOpName) let cancellationToken = context.CancellationToken let! sourceText = context.Document.GetTextAsync(cancellationToken) let! _, parsedInput, checkFileResults = checker.ParseAndCheckDocument(context.Document, projectOptions, sourceText = sourceText, userOpName = userOpName) @@ -169,7 +169,7 @@ type internal FSharpImplementInterfaceCodeFixProvider | _ -> Some context.Span.End let! interfaceState = queryInterfaceState appendBracketAt interfacePos tokens parsedInput - let! symbol = Tokenizer.getSymbolAtPosition(context.Document.Id, sourceText, fixupPosition, context.Document.FilePath, defines, SymbolLookupKind.Greedy, false) + let! symbol = Tokenizer.getSymbolAtPosition(context.Document.Id, sourceText, fixupPosition, context.Document.FilePath, defines, SymbolLookupKind.Greedy, false, false) let fcsTextLineNumber = textLine.LineNumber + 1 let lineContents = textLine.ToString() let! options = context.Document.GetOptionsAsync(cancellationToken) diff --git a/vsintegration/src/FSharp.Editor/CodeFix/RemoveUnusedOpens.fs b/vsintegration/src/FSharp.Editor/CodeFix/RemoveUnusedOpens.fs index 8b659aafb32..9f9d81cb9b9 100644 --- a/vsintegration/src/FSharp.Editor/CodeFix/RemoveUnusedOpens.fs +++ b/vsintegration/src/FSharp.Editor/CodeFix/RemoveUnusedOpens.fs @@ -22,6 +22,7 @@ type internal FSharpRemoveUnusedOpensCodeFixProvider projectInfoManager: FSharpProjectOptionsManager ) = inherit CodeFixProvider() + let userOpName = "FSharpRemoveUnusedOpensCodeFixProvider" let fixableDiagnosticIds = [FSharpIDEDiagnosticIds.RemoveUnnecessaryImportsDiagnosticId] let createCodeFix (title: string, context: CodeFixContext) = @@ -32,7 +33,7 @@ type internal FSharpRemoveUnusedOpensCodeFixProvider let document = context.Document let! sourceText = document.GetTextAsync() let checker = checkerProvider.Checker - let! _parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, context.CancellationToken) + let! _parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, context.CancellationToken, userOpName) let! unusedOpens = UnusedOpensDiagnosticAnalyzer.GetUnusedOpenRanges(document, projectOptions, checker) let changes = unusedOpens diff --git a/vsintegration/src/FSharp.Editor/CodeFix/RenameUnusedValue.fs b/vsintegration/src/FSharp.Editor/CodeFix/RenameUnusedValue.fs index 67379326323..2a185cdbb8e 100644 --- a/vsintegration/src/FSharp.Editor/CodeFix/RenameUnusedValue.fs +++ b/vsintegration/src/FSharp.Editor/CodeFix/RenameUnusedValue.fs @@ -57,11 +57,11 @@ type internal FSharpRenameUnusedValueCodeFixProvider // We have to use the additional check for backtickes because `IsOperatorOrBacktickedName` operates on display names // where backtickes are replaced with parens. if not (PrettyNaming.IsOperatorOrBacktickedName ident) && not (ident.StartsWith "``") then - let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, context.CancellationToken) + let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, context.CancellationToken, userOpName) let! _, _, checkResults = checker.ParseAndCheckDocument(document, projectOptions, sourceText = sourceText, userOpName=userOpName) let m = RoslynHelpers.TextSpanToFSharpRange(document.FilePath, context.Span, sourceText) let defines = CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions - let! lexerSymbol = Tokenizer.getSymbolAtPosition (document.Id, sourceText, context.Span.Start, document.FilePath, defines, SymbolLookupKind.Greedy, false) + let! lexerSymbol = Tokenizer.getSymbolAtPosition (document.Id, sourceText, context.Span.Start, document.FilePath, defines, SymbolLookupKind.Greedy, false, false) let lineText = (sourceText.Lines.GetLineFromPosition context.Span.Start).ToString() let! symbolUse = checkResults.GetSymbolUseAtLocation(m.StartLine, m.EndColumn, lineText, lexerSymbol.FullIsland, userOpName=userOpName) let symbolName = symbolUse.Symbol.DisplayName diff --git a/vsintegration/src/FSharp.Editor/CodeFix/ReplaceWithSuggestion.fs b/vsintegration/src/FSharp.Editor/CodeFix/ReplaceWithSuggestion.fs index 969cfb55a16..628508e76b6 100644 --- a/vsintegration/src/FSharp.Editor/CodeFix/ReplaceWithSuggestion.fs +++ b/vsintegration/src/FSharp.Editor/CodeFix/ReplaceWithSuggestion.fs @@ -33,7 +33,7 @@ type internal FSharpReplaceWithSuggestionCodeFixProvider do! Option.guard settings.CodeFixes.SuggestNamesForErrors let document = context.Document - let! _, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, context.CancellationToken) + let! _, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, context.CancellationToken, userOpName) let! parseFileResults, _, checkFileResults = checker.ParseAndCheckDocument(document, projectOptions, userOpName=userOpName) // This is all needed to get a declaration list diff --git a/vsintegration/src/FSharp.Editor/CodeLens/FSharpCodeLensService.fs b/vsintegration/src/FSharp.Editor/CodeLens/FSharpCodeLensService.fs index 668606afa20..dd2b8271dc8 100644 --- a/vsintegration/src/FSharp.Editor/CodeLens/FSharpCodeLensService.fs +++ b/vsintegration/src/FSharp.Editor/CodeLens/FSharpCodeLensService.fs @@ -52,6 +52,7 @@ type internal FSharpCodeLensService ) as self = let lineLens = codeLens + let userOpName = "FSharpCodeLensService" let visit pos parseTree = AstTraversal.Traverse(pos, parseTree, { new AstTraversal.AstVisitorBase<_>() with @@ -154,7 +155,7 @@ type internal FSharpCodeLensService logInfof "Rechecking code due to buffer edit!" #endif let! document = workspace.CurrentSolution.GetDocument(documentId.Value) |> Option.ofObj - let! _, options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, bufferChangedCts.Token) + let! _, options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, bufferChangedCts.Token, userOpName) let! _, parsedInput, checkFileResults = checker.ParseAndCheckDocument(document, options, "LineLens", allowStaleResults=true) #if DEBUG logInfof "Getting uses of all symbols!" diff --git a/vsintegration/src/FSharp.Editor/Commands/HelpContextService.fs b/vsintegration/src/FSharp.Editor/Commands/HelpContextService.fs index 1683cb6a4a7..ffdb586ff57 100644 --- a/vsintegration/src/FSharp.Editor/Commands/HelpContextService.fs +++ b/vsintegration/src/FSharp.Editor/Commands/HelpContextService.fs @@ -98,7 +98,7 @@ type internal FSharpHelpContextService member this.GetHelpTermAsync(document, textSpan, cancellationToken) = asyncMaybe { - let! _parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) + let! _parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) let! sourceText = document.GetTextAsync(cancellationToken) let! textVersion = document.GetTextVersionAsync(cancellationToken) let defines = projectInfoManager.GetCompilationDefinesForEditingDocument(document) diff --git a/vsintegration/src/FSharp.Editor/Commands/XmlDocCommandService.fs b/vsintegration/src/FSharp.Editor/Commands/XmlDocCommandService.fs index 11922d0d0d0..107cde020bf 100644 --- a/vsintegration/src/FSharp.Editor/Commands/XmlDocCommandService.fs +++ b/vsintegration/src/FSharp.Editor/Commands/XmlDocCommandService.fs @@ -67,7 +67,7 @@ type internal XmlDocCommandFilter // XmlDocable line #1 are 1-based, editor is 0-based let curLineNum = wpfTextView.Caret.Position.BufferPosition.GetContainingLine().LineNumber + 1 let! document = document.Value - let! parsingOptions, _options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, CancellationToken.None) + let! parsingOptions, _options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, CancellationToken.None, userOpName) let! sourceText = document.GetTextAsync(CancellationToken.None) let! parsedInput = checker.ParseDocument(document, parsingOptions, sourceText, userOpName) let xmlDocables = XmlDocParser.getXmlDocables (sourceText.ToFSharpSourceText(), Some parsedInput) diff --git a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs index 11c5f3f0c57..acca943c970 100644 --- a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs +++ b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs @@ -228,7 +228,7 @@ type internal FSharpCompletionProvider let! sourceText = context.Document.GetTextAsync(context.CancellationToken) let defines = projectInfoManager.GetCompilationDefinesForEditingDocument(document) do! Option.guard (CompletionUtils.shouldProvideCompletion(document.Id, document.FilePath, defines, sourceText, context.Position)) - let! _parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, context.CancellationToken) + let! _parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, context.CancellationToken, userOpName) let! textVersion = context.Document.GetTextVersionAsync(context.CancellationToken) let getAllSymbols(fileCheckResults: FSharpCheckFileResults) = if settings.IntelliSense.IncludeSymbolsFromUnopenedNamespacesOrModules @@ -298,7 +298,7 @@ type internal FSharpCompletionProvider let! sourceText = document.GetTextAsync(cancellationToken) let textWithItemCommitted = sourceText.WithChanges(TextChange(item.Span, nameInCode)) let line = sourceText.Lines.GetLineFromPosition(item.Span.Start) - let! parsingOptions, _options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) + let! parsingOptions, _options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) let! parsedInput = checker.ParseDocument(document, parsingOptions, sourceText, userOpName) let fullNameIdents = fullName |> Option.map (fun x -> x.Split '.') |> Option.defaultValue [||] diff --git a/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs b/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs index 02f4e938925..de4d3c597d0 100644 --- a/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs +++ b/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs @@ -197,7 +197,7 @@ type internal FSharpSignatureHelpProvider member this.GetItemsAsync(document, position, triggerInfo, cancellationToken) = asyncMaybe { try - let! _parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) + let! _parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) let! sourceText = document.GetTextAsync(cancellationToken) let! textVersion = document.GetTextVersionAsync(cancellationToken) diff --git a/vsintegration/src/FSharp.Editor/Debugging/BreakpointResolutionService.fs b/vsintegration/src/FSharp.Editor/Debugging/BreakpointResolutionService.fs index 42bd5f9282d..17e2724d6ee 100644 --- a/vsintegration/src/FSharp.Editor/Debugging/BreakpointResolutionService.fs +++ b/vsintegration/src/FSharp.Editor/Debugging/BreakpointResolutionService.fs @@ -44,7 +44,7 @@ type internal FSharpBreakpointResolutionService interface IFSharpBreakpointResolutionService with member this.ResolveBreakpointAsync(document: Document, textSpan: TextSpan, cancellationToken: CancellationToken): Task = asyncMaybe { - let! parsingOptions, _options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) + let! parsingOptions, _options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) let! sourceText = document.GetTextAsync(cancellationToken) let! range = FSharpBreakpointResolutionService.GetBreakpointLocation(checkerProvider.Checker, sourceText, document.Name, textSpan, parsingOptions) let! span = RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, range) diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/DocumentDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/DocumentDiagnosticAnalyzer.fs index 2e7a44e2511..a8534353c65 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/DocumentDiagnosticAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/DocumentDiagnosticAnalyzer.fs @@ -112,7 +112,7 @@ type internal FSharpDocumentDiagnosticAnalyzer [] () = member this.AnalyzeSyntaxAsync(document: Document, cancellationToken: CancellationToken): Task> = let projectInfoManager = getProjectInfoManager document asyncMaybe { - let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) + let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) let! sourceText = document.GetTextAsync(cancellationToken) let! textVersion = document.GetTextVersionAsync(cancellationToken) return! @@ -125,7 +125,7 @@ type internal FSharpDocumentDiagnosticAnalyzer [] () = member this.AnalyzeSemanticsAsync(document: Document, cancellationToken: CancellationToken): Task> = let projectInfoManager = getProjectInfoManager document asyncMaybe { - let! parsingOptions, _, projectOptions = projectInfoManager.TryGetOptionsForDocumentOrProject(document, cancellationToken) + let! parsingOptions, _, projectOptions = projectInfoManager.TryGetOptionsForDocumentOrProject(document, cancellationToken, userOpName) let! sourceText = document.GetTextAsync(cancellationToken) let! textVersion = document.GetTextVersionAsync(cancellationToken) if document.Project.Name <> FSharpConstants.FSharpMiscellaneousFilesName || isScriptFile document.FilePath then diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs index 09ee9cc2390..e888ccdc7ce 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs @@ -41,7 +41,7 @@ type internal SimplifyNameDiagnosticAnalyzer [] () = do! Option.guard document.FSharpOptions.CodeFixes.SimplifyName do Trace.TraceInformation("{0:n3} (start) SimplifyName", DateTime.Now.TimeOfDay.TotalSeconds) do! Async.Sleep DefaultTuning.SimplifyNameInitialDelay |> liftAsync - let! _parsingOptions, projectOptions = getProjectInfoManager(document).TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) + let! _parsingOptions, projectOptions = getProjectInfoManager(document).TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) let! textVersion = document.GetTextVersionAsync(cancellationToken) let textVersionHash = textVersion.GetHashCode() let! _ = guard.WaitAsync(cancellationToken) |> Async.AwaitTask |> liftAsync diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs index 28f1b1f9c4f..66c0a60e452 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs @@ -31,7 +31,7 @@ type internal UnusedDeclarationsAnalyzer [] () = do Trace.TraceInformation("{0:n3} (start) UnusedDeclarationsAnalyzer", DateTime.Now.TimeOfDay.TotalSeconds) do! Async.Sleep DefaultTuning.UnusedDeclarationsAnalyzerInitialDelay |> liftAsync // be less intrusive, give other work priority most of the time - match! getProjectInfoManager(document).TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) with + match! getProjectInfoManager(document).TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) with | (_parsingOptions, projectOptions) -> let! sourceText = document.GetTextAsync() let checker = getChecker document diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/UnusedOpensDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/UnusedOpensDiagnosticAnalyzer.fs index 629989ca454..f9e4d917c2d 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/UnusedOpensDiagnosticAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/UnusedOpensDiagnosticAnalyzer.fs @@ -51,7 +51,7 @@ type internal UnusedOpensDiagnosticAnalyzer [] () = asyncMaybe { do Trace.TraceInformation("{0:n3} (start) UnusedOpensAnalyzer", DateTime.Now.TimeOfDay.TotalSeconds) do! Async.Sleep DefaultTuning.UnusedOpensAnalyzerInitialDelay |> liftAsync // be less intrusive, give other work priority most of the time - let! _parsingOptions, projectOptions = getProjectInfoManager(document).TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) + let! _parsingOptions, projectOptions = getProjectInfoManager(document).TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) let! sourceText = document.GetTextAsync() let checker = getChecker document let! unusedOpens = UnusedOpensDiagnosticAnalyzer.GetUnusedOpenRanges(document, projectOptions, checker) diff --git a/vsintegration/src/FSharp.Editor/DocumentHighlights/DocumentHighlightsService.fs b/vsintegration/src/FSharp.Editor/DocumentHighlights/DocumentHighlightsService.fs index 10ee6533790..ade8eb32a8f 100644 --- a/vsintegration/src/FSharp.Editor/DocumentHighlights/DocumentHighlightsService.fs +++ b/vsintegration/src/FSharp.Editor/DocumentHighlights/DocumentHighlightsService.fs @@ -58,7 +58,7 @@ type internal FSharpDocumentHighlightsService [] (checkerP let textLine = sourceText.Lines.GetLineFromPosition(position) let textLinePos = sourceText.Lines.GetLinePosition(position) let fcsTextLineNumber = Line.fromZ textLinePos.Line - let! symbol = Tokenizer.getSymbolAtPosition(documentKey, sourceText, position, filePath, defines, SymbolLookupKind.Greedy, false) + let! symbol = Tokenizer.getSymbolAtPosition(documentKey, sourceText, position, filePath, defines, SymbolLookupKind.Greedy, false, false) let! _, _, checkFileResults = checker.ParseAndCheckDocument(filePath, textVersionHash, sourceText, options, languageServicePerformanceOptions, userOpName = userOpName) let! symbolUse = checkFileResults.GetSymbolUseAtLocation(fcsTextLineNumber, symbol.Ident.idRange.EndColumn, textLine.ToString(), symbol.FullIsland, userOpName=userOpName) let! symbolUses = checkFileResults.GetUsesOfSymbolInFile(symbolUse.Symbol) |> liftAsync @@ -75,7 +75,7 @@ type internal FSharpDocumentHighlightsService [] (checkerP interface IFSharpDocumentHighlightsService with member __.GetDocumentHighlightsAsync(document, position, _documentsToSearch, cancellationToken) : Task> = asyncMaybe { - let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) + let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) let! sourceText = document.GetTextAsync(cancellationToken) let! textVersion = document.GetTextVersionAsync(cancellationToken) let defines = CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions diff --git a/vsintegration/src/FSharp.Editor/Formatting/BraceMatchingService.fs b/vsintegration/src/FSharp.Editor/Formatting/BraceMatchingService.fs index 794fd5de362..8b6cacb5436 100644 --- a/vsintegration/src/FSharp.Editor/Formatting/BraceMatchingService.fs +++ b/vsintegration/src/FSharp.Editor/Formatting/BraceMatchingService.fs @@ -17,7 +17,7 @@ type internal FSharpBraceMatchingService projectInfoManager: FSharpProjectOptionsManager ) = - static let defaultUserOpName = "BraceMatching" + static let userOpName = "BraceMatching" static member GetBraceMatchingResult(checker: FSharpChecker, sourceText: SourceText, fileName, parsingOptions: FSharpParsingOptions, position: int, userOpName: string, [] forFormatting: bool) = async { @@ -37,9 +37,9 @@ type internal FSharpBraceMatchingService interface IFSharpBraceMatcher with member this.FindBracesAsync(document, position, cancellationToken) = asyncMaybe { - let! parsingOptions, _options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) + let! parsingOptions, _options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) let! sourceText = document.GetTextAsync(cancellationToken) - let! (left, right) = FSharpBraceMatchingService.GetBraceMatchingResult(checkerProvider.Checker, sourceText, document.Name, parsingOptions, position, defaultUserOpName) + let! (left, right) = FSharpBraceMatchingService.GetBraceMatchingResult(checkerProvider.Checker, sourceText, document.Name, parsingOptions, position, userOpName) let! leftSpan = RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, left) let! rightSpan = RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, right) return FSharpBraceMatchingResult(leftSpan, rightSpan) diff --git a/vsintegration/src/FSharp.Editor/Formatting/EditorFormattingService.fs b/vsintegration/src/FSharp.Editor/Formatting/EditorFormattingService.fs index 4cc4b10c5a2..01f3938758c 100644 --- a/vsintegration/src/FSharp.Editor/Formatting/EditorFormattingService.fs +++ b/vsintegration/src/FSharp.Editor/Formatting/EditorFormattingService.fs @@ -29,7 +29,7 @@ type internal FSharpEditorFormattingService static let getIndentation (line : string) = line |> Seq.takeWhile ((=) ' ') |> Seq.length - static member GetFormattingChanges(documentId: DocumentId, sourceText: SourceText, filePath: string, checker: FSharpChecker, indentStyle: FormattingOptions.IndentStyle, options: (FSharpParsingOptions * FSharpProjectOptions) option, position: int) = + static member GetFormattingChanges(documentId: DocumentId, sourceText: SourceText, filePath: string, checker: FSharpChecker, indentStyle: FormattingOptions.IndentStyle, parsingOptions: FSharpParsingOptions, position: int) = // Logic for determining formatting changes: // If first token on the current line is a closing brace, // match the indent with the indent on the line that opened it @@ -40,8 +40,6 @@ type internal FSharpEditorFormattingService // (this is what C# does) do! Option.guard (indentStyle = FormattingOptions.IndentStyle.Smart) - let! parsingOptions, _projectOptions = options - let line = sourceText.Lines.[sourceText.Lines.IndexOf position] let defines = CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions @@ -151,8 +149,8 @@ type internal FSharpEditorFormattingService let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask let! options = document.GetOptionsAsync(cancellationToken) |> Async.AwaitTask let indentStyle = options.GetOption(FormattingOptions.SmartIndent, FSharpConstants.FSharpLanguageName) - let! projectOptionsOpt = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) - let! textChange = FSharpEditorFormattingService.GetFormattingChanges(document.Id, sourceText, document.FilePath, checkerProvider.Checker, indentStyle, projectOptionsOpt, position) + let parsingOptions = projectInfoManager.TryGetQuickParsingOptionsForEditingDocumentOrProject(document) + let! textChange = FSharpEditorFormattingService.GetFormattingChanges(document.Id, sourceText, document.FilePath, checkerProvider.Checker, indentStyle, parsingOptions, position) return textChange |> Option.toList |> toIList } @@ -162,12 +160,9 @@ type internal FSharpEditorFormattingService let! options = document.GetOptionsAsync(cancellationToken) |> Async.AwaitTask let tabSize = options.GetOption(FormattingOptions.TabSize, FSharpConstants.FSharpLanguageName) - match! projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) with - | Some (parsingOptions, _) -> - let! textChanges = FSharpEditorFormattingService.GetPasteChanges(document.Id, sourceText, document.FilePath, settings.Formatting, tabSize, parsingOptions, currentClipboard, span) - return textChanges |> Option.defaultValue Seq.empty |> toIList - | None -> - return toIList Seq.empty + let parsingOptions = projectInfoManager.TryGetQuickParsingOptionsForEditingDocumentOrProject(document) + let! textChanges = FSharpEditorFormattingService.GetPasteChanges(document.Id, sourceText, document.FilePath, settings.Formatting, tabSize, parsingOptions, currentClipboard, span) + return textChanges |> Option.defaultValue Seq.empty |> toIList } interface IFSharpEditorFormattingService with diff --git a/vsintegration/src/FSharp.Editor/Formatting/IndentationService.fs b/vsintegration/src/FSharp.Editor/Formatting/IndentationService.fs index a888518523d..32b06175449 100644 --- a/vsintegration/src/FSharp.Editor/Formatting/IndentationService.fs +++ b/vsintegration/src/FSharp.Editor/Formatting/IndentationService.fs @@ -61,7 +61,7 @@ type internal FSharpIndentationService true | _ -> false - static member GetDesiredIndentation(documentId: DocumentId, sourceText: SourceText, filePath: string, lineNumber: int, tabSize: int, indentStyle: FormattingOptions.IndentStyle, options: (FSharpParsingOptions * FSharpProjectOptions) option): Option = + static member GetDesiredIndentation(documentId: DocumentId, sourceText: SourceText, filePath: string, lineNumber: int, tabSize: int, indentStyle: FormattingOptions.IndentStyle, parsingOptions: FSharpParsingOptions): Option = // Match indentation with previous line let rec tryFindPreviousNonEmptyLine l = @@ -81,8 +81,6 @@ type internal FSharpIndentationService |> Seq.takeWhile ((=) ' ') |> Seq.length - let! parsingOptions, _ = options - // Only use smart indentation after tokens that need indentation // if the option is enabled return @@ -100,8 +98,8 @@ type internal FSharpIndentationService let! options = document.GetOptionsAsync(cancellationToken) |> Async.AwaitTask let tabSize = options.GetOption(FormattingOptions.TabSize, FSharpConstants.FSharpLanguageName) let indentStyle = options.GetOption(FormattingOptions.SmartIndent, FSharpConstants.FSharpLanguageName) - let! projectOptionsOpt = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) - let indent = FSharpIndentationService.GetDesiredIndentation(document.Id, sourceText, document.FilePath, lineNumber, tabSize, indentStyle, projectOptionsOpt) + let parsingOptions = projectInfoManager.TryGetQuickParsingOptionsForEditingDocumentOrProject(document) + let indent = FSharpIndentationService.GetDesiredIndentation(document.Id, sourceText, document.FilePath, lineNumber, tabSize, indentStyle, parsingOptions) return match indent with | None -> Nullable() diff --git a/vsintegration/src/FSharp.Editor/InlineRename/InlineRenameService.fs b/vsintegration/src/FSharp.Editor/InlineRename/InlineRenameService.fs index 92778109d04..15704641c09 100644 --- a/vsintegration/src/FSharp.Editor/InlineRename/InlineRenameService.fs +++ b/vsintegration/src/FSharp.Editor/InlineRename/InlineRenameService.fs @@ -155,7 +155,7 @@ type internal InlineRenameService let textLine = sourceText.Lines.GetLineFromPosition(position) let textLinePos = sourceText.Lines.GetLinePosition(position) let fcsTextLineNumber = Line.fromZ textLinePos.Line - let! symbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy, false) + let! symbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy, false, false) let! _, _, checkFileResults = checker.ParseAndCheckDocument(document, options, userOpName = userOpName) let! symbolUse = checkFileResults.GetSymbolUseAtLocation(fcsTextLineNumber, symbol.Ident.idRange.EndColumn, textLine.Text.ToString(), symbol.FullIsland, userOpName=userOpName) let! declLoc = symbolUse.GetDeclarationLocation(document) @@ -169,7 +169,7 @@ type internal InlineRenameService interface IFSharpEditorInlineRenameService with member __.GetRenameInfoAsync(document: Document, position: int, cancellationToken: CancellationToken) : Task = asyncMaybe { - let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) + let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) let! sourceText = document.GetTextAsync(cancellationToken) let defines = CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions return! InlineRenameService.GetInlineRenameInfo(checkerProvider.Checker, projectInfoManager, document, sourceText, position, defines, projectOptions) diff --git a/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs b/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs index 96921834f38..d42c4478ed2 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs @@ -75,7 +75,7 @@ module private FSharpProjectOptionsHelpers = [] type private FSharpProjectOptionsMessage = - | TryGetOptionsByDocument of Document * AsyncReplyChannel<(FSharpParsingOptions * FSharpProjectOptions) option> * CancellationToken + | TryGetOptionsByDocument of Document * AsyncReplyChannel<(FSharpParsingOptions * FSharpProjectOptions) option> * CancellationToken * userOpName: string | TryGetOptionsByProject of Project * AsyncReplyChannel<(FSharpParsingOptions * FSharpProjectOptions) option> * CancellationToken | ClearOptions of ProjectId | ClearSingleFileOptionsCache of DocumentId @@ -92,13 +92,13 @@ type private FSharpProjectOptionsReactor (workspace: Workspace, settings: Editor let cache = ConcurrentDictionary() let singleFileCache = ConcurrentDictionary() - let rec tryComputeOptionsByFile (document: Document) (ct: CancellationToken) = + let rec tryComputeOptionsByFile (document: Document) (ct: CancellationToken) userOpName = async { let! fileStamp = document.GetTextVersionAsync(ct) |> Async.AwaitTask match singleFileCache.TryGetValue(document.Id) with | false, _ -> let! sourceText = document.GetTextAsync(ct) |> Async.AwaitTask - let! scriptProjectOptions, _ = checkerProvider.Checker.GetProjectOptionsFromScript(document.FilePath, sourceText.ToFSharpSourceText(), SessionsProperties.fsiPreview) + let! scriptProjectOptions, _ = checkerProvider.Checker.GetProjectOptionsFromScript(document.FilePath, sourceText.ToFSharpSourceText(), SessionsProperties.fsiPreview, userOpName=userOpName) let projectOptions = if isScriptFile document.FilePath then scriptProjectOptions @@ -129,7 +129,7 @@ type private FSharpProjectOptionsReactor (workspace: Workspace, settings: Editor | true, (fileStamp2, parsingOptions, projectOptions) -> if fileStamp <> fileStamp2 then singleFileCache.TryRemove(document.Id) |> ignore - return! tryComputeOptionsByFile document ct + return! tryComputeOptionsByFile document ct userOpName else return Some(parsingOptions, projectOptions) } @@ -244,7 +244,7 @@ type private FSharpProjectOptionsReactor (workspace: Workspace, settings: Editor async { while true do match! agent.Receive() with - | FSharpProjectOptionsMessage.TryGetOptionsByDocument(document, reply, ct) -> + | FSharpProjectOptionsMessage.TryGetOptionsByDocument(document, reply, ct, userOpName) -> if ct.IsCancellationRequested then reply.Reply None else @@ -253,7 +253,7 @@ type private FSharpProjectOptionsReactor (workspace: Workspace, settings: Editor if document.Project.Solution.Workspace.Kind = WorkspaceKind.MiscellaneousFiles then reply.Reply None elif document.Project.Name = FSharpConstants.FSharpMiscellaneousFilesName then - let! options = tryComputeOptionsByFile document ct + let! options = tryComputeOptionsByFile document ct userOpName reply.Reply options else // We only care about the latest project in the workspace's solution. @@ -300,8 +300,8 @@ type private FSharpProjectOptionsReactor (workspace: Workspace, settings: Editor member __.TryGetOptionsByProjectAsync(project, ct) = agent.PostAndAsyncReply(fun reply -> FSharpProjectOptionsMessage.TryGetOptionsByProject(project, reply, ct)) - member __.TryGetOptionsByDocumentAsync(document, ct) = - agent.PostAndAsyncReply(fun reply -> FSharpProjectOptionsMessage.TryGetOptionsByDocument(document, reply, ct)) + member __.TryGetOptionsByDocumentAsync(document, ct, userOpName) = + agent.PostAndAsyncReply(fun reply -> FSharpProjectOptionsMessage.TryGetOptionsByDocument(document, reply, ct, userOpName)) member __.ClearOptionsByProjectId(projectId) = agent.Post(FSharpProjectOptionsMessage.ClearOptions(projectId)) @@ -379,23 +379,29 @@ type internal FSharpProjectOptionsManager reactor.TryGetOptionsByProjectAsync(project) /// Get the exact options for a document or project - member this.TryGetOptionsForDocumentOrProject(document: Document, cancellationToken) = + member this.TryGetOptionsForDocumentOrProject(document: Document, cancellationToken, userOpName) = async { - match! reactor.TryGetOptionsByDocumentAsync(document, cancellationToken) with + match! reactor.TryGetOptionsByDocumentAsync(document, cancellationToken, userOpName) with | Some(parsingOptions, projectOptions) -> return Some(parsingOptions, None, projectOptions) | _ -> return None } - /// Get the options for a document or project relevant for syntax processing. - /// Quicker then TryGetOptionsForDocumentOrProject as it doesn't need to recompute the exact project options for a script. - member this.TryGetOptionsForEditingDocumentOrProject(document:Document, cancellationToken) = + /// 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) + let! result = this.TryGetOptionsForDocumentOrProject(document, cancellationToken, userOpName) return result |> Option.map(fun (parsingOptions, _, projectOptions) -> parsingOptions, projectOptions) } + /// 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) = + match reactor.TryGetCachedOptionsByProjectId(document.Project.Id) with + | Some (_, parsingOptions, _) -> parsingOptions + | _ -> { FSharpParsingOptions.Default with IsInteractive = FSharpFileUtilities.isScriptFile document.Name } + [] /// This handles commandline change notifications from the Dotnet Project-system /// Prior to VS 15.7 path contained path to project file, post 15.7 contains target binpath diff --git a/vsintegration/src/FSharp.Editor/LanguageService/SymbolHelpers.fs b/vsintegration/src/FSharp.Editor/LanguageService/SymbolHelpers.fs index 3dbe12fc40d..37635ea5d69 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/SymbolHelpers.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/SymbolHelpers.fs @@ -25,9 +25,9 @@ module internal SymbolHelpers = let textLine = sourceText.Lines.GetLineFromPosition(position) let textLinePos = sourceText.Lines.GetLinePosition(position) let fcsTextLineNumber = Line.fromZ textLinePos.Line - let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) + let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) let defines = CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions - let! symbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy, false) + let! symbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy, false, false) let settings = document.FSharpOptions let! _, _, checkFileResults = checker.ParseAndCheckDocument(document.FilePath, textVersionHash, sourceText, projectOptions, settings.LanguageServicePerformance, userOpName = userOpName) let! symbolUse = checkFileResults.GetSymbolUseAtLocation(fcsTextLineNumber, symbol.Ident.idRange.EndColumn, textLine.ToString(), symbol.FullIsland, userOpName=userOpName) @@ -118,9 +118,9 @@ module internal SymbolHelpers = let! sourceText = document.GetTextAsync(cancellationToken) let originalText = sourceText.ToString(symbolSpan) do! Option.guard (originalText.Length > 0) - let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) + let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) let defines = CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions - let! symbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, symbolSpan.Start, document.FilePath, defines, SymbolLookupKind.Greedy, false) + let! symbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, symbolSpan.Start, document.FilePath, defines, SymbolLookupKind.Greedy, false, false) let! _, _, checkFileResults = checker.ParseAndCheckDocument(document, projectOptions, userOpName = userOpName) let textLine = sourceText.Lines.GetLineFromPosition(symbolSpan.Start) let textLinePos = sourceText.Lines.GetLinePosition(symbolSpan.Start) diff --git a/vsintegration/src/FSharp.Editor/LanguageService/Tokenizer.fs b/vsintegration/src/FSharp.Editor/LanguageService/Tokenizer.fs index 0c48144db02..2ecc21caf0d 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/Tokenizer.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/Tokenizer.fs @@ -33,7 +33,8 @@ type internal LexerSymbolKind = | GenericTypeParameter = 3 | StaticallyResolvedTypeParameter = 4 | ActivePattern = 5 - | Other = 6 + | String = 6 + | Other = 7 type internal LexerSymbol = { Kind: LexerSymbolKind @@ -147,11 +148,14 @@ module internal Tokenizer = | FSharpGlyph.Variable -> Glyph.Local | FSharpGlyph.Error -> Glyph.Error - let GetImageIdForSymbol(symbol:FSharpSymbol, kind:LexerSymbolKind) = + let GetImageIdForSymbol(symbolOpt:FSharpSymbol option, kind:LexerSymbolKind) = let imageId = match kind with | LexerSymbolKind.Operator -> KnownImageIds.Operator | _ -> + match symbolOpt with + | None -> KnownImageIds.Package + | Some symbol -> match symbol with | :? FSharpUnionCase as x -> match Some x.Accessibility with @@ -345,6 +349,7 @@ module internal Tokenizer = member token.IsIdentifier = (token.CharClass = FSharpTokenCharKind.Identifier) member token.IsOperator = (token.ColorClass = FSharpTokenColorKind.Operator) member token.IsPunctuation = (token.ColorClass = FSharpTokenColorKind.Punctuation) + member token.IsString = (token.ColorClass = FSharpTokenColorKind.String) /// This is the information we save for each token in a line for each active document. /// It is a memory-critical data structure - do not make larger. This used to be ~100 bytes class, is now 8-byte struct @@ -375,6 +380,7 @@ module internal Tokenizer = if token.IsOperator then LexerSymbolKind.Operator elif token.IsIdentifier then LexerSymbolKind.Ident elif token.IsPunctuation then LexerSymbolKind.Punctuation + elif token.IsString then LexerSymbolKind.String else LexerSymbolKind.Other Debug.Assert(uint32 token.Tag < 0xFFFFu) Debug.Assert(uint32 kind < 0xFFu) @@ -612,7 +618,8 @@ module internal Tokenizer = linePos: LinePosition, lineStr: string, lookupKind: SymbolLookupKind, - wholeActivePatterns: bool + wholeActivePatterns: bool, + allowStringToken: bool ) : LexerSymbol option = @@ -704,6 +711,7 @@ module internal Tokenizer = | LexerSymbolKind.StaticallyResolvedTypeParameter -> true | _ -> false) |> Option.orElseWith (fun _ -> tokensUnderCursor |> List.tryFind (fun token -> token.Kind = LexerSymbolKind.Operator)) + |> Option.orElseWith (fun _ -> if allowStringToken then tokensUnderCursor |> List.tryFind (fun token -> token.Kind = LexerSymbolKind.String) else None) |> Option.map (fun token -> let partialName = QuickParse.GetPartialLongNameEx(lineStr, token.RightColumn) let identStr = lineStr.Substring(token.LeftColumn, token.MatchedLength) @@ -767,13 +775,14 @@ module internal Tokenizer = fileName: string, defines: string list, lookupKind: SymbolLookupKind, - wholeActivePatterns: bool + wholeActivePatterns: bool, + allowStringToken: bool ) : LexerSymbol option = try let lineData, textLinePos, lineContents = getCachedSourceLineData(documentKey, sourceText, position, fileName, defines) - getSymbolFromSavedTokens(fileName, lineData.SavedTokens, textLinePos, lineContents, lookupKind, wholeActivePatterns) + getSymbolFromSavedTokens(fileName, lineData.SavedTokens, textLinePos, lineContents, lookupKind, wholeActivePatterns, allowStringToken) with | :? System.OperationCanceledException -> reraise() | ex -> diff --git a/vsintegration/src/FSharp.Editor/Navigation/FindUsagesService.fs b/vsintegration/src/FSharp.Editor/Navigation/FindUsagesService.fs index ff841e4b5fc..9988f74d6c6 100644 --- a/vsintegration/src/FSharp.Editor/Navigation/FindUsagesService.fs +++ b/vsintegration/src/FSharp.Editor/Navigation/FindUsagesService.fs @@ -51,13 +51,13 @@ type internal FSharpFindUsagesService asyncMaybe { let! sourceText = document.GetTextAsync(context.CancellationToken) |> Async.AwaitTask |> liftAsync let checker = checkerProvider.Checker - let! parsingOptions, _, projectOptions = projectInfoManager.TryGetOptionsForDocumentOrProject(document, context.CancellationToken) + let! parsingOptions, _, projectOptions = projectInfoManager.TryGetOptionsForDocumentOrProject(document, context.CancellationToken, userOpName) let! _, _, checkFileResults = checker.ParseAndCheckDocument(document, projectOptions, sourceText = sourceText, userOpName = userOpName) let textLine = sourceText.Lines.GetLineFromPosition(position).ToString() let lineNumber = sourceText.Lines.GetLinePosition(position).Line + 1 let defines = CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions - let! symbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy, false) + let! symbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy, false, false) let! symbolUse = checkFileResults.GetSymbolUseAtLocation(lineNumber, symbol.Ident.idRange.EndColumn, textLine, symbol.FullIsland, userOpName=userOpName) let! declaration = checkFileResults.GetDeclarationLocation (lineNumber, symbol.Ident.idRange.EndColumn, textLine, symbol.FullIsland, false, userOpName=userOpName) |> liftAsync let tags = FSharpGlyphTags.GetTags(Tokenizer.GetGlyphForSymbol (symbolUse.Symbol, symbol.Kind)) diff --git a/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs b/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs index a607442e462..18221c0f316 100644 --- a/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs +++ b/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs @@ -168,11 +168,11 @@ type internal GoToDefinition(checker: FSharpChecker, projectInfoManager: FSharpP /// Helper function that is used to determine the navigation strategy to apply, can be tuned towards signatures or implementation files. member private __.FindSymbolHelper (originDocument: Document, originRange: range, sourceText: SourceText, preferSignature: bool) = asyncMaybe { - let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(originDocument, CancellationToken.None) + let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(originDocument, CancellationToken.None, userOpName) let defines = CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions let! originTextSpan = RoslynHelpers.TryFSharpRangeToTextSpan (sourceText, originRange) let position = originTextSpan.Start - let! lexerSymbol = Tokenizer.getSymbolAtPosition (originDocument.Id, sourceText, position, originDocument.FilePath, defines, SymbolLookupKind.Greedy, false) + let! lexerSymbol = Tokenizer.getSymbolAtPosition (originDocument.Id, sourceText, position, originDocument.FilePath, defines, SymbolLookupKind.Greedy, false, false) let textLinePos = sourceText.Lines.GetLinePosition position let fcsTextLineNumber = Line.fromZ textLinePos.Line @@ -190,7 +190,7 @@ type internal GoToDefinition(checker: FSharpChecker, projectInfoManager: FSharpP if not (File.Exists fsfilePath) then return! None else let! implDoc = originDocument.Project.Solution.TryGetDocumentFromPath fsfilePath let! implSourceText = implDoc.GetTextAsync () - let! _parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(implDoc, CancellationToken.None) + let! _parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(implDoc, CancellationToken.None, userOpName) let! _, _, checkFileResults = checker.ParseAndCheckDocument (implDoc, projectOptions, sourceText=implSourceText, userOpName=userOpName) let! symbolUses = checkFileResults.GetUsesOfSymbolInFile symbol |> liftAsync let! implSymbol = symbolUses |> Array.tryHead @@ -220,7 +220,7 @@ type internal GoToDefinition(checker: FSharpChecker, projectInfoManager: FSharpP member private this.FindDefinitionAtPosition(originDocument: Document, position: int) = asyncMaybe { - let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(originDocument, CancellationToken.None) + let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(originDocument, CancellationToken.None, userOpName) let! sourceText = originDocument.GetTextAsync () |> liftTaskAsync let defines = CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions let textLine = sourceText.Lines.GetLineFromPosition position @@ -232,7 +232,7 @@ type internal GoToDefinition(checker: FSharpChecker, projectInfoManager: FSharpP let! _, _, checkFileResults = checker.ParseAndCheckDocument (originDocument, projectOptions, sourceText=sourceText, userOpName=userOpName) - let! lexerSymbol = Tokenizer.getSymbolAtPosition (originDocument.Id, sourceText, position,originDocument.FilePath, defines, SymbolLookupKind.Greedy, false) + let! lexerSymbol = Tokenizer.getSymbolAtPosition (originDocument.Id, sourceText, position,originDocument.FilePath, defines, SymbolLookupKind.Greedy, false, false) let idRange = lexerSymbol.Ident.idRange let! declarations = checkFileResults.GetDeclarationLocation (fcsTextLineNumber, lexerSymbol.Ident.idRange.EndColumn, textLine.ToString(), lexerSymbol.FullIsland, preferSignature, userOpName=userOpName) |> liftAsync @@ -307,7 +307,7 @@ type internal GoToDefinition(checker: FSharpChecker, projectInfoManager: FSharpP let! implDocument = originDocument.Project.Solution.TryGetDocumentFromPath implFilePath let! implVersion = implDocument.GetTextVersionAsync () |> liftTaskAsync let! implSourceText = implDocument.GetTextAsync () |> liftTaskAsync - let! _parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(implDocument, CancellationToken.None) + let! _parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(implDocument, CancellationToken.None, userOpName) let! targetRange = this.FindSymbolDeclarationInFile(targetSymbolUse, implFilePath, implSourceText, projectOptions, implVersion.GetHashCode()) diff --git a/vsintegration/src/FSharp.Editor/Navigation/NavigateToSearchService.fs b/vsintegration/src/FSharp.Editor/Navigation/NavigateToSearchService.fs index 428ca48ef62..3fb063047ec 100644 --- a/vsintegration/src/FSharp.Editor/Navigation/NavigateToSearchService.fs +++ b/vsintegration/src/FSharp.Editor/Navigation/NavigateToSearchService.fs @@ -172,6 +172,7 @@ type internal FSharpNavigateToSearchService projectInfoManager: FSharpProjectOptionsManager ) = + let userOpName = "FSharpNavigateToSearchService" let kindsProvided = ImmutableHashSet.Create(FSharpNavigateToItemKind.Module, FSharpNavigateToItemKind.Class, FSharpNavigateToItemKind.Field, FSharpNavigateToItemKind.Property, FSharpNavigateToItemKind.Method, FSharpNavigateToItemKind.Enum, FSharpNavigateToItemKind.EnumItem) :> IImmutableSet // Save the backing navigation data in a memory cache held in a sliding window @@ -261,7 +262,7 @@ type internal FSharpNavigateToSearchService member __.SearchDocumentAsync(document, searchPattern, kinds, cancellationToken) : Task> = asyncMaybe { - let! parsingOptions, _, _ = projectInfoManager.TryGetOptionsForDocumentOrProject(document, cancellationToken) + let! parsingOptions, _, _ = projectInfoManager.TryGetOptionsForDocumentOrProject(document, cancellationToken, userOpName) let! items = getCachedIndexedNavigableItems(document, parsingOptions, kinds) |> liftAsync return items.Find(searchPattern) } diff --git a/vsintegration/src/FSharp.Editor/Navigation/NavigationBarItemService.fs b/vsintegration/src/FSharp.Editor/Navigation/NavigationBarItemService.fs index d8edebd3ac1..13350004ab1 100644 --- a/vsintegration/src/FSharp.Editor/Navigation/NavigationBarItemService.fs +++ b/vsintegration/src/FSharp.Editor/Navigation/NavigationBarItemService.fs @@ -32,7 +32,7 @@ type internal FSharpNavigationBarItemService interface IFSharpNavigationBarItemService with member __.GetItemsAsync(document, cancellationToken) : Task> = asyncMaybe { - let! parsingOptions, _options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) + let! parsingOptions, _options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) let! sourceText = document.GetTextAsync(cancellationToken) let! parsedInput = checkerProvider.Checker.ParseDocument(document, parsingOptions, sourceText=sourceText, userOpName=userOpName) let navItems = FSharpNavigation.getNavigation parsedInput diff --git a/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs b/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs index a6ea0c90332..f5e4b1611f1 100644 --- a/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs +++ b/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs @@ -26,7 +26,7 @@ open Internal.Utilities.StructuredFormat type internal QuickInfo = { StructuredText: FSharpStructuredToolTipText Span: TextSpan - Symbol: FSharpSymbol + Symbol: FSharpSymbol option SymbolKind: LexerSymbolKind } module internal FSharpQuickInfo = @@ -58,7 +58,7 @@ module internal FSharpQuickInfo = // project options need to be retrieved because the signature file could be in another project let! extParsingOptions, extProjectOptions = projectInfoManager.TryGetOptionsByProject(document.Project, cancellationToken) let extDefines = CompilerEnvironment.GetCompilationDefinesForEditing extParsingOptions - let! extLexerSymbol = Tokenizer.getSymbolAtPosition(extDocId, extSourceText, extSpan.Start, declRange.FileName, extDefines, SymbolLookupKind.Greedy, true) + let! extLexerSymbol = Tokenizer.getSymbolAtPosition(extDocId, extSourceText, extSpan.Start, declRange.FileName, extDefines, SymbolLookupKind.Greedy, true, true) let! _, _, extCheckFileResults = checker.ParseAndCheckDocument(extDocument, extProjectOptions, allowStaleResults=true, sourceText=extSourceText, userOpName = userOpName) let! extQuickInfoText = @@ -75,7 +75,7 @@ module internal FSharpQuickInfo = return { StructuredText = extQuickInfoText Span = span - Symbol = extSymbolUse.Symbol + Symbol = Some extSymbolUse.Symbol SymbolKind = extLexerSymbol.Kind } } @@ -88,26 +88,25 @@ module internal FSharpQuickInfo = position: int, cancellationToken: CancellationToken ) - : Async<(FSharpSymbolUse * QuickInfo option * QuickInfo option) option> = + : Async<(range * QuickInfo option * QuickInfo option) option> = asyncMaybe { let! sourceText = document.GetTextAsync cancellationToken - let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) + let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) let defines = CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions - let! lexerSymbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy, true) + let! lexerSymbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy, true, true) let idRange = lexerSymbol.Ident.idRange let! _, _, checkFileResults = checker.ParseAndCheckDocument(document, projectOptions, allowStaleResults = true, sourceText=sourceText, userOpName = userOpName) let textLinePos = sourceText.Lines.GetLinePosition position let fcsTextLineNumber = Line.fromZ textLinePos.Line let lineText = (sourceText.Lines.GetLineFromPosition position).ToString() - let! symbolUse = checkFileResults.GetSymbolUseAtLocation (fcsTextLineNumber, idRange.EndColumn, lineText, lexerSymbol.FullIsland, userOpName=userOpName) /// Gets the QuickInfo information for the orignal target - let getTargetSymbolQuickInfo () = + let getTargetSymbolQuickInfo (symbol, tag) = asyncMaybe { let! targetQuickInfo = checkFileResults.GetStructuredToolTipText - (fcsTextLineNumber, idRange.EndColumn, lineText, lexerSymbol.FullIsland, FSharpTokenTag.IDENT, userOpName=userOpName) |> liftAsync + (fcsTextLineNumber, idRange.EndColumn, lineText, lexerSymbol.FullIsland,tag, userOpName=userOpName) |> liftAsync match targetQuickInfo with | FSharpToolTipText [] @@ -116,21 +115,29 @@ module internal FSharpQuickInfo = let! targetTextSpan = RoslynHelpers.TryFSharpRangeToTextSpan (sourceText, lexerSymbol.Range) return { StructuredText = targetQuickInfo Span = targetTextSpan - Symbol = symbolUse.Symbol + Symbol = symbol SymbolKind = lexerSymbol.Kind } } + match lexerSymbol.Kind with + | LexerSymbolKind.String -> + let! targetQuickInfo = getTargetSymbolQuickInfo (None, FSharpTokenTag.STRING) + return lexerSymbol.Range, None, Some targetQuickInfo + + | _ -> + let! symbolUse = checkFileResults.GetSymbolUseAtLocation (fcsTextLineNumber, idRange.EndColumn, lineText, lexerSymbol.FullIsland, userOpName=userOpName) + // if the target is in a signature file, adjusting the quick info is unnecessary if isSignatureFile document.FilePath then - let! targetQuickInfo = getTargetSymbolQuickInfo() - return symbolUse, None, Some targetQuickInfo + let! targetQuickInfo = getTargetSymbolQuickInfo (Some symbolUse.Symbol, FSharpTokenTag.IDENT) + return symbolUse.RangeAlternate, None, Some targetQuickInfo else // find the declaration location of the target symbol, with a preference for signature files let! findSigDeclarationResult = checkFileResults.GetDeclarationLocation (idRange.StartLine, idRange.EndColumn, lineText, lexerSymbol.FullIsland, preferFlag=true, userOpName=userOpName) |> liftAsync // it is necessary to retrieve the backup quick info because this acquires // the textSpan designating where we want the quick info to appear. - let! targetQuickInfo = getTargetSymbolQuickInfo() + let! targetQuickInfo = getTargetSymbolQuickInfo (Some symbolUse.Symbol, FSharpTokenTag.IDENT) let! result = match findSigDeclarationResult with @@ -146,15 +153,16 @@ module internal FSharpQuickInfo = match findImplDefinitionResult with | FSharpFindDeclResult.DeclNotFound _ - | FSharpFindDeclResult.ExternalDecl _ -> return symbolUse, Some sigQuickInfo, None + | FSharpFindDeclResult.ExternalDecl _ -> + return symbolUse.RangeAlternate, Some sigQuickInfo, None | FSharpFindDeclResult.DeclFound declRange -> let! implQuickInfo = getQuickInfoFromRange(checker, projectInfoManager, document, declRange, cancellationToken) - return symbolUse, Some sigQuickInfo, Some { implQuickInfo with Span = targetQuickInfo.Span } + return symbolUse.RangeAlternate, Some sigQuickInfo, Some { implQuickInfo with Span = targetQuickInfo.Span } } | _ -> async.Return None |> liftAsync - return result |> Option.defaultValue (symbolUse, None, Some targetQuickInfo) + return result |> Option.defaultValue (symbolUse.RangeAlternate, None, Some targetQuickInfo) } type internal FSharpAsyncQuickInfoSource @@ -180,7 +188,7 @@ type internal FSharpAsyncQuickInfoSource let textLine = sourceText.Lines.GetLineFromPosition position let textLineNumber = textLine.LineNumber + 1 // Roslyn line numbers are zero-based let defines = CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions - let! symbol = Tokenizer.getSymbolAtPosition (documentId, sourceText, position, filePath, defines, SymbolLookupKind.Precise, true) + let! symbol = Tokenizer.getSymbolAtPosition (documentId, sourceText, position, filePath, defines, SymbolLookupKind.Precise, true, true) let! res = checkFileResults.GetStructuredToolTipText (textLineNumber, symbol.Ident.idRange.EndColumn, textLine.ToString(), symbol.FullIsland, FSharpTokenTag.IDENT, userOpName=FSharpQuickInfo.userOpName) |> liftAsync match res with | FSharpToolTipText [] @@ -190,7 +198,7 @@ type internal FSharpAsyncQuickInfoSource let! symbolSpan = RoslynHelpers.TryFSharpRangeToTextSpan (sourceText, symbol.Range) return { StructuredText = res Span = symbolSpan - Symbol = symbolUse.Symbol + Symbol = Some symbolUse.Symbol SymbolKind = symbol.Kind } } @@ -211,20 +219,20 @@ type internal FSharpAsyncQuickInfoSource | false -> Task.FromResult(null) | true -> let triggerPoint = triggerPoint.GetValueOrDefault() - let documentationBuilder = XmlDocumentation.CreateDocumentationBuilder(xmlMemberIndexService) asyncMaybe { let document = textBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges() - let! symbolUse, sigQuickInfo, targetQuickInfo = FSharpQuickInfo.getQuickInfo(checkerProvider.Checker, projectInfoManager, document, triggerPoint.Position, cancellationToken) + let! symbolUseRange, sigQuickInfo, targetQuickInfo = FSharpQuickInfo.getQuickInfo(checkerProvider.Checker, projectInfoManager, document, triggerPoint.Position, cancellationToken) let getTrackingSpan (span:TextSpan) = textBuffer.CurrentSnapshot.CreateTrackingSpan(span.Start, span.Length, SpanTrackingMode.EdgeInclusive) + let documentationBuilder = XmlDocumentation.CreateDocumentationBuilder(xmlMemberIndexService) match sigQuickInfo, targetQuickInfo with | None, None -> return null | Some quickInfo, None - | None, Some quickInfo-> + | None, Some quickInfo -> let mainDescription, docs = FSharpAsyncQuickInfoSource.BuildSingleQuickInfoItem documentationBuilder quickInfo let imageId = Tokenizer.GetImageIdForSymbol(quickInfo.Symbol, quickInfo.SymbolKind) - let navigation = QuickInfoNavigation(statusBar, checkerProvider.Checker, projectInfoManager, document, symbolUse.RangeAlternate) + let navigation = QuickInfoNavigation(statusBar, checkerProvider.Checker, projectInfoManager, document, symbolUseRange) let content = QuickInfoViewProvider.provideContent(imageId, mainDescription, docs, navigation) let span = getTrackingSpan quickInfo.Span return QuickInfoItem(span, content) @@ -254,7 +262,7 @@ type internal FSharpAsyncQuickInfoSource ] |> ResizeArray let docs = joinWithLineBreaks [documentation; typeParameterMap; usage; exceptions] let imageId = Tokenizer.GetImageIdForSymbol(targetQuickInfo.Symbol, targetQuickInfo.SymbolKind) - let navigation = QuickInfoNavigation(statusBar, checkerProvider.Checker, projectInfoManager, document, symbolUse.RangeAlternate) + let navigation = QuickInfoNavigation(statusBar, checkerProvider.Checker, projectInfoManager, document, symbolUseRange) let content = QuickInfoViewProvider.provideContent(imageId, mainDescription, docs, navigation) let span = getTrackingSpan targetQuickInfo.Span return QuickInfoItem(span, content) diff --git a/vsintegration/src/FSharp.Editor/Structure/BlockStructureService.fs b/vsintegration/src/FSharp.Editor/Structure/BlockStructureService.fs index 9123aea5f1e..13c74ef0f53 100644 --- a/vsintegration/src/FSharp.Editor/Structure/BlockStructureService.fs +++ b/vsintegration/src/FSharp.Editor/Structure/BlockStructureService.fs @@ -152,7 +152,7 @@ type internal FSharpBlockStructureService [] (checkerProvi member __.GetBlockStructureAsync(document, cancellationToken) : Task = asyncMaybe { - let! parsingOptions, _options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken) + let! parsingOptions, _options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, cancellationToken, userOpName) let! sourceText = document.GetTextAsync(cancellationToken) let! parsedInput = checkerProvider.Checker.ParseDocument(document, parsingOptions, sourceText, userOpName) return createBlockSpans document.FSharpOptions.Advanced.IsBlockStructureEnabled sourceText parsedInput |> Seq.toImmutableArray diff --git a/vsintegration/tests/UnitTests/EditorFormattingServiceTests.fs b/vsintegration/tests/UnitTests/EditorFormattingServiceTests.fs index fbcfc1125af..3a5b70f2051 100644 --- a/vsintegration/tests/UnitTests/EditorFormattingServiceTests.fs +++ b/vsintegration/tests/UnitTests/EditorFormattingServiceTests.fs @@ -78,7 +78,7 @@ marker4""" let lineNumber = sourceText.Lines |> Seq.findIndex (fun line -> line.Span.Contains position) let parsingOptions, _ = checker.GetParsingOptionsFromProjectOptions projectOptions - let changesOpt = FSharpEditorFormattingService.GetFormattingChanges(documentId, sourceText, filePath, checker, indentStyle, Some (parsingOptions, projectOptions), position) |> Async.RunSynchronously + let changesOpt = FSharpEditorFormattingService.GetFormattingChanges(documentId, sourceText, filePath, checker, indentStyle, parsingOptions, position) |> Async.RunSynchronously match changesOpt with | None -> Assert.Fail("Expected a text change, but got None") | Some changes -> diff --git a/vsintegration/tests/UnitTests/GoToDefinitionServiceTests.fs b/vsintegration/tests/UnitTests/GoToDefinitionServiceTests.fs index 755b66ca085..4408b27e5ac 100644 --- a/vsintegration/tests/UnitTests/GoToDefinitionServiceTests.fs +++ b/vsintegration/tests/UnitTests/GoToDefinitionServiceTests.fs @@ -52,7 +52,7 @@ module GoToDefinitionServiceTests = let textLine = sourceText.Lines.GetLineFromPosition position let textLinePos = sourceText.Lines.GetLinePosition position let fcsTextLineNumber = Line.fromZ textLinePos.Line - let! lexerSymbol = Tokenizer.getSymbolAtPosition(documentKey, sourceText, position, filePath, defines, SymbolLookupKind.Greedy, false) + let! lexerSymbol = Tokenizer.getSymbolAtPosition(documentKey, sourceText, position, filePath, defines, SymbolLookupKind.Greedy, false, false) let! _, _, checkFileResults = checker.ParseAndCheckDocument (filePath, textVersionHash, sourceText, options, LanguageServicePerformanceOptions.Default, userOpName=userOpName) |> Async.RunSynchronously let declarations = checkFileResults.GetDeclarationLocation (fcsTextLineNumber, lexerSymbol.Ident.idRange.EndColumn, textLine.ToString(), lexerSymbol.FullIsland, false, userOpName=userOpName) |> Async.RunSynchronously diff --git a/vsintegration/tests/UnitTests/IndentationServiceTests.fs b/vsintegration/tests/UnitTests/IndentationServiceTests.fs index d16c48ddab2..a1a8cb0943f 100644 --- a/vsintegration/tests/UnitTests/IndentationServiceTests.fs +++ b/vsintegration/tests/UnitTests/IndentationServiceTests.fs @@ -176,7 +176,7 @@ while true do let sourceText = SourceText.From(template) let parsingOptions, _ = checker.GetParsingOptionsFromProjectOptions projectOptions - let actualIndentation = FSharpIndentationService.GetDesiredIndentation(documentId, sourceText, filePath, lineNumber, tabSize, indentStyle, Some (parsingOptions, projectOptions)) + let actualIndentation = FSharpIndentationService.GetDesiredIndentation(documentId, sourceText, filePath, lineNumber, tabSize, indentStyle, parsingOptions) match expectedIndentation with | None -> Assert.IsTrue(actualIndentation.IsNone, "No indentation was expected at line {0}", lineNumber) | Some indentation -> Assert.AreEqual(expectedIndentation.Value, actualIndentation.Value, "Indentation on line {0} doesn't match", lineNumber) @@ -189,7 +189,7 @@ while true do let sourceText = SourceText.From(template) let parsingOptions, _ = checker.GetParsingOptionsFromProjectOptions projectOptions - let actualIndentation = FSharpIndentationService.GetDesiredIndentation(documentId, sourceText, filePath, lineNumber, tabSize, indentStyle, Some (parsingOptions, projectOptions)) + let actualIndentation = FSharpIndentationService.GetDesiredIndentation(documentId, sourceText, filePath, lineNumber, tabSize, indentStyle, parsingOptions) match expectedIndentation with | None -> Assert.IsTrue(actualIndentation.IsNone, "No indentation was expected at line {0}", lineNumber) | Some indentation -> Assert.AreEqual(expectedIndentation.Value, actualIndentation.Value, "Indentation on line {0} doesn't match", lineNumber)