diff --git a/fcs/.gitignore b/fcs/.gitignore
new file mode 100644
index 00000000000..09ed5be8e7e
--- /dev/null
+++ b/fcs/.gitignore
@@ -0,0 +1 @@
+/FSharp.Compiler.Service.netstandard
diff --git a/fcs/FSharp.Compiler.Service.netstandard/FSharp.Compiler.Service.netstandard.fsproj b/fcs/FSharp.Compiler.Service.netstandard/FSharp.Compiler.Service.netstandard.fsproj
index 0ebd29eea3d..6f54345b348 100644
--- a/fcs/FSharp.Compiler.Service.netstandard/FSharp.Compiler.Service.netstandard.fsproj
+++ b/fcs/FSharp.Compiler.Service.netstandard/FSharp.Compiler.Service.netstandard.fsproj
@@ -500,6 +500,12 @@
CodeGen/IlxGen.fs
+
+ Driver\DependencyManager.Integration.fsi
+
+
+ Driver\DependencyManager.Integration.fs
+
Driver/CompileOps.fsi
diff --git a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj
index eebbaa0a931..dfaf75dcc8b 100644
--- a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj
+++ b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj
@@ -475,6 +475,12 @@
CodeGen/IlxGen.fs
+
+ Driver\DependencyManager.Integration.fsi
+
+
+ Driver\DependencyManager.Integration.fs
+
Driver/CompileOps.fsi
diff --git a/src/buildfromsource/FSharp.Compiler.Private/FSComp.fs b/src/buildfromsource/FSharp.Compiler.Private/FSComp.fs
index abc321272d5..62168e09f02 100644
--- a/src/buildfromsource/FSharp.Compiler.Private/FSComp.fs
+++ b/src/buildfromsource/FSharp.Compiler.Private/FSComp.fs
@@ -4300,6 +4300,15 @@ type internal SR private() =
/// An error occurred while reading the F# metadata of assembly '%s'. A reserved construct was utilized. You may need to upgrade your F# compiler or use an earlier version of the assembly that doesn't make use of a specific construct.
/// (Originally from ..\FSComp.txt:1424)
static member pickleUnexpectedNonZero(a0 : System.String) = (3219, GetStringFunc("pickleUnexpectedNonZero",",,,%s,,,") a0)
+ /// The dependency manager extension '%s' could not be loaded. Message: %s
+ /// (Originally from ..\FSComp.txt:1425)
+ static member couldNotLoadDependencyManagerExtenstion(a0 : System.String, a1 : System.String) = (3220, GetStringFunc("couldNotLoadDependencyManagerExtenstion",",,,%s,,,%s,,,") a0 a1)
+ /// Package manager key '%s' was not registered in %s. Currently registered: %s
+ /// (Originally from ..\FSComp.txt:1426)
+ static member packageManagerUnknown(a0 : System.String, a1 : System.String, a2 : System.String) = (3221, GetStringFunc("packageManagerUnknown",",,,%s,,,%s,,,%s,,,") a0 a1 a2)
+ /// %s
+ /// (Originally from ..\FSComp.txt:1427)
+ static member packageManagerError(a0 : System.String) = (3222, GetStringFunc("packageManagerError",",,,%s,,,") a0)
/// Call this method once to validate that all known resources are valid; throws if not
static member RunStartupValidation() =
@@ -5698,4 +5707,7 @@ type internal SR private() =
ignore(GetString("notAFunctionButMaybeDeclaration"))
ignore(GetString("ArgumentsInSigAndImplMismatch"))
ignore(GetString("pickleUnexpectedNonZero"))
+ ignore(GetString("couldNotLoadDependencyManagerExtenstion"))
+ ignore(GetString("packageManagerUnknown"))
+ ignore(GetString("packageManagerError"))
()
diff --git a/src/buildfromsource/FSharp.Compiler.Private/FSComp.resx b/src/buildfromsource/FSharp.Compiler.Private/FSComp.resx
index 71f965fc9fa..fe54353fcdd 100644
--- a/src/buildfromsource/FSharp.Compiler.Private/FSComp.resx
+++ b/src/buildfromsource/FSharp.Compiler.Private/FSComp.resx
@@ -4303,4 +4303,13 @@
An error occurred while reading the F# metadata of assembly '{0}'. A reserved construct was utilized. You may need to upgrade your F# compiler or use an earlier version of the assembly that doesn't make use of a specific construct.
+
+ The dependency manager extension {0} could not be loaded. Message: {1}
+
+
+ Package manager key '{0}' was not registered in {1}. Currently registered: {2}
+
+
+ {0}
+
\ No newline at end of file
diff --git a/src/buildfromsource/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/buildfromsource/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj
index 6e4a625372c..2c761f10279 100644
--- a/src/buildfromsource/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj
+++ b/src/buildfromsource/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj
@@ -454,7 +454,12 @@
CodeGen\IlxGen.fs
-
+
+ Driver\DependencyManager.Integration.fsi
+
+
+ Driver\DependencyManager.Integration.fs
+
Driver\CompileOps.fsi
@@ -628,7 +633,6 @@
-
@@ -638,6 +642,7 @@
+
diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs
index 0cab042759a..f91942b029e 100644
--- a/src/fsharp/CompileOps.fs
+++ b/src/fsharp/CompileOps.fs
@@ -77,7 +77,6 @@ let FSharpScriptFileSuffixes = [".fsscript";".fsx"]
let doNotRequireNamespaceOrModuleSuffixes = [".mli";".ml"] @ FSharpScriptFileSuffixes
let FSharpLightSyntaxFileSuffixes : string list = [ ".fs";".fsscript";".fsx";".fsi" ]
-
//----------------------------------------------------------------------------
// ERROR REPORTING
//--------------------------------------------------------------------------
@@ -2200,8 +2199,9 @@ type TcConfigBuilder =
mutable implicitlyResolveAssemblies: bool
mutable light: bool option
mutable conditionalCompilationDefines: string list
- mutable loadedSources: (range * string) list
+ mutable loadedSources: (range * string * string) list
mutable referencedDLLs : AssemblyReference list
+ mutable packageManagerLines : Map
mutable projectReferences : IProjectReference list
mutable knownUnresolvedReferences : UnresolvedAssemblyReference list
optimizeForMemory: bool
@@ -2361,6 +2361,7 @@ type TcConfigBuilder =
framework = true
implicitlyResolveAssemblies = true
referencedDLLs = []
+ packageManagerLines = Map.empty
projectReferences = []
knownUnresolvedReferences = []
loadedSources = []
@@ -2563,18 +2564,19 @@ type TcConfigBuilder =
if ok && not (List.contains absolutePath tcConfigB.includes) then
tcConfigB.includes <- tcConfigB.includes ++ absolutePath
- member tcConfigB.AddLoadedSource(m, path, pathLoadedFrom) =
- if FileSystem.IsInvalidPathShim(path) then
- warning(Error(FSComp.SR.buildInvalidFilename(path), m))
+ member tcConfigB.AddLoadedSource(m, originalPath, pathLoadedFrom) =
+ if FileSystem.IsInvalidPathShim(originalPath) then
+ warning(Error(FSComp.SR.buildInvalidFilename(originalPath), m))
else
let path =
- match TryResolveFileUsingPaths(tcConfigB.includes @ [pathLoadedFrom], m, path) with
+ match TryResolveFileUsingPaths(tcConfigB.includes @ [pathLoadedFrom], m, originalPath) with
| Some(path) -> path
| None ->
- // File doesn't exist in the paths. Assume it will be in the load-ed from directory.
- ComputeMakePathAbsolute pathLoadedFrom path
- if not (List.contains path (List.map snd tcConfigB.loadedSources)) then
- tcConfigB.loadedSources <- tcConfigB.loadedSources ++ (m, path)
+ // File doesn't exist in the paths. Assume it will be in the load-ed from directory.
+ ComputeMakePathAbsolute pathLoadedFrom originalPath
+ if not (List.contains path (List.map (fun (_, _, path) -> path) tcConfigB.loadedSources)) then
+ tcConfigB.loadedSources <- tcConfigB.loadedSources ++ (m, originalPath, path)
+
member tcConfigB.AddEmbeddedSourceFile (file) =
tcConfigB.embedSourceList <- tcConfigB.embedSourceList ++ file
@@ -2589,6 +2591,13 @@ type TcConfigBuilder =
let projectReference = tcConfigB.projectReferences |> List.tryPick (fun pr -> if pr.FileName = path then Some pr else None)
tcConfigB.referencedDLLs <- tcConfigB.referencedDLLs ++ AssemblyReference(m, path, projectReference)
+ member tcConfigB.AddDependencyManagerText (packageManager:DependencyManagerIntegration.IDependencyManagerProvider,m,path:string) =
+ let path = DependencyManagerIntegration.removeDependencyManagerKey packageManager.Key path
+
+ match tcConfigB.packageManagerLines |> Map.tryFind packageManager.Key with
+ | Some lines -> tcConfigB.packageManagerLines <- Map.add packageManager.Key (lines ++ (path, m)) tcConfigB.packageManagerLines
+ | _ -> tcConfigB.packageManagerLines <- Map.add packageManager.Key [path, m] tcConfigB.packageManagerLines
+
member tcConfigB.RemoveReferencedAssemblyByPath (m, path) =
tcConfigB.referencedDLLs <- tcConfigB.referencedDLLs |> List.filter (fun ar-> ar.Range <> m || ar.Text <> path)
@@ -2889,6 +2898,7 @@ type TcConfig private (data : TcConfigBuilder, validate:bool) =
member x.embedAllSource = data.embedAllSource
member x.embedSourceList = data.embedSourceList
member x.sourceLink = data.sourceLink
+ member x.packageManagerLines = data.packageManagerLines
member x.ignoreSymbolStoreSequencePoints = data.ignoreSymbolStoreSequencePoints
member x.internConstantStrings = data.internConstantStrings
member x.extraOptimizationIterations = data.extraOptimizationIterations
@@ -3022,13 +3032,23 @@ type TcConfig private (data : TcConfigBuilder, validate:bool) =
member tcConfig.GetAvailableLoadedSources() =
use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parameter
- let resolveLoadedSource (m, path) =
+ let resolveLoadedSource (m, originalPath, path) =
try
if not(FileSystem.SafeExists(path)) then
- error(LoadedSourceNotFoundIgnoring(path, m))
- None
- else Some(m, path)
+ let secondTrial =
+ tcConfig.includes
+ |> List.tryPick (fun root ->
+ let path = ComputeMakePathAbsolute root originalPath
+ if FileSystem.SafeExists(path) then Some path else None)
+
+ match secondTrial with
+ | Some path -> Some(m,path)
+ | None ->
+ error(LoadedSourceNotFoundIgnoring(path,m))
+ None
+ else Some(m,path)
with e -> errorRecovery e m; None
+
tcConfig.loadedSources
|> List.choose resolveLoadedSource
|> List.distinct
@@ -4844,11 +4864,10 @@ let RequireDLL (ctok, tcImports:TcImports, tcEnv, thisAssemblyName, m, file) =
let tcEnv = (tcEnv, asms) ||> List.fold (fun tcEnv asm -> AddCcuToTcEnv(g, amap, m, tcEnv, thisAssemblyName, asm.FSharpViewOfMetadata, asm.AssemblyAutoOpenAttributes, asm.AssemblyInternalsVisibleToAttributes))
tcEnv, (dllinfos, asms)
-
-
let ProcessMetaCommandsFromInput
- (nowarnF: 'state -> range * string -> 'state,
- dllRequireF: 'state -> range * string -> 'state,
+ (nowarnF: 'state -> range * string -> 'state,
+ dllRequireF: 'state -> range * string -> 'state,
+ packageRequireF: 'state -> DependencyManagerIntegration.IDependencyManagerProvider * range * string -> 'state,
loadSourceF: 'state -> range * string -> unit)
(tcConfig:TcConfigBuilder, inp, pathOfMetaCommandSource, state0) =
@@ -4874,15 +4893,22 @@ let ProcessMetaCommandsFromInput
| _ ->
errorR(Error(FSComp.SR.buildInvalidHashIDirective(), m))
state
- | ParsedHashDirective("nowarn", numbers, m) ->
- List.fold (fun state d -> nowarnF state (m, d)) state numbers
- | ParsedHashDirective(("reference" | "r"), args, m) ->
+ | ParsedHashDirective("nowarn",numbers,m) ->
+ List.fold (fun state d -> nowarnF state (m,d)) state numbers
+
+ | ParsedHashDirective(("reference" | "r"),args,m) ->
if not canHaveScriptMetaCommands then
errorR(HashReferenceNotAllowedInNonScript(m))
match args with
| [path] ->
matchedm<-m
- dllRequireF state (m, path)
+ match DependencyManagerIntegration.tryFindDependencyManagerInPath m (path:string) with
+ | DependencyManagerIntegration.ReferenceType.RegisteredDependencyManager packageManager ->
+ packageRequireF state (packageManager,m,path)
+ | DependencyManagerIntegration.ReferenceType.Library path ->
+ dllRequireF state (m,path)
+ | DependencyManagerIntegration.ReferenceType.UnknownType ->
+ state // error already reported
| _ ->
errorR(Error(FSComp.SR.buildInvalidHashrDirective(), m))
state
@@ -4959,19 +4985,21 @@ let ProcessMetaCommandsFromInput
let ApplyNoWarnsToTcConfig (tcConfig:TcConfig, inp:ParsedInput, pathOfMetaCommandSource) =
// Clone
let tcConfigB = tcConfig.CloneOfOriginalBuilder
- let addNoWarn = fun () (m, s) -> tcConfigB.TurnWarningOff(m, s)
- let addReferencedAssemblyByPath = fun () (_m, _s) -> ()
- let addLoadedSource = fun () (_m, _s) -> ()
- ProcessMetaCommandsFromInput (addNoWarn, addReferencedAssemblyByPath, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ())
+ let addNoWarn = fun () (m,s) -> tcConfigB.TurnWarningOff(m, s)
+ let addReferencedAssemblyByPath = fun () (_m,_s) -> ()
+ let addDependencyManagerText = fun () (_prefix,_m,_s) -> ()
+ let addLoadedSource = fun () (_m,_s) -> ()
+ ProcessMetaCommandsFromInput (addNoWarn, addReferencedAssemblyByPath, addDependencyManagerText, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ())
TcConfig.Create(tcConfigB, validate=false)
let ApplyMetaCommandsFromInputToTcConfig (tcConfig:TcConfig, inp:ParsedInput, pathOfMetaCommandSource) =
// Clone
let tcConfigB = tcConfig.CloneOfOriginalBuilder
let getWarningNumber = fun () _ -> ()
- let addReferencedAssemblyByPath = fun () (m, s) -> tcConfigB.AddReferencedAssemblyByPath(m, s)
- let addLoadedSource = fun () (m, s) -> tcConfigB.AddLoadedSource(m, s, pathOfMetaCommandSource)
- ProcessMetaCommandsFromInput (getWarningNumber, addReferencedAssemblyByPath, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ())
+ let addReferencedAssemblyByPath = fun () (m,s) -> tcConfigB.AddReferencedAssemblyByPath(m,s)
+ let addDependencyManagerText = fun () (packageManager, m,s) -> tcConfigB.AddDependencyManagerText(packageManager,m,s)
+ let addLoadedSource = fun () (m,s) -> tcConfigB.AddLoadedSource(m,s,pathOfMetaCommandSource)
+ ProcessMetaCommandsFromInput (getWarningNumber, addReferencedAssemblyByPath, addDependencyManagerText, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ())
TcConfig.Create(tcConfigB, validate=false)
//----------------------------------------------------------------------------
@@ -5019,9 +5047,9 @@ type CodeContext =
| CompilationAndEvaluation // in fsi.exe
| Compilation // in fsc.exe
| Editing // in VS
-
-module private ScriptPreprocessClosure =
+
+module ScriptPreprocessClosure =
open Internal.Utilities.Text.Lexing
/// Represents an input to the closure finding process
@@ -5097,11 +5125,12 @@ module private ScriptPreprocessClosure =
let ApplyMetaCommandsFromInputToTcConfigAndGatherNoWarn (tcConfig:TcConfig, inp:ParsedInput, pathOfMetaCommandSource) =
let tcConfigB = tcConfig.CloneOfOriginalBuilder
let nowarns = ref []
- let getWarningNumber = fun () (m, s) -> nowarns := (s, m) :: !nowarns
- let addReferencedAssemblyByPath = fun () (m, s) -> tcConfigB.AddReferencedAssemblyByPath(m, s)
- let addLoadedSource = fun () (m, s) -> tcConfigB.AddLoadedSource(m, s, pathOfMetaCommandSource)
+ let getWarningNumber = fun () (m,s) -> nowarns := (s,m) :: !nowarns
+ let addReferencedAssemblyByPath = fun () (m,s) -> tcConfigB.AddReferencedAssemblyByPath(m,s)
+ let addDependencyManagerText = fun () (packageManagerPrefix,m,s) -> tcConfigB.AddDependencyManagerText(packageManagerPrefix,m,s)
+ let addLoadedSource = fun () (m,s) -> tcConfigB.AddLoadedSource(m,s,pathOfMetaCommandSource)
try
- ProcessMetaCommandsFromInput (getWarningNumber, addReferencedAssemblyByPath, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ())
+ ProcessMetaCommandsFromInput (getWarningNumber, addReferencedAssemblyByPath, addDependencyManagerText, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ())
with ReportedError _ ->
// Recover by using whatever did end up in the tcConfig
()
@@ -5113,12 +5142,50 @@ module private ScriptPreprocessClosure =
let tcConfigB = tcConfig.CloneOfOriginalBuilder
TcConfig.Create(tcConfigB, validate=false), nowarns
- let FindClosureFiles(closureSources, tcConfig:TcConfig, codeContext, lexResourceManager:Lexhelp.LexResourceManager) =
- let tcConfig = ref tcConfig
+ let FindClosureFiles(mainFile, _m, closureSources, origTcConfig:TcConfig, codeContext, lexResourceManager:Lexhelp.LexResourceManager) =
+ let tcConfig = ref origTcConfig
let observedSources = Observed()
- let rec loop (ClosureSource(filename, m, source, parseRequired)) =
- [ if not (observedSources.HaveSeen(filename)) then
+ let loadScripts = HashSet<_>()
+
+ // Resolve the packages
+ let rec resolveDependencyManagerSources scriptName =
+ if not (loadScripts.Contains scriptName) then
+ [ for kv in tcConfig.Value.packageManagerLines do
+ let packageManagerKey,packageManagerLines = kv.Key,kv.Value
+ match packageManagerLines with
+ | [] -> ()
+ | (_,m)::_ ->
+ match origTcConfig.packageManagerLines |> Map.tryFind packageManagerKey with
+ | Some oldDependencyManagerLines when oldDependencyManagerLines = packageManagerLines -> ()
+ | _ ->
+ match DependencyManagerIntegration.tryFindDependencyManagerByKey m packageManagerKey with
+ | None ->
+ errorR(DependencyManagerIntegration.createPackageManagerUnknownError packageManagerKey m)
+ | Some packageManager ->
+ let packageManagerTextLines = packageManagerLines |> List.map fst
+ match DependencyManagerIntegration.resolve packageManager tcConfig.Value.implicitIncludeDir mainFile scriptName m packageManagerTextLines with
+ | None -> () // error already reported
+ | Some (loadScript,additionalIncludeFolders) ->
+ // This may incrementally update tcConfig too with new #r references
+ // New package text is ignored on this second phase
+
+ if not (isNil additionalIncludeFolders) then
+ let tcConfigB = tcConfig.Value.CloneOfOriginalBuilder
+ for folder in additionalIncludeFolders do
+ tcConfigB.AddIncludePath(m,folder,"")
+ tcConfig := TcConfig.Create(tcConfigB, validate=false)
+
+ match loadScript with
+ | Some loadScript ->
+ let loadScriptText = File.ReadAllText loadScript
+ loadScripts.Add loadScript |> ignore
+ yield! loop (ClosureSource(loadScript,m,loadScriptText,true))
+ | None -> () ]
+ else []
+
+ and loop (ClosureSource(filename, m, source, parseRequired)) =
+ [ if not (observedSources.HaveSeen(filename)) then
observedSources.SetSeen(filename)
//printfn "visiting %s" filename
if IsScript(filename) || parseRequired then
@@ -5133,15 +5200,20 @@ module private ScriptPreprocessClosure =
let errorLogger = CapturingErrorLogger("FindClosureMetaCommands")
use _unwindEL = PushErrorLoggerPhaseUntilUnwind (fun _ -> errorLogger)
let pathOfMetaCommandSource = Path.GetDirectoryName(filename)
+
let preSources = (!tcConfig).GetAvailableLoadedSources()
let tcConfigResult, noWarns = ApplyMetaCommandsFromInputToTcConfigAndGatherNoWarn (!tcConfig, parsedScriptAst, pathOfMetaCommandSource)
tcConfig := tcConfigResult // We accumulate the tcConfig in order to collect assembly references
-
+
+ yield! resolveDependencyManagerSources filename
+
let postSources = (!tcConfig).GetAvailableLoadedSources()
let sources = if preSources.Length < postSources.Length then postSources.[preSources.Length..] else []
- //for (_, subFile) in sources do
+ yield! resolveDependencyManagerSources filename
+
+ //for (_,subFile) in sources do
// printfn "visiting %s - has subsource of %s " filename subFile
for (m, subFile) in sources do
@@ -5162,7 +5234,9 @@ module private ScriptPreprocessClosure =
//printfn "yielding non-script source %s" filename
yield ClosureFile(filename, m, None, [], [], []) ]
- closureSources |> List.collect loop, !tcConfig
+ let sources = closureSources |> List.collect loop
+
+ sources, !tcConfig
/// Reduce the full directive closure into LoadClosure
let GetLoadClosure(ctok, rootFilename, closureFiles, tcConfig:TcConfig, codeContext) =
@@ -5217,7 +5291,7 @@ module private ScriptPreprocessClosure =
UnresolvedReferences = unresolvedReferences
Inputs = sourceInputs
NoWarns = List.groupByFirst globalNoWarns
- OriginalLoadReferences = tcConfig.loadedSources
+ OriginalLoadReferences = tcConfig.loadedSources |> List.map (fun (m,_,path) -> m,path)
ResolutionDiagnostics = resolutionDiagnostics
AllRootFileDiagnostics = allRootDiagnostics
LoadClosureRootFileDiagnostics = loadClosureRootDiagnostics }
@@ -5239,15 +5313,15 @@ module private ScriptPreprocessClosure =
let tcConfig = CreateScriptSourceTcConfig(legacyReferenceResolver, defaultFSharpBinariesDir, filename, codeContext, useSimpleResolution, useFsiAuxLib, Some references0, applyCommmandLineArgs, assumeDotNetFramework)
let closureSources = [ClosureSource(filename, range0, source, true)]
- let closureFiles, tcConfig = FindClosureFiles(closureSources, tcConfig, codeContext, lexResourceManager)
+ let closureFiles, tcConfig = FindClosureFiles(filename, range0, closureSources, tcConfig, codeContext, lexResourceManager)
GetLoadClosure(ctok, filename, closureFiles, tcConfig, codeContext)
-
+
/// 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 mainFile = fst (List.last files)
- let closureSources = files |> List.collect (fun (filename, m) -> ClosureSourceOfFilename(filename, m, tcConfig.inputCodePage, true))
- let closureFiles, tcConfig = FindClosureFiles(closureSources, tcConfig, codeContext, lexResourceManager)
+ let GetFullClosureOfScriptFiles(ctok, tcConfig:TcConfig,files:(string*range) list,codeContext,lexResourceManager:Lexhelp.LexResourceManager) =
+ 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)
type LoadClosure with
@@ -5261,8 +5335,7 @@ type LoadClosure with
static member ComputeClosureOfSourceFiles (ctok, tcConfig:TcConfig, files:(string*range) list, codeContext, lexResourceManager:Lexhelp.LexResourceManager) =
use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse
ScriptPreprocessClosure.GetFullClosureOfScriptFiles (ctok, tcConfig, files, codeContext, lexResourceManager)
-
-
+
//----------------------------------------------------------------------------
// Initial type checking environment
diff --git a/src/fsharp/CompileOps.fsi b/src/fsharp/CompileOps.fsi
index 77916b63f49..40bfe37eb97 100755
--- a/src/fsharp/CompileOps.fsi
+++ b/src/fsharp/CompileOps.fsi
@@ -258,9 +258,11 @@ type TcConfigBuilder =
mutable light: bool option
mutable conditionalCompilationDefines: string list
/// Sources added into the build with #load
- mutable loadedSources: (range * string) list
+ mutable loadedSources: (range * string * string) list
mutable referencedDLLs: AssemblyReference list
+ mutable packageManagerLines: Map
+
mutable projectReferences: IProjectReference list
mutable knownUnresolvedReferences: UnresolvedAssemblyReference list
optimizeForMemory: bool
@@ -659,8 +661,8 @@ val WriteOptimizationData: TcGlobals * filename: string * inMem: bool * CcuThunk
val RequireDLL: CompilationThreadToken * TcImports * TcEnv * thisAssemblyName: string * referenceRange: range * file: string -> TcEnv * (ImportedBinary list * ImportedAssembly list)
/// Processing # commands
-val ProcessMetaCommandsFromInput:
- (('T -> range * string -> 'T) * ('T -> range * string -> 'T) * ('T -> range * string -> unit))
+val ProcessMetaCommandsFromInput :
+ (('T -> range * string -> 'T) * ('T -> range * string -> 'T) * ('T -> DependencyManagerIntegration.IDependencyManagerProvider * range * string -> 'T) * ('T -> range * string -> unit))
-> TcConfigBuilder * Ast.ParsedInput * string * 'T
-> 'T
diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs
new file mode 100644
index 00000000000..8f3b71a3b72
--- /dev/null
+++ b/src/fsharp/DependencyManager.Integration.fs
@@ -0,0 +1,237 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+/// Helper members to integrate DependencyManagers into F# codebase
+module internal Microsoft.FSharp.Compiler.DependencyManagerIntegration
+
+open System
+open System.Reflection
+open System.IO
+open Microsoft.FSharp.Compiler.ErrorLogger
+
+// NOTE: this contains mostly members whose intents are :
+// * to keep ReferenceLoading.PaketHandler usable outside of F# (so it can be used in scriptcs & others)
+// * to minimize footprint of integration in fsi/CompileOps
+
+/// hardcoded to net461 as we don't have fsi on netcore
+let targetFramework = "net461"
+
+module ReflectionHelper =
+ let assemblyHasAttribute (theAssembly: Assembly) attributeName =
+ try
+ CustomAttributeExtensions.GetCustomAttributes(theAssembly)
+ |> Seq.exists (fun a -> a.GetType().Name = attributeName)
+ with | _ -> false
+
+ let getAttributeNamed (theType: Type) attributeName =
+ try
+ theType.GetTypeInfo().GetCustomAttributes false
+ |> Seq.tryFind (fun a -> a.GetType().Name = attributeName)
+ with | _ -> None
+
+ let getInstanceProperty<'treturn> (theType: Type) propertyName =
+ try
+ let property = theType.GetProperty(propertyName, typeof<'treturn>)
+ if isNull property then
+ None
+ elif not (property.GetGetMethod().IsStatic)
+ && property.GetIndexParameters() = Array.empty
+ then
+ Some property
+ else
+ None
+ with | _ -> None
+
+ let getInstanceMethod<'treturn> (theType: Type) (parameterTypes: Type array) methodName =
+ try
+ let theMethod = theType.GetMethod(methodName, parameterTypes)
+ if isNull theMethod then
+ None
+ else
+ Some theMethod
+ with | _ -> None
+
+ let implements<'timplemented> (theType: Type) =
+ typeof<'timplemented>.IsAssignableFrom(theType)
+
+(* this is the loose contract for now, just to define the shape, but this is resolved through reflection *)
+type internal IDependencyManagerProvider =
+ inherit System.IDisposable
+ abstract Name : string
+ abstract ToolName: string
+ abstract Key: string
+ abstract ResolveDependencies : targetFramework: string * scriptDir: string * mainScriptName: string * scriptName: string * packageManagerTextLines: string seq -> string option * string list
+
+[]
+type ReferenceType =
+| RegisteredDependencyManager of IDependencyManagerProvider
+| Library of string
+| UnknownType
+
+type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyInfo, toolNameProperty: PropertyInfo, keyProperty: PropertyInfo, resolveDeps: MethodInfo) =
+ let instance = Activator.CreateInstance(theType) :?> IDisposable
+ let nameProperty = nameProperty.GetValue >> string
+ let toolNameProperty = toolNameProperty.GetValue >> string
+ let keyProperty = keyProperty.GetValue >> string
+ static member InstanceMaker (theType: System.Type) =
+ if not (ReflectionHelper.implements theType) then None
+ else
+ match ReflectionHelper.getAttributeNamed theType "FSharpDependencyManagerAttribute" with
+ | None -> None
+ | Some _ ->
+ match ReflectionHelper.getInstanceProperty theType "Name" with
+ | None -> None
+ | Some nameProperty ->
+ match ReflectionHelper.getInstanceProperty theType "ToolName" with
+ | None -> None
+ | Some toolNameProperty ->
+ match ReflectionHelper.getInstanceProperty theType "Key" with
+ | None -> None
+ | Some keyProperty ->
+ match ReflectionHelper.getInstanceMethod theType [|typeof;typeof;typeof;typeof;typeof;|] "ResolveDependencies" with
+ | None -> None
+ | Some resolveDependenciesMethod ->
+ Some (fun () -> new ReflectionDependencyManagerProvider(theType, nameProperty, toolNameProperty, keyProperty, resolveDependenciesMethod) :> IDependencyManagerProvider)
+
+ interface IDependencyManagerProvider with
+ member __.Name = instance |> nameProperty
+ member __.ToolName = instance |> toolNameProperty
+ member __.Key = instance |> keyProperty
+ member __.ResolveDependencies(targetFramework, scriptDir, mainScriptName, scriptName, packageManagerTextLines) =
+ let arguments = [|box targetFramework; box scriptDir; box mainScriptName; box scriptName; box packageManagerTextLines|]
+ resolveDeps.Invoke(instance, arguments) :?> _
+ interface IDisposable with
+ member __.Dispose () = instance.Dispose()
+
+
+let assemblySearchPaths = lazy (
+ [
+ let assemblyLocation =
+ typeof.GetTypeInfo().Assembly.Location
+ yield Path.GetDirectoryName assemblyLocation
+ let executingAssembly =
+ typeof.GetTypeInfo().Assembly
+ yield Path.GetDirectoryName(executingAssembly.Location)
+#if !FX_NO_APP_DOMAINS
+ yield AppDomain.CurrentDomain.BaseDirectory
+#else
+#endif
+ ]
+ |> List.distinct)
+
+let enumerateDependencyManagerAssembliesFromCurrentAssemblyLocation m =
+ assemblySearchPaths.Force()
+ |> Seq.collect (fun path -> Directory.EnumerateFiles(path,"*DependencyManager*.dll"))
+ |> Seq.choose (fun path ->
+ try
+ Some(AbstractIL.Internal.Library.Shim.FileSystem.AssemblyLoadFrom path)
+ with
+ | exn ->
+ warning(Error(FSComp.SR.couldNotLoadDependencyManagerExtenstion(path,exn.Message),m))
+ None)
+ |> Seq.filter (fun a -> ReflectionHelper.assemblyHasAttribute a "FSharpDependencyManagerAttribute")
+
+type ProjectDependencyManager() =
+ interface IDependencyManagerProvider with
+ member __.Name = "Project loader"
+ member __.ToolName = ""
+ member __.Key = "project"
+ member __.ResolveDependencies(_targetFramework:string, _scriptDir: string, _mainScriptName: string, _scriptName: string, _packageManagerTextLines: string seq) =
+ None,[]
+
+ interface System.IDisposable with
+ member __.Dispose() = ()
+
+type RefDependencyManager() =
+ interface IDependencyManagerProvider with
+ member __.Name = "Ref library loader"
+ member __.ToolName = ""
+ member __.Key = "ref"
+ member __.ResolveDependencies(_targetFramework:string, _scriptDir: string, _mainScriptName: string, _scriptName: string, _packageManagerTextLines: string seq) =
+ None,[]
+
+ interface System.IDisposable with
+ member __.Dispose() = ()
+
+type ImplDependencyManager() =
+ interface IDependencyManagerProvider with
+ member __.Name = "Impl library loader"
+ member __.ToolName = ""
+ member __.Key = "impl"
+ member __.ResolveDependencies(_targetFramework:string, _scriptDir: string, _mainScriptName: string, _scriptName: string, _packageManagerTextLines: string seq) =
+ None,[]
+
+ interface System.IDisposable with
+ member __.Dispose() = ()
+
+
+// TBD: Need to do something about this
+let registeredDependencyManagers = ref None
+
+let RegisteredDependencyManagers m =
+ match !registeredDependencyManagers with
+ | Some managers -> managers
+ | None ->
+ let defaultProviders =
+ [new ProjectDependencyManager() :> IDependencyManagerProvider
+ new RefDependencyManager() :> IDependencyManagerProvider
+ new ImplDependencyManager() :> IDependencyManagerProvider]
+
+ let loadedProviders =
+ enumerateDependencyManagerAssembliesFromCurrentAssemblyLocation m
+ |> Seq.collect (fun a -> a.GetTypes())
+ |> Seq.choose ReflectionDependencyManagerProvider.InstanceMaker
+ |> Seq.map (fun maker -> maker ())
+
+ defaultProviders
+ |> Seq.append loadedProviders
+ |> Seq.map (fun pm -> pm.Key, pm)
+ |> Map.ofSeq
+
+let createPackageManagerUnknownError packageManagerKey m =
+ let registeredKeys = String.Join(", ", RegisteredDependencyManagers m |> Seq.map (fun kv -> kv.Value.Key))
+ let searchPaths = assemblySearchPaths.Force()
+ Error(FSComp.SR.packageManagerUnknown(packageManagerKey, String.Join(", ", searchPaths), registeredKeys),m)
+
+let tryFindDependencyManagerInPath m (path:string) : ReferenceType =
+ try
+ if path.Contains ":" && not (System.IO.Path.IsPathRooted path) then
+ let managers = RegisteredDependencyManagers m
+ match managers |> Seq.tryFind (fun kv -> path.StartsWith(kv.Value.Key + ":" )) with
+ | None ->
+ errorR(createPackageManagerUnknownError (path.Split(':').[0]) m)
+ ReferenceType.UnknownType
+ | Some kv -> ReferenceType.RegisteredDependencyManager kv.Value
+ else
+ ReferenceType.Library path
+ with
+ | e ->
+ errorR(Error(FSComp.SR.packageManagerError(e.Message),m))
+ ReferenceType.UnknownType
+
+let removeDependencyManagerKey (packageManagerKey:string) (path:string) = path.Substring(packageManagerKey.Length + 1).Trim()
+
+let tryFindDependencyManagerByKey m (key:string) : IDependencyManagerProvider option =
+ try
+ RegisteredDependencyManagers m |> Map.tryFind key
+ with
+ | e ->
+ errorR(Error(FSComp.SR.packageManagerError(e.Message),m))
+ None
+
+let resolve (packageManager:IDependencyManagerProvider) implicitIncludeDir mainScriptName fileName m packageManagerTextLines =
+ try
+ let loadScript,additionalIncludeFolders =
+ packageManager.ResolveDependencies(
+ targetFramework,
+ implicitIncludeDir,
+ mainScriptName,
+ fileName,
+ packageManagerTextLines)
+
+ Some(loadScript,additionalIncludeFolders)
+ with e ->
+ if e.InnerException <> null then
+ errorR(Error(FSComp.SR.packageManagerError(e.InnerException.Message),m))
+ else
+ errorR(Error(FSComp.SR.packageManagerError(e.Message),m))
+ None
\ No newline at end of file
diff --git a/src/fsharp/DependencyManager.Integration.fsi b/src/fsharp/DependencyManager.Integration.fsi
new file mode 100644
index 00000000000..bde6e9c705f
--- /dev/null
+++ b/src/fsharp/DependencyManager.Integration.fsi
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+/// Helper members to integrate DependencyManagers into F# codebase
+module internal Microsoft.FSharp.Compiler.DependencyManagerIntegration
+
+open Microsoft.FSharp.Compiler.Range
+
+type IDependencyManagerProvider =
+ inherit System.IDisposable
+ abstract Name : string
+ abstract ToolName: string
+ abstract Key: string
+ abstract ResolveDependencies : string * string * string * string * string seq -> string option * string list
+
+[]
+type ReferenceType =
+| RegisteredDependencyManager of IDependencyManagerProvider
+| Library of string
+| UnknownType
+
+val tryFindDependencyManagerInPath : range -> string -> ReferenceType
+val tryFindDependencyManagerByKey : range -> string -> IDependencyManagerProvider option
+val removeDependencyManagerKey : string -> string -> string
+val createPackageManagerUnknownError : string -> range -> exn
+
+val resolve : IDependencyManagerProvider -> string -> string -> string -> range -> string seq -> (string option * string list) option
diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt
index deeb8d5daf0..e6aaddd1662 100644
--- a/src/fsharp/FSComp.txt
+++ b/src/fsharp/FSComp.txt
@@ -1422,3 +1422,6 @@ notAFunctionButMaybeIndexer,"This expression is not a function and cannot be app
notAFunctionButMaybeDeclaration,"This value is not a function and cannot be applied. Did you forget to terminate a declaration?"
3218,ArgumentsInSigAndImplMismatch,"The argument names in the signature '%s' and implementation '%s' do not match. The argument name from the signature file will be used. This may cause problems when debugging or profiling."
3219,pickleUnexpectedNonZero,"An error occurred while reading the F# metadata of assembly '%s'. A reserved construct was utilized. You may need to upgrade your F# compiler or use an earlier version of the assembly that doesn't make use of a specific construct."
+3220,couldNotLoadDependencyManagerExtenstion,"The dependency manager extension '%s' could not be loaded. Message: %s"
+3221,packageManagerUnknown,"Package manager key '%s' was not registered in %s. Currently registered: %s"
+3222,packageManagerError,"%s"
diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj
index 214f60cdc9f..93eccd4f62c 100644
--- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj
+++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj
@@ -505,6 +505,12 @@
CodeGen\IlxGen.fs
+
+ Driver\DependencyManager.Integration.fsi
+
+
+ Driver\DependencyManager.Integration.fs
+
@@ -681,6 +687,13 @@
+
+
+ FSharp.DependencyManager.Paket
+ {25555554-522d-4cf7-97e4-ba940f0b18f3}
+ True
+
+
@@ -722,4 +735,4 @@
FSharp.Core
-
\ No newline at end of file
+
diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.netcore.nuspec b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.netcore.nuspec
index 3b663e8d3d5..fad0fec3d49 100644
--- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.netcore.nuspec
+++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.netcore.nuspec
@@ -23,6 +23,7 @@
+
diff --git a/src/fsharp/FSharp.Compiler.Private/project.json b/src/fsharp/FSharp.Compiler.Private/project.json
index 09cfefb19fc..d368de741a5 100644
--- a/src/fsharp/FSharp.Compiler.Private/project.json
+++ b/src/fsharp/FSharp.Compiler.Private/project.json
@@ -8,6 +8,7 @@
"System.Linq.Queryable": "4.3.0",
"System.Net.Requests": "4.3.0",
"System.Reflection.Emit": "4.3.0",
+ "System.Reflection.Extensions": "4.3.0",
"System.Reflection.Metadata": "1.4.2",
"System.Reflection.TypeExtensions": "4.3.0",
"System.Runtime": "4.3.0",
diff --git a/src/fsharp/Fsc-proto/Fsc-proto.fsproj b/src/fsharp/Fsc-proto/Fsc-proto.fsproj
index fd3d209e512..22dda9b1bbb 100644
--- a/src/fsharp/Fsc-proto/Fsc-proto.fsproj
+++ b/src/fsharp/Fsc-proto/Fsc-proto.fsproj
@@ -420,6 +420,12 @@
IlxGen.fs
+
+ Driver\DependencyManager.Integration.fsi
+
+
+ Driver\DependencyManager.Integration.fs
+
CompileOps.fsi
diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs
index 3a178a5c185..216b282004b 100644
--- a/src/fsharp/fsi/fsi.fs
+++ b/src/fsharp/fsi/fsi.fs
@@ -985,6 +985,8 @@ type internal FsiDynamicCompiler
let mutable fragmentId = 0
let mutable prevIt : ValRef option = None
+ let mutable needsPackageResolution = false
+
let generateDebugInfo = tcConfigB.debuginfo
let valuePrinter = FsiValuePrinter(fsi, tcGlobals, generateDebugInfo, resolveAssemblyRef, outWriter)
@@ -1273,6 +1275,40 @@ type internal FsiDynamicCompiler
resolutions,
{ istate with tcState = tcState.NextStateAfterIncrementalFragment(tcEnv); optEnv = optEnv }
+
+ member __.EvalDependencyManagerTextFragment (packageManager:DependencyManagerIntegration.IDependencyManagerProvider,m,path: string) =
+ let path = DependencyManagerIntegration.removeDependencyManagerKey packageManager.Key path
+
+ match tcConfigB.packageManagerLines |> Map.tryFind packageManager.Key with
+ | Some lines -> tcConfigB.packageManagerLines <- Map.add packageManager.Key (lines @ [path,m]) tcConfigB.packageManagerLines
+ | _ -> tcConfigB.packageManagerLines <- Map.add packageManager.Key [path,m] tcConfigB.packageManagerLines
+
+ needsPackageResolution <- true
+
+ member fsiDynamicCompiler.CommitDependencyManagerText (ctok, istate: FsiDynamicCompilerState, lexResourceManager, errorLogger) =
+ if not needsPackageResolution then istate else
+ needsPackageResolution <- false
+
+ tcConfigB.packageManagerLines |> Seq.fold(fun istate kv ->
+ let packageManagerKey,packageManagerLines = kv.Key, kv.Value
+ match packageManagerLines with
+ | [] -> istate
+ | (_, m)::_ ->
+ let packageManagerTextLines = packageManagerLines |> List.map fst
+ match DependencyManagerIntegration.tryFindDependencyManagerByKey m packageManagerKey with
+ | None ->
+ errorR(DependencyManagerIntegration.createPackageManagerUnknownError packageManagerKey m)
+ istate
+ | Some packageManager ->
+ match DependencyManagerIntegration.resolve packageManager tcConfigB.implicitIncludeDir "stdin.fsx" "stdin.fsx" m packageManagerTextLines with
+ | None -> istate // error already reported
+ | Some (loadScript, additionalIncludeFolders) ->
+ for folder in additionalIncludeFolders do
+ tcConfigB.AddIncludePath(m, folder, "")
+ match loadScript with
+ | Some loadScript -> fsiDynamicCompiler.EvalSourceFiles(ctok, istate, m, [loadScript], lexResourceManager, errorLogger)
+ | None -> istate) istate
+
member fsiDynamicCompiler.ProcessMetaCommandsFromInputAsInteractiveCommands(ctok, istate, sourceFile, inp) =
WithImplicitHome
(tcConfigB, directoryName sourceFile)
@@ -1280,6 +1316,7 @@ type internal FsiDynamicCompiler
ProcessMetaCommandsFromInput
((fun st (m,nm) -> tcConfigB.TurnWarningOff(m,nm); st),
(fun st (m,nm) -> snd (fsiDynamicCompiler.EvalRequireReference (ctok, st, m, nm))),
+ (fun st (packageManagerPrefix,m,nm) -> fsiDynamicCompiler.EvalDependencyManagerTextFragment (packageManagerPrefix,m,nm); st),
(fun _ _ -> ()))
(tcConfigB, inp, Path.GetDirectoryName sourceFile, istate))
@@ -1896,34 +1933,48 @@ type internal FsiInteractionProcessor
istate |> InteractiveCatch errorLogger (fun istate ->
match action with
| IDefns ([ ],_) ->
+ let istate = fsiDynamicCompiler.CommitDependencyManagerText(ctok, istate, lexResourceManager, errorLogger)
istate,Completed None
+
| IDefns ([ SynModuleDecl.DoExpr(_,expr,_)],_) ->
+ let istate = fsiDynamicCompiler.CommitDependencyManagerText(ctok, istate, lexResourceManager, errorLogger)
fsiDynamicCompiler.EvalParsedExpression(ctok, errorLogger, istate, expr)
+
| IDefns (defs,_) ->
+ let istate = fsiDynamicCompiler.CommitDependencyManagerText(ctok, istate, lexResourceManager, errorLogger)
fsiDynamicCompiler.EvalParsedDefinitions (ctok, errorLogger, istate, true, false, defs),Completed None
| IHash (ParsedHashDirective("load",sourceFiles,m),_) ->
+ let istate = fsiDynamicCompiler.CommitDependencyManagerText(ctok, istate, lexResourceManager, errorLogger)
fsiDynamicCompiler.EvalSourceFiles (ctok, istate, m, sourceFiles, lexResourceManager, errorLogger),Completed None
| IHash (ParsedHashDirective(("reference" | "r"),[path],m),_) ->
- let resolutions,istate = fsiDynamicCompiler.EvalRequireReference(ctok, istate, m, path)
- resolutions |> List.iter (fun ar ->
- let format =
- if tcConfig.shadowCopyReferences then
- let resolvedPath = ar.resolvedPath.ToUpperInvariant()
- let fileTime = File.GetLastWriteTimeUtc(resolvedPath)
- match referencedAssemblies.TryGetValue(resolvedPath) with
- | false, _ ->
- referencedAssemblies.Add(resolvedPath, fileTime)
- FSIstrings.SR.fsiDidAHashr(ar.resolvedPath)
- | true, time when time <> fileTime ->
- FSIstrings.SR.fsiDidAHashrWithStaleWarning(ar.resolvedPath)
- | _ ->
- FSIstrings.SR.fsiDidAHashr(ar.resolvedPath)
- else
- FSIstrings.SR.fsiDidAHashrWithLockWarning(ar.resolvedPath)
- fsiConsoleOutput.uprintnfnn "%s" format)
- istate,Completed None
+ match DependencyManagerIntegration.tryFindDependencyManagerInPath m (path:string) with
+ | DependencyManagerIntegration.ReferenceType.RegisteredDependencyManager packageManager ->
+ fsiDynamicCompiler.EvalDependencyManagerTextFragment(packageManager,m,path)
+ istate,Completed None
+ | DependencyManagerIntegration.ReferenceType.UnknownType ->
+ // error already reported
+ istate,Completed None
+ | DependencyManagerIntegration.ReferenceType.Library path ->
+ let resolutions,istate = fsiDynamicCompiler.EvalRequireReference(ctok, istate, m, path)
+ resolutions |> List.iter (fun ar ->
+ let format =
+ if tcConfig.shadowCopyReferences then
+ let resolvedPath = ar.resolvedPath.ToUpperInvariant()
+ let fileTime = File.GetLastWriteTimeUtc(resolvedPath)
+ match referencedAssemblies.TryGetValue(resolvedPath) with
+ | false, _ ->
+ referencedAssemblies.Add(resolvedPath, fileTime)
+ FSIstrings.SR.fsiDidAHashr(ar.resolvedPath)
+ | true, time when time <> fileTime ->
+ FSIstrings.SR.fsiDidAHashrWithStaleWarning(ar.resolvedPath)
+ | _ ->
+ FSIstrings.SR.fsiDidAHashr(ar.resolvedPath)
+ else
+ FSIstrings.SR.fsiDidAHashrWithLockWarning(ar.resolvedPath)
+ fsiConsoleOutput.uprintnfnn "%s" format)
+ istate,Completed None
| IHash (ParsedHashDirective("I",[path],m),_) ->
tcConfigB.AddIncludePath (m,path, tcConfig.implicitIncludeDir)
@@ -2079,10 +2130,6 @@ type internal FsiInteractionProcessor
reusingLexbufForParsing tokenizer.LexBuffer (fun () ->
Parser.typedSeqExprEOF tokenizer.Lexer tokenizer.LexBuffer)
-// let parseType (tokenizer:LexFilter.LexFilter) =
-// reusingLexbufForParsing tokenizer.LexBuffer (fun () ->
-// Parser.typEOF tokenizer.Lexer tokenizer.LexBuffer)
-
let mainThreadProcessParsedExpression ctok errorLogger (expr, istate) =
istate |> InteractiveCatch errorLogger (fun istate ->
istate |> mainThreadProcessAction ctok (fun ctok _tcConfig istate ->
diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/UnknownDependencyManager/script1.fsx b/tests/fsharpqa/Source/InteractiveSession/Misc/UnknownDependencyManager/script1.fsx
new file mode 100644
index 00000000000..38c8173ec88
--- /dev/null
+++ b/tests/fsharpqa/Source/InteractiveSession/Misc/UnknownDependencyManager/script1.fsx
@@ -0,0 +1,5 @@
+//Package manager key 'unk' was not registered.
+
+#r "unk: blubblub"
+
+let x = 1
\ No newline at end of file
diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/env.lst b/tests/fsharpqa/Source/InteractiveSession/Misc/env.lst
index 13803307162..f18e59e67d6 100644
--- a/tests/fsharpqa/Source/InteractiveSession/Misc/env.lst
+++ b/tests/fsharpqa/Source/InteractiveSession/Misc/env.lst
@@ -165,3 +165,6 @@ NOMONO SOURCE=Regressions01.fs COMPILE_ONLY=1 FSIMODE=PIPE SCFLAGS="--nologo"
SOURCE=..\\Misc\\ccc\\RelativeHashRResolution03_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo --simpleresolution --noframework -r:\"%FSCOREDLLPATH%\"" # RelativeHashRResolution03_fscrelativesimple
SOURCE=..\\Misc\\aaa\\bbb\\RelativeHashRResolution04_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo --simpleresolution --noframework -r:\"%FSCOREDLLPATH%\"" # RelativeHashRResolution04_fscrelativesimple
SOURCE=..\\Misc\\aaa\\bbb\\RelativeHashRResolution05_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo --simpleresolution --noframework -r:\"%FSCOREDLLPATH%\"" # RelativeHashRResolution05_fscrelativesimple
+
+# dependency managers
+SOURCE="UnknownDependencyManager\\script1.fsx" COMPILE_ONLY=1 FSIMODE=FEED SCFLAGS="--nologo" # with unknown manager
\ No newline at end of file
diff --git a/vsintegration/tests/unittests/Tests.LanguageService.ErrorList.fs b/vsintegration/tests/unittests/Tests.LanguageService.ErrorList.fs
index d72c2c4032f..f2efba1c5d4 100644
--- a/vsintegration/tests/unittests/Tests.LanguageService.ErrorList.fs
+++ b/vsintegration/tests/unittests/Tests.LanguageService.ErrorList.fs
@@ -55,13 +55,19 @@ type UsingMSBuild() as this =
member private this.VerifyErrorListCountAtOpenProject(fileContents : string, num : int) =
let (solution, project, file) = this.CreateSingleFileProject(fileContents)
let errorList = GetErrors(project)
+ let errorTexts = new System.Text.StringBuilder()
for error in errorList do
printfn "%A" error.Severity
- printf "%s\n" (error.ToString())
- if (num = errorList.Length) then
- ()
- else
- failwithf "The error list number is not the expected %d" num
+ let s = error.ToString()
+ errorTexts.AppendLine s |> ignore
+ printf "%s\n" s
+
+ if num <> errorList.Length then
+ failwithf "The error list number is not the expected %d but %d%s%s"
+ num
+ errorList.Length
+ System.Environment.NewLine
+ (errorTexts.ToString())
//Verify the warning list Count
member private this.VerifyWarningListCountAtOpenProject(fileContents : string, expectedNum : int, ?addtlRefAssy : list) =