From 538684ef567c7eb7f52ab8c54da07f722795b8f2 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Mon, 13 Mar 2017 12:49:41 +0100 Subject: [PATCH 01/38] Add prototype for "#r paket:" --- FSharp.sln | 17 ++ VisualFSharp.sln | 15 ++ src/fsharp/CompileOps.fs | 126 +++++++--- src/fsharp/CompileOps.fsi | 6 +- src/fsharp/DependencyManager.Integration.fs | 160 +++++++++++++ src/fsharp/DependencyManager.Integration.fsi | 21 ++ src/fsharp/FSComp.txt | 2 + .../FSharp.Compiler-proto.fsproj | 6 + .../FSharp.Compiler/FSharp.Compiler.fsproj | 13 +- .../FSharp.DependencyManager.Paket.fsproj | 70 ++++++ .../PaketDependencyManager.fs | 19 ++ .../PaketDependencyManager.fsi | 11 + .../ReferenceLoading.PaketHandler.fs | 224 ++++++++++++++++++ .../assemblyattribute.fs | 5 + .../FSharp.LanguageService.Compiler.fsproj | 13 +- src/fsharp/fsi/fsi.fs | 85 +++++-- .../InteractiveSession/Paket/.paket/paket.exe | Bin 0 -> 49664 bytes .../Paket/.paket/paket.exe.config | 6 + .../paket.dependencies | 3 + .../Paket/PaketWithBrokenDepsFile/plot.fsx | 7 + .../paket.dependencies | 7 + .../PaketWithDepsCanHaveGroups/paket.lock | 7 + .../Paket/PaketWithDepsCanHaveGroups/plot.fsx | 5 + .../PaketWithDepsFile/paket.dependencies | 4 + .../Paket/PaketWithDepsFile/paket.lock | 7 + .../Paket/PaketWithDepsFile/plot.fsx | 5 + .../package-feed/nunit.2.6.4.nupkg | Bin 0 -> 99004 bytes .../PaketWithLocalSources/paket.dependencies | 3 + .../Paket/PaketWithLocalSources/script1.fsx | 6 + .../.paket/paket.exe.config | 6 + .../Paket/PaketWithRemoteFile/UseGlobbing.fsx | 4 + .../PaketWithRemoteFile/paket.dependencies | 3 + .../Paket/SimplePaketFailTest/plot.fsx | 7 + .../Paket/SimplePaketTest/plot.fsx | 5 + .../.paket/paket.exe.config | 6 + .../Paket/SimplePaketTestTrim/plot.fsx | 8 + .../Source/InteractiveSession/Paket/env.lst | 9 + .../Paket/transitiveloadscripts/a.fsx | 4 + .../Paket/transitiveloadscripts/b.fsx | 6 + .../Paket/transitiveloadscripts/c.fsx | 2 + tests/fsharpqa/Source/test.lst | 1 + .../Source.extension.vsixmanifest | 2 + .../VisualFSharpOpenSource.csproj | 4 + 43 files changed, 867 insertions(+), 53 deletions(-) create mode 100644 src/fsharp/DependencyManager.Integration.fs create mode 100644 src/fsharp/DependencyManager.Integration.fsi create mode 100644 src/fsharp/FSharp.DependencyManager.Paket/FSharp.DependencyManager.Paket.fsproj create mode 100644 src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fs create mode 100644 src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fsi create mode 100644 src/fsharp/FSharp.DependencyManager.Paket/ReferenceLoading.PaketHandler.fs create mode 100644 src/fsharp/FSharp.DependencyManager.Paket/assemblyattribute.fs create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/.paket/paket.exe create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/.paket/paket.exe.config create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithBrokenDepsFile/paket.dependencies create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithBrokenDepsFile/plot.fsx create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsCanHaveGroups/paket.dependencies create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsCanHaveGroups/paket.lock create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsCanHaveGroups/plot.fsx create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsFile/paket.dependencies create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsFile/paket.lock create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsFile/plot.fsx create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithLocalSources/package-feed/nunit.2.6.4.nupkg create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithLocalSources/paket.dependencies create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithLocalSources/script1.fsx create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithRemoteFile/.paket/paket.exe.config create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithRemoteFile/UseGlobbing.fsx create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithRemoteFile/paket.dependencies create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/SimplePaketFailTest/plot.fsx create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/SimplePaketTest/plot.fsx create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/SimplePaketTestTrim/.paket/paket.exe.config create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/SimplePaketTestTrim/plot.fsx create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/env.lst create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/transitiveloadscripts/a.fsx create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/transitiveloadscripts/b.fsx create mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/transitiveloadscripts/c.fsx diff --git a/FSharp.sln b/FSharp.sln index 3cac84673ce..4d740ce51b2 100644 --- a/FSharp.sln +++ b/FSharp.sln @@ -4,6 +4,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler", "src\fsharp\FSharp.Compiler\FSharp.Compiler.fsproj", "{2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}" + ProjectSection(ProjectDependencies) = postProject + {25555554-522D-4CF7-97E4-BA940F0B18F3} = {25555554-522D-4CF7-97E4-BA940F0B18F3} + EndProjectSection EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Server.Shared", "src\fsharp\FSharp.Compiler.Server.Shared\FSharp.Compiler.Server.Shared.fsproj", "{D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}" EndProject @@ -45,6 +48,8 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ILComparer", "tests\fsharpq EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.LanguageService.Compiler", "src\fsharp\FSharp.LanguageService.Compiler\FSharp.LanguageService.Compiler.fsproj", "{A437A6EC-5323-47C2-8F86-E2CAC54FF152}" EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.DependencyManager.Paket", "src\fsharp\FSharp.DependencyManager.Paket\FSharp.DependencyManager.Paket.fsproj", "{25555554-522D-4CF7-97E4-BA940F0B18F3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -218,6 +223,18 @@ Global {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.Release|Any CPU.Build.0 = Release|Any CPU {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.Release|x86.ActiveCfg = Release|Any CPU {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.Release|x86.Build.0 = Release|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Debug|x86.ActiveCfg = Debug|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Debug|x86.Build.0 = Debug|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Proto|Any CPU.Build.0 = Proto|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Proto|x86.ActiveCfg = Proto|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Proto|x86.Build.0 = Proto|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Release|Any CPU.Build.0 = Release|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Release|x86.ActiveCfg = Release|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/VisualFSharp.sln b/VisualFSharp.sln index 42d36f17d85..80fc2d19e5b 100644 --- a/VisualFSharp.sln +++ b/VisualFSharp.sln @@ -136,6 +136,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Utils", "Utils", "{D086C8C6 EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "LanguageServiceProfiling", "vsintegration\Utils\LanguageServiceProfiling\LanguageServiceProfiling.fsproj", "{E7FA3A71-51AF-4FCA-9C2F-7C853E515903}" EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.DependencyManager.Paket", "src\fsharp\FSharp.DependencyManager.Paket\FSharp.DependencyManager.Paket.fsproj", "{25555554-522D-4CF7-97E4-BA940F0B18F3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -749,6 +751,18 @@ Global {E7FA3A71-51AF-4FCA-9C2F-7C853E515903}.Release|Any CPU.Build.0 = Release|Any CPU {E7FA3A71-51AF-4FCA-9C2F-7C853E515903}.Release|x86.ActiveCfg = Release|Any CPU {E7FA3A71-51AF-4FCA-9C2F-7C853E515903}.Release|x86.Build.0 = Release|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Debug|x86.ActiveCfg = Debug|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Debug|x86.Build.0 = Debug|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Proto|Any CPU.Build.0 = Proto|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Proto|x86.ActiveCfg = Proto|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Proto|x86.Build.0 = Proto|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Release|Any CPU.Build.0 = Release|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Release|x86.ActiveCfg = Release|Any CPU + {25555554-522D-4CF7-97E4-BA940F0B18F3}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -811,5 +825,6 @@ Global {2E60864A-E3FF-4BCC-810F-DC7C34E6B236} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} {D086C8C6-D00D-4C3B-9AB2-A4286C9F5922} = {4C7B48D7-19AF-4AE7-9D1D-3BB289D5480D} {E7FA3A71-51AF-4FCA-9C2F-7C853E515903} = {D086C8C6-D00D-4C3B-9AB2-A4286C9F5922} + {25555554-522D-4CF7-97E4-BA940F0B18F3} = {B8DDA694-7939-42E3-95E5-265C2217C142} EndGlobalSection EndGlobal diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 27db98d802b..7ace63cdd0f 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -85,7 +85,6 @@ let FSharpScriptFileSuffixes = [".fsscript";".fsx"] let doNotRequireNamespaceOrModuleSuffixes = [".mli";".ml"] @ FSharpScriptFileSuffixes let FSharpLightSyntaxFileSuffixes : string list = [ ".fs";".fsscript";".fsx";".fsi" ] - //---------------------------------------------------------------------------- // ERROR REPORTING //-------------------------------------------------------------------------- @@ -2026,8 +2025,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 @@ -2190,6 +2190,7 @@ type TcConfigBuilder = framework=true implicitlyResolveAssemblies=true referencedDLLs = [] + packageManagerLines = Map.empty projectReferences = [] knownUnresolvedReferences = [] loadedSources = [] @@ -2379,18 +2380,18 @@ 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) + 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 @@ -2405,6 +2406,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) @@ -2746,6 +2754,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 @@ -2855,13 +2864,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 + 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 @@ -4619,11 +4638,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, + packageRequireF: 'state -> DependencyManagerIntegration.IDependencyManagerProvider * range * string -> 'state, loadSourceF: 'state -> range * string -> unit) (tcConfig:TcConfigBuilder, inp, pathOfMetaCommandSource, state0) = @@ -4651,13 +4669,18 @@ let ProcessMetaCommandsFromInput state | 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 + | Some packageManager -> + packageRequireF state (packageManager,m,path) + | None -> + dllRequireF state (m,path) | _ -> errorR(Error(FSComp.SR.buildInvalidHashrDirective(),m)) state @@ -4736,8 +4759,9 @@ let ApplyNoWarnsToTcConfig (tcConfig:TcConfig, inp:ParsedInput, pathOfMetaComman let tcConfigB = tcConfig.CloneOfOriginalBuilder 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, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ()) + ProcessMetaCommandsFromInput (addNoWarn, addReferencedAssemblyByPath, addDependencyManagerText, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ()) TcConfig.Create(tcConfigB, validate=false) let ApplyMetaCommandsFromInputToTcConfig (tcConfig:TcConfig, inp:ParsedInput, pathOfMetaCommandSource) = @@ -4745,8 +4769,9 @@ let ApplyMetaCommandsFromInputToTcConfig (tcConfig:TcConfig, inp:ParsedInput, pa let tcConfigB = tcConfig.CloneOfOriginalBuilder let getWarningNumber = fun () _ -> () 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, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ()) + ProcessMetaCommandsFromInput (getWarningNumber, addReferencedAssemblyByPath, addDependencyManagerText, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ()) TcConfig.Create(tcConfigB, validate=false) //---------------------------------------------------------------------------- @@ -4795,8 +4820,7 @@ type CodeContext = | 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 @@ -4876,9 +4900,10 @@ module private ScriptPreprocessClosure = let nowarns = ref [] 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 () @@ -4890,12 +4915,45 @@ 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 -> + let registeredKeys = String.Join(", ", DependencyManagerIntegration.RegisteredDependencyManagers() |> Seq.map (fun kv -> kv.Value.Key)) + errorR(Error(FSComp.SR.packageManagerUnknown(packageManagerKey, registeredKeys),m)) + | Some packageManager -> + let packageManagerTextLines = packageManagerLines |> List.map fst + match DependencyManagerIntegration.resolve packageManager tcConfig.Value.implicitIncludeDir scriptName m packageManagerTextLines with + | None -> () // error already reported + | Some (additionalIncludeFolders,loadScript,loadScriptText) -> + loadScripts.Add loadScript |> ignore + // This may incrementally update tcConfig too with new #r references + // New package text is ignored on this second phase + let tcConfigB = tcConfig.Value.CloneOfOriginalBuilder + for folder in additionalIncludeFolders do + tcConfigB.AddIncludePath(m,folder,"") + tcConfig := TcConfig.Create(tcConfigB, validate=false) + + yield! loop (ClosureSource(loadScript,m,loadScriptText,true)) ] + 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 @@ -4910,17 +4968,21 @@ 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 [] + yield! resolveDependencyManagerSources filename + //for (_,subFile) in sources do // printfn "visiting %s - has subsource of %s " filename subFile - for (m,subFile) in sources do if IsScript(subFile) then for subSource in ClosureSourceOfFilename(subFile,m,tcConfigResult.inputCodePage,false) do @@ -4939,7 +5001,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) = @@ -4994,7 +5058,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 } @@ -5016,15 +5080,15 @@ module private ScriptPreprocessClosure = let tcConfig = CreateScriptSourceTcConfig(referenceResolver, 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 mainFile, mainFileRange = 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 closureFiles,tcConfig = FindClosureFiles(mainFile, mainFileRange, closureSources, tcConfig, codeContext, lexResourceManager) GetLoadClosure(ctok, mainFile, closureFiles, tcConfig, codeContext) type LoadClosure with diff --git a/src/fsharp/CompileOps.fsi b/src/fsharp/CompileOps.fsi index 95b4e178bea..b1da48cf4da 100755 --- a/src/fsharp/CompileOps.fsi +++ b/src/fsharp/CompileOps.fsi @@ -257,9 +257,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 @@ -660,7 +662,7 @@ val RequireDLL : CompilationThreadToken * TcImports * TcEnv * thisAssemblyName: /// Processing # commands val ProcessMetaCommandsFromInput : - (('T -> range * string -> 'T) * ('T -> range * string -> 'T) * ('T -> range * string -> unit)) + (('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..02e555f7367 --- /dev/null +++ b/src/fsharp/DependencyManager.Integration.fs @@ -0,0 +1,160 @@ +// 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 + theAssembly.GetCustomAttributes false + |> Seq.tryFind (fun a -> a.GetType().Name = attributeName) + |> function | Some _ -> true | _ -> false + with | _ -> false + let getAttributeNamed (theType: Type) attributeName = + try + theType.GetCustomAttributes false + |> Seq.tryFind (fun a -> a.GetType().Name = attributeName) + with | _ -> None + + let getInstanceProperty<'treturn> (theType: Type) indexParameterTypes propertyName = + try + let property = theType.GetProperty(propertyName, typeof<'treturn>) + if isNull property then + None + elif not (property.GetGetMethod().IsStatic) + && property.GetIndexParameters() = indexParameterTypes + 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 * scriptName: string * packageManagerTextLines: string seq -> string * string list + +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 + // maybe CE might be better + match ReflectionHelper.getAttributeNamed theType "FSharpDependencyManagerAttribute" with + | None -> None + | Some _ -> + match ReflectionHelper.getInstanceProperty theType Array.empty "Name" with + | None -> None + | Some nameProperty -> + match ReflectionHelper.getInstanceProperty theType Array.empty "ToolName" with + | None -> None + | Some toolNameProperty -> + match ReflectionHelper.getInstanceProperty theType Array.empty "Key" with + | None -> None + | Some keyProperty -> + match ReflectionHelper.getInstanceMethod theType [|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, scriptName, packageManagerTextLines) = + let arguments = [|box targetFramework; box scriptDir; box scriptName; box packageManagerTextLines|] + resolveDeps.Invoke(instance, arguments) :?> _ + interface IDisposable with + member __.Dispose () = instance.Dispose() + + +let enumerateDependencyManagerAssembliesFromCurrentAssemblyLocation () = + let assemblyLocation = typeof.Assembly.Location + let assemblySearchPath = Path.GetDirectoryName assemblyLocation + Directory.EnumerateFiles(assemblySearchPath,"*DependencyManager*.dll") + |> Seq.choose (fun path -> try Assembly.LoadFrom path |> Some with | _ -> None) + |> Seq.filter (fun a -> ReflectionHelper.assemblyHasAttribute a "FSharpDependencyManagerAttribute") + +let registeredDependencyManagers = lazy ( + + let managers = + enumerateDependencyManagerAssembliesFromCurrentAssemblyLocation() + |> Seq.collect (fun a -> a.GetTypes()) + |> Seq.choose ReflectionDependencyManagerProvider.InstanceMaker + |> Seq.map (fun maker -> maker ()) + + // TODO: handle conflicting keys + managers + |> Seq.map (fun pm -> pm.Key, pm) + |> Map.ofSeq +) + +let RegisteredDependencyManagers() = registeredDependencyManagers.Force() + +let tryFindDependencyManagerInPath m (path:string) : IDependencyManagerProvider option = + try + match RegisteredDependencyManagers() |> Seq.tryFind (fun kv -> path.StartsWith(kv.Value.Key + ":" )) with + | None -> None + | Some kv -> Some kv.Value + with + | e -> + errorR(Error(FSComp.SR.packageManagerError(e.Message),m)) + None + +let removeDependencyManagerKey (packageManagerKey:string) (path:string) = path.Substring(packageManagerKey.Length + 1).Trim() + +let tryFindDependencyManagerByKey m (key:string) : IDependencyManagerProvider option = + try + RegisteredDependencyManagers() |> Map.tryFind key + with + | e -> + errorR(Error(FSComp.SR.packageManagerError(e.Message),m)) + None + +let resolve (packageManager:IDependencyManagerProvider) implicitIncludeDir fileName m packageManagerTextLines = + try + let loadScript,additionalIncludeFolders = + packageManager.ResolveDependencies( + targetFramework, + implicitIncludeDir, + fileName, + packageManagerTextLines) + + Some(additionalIncludeFolders,loadScript,File.ReadAllText(loadScript)) + 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..c53625a2d20 --- /dev/null +++ b/src/fsharp/DependencyManager.Integration.fsi @@ -0,0 +1,21 @@ +// 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 seq -> string * string list + +val RegisteredDependencyManagers : unit -> Map +val tryFindDependencyManagerInPath : range -> string -> IDependencyManagerProvider option +val tryFindDependencyManagerByKey : range -> string -> IDependencyManagerProvider option + +val removeDependencyManagerKey : string -> string -> string + +val resolve : IDependencyManagerProvider -> string -> string -> range -> string seq -> (string list * string * string) option diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 2db6b55d755..f74446837f2 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1333,6 +1333,8 @@ tcGlobalsSystemTypeNotFound,"The system type '%s' was required but no referenced 3213,typrelMemberHasMultiplePossibleDispatchSlots,"The member '%s' matches multiple overloads of the same method.\nPlease restrict it to one of the following:%s." 3214,methodIsNotStatic,"Method or object constructor '%s' is not static" 3215,parsUnexpectedSymbolEqualsInsteadOfIn,"Unexpected symbol '=' in expression. Did you intend to use 'for x in y .. z do' instead?" +3216,packageManagerUnknown,"Package manager key '%s' was not registered. Currently registered: %s" +3217,packageManagerError,"%s" keywordDescriptionAbstract,"Indicates a method that either has no implementation in the type in which it is declared or that is virtual and has a default implementation." keyworkDescriptionAnd,"Used in mutually recursive bindings, in property declarations, and with multiple constraints on generic parameters." keywordDescriptionAs,"Used to give the current class object an object name. Also used to give a name to a whole pattern within a pattern match." diff --git a/src/fsharp/FSharp.Compiler-proto/FSharp.Compiler-proto.fsproj b/src/fsharp/FSharp.Compiler-proto/FSharp.Compiler-proto.fsproj index e2fd82d83f3..1a3a2d455be 100644 --- a/src/fsharp/FSharp.Compiler-proto/FSharp.Compiler-proto.fsproj +++ b/src/fsharp/FSharp.Compiler-proto/FSharp.Compiler-proto.fsproj @@ -422,6 +422,12 @@ IlxGen.fs + + Driver\DependencyManager.Integration.fsi + + + Driver\DependencyManager.Integration.fs + CompileOps.fsi diff --git a/src/fsharp/FSharp.Compiler/FSharp.Compiler.fsproj b/src/fsharp/FSharp.Compiler/FSharp.Compiler.fsproj index f5160d9a72b..74874d551bb 100644 --- a/src/fsharp/FSharp.Compiler/FSharp.Compiler.fsproj +++ b/src/fsharp/FSharp.Compiler/FSharp.Compiler.fsproj @@ -493,6 +493,12 @@ CodeGen\IlxGen.fs + + Driver\DependencyManager.Integration.fsi + + + Driver\DependencyManager.Integration.fs + Driver\CompileOps.fsi @@ -526,6 +532,11 @@ + + FSharp.DependencyManager.Paket + {25555554-522d-4cf7-97e4-ba940f0b18f3} + True + @@ -593,4 +604,4 @@ FSharp.Core - \ No newline at end of file + diff --git a/src/fsharp/FSharp.DependencyManager.Paket/FSharp.DependencyManager.Paket.fsproj b/src/fsharp/FSharp.DependencyManager.Paket/FSharp.DependencyManager.Paket.fsproj new file mode 100644 index 00000000000..a2531eb83d1 --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager.Paket/FSharp.DependencyManager.Paket.fsproj @@ -0,0 +1,70 @@ + + + + + $(MSBuildProjectDirectory)\..\.. + FSharp.DependencyManager.Paket + + + + Debug + AnyCPU + Library + FSharp.DependencyManager.Paket + EXTENSIONTYPING;$(DefineConstants) + COMPILER;$(DefineConstants) + INCLUDE_METADATA_READER;$(DefineConstants) + INCLUDE_METADATA_WRITER;$(DefineConstants) + $(NoWarn);62;9 + {25555554-522D-4CF7-97E4-BA940F0B18F3} + true + $(OtherFlags) /warnon:1182 + + + + + + $(NuGeReleaseVersion) + $(PackageVersionMajor)-$(PackageVersionMinor) + $(NuGetPerBuildPreReleaseVersion)-0 + + + + + + + + + + + + + Microsoft + StrongName + + + + + + $(FSharpSourcesRoot)\..\loc\lcl\{Lang}\$(AssemblyName).dll.lcl + $(FSharpSourcesRoot)\..\loc\lci\$(AssemblyName).dll.lci + false + false + + + + + + + + + + {DED3BBD7-53F4-428A-8C9F-27968E768605} + FSharp.Core + + + + + + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fs b/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fs new file mode 100644 index 00000000000..6e111f8488b --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fs @@ -0,0 +1,19 @@ +namespace Microsoft.FSharp.DependencyManager.Paket + +// used as a marker that compiler scans for, although there is no hard dependency, filtered by name +type FSharpDependencyManagerAttribute() = + inherit System.Attribute() + +type [] PaketDependencyManager() = + member __.Name = "Paket" + member __.ToolName = "paket.exe" + member __.Key = "paket" + member __.ResolveDependencies(targetFramework:string, scriptDir: string, scriptName: string, packageManagerTextLines: string seq) = + ReferenceLoading.PaketHandler.ResolveDependencies( + targetFramework, + scriptDir, + scriptName, + packageManagerTextLines) + + interface System.IDisposable with + member __.Dispose() = () diff --git a/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fsi b/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fsi new file mode 100644 index 00000000000..d36d8540da9 --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fsi @@ -0,0 +1,11 @@ +namespace Microsoft.FSharp.DependencyManager.Paket +type [] FSharpDependencyManagerAttribute = + inherit System.Attribute + new : unit -> FSharpDependencyManagerAttribute +type [] PaketDependencyManager = + interface System.IDisposable + new : unit -> PaketDependencyManager + member Name : string + member ToolName: string + member Key: string + member ResolveDependencies : targetFramework: string * scriptDir: string * scriptName: string * dependencyManagerTextLines: string seq -> string * string list diff --git a/src/fsharp/FSharp.DependencyManager.Paket/ReferenceLoading.PaketHandler.fs b/src/fsharp/FSharp.DependencyManager.Paket/ReferenceLoading.PaketHandler.fs new file mode 100644 index 00000000000..f0a351a1215 --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager.Paket/ReferenceLoading.PaketHandler.fs @@ -0,0 +1,224 @@ +// 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. +// NOTE: this file is used by other parties integrating paket reference loading in scripting environments. +// Do not add any reference to F# codebase other than FSharp.Core. + +// This file should end up in paket repository instead of F#. + +/// Paket invokation for In-Script reference loading +module internal ReferenceLoading.PaketHandler + +open System +open System.IO +let PM_EXE = "paket.exe" +let PM_DIR = ".paket" + +let userProfile = + let res = Environment.GetEnvironmentVariable("USERPROFILE") + if System.String.IsNullOrEmpty res then + Environment.GetEnvironmentVariable("HOME") + else res + +let MakeDependencyManagerCommand scriptType packageManagerTargetFramework projectRootDirArgument = + sprintf "install --generate-load-scripts load-script-type %s load-script-framework %s project-root \"%s\"" + scriptType packageManagerTargetFramework (System.IO.Path.GetFullPath projectRootDirArgument) + +let getDirectoryAndAllParentDirectories (directory: DirectoryInfo) = + let rec allParents (directory: DirectoryInfo) = + seq { + match directory.Parent with + | null -> () + | parent -> + yield parent + yield! allParents parent + } + + seq { + yield directory + yield! allParents directory + } + +let runningOnMono = +#if ENABLE_MONO_SUPPORT +// Officially supported way to detect if we are running on Mono. +// See http://www.mono-project.com/FAQ:_Technical +// "How can I detect if am running in Mono?" section + try + System.Type.GetType("Mono.Runtime") <> null + with e-> + // Must be robust in the case that someone else has installed a handler into System.AppDomain.OnTypeResolveEvent + // that is not reliable. + // This is related to bug 5506--the issue is actually a bug in VSTypeResolutionService.EnsurePopulated which is + // called by OnTypeResolveEvent. The function throws a NullReferenceException. I'm working with that team to get + // their issue fixed but we need to be robust here anyway. + false +#else + false +#endif + +/// Walks up directory structure and tries to find paket.exe +let findPaketExe (prioritizedSearchPaths: string seq) (baseDir: DirectoryInfo) = + let prioritizedSearchPaths = prioritizedSearchPaths |> Seq.map (fun d -> DirectoryInfo d) + + // for each given directory, we look for paket.exe and .paket/paket.exe + let getPaketAndExe (directory: DirectoryInfo) = + match directory.GetFiles(PM_EXE) with + | [| exe |] -> Some exe.FullName + | _ -> + match directory.GetDirectories(PM_DIR) with + | [| dir |] -> + match dir.GetFiles(PM_EXE) with + | [| exe |] -> Some exe.FullName + | _ -> None + | _ -> None + + let allDirs = + Seq.concat [prioritizedSearchPaths ; getDirectoryAndAllParentDirectories baseDir] + + allDirs + |> Seq.choose getPaketAndExe + |> Seq.tryHead + +/// Resolves absolute load script location: something like +/// baseDir/.paket/load/scriptName +/// or +/// baseDir/.paket/load/frameworkDir/scriptName +let GetPaketLoadScriptLocation baseDir optionalFrameworkDir scriptName = + let paketLoadFolder = System.IO.Path.Combine(PM_DIR,"load") + let frameworkDir = + match optionalFrameworkDir with + | None -> paketLoadFolder + | Some frameworkDir -> System.IO.Path.Combine(paketLoadFolder, frameworkDir) + + System.IO.Path.Combine(baseDir, frameworkDir, scriptName) + + +/// Resolve packages loaded into scripts using `paket:` in `#r` directives such as `#r @"paket: nuget AmazingNugetPackage"`. +/// This function will throw if the resolution is not successful or the tool wasn't found +/// A string given to paket command to select the output language. Can be `fsx` or `csx` +/// A string given to paket command to fix the framework. +/// List of directories which are checked first to resolve `paket.exe`. +/// +/// filename for the script (not necessarily existing if interactive evaluation) +/// Package manager text lines from script, those are meant to be just the inner part, without `#r "paket:` prefix +let ResolveDependenciesForLanguage(fileType,targetFramework:string,prioritizedSearchPaths: string seq, scriptDir: string, scriptName: string,packageManagerTextLinesFromScript: string seq) = + let workingDir = Path.Combine(Path.GetTempPath(), "script-packages", string(abs(hash (scriptDir,scriptName)))) + let depsFileName = "paket.dependencies" + let workingDirSpecFile = FileInfo(Path.Combine(workingDir,depsFileName)) + if not (Directory.Exists workingDir) then + Directory.CreateDirectory workingDir |> ignore + + let packageManagerTextLinesFromScript = + packageManagerTextLinesFromScript + |> Seq.toList + |> List.filter (not << String.IsNullOrWhiteSpace) + + let rootDir,packageManagerTextLines = + let rec findSpecFile dir = + let fi = FileInfo(Path.Combine(dir,depsFileName)) + if fi.Exists then + let lockfileName = "paket.lock" + let lockFile = FileInfo(Path.Combine(fi.Directory.FullName,lockfileName)) + let depsFileLines = File.ReadAllLines fi.FullName + if lockFile.Exists then + let originalDepsFile = FileInfo(workingDirSpecFile.FullName + ".original") + if not originalDepsFile.Exists || + File.ReadAllLines originalDepsFile.FullName <> depsFileLines + then + File.Copy(fi.FullName,originalDepsFile.FullName,true) + let targetLockFile = FileInfo(Path.Combine(workingDir,lockfileName)) + File.Copy(lockFile.FullName,targetLockFile.FullName,true) + + let lines = + if List.isEmpty packageManagerTextLinesFromScript then + Array.toList depsFileLines + else + (Array.toList depsFileLines) @ ("group Main" :: packageManagerTextLinesFromScript) + + fi.Directory.FullName, lines + elif not (isNull fi.Directory.Parent) then + findSpecFile fi.Directory.Parent.FullName + else + let withImplicitSource = + match packageManagerTextLinesFromScript with + | line::_ when line.StartsWith "source" -> packageManagerTextLinesFromScript + | _ -> "source https://nuget.org/api/v2" :: packageManagerTextLinesFromScript + workingDir, ("framework: " + targetFramework) :: withImplicitSource + + findSpecFile scriptDir + + /// hardcoded to load the "Main" group (implicit in paket) + let loadScript = GetPaketLoadScriptLocation workingDir (Some targetFramework) ("main.group." + fileType) + let additionalIncludeFolders() = + [Path.Combine(workingDir,"paket-files")] + |> List.filter Directory.Exists + + if workingDirSpecFile.Exists && + (File.ReadAllLines(workingDirSpecFile.FullName) |> Array.toList) = packageManagerTextLines && + File.Exists loadScript + then + (loadScript,additionalIncludeFolders()) + else + let toolPathOpt = + // we try to resolve .paket/paket.exe any place up in the folder structure from current script + match findPaketExe prioritizedSearchPaths (DirectoryInfo scriptDir) with + | Some paketExe -> Some paketExe + | None -> + let profileExe = Path.Combine (userProfile, PM_DIR, PM_EXE) + if File.Exists profileExe then Some profileExe + else None + + match toolPathOpt with + | None -> + failwithf "Paket was not found in '%s' or a parent directory, or '%s'. Please download the tool and place it in one of the locations." + scriptDir userProfile + + | Some toolPath -> + try File.Delete(loadScript) with _ -> () + let toolPath = if runningOnMono then "mono " + toolPath else toolPath + File.WriteAllLines(workingDirSpecFile.FullName, packageManagerTextLines) + let startInfo = + System.Diagnostics.ProcessStartInfo( + FileName = toolPath, + WorkingDirectory = workingDir, + RedirectStandardOutput = true, + RedirectStandardError = true, + Arguments = MakeDependencyManagerCommand fileType targetFramework rootDir, + CreateNoWindow = true, + UseShellExecute = false) + + use p = new System.Diagnostics.Process() + let errors = ResizeArray<_>() + let log = ResizeArray<_>() + p.StartInfo <- startInfo + p.ErrorDataReceived.Add(fun d -> if not (isNull d.Data) then errors.Add d.Data) + p.OutputDataReceived.Add(fun d -> + if not (isNull d.Data) then + try + Console.ForegroundColor <- ConsoleColor.Green + Console.Write ":paket> " + Console.ResetColor() + Console.WriteLine d.Data + log.Add d.Data + finally + Console.ResetColor() + ) + p.Start() |> ignore + p.BeginErrorReadLine() + p.BeginOutputReadLine() + p.WaitForExit() + + if p.ExitCode <> 0 then + let msg = String.Join(Environment.NewLine, errors) + failwithf "Package resolution using '%s' failed, see directory '%s'.%s%s" + toolPath workingDir Environment.NewLine msg + else + (loadScript,additionalIncludeFolders()) + +/// Resolve packages loaded into scripts using `paket:` in `#r` directives such as `#r @"paket: nuget AmazingNugetPackage"`. +/// This function will throw if the resolution is not successful or the tool wasn't found +/// A string given to paket command to fix the framework. +/// +/// filename for the script (not necessarily existing if interactive evaluation) +/// Package manager text lines from script, those are meant to be just the inner part, without `#r "paket:` prefix +let ResolveDependencies(targetFramework:string, scriptDir: string, scriptName: string,packageManagerTextLinesFromScript: string seq) = + ResolveDependenciesForLanguage("fsx",targetFramework,Seq.empty, scriptDir, scriptName,packageManagerTextLinesFromScript) diff --git a/src/fsharp/FSharp.DependencyManager.Paket/assemblyattribute.fs b/src/fsharp/FSharp.DependencyManager.Paket/assemblyattribute.fs new file mode 100644 index 00000000000..2a599ff0e8c --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager.Paket/assemblyattribute.fs @@ -0,0 +1,5 @@ +namespace Microsoft.FSharp.DependencyManager.Paket + +[] +do() + diff --git a/src/fsharp/FSharp.LanguageService.Compiler/FSharp.LanguageService.Compiler.fsproj b/src/fsharp/FSharp.LanguageService.Compiler/FSharp.LanguageService.Compiler.fsproj index 3175db0692a..4f28d3f48eb 100644 --- a/src/fsharp/FSharp.LanguageService.Compiler/FSharp.LanguageService.Compiler.fsproj +++ b/src/fsharp/FSharp.LanguageService.Compiler/FSharp.LanguageService.Compiler.fsproj @@ -1,4 +1,4 @@ - + @@ -475,6 +475,12 @@ CodeGen/IlxGen.fs + + Driver\DependencyManager.Integration.fsi + + + Driver\DependencyManager.Integration.fs + Driver\CompileOps.fsi @@ -576,6 +582,11 @@ + + FSharp.DependencyManager.Paket + {25555554-522d-4cf7-97e4-ba940f0b18f3} + True + diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 57a4b9f5514..3a7dcab1027 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -969,6 +969,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) @@ -1220,6 +1222,41 @@ 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 + + let istate = ref istate + for kv in tcConfigB.packageManagerLines do + let packageManagerKey,packageManagerLines = kv.Key,kv.Value + match packageManagerLines with + | [] -> () + | (_,m)::_ -> + let packageManagerTextLines = packageManagerLines |> List.map fst + match DependencyManagerIntegration.tryFindDependencyManagerByKey m packageManagerKey with + | None -> + let registeredKeys = String.Join(", ", DependencyManagerIntegration.RegisteredDependencyManagers() |> Seq.map (fun kv -> kv.Value.Key)) + errorR(Error(FSComp.SR.packageManagerUnknown(packageManagerKey, registeredKeys),m)) + | Some packageManager -> + match DependencyManagerIntegration.resolve packageManager tcConfigB.implicitIncludeDir "stdin.fsx" m packageManagerTextLines with + | None -> () // error already reported + | Some (additionalIncludeFolders, loadScript,_loadScriptText) -> + for folder in additionalIncludeFolders do + tcConfigB.AddIncludePath(m,folder,"") + istate := fsiDynamicCompiler.EvalSourceFiles (ctok, !istate, m, [loadScript], lexResourceManager, errorLogger) + + !istate + member fsiDynamicCompiler.ProcessMetaCommandsFromInputAsInteractiveCommands(ctok, istate, sourceFile, inp) = WithImplicitHome (tcConfigB, directoryName sourceFile) @@ -1227,6 +1264,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)) @@ -1864,36 +1902,47 @@ 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 = + match DependencyManagerIntegration.tryFindDependencyManagerInPath m (path:string) with + | Some packageManager -> + fsiDynamicCompiler.EvalDependencyManagerTextFragment(packageManager,m,path) + istate,Completed None + | None -> + let resolutions,istate = fsiDynamicCompiler.EvalRequireReference(ctok, istate, m, path) + resolutions |> List.iter (fun ar -> + let format = #if FSI_SHADOW_COPY_REFERENCES - 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 + 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 #endif - FSIstrings.SR.fsiDidAHashrWithLockWarning(ar.resolvedPath) - fsiConsoleOutput.uprintnfnn "%s" format) - istate,Completed None + FSIstrings.SR.fsiDidAHashrWithLockWarning(ar.resolvedPath) + fsiConsoleOutput.uprintnfnn "%s" format) + istate,Completed None | IHash (ParsedHashDirective("I",[path],m),_) -> tcConfigB.AddIncludePath (m,path, tcConfig.implicitIncludeDir) diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/.paket/paket.exe b/tests/fsharpqa/Source/InteractiveSession/Paket/.paket/paket.exe new file mode 100644 index 0000000000000000000000000000000000000000..e24fa74fd060455605d91258d05eecb53f0cdf20 GIT binary patch literal 49664 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 literal 0 HcmV?d00001 diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/.paket/paket.exe.config b/tests/fsharpqa/Source/InteractiveSession/Paket/.paket/paket.exe.config new file mode 100644 index 00000000000..2fc733f95b1 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/.paket/paket.exe.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithBrokenDepsFile/paket.dependencies b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithBrokenDepsFile/paket.dependencies new file mode 100644 index 00000000000..2c6d4924077 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithBrokenDepsFile/paket.dependencies @@ -0,0 +1,3 @@ +framework: net461 +source https://nuget.org/api/v2 +nuget SomethingThatShouldReallyNotExistAtAll \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithBrokenDepsFile/plot.fsx b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithBrokenDepsFile/plot.fsx new file mode 100644 index 00000000000..ef9314286b5 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithBrokenDepsFile/plot.fsx @@ -0,0 +1,7 @@ +//Package resolution + +#r "paket: " + +open XPlot.Plotly + +Chart.Line [ 1 .. 10 ] \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsCanHaveGroups/paket.dependencies b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsCanHaveGroups/paket.dependencies new file mode 100644 index 00000000000..e86188b05db --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsCanHaveGroups/paket.dependencies @@ -0,0 +1,7 @@ +framework: net461 +source https://nuget.org/api/v2 + +group Test + framework: net461 + source https://nuget.org/api/v2 + nuget NUnit diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsCanHaveGroups/paket.lock b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsCanHaveGroups/paket.lock new file mode 100644 index 00000000000..3a629dc0612 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsCanHaveGroups/paket.lock @@ -0,0 +1,7 @@ +FRAMEWORK: NET461 + +GROUP Test +FRAMEWORK: NET461 +NUGET + remote: https://www.nuget.org/api/v2 + NUnit (3.6.1) diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsCanHaveGroups/plot.fsx b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsCanHaveGroups/plot.fsx new file mode 100644 index 00000000000..d7b6631287c --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsCanHaveGroups/plot.fsx @@ -0,0 +1,5 @@ +#r "paket: nuget XPlot.Plotly" + +open XPlot.Plotly + +Chart.Line [ 1 .. 10 ] \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsFile/paket.dependencies b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsFile/paket.dependencies new file mode 100644 index 00000000000..9cdb7e7a90c --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsFile/paket.dependencies @@ -0,0 +1,4 @@ +framework: net461 +source https://nuget.org/api/v2 +nuget FSharp.Data +nuget XPlot.Plotly \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsFile/paket.lock b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsFile/paket.lock new file mode 100644 index 00000000000..d34f29fc829 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsFile/paket.lock @@ -0,0 +1,7 @@ +FRAMEWORK: NET461 +NUGET + remote: https://www.nuget.org/api/v2 + FSharp.Data (2.3.2) + Newtonsoft.Json (9.0.1) + XPlot.Plotly (1.4.2) + Newtonsoft.Json (9.0.1) diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsFile/plot.fsx b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsFile/plot.fsx new file mode 100644 index 00000000000..bf3945e1853 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithDepsFile/plot.fsx @@ -0,0 +1,5 @@ +#r "paket: " + +open XPlot.Plotly + +Chart.Line [ 1 .. 10 ] \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithLocalSources/package-feed/nunit.2.6.4.nupkg b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithLocalSources/package-feed/nunit.2.6.4.nupkg new file mode 100644 index 0000000000000000000000000000000000000000..379b15bf5cd076569cd68476cd21a17795c0587c GIT binary patch literal 99004 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 >hQImg~$(c$n`hbCh2eY%N!*i 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] +let f = () \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithRemoteFile/.paket/paket.exe.config b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithRemoteFile/.paket/paket.exe.config new file mode 100644 index 00000000000..2fc733f95b1 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithRemoteFile/.paket/paket.exe.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithRemoteFile/UseGlobbing.fsx b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithRemoteFile/UseGlobbing.fsx new file mode 100644 index 00000000000..a4a73c8a67a --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithRemoteFile/UseGlobbing.fsx @@ -0,0 +1,4 @@ +#r "paket: " +#load @"fsharp\FAKE\src\app\FakeLib\Globbing\Globbing.fs" + +let f = Fake.Globbing.search \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithRemoteFile/paket.dependencies b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithRemoteFile/paket.dependencies new file mode 100644 index 00000000000..46698a173dd --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/PaketWithRemoteFile/paket.dependencies @@ -0,0 +1,3 @@ +source https://nuget.org/api/v2 +nuget NUnit +github fsharp/FAKE src/app/FakeLib/Globbing/Globbing.fs \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/SimplePaketFailTest/plot.fsx b/tests/fsharpqa/Source/InteractiveSession/Paket/SimplePaketFailTest/plot.fsx new file mode 100644 index 00000000000..5170eef2e59 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/SimplePaketFailTest/plot.fsx @@ -0,0 +1,7 @@ +//Package resolution + +#r "paket: nuget SomeInvalidNugetPackage" + +open XPlot.Plotly + +Chart.Line [ 1 .. 10 ] \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/SimplePaketTest/plot.fsx b/tests/fsharpqa/Source/InteractiveSession/Paket/SimplePaketTest/plot.fsx new file mode 100644 index 00000000000..d7b6631287c --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/SimplePaketTest/plot.fsx @@ -0,0 +1,5 @@ +#r "paket: nuget XPlot.Plotly" + +open XPlot.Plotly + +Chart.Line [ 1 .. 10 ] \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/SimplePaketTestTrim/.paket/paket.exe.config b/tests/fsharpqa/Source/InteractiveSession/Paket/SimplePaketTestTrim/.paket/paket.exe.config new file mode 100644 index 00000000000..2fc733f95b1 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/SimplePaketTestTrim/.paket/paket.exe.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/SimplePaketTestTrim/plot.fsx b/tests/fsharpqa/Source/InteractiveSession/Paket/SimplePaketTestTrim/plot.fsx new file mode 100644 index 00000000000..eba5057696a --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/SimplePaketTestTrim/plot.fsx @@ -0,0 +1,8 @@ +#r "paket:nuget XPlot.Plotly" + +// note we don't have space at paket:nuget +// this should work + +open XPlot.Plotly + +Chart.Line [ 1 .. 10 ] \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/env.lst b/tests/fsharpqa/Source/InteractiveSession/Paket/env.lst new file mode 100644 index 00000000000..129dc8afe7e --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/env.lst @@ -0,0 +1,9 @@ + SOURCE="SimplePaketTest\\plot.fsx" COMPILE_ONLY=1 FSIMODE=FEED SCFLAGS="--nologo" # simple direct deps + SOURCE="SimplePaketTestTrim\\plot.fsx" COMPILE_ONLY=1 FSIMODE=FEED SCFLAGS="--nologo" # simple direct deps, with missing space in directive + SOURCE="SimplePaketFailTest\\plot.fsx" COMPILE_ONLY=1 FSIMODE=FEED SCFLAGS="--nologo" # non-existent package + SOURCE="PaketWithDepsFile\\plot.fsx" COMPILE_ONLY=1 FSIMODE=FEED SCFLAGS="--nologo" # with deps file + SOURCE="PaketWithDepsCanHaveGroups\\plot.fsx" COMPILE_ONLY=1 FSIMODE=FEED SCFLAGS="--nologo" # with deps file with groups (appending to groups may kill the source) + SOURCE="PaketWithBrokenDepsFile\\plot.fsx" COMPILE_ONLY=1 FSIMODE=FEED SCFLAGS="--nologo" # with broken deps file + SOURCE="PaketWithRemoteFile\\UseGlobbing.fsx" COMPILE_ONLY=1 FSIMODE=FEED SCFLAGS="--nologo" # use paket remote file + SOURCE="PaketWithLocalSources\\script1.fsx" COMPILE_ONLY=1 FSIMODE=FEED SCFLAGS="--nologo" # with local nupgk + SOURCE="transitiveloadscripts\\a.fsx" COMPILE_ONLY=1 FSIMODE=FEED SCFLAGS="--nologo" # transitive load script woes \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/transitiveloadscripts/a.fsx b/tests/fsharpqa/Source/InteractiveSession/Paket/transitiveloadscripts/a.fsx new file mode 100644 index 00000000000..0cd7912ba74 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/transitiveloadscripts/a.fsx @@ -0,0 +1,4 @@ +#load "b.fsx" +#load "c.fsx" + +open FSharp.Data \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/transitiveloadscripts/b.fsx b/tests/fsharpqa/Source/InteractiveSession/Paket/transitiveloadscripts/b.fsx new file mode 100644 index 00000000000..5517e10e270 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/transitiveloadscripts/b.fsx @@ -0,0 +1,6 @@ +#load "c.fsx" +#r "paket: nuget FSharp.Data" +printfn "---->b.fsx" +open FSharp.Data +open NUnit +printfn "---->b.fsx///" \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/transitiveloadscripts/c.fsx b/tests/fsharpqa/Source/InteractiveSession/Paket/transitiveloadscripts/c.fsx new file mode 100644 index 00000000000..6b6afab3b43 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Paket/transitiveloadscripts/c.fsx @@ -0,0 +1,2 @@ +#r "paket: nuget NUnit" +printfn "---->c.fsx" \ No newline at end of file diff --git a/tests/fsharpqa/Source/test.lst b/tests/fsharpqa/Source/test.lst index 6345ef46fbf..470d2389d5e 100644 --- a/tests/fsharpqa/Source/test.lst +++ b/tests/fsharpqa/Source/test.lst @@ -250,6 +250,7 @@ Misc01 EntryPoint Misc01 Globalization Misc01,NoMT Import Misc01,NoMT ..\..\..\testsprivate\fsharpqa\Source\InteractiveSession\AssemblyLoading +Misc01,NoMT InteractiveSession\Paket Misc01,NoMT InteractiveSession\Misc Misc01,NoMT InteractiveSession\Misc\GenericConstraintWoes\issue2411 Misc01 Libraries\Control diff --git a/vsintegration/Vsix/VisualFSharpOpenSource/Source.extension.vsixmanifest b/vsintegration/Vsix/VisualFSharpOpenSource/Source.extension.vsixmanifest index 9f0bbdcccb5..34c9eb9d759 100644 --- a/vsintegration/Vsix/VisualFSharpOpenSource/Source.extension.vsixmanifest +++ b/vsintegration/Vsix/VisualFSharpOpenSource/Source.extension.vsixmanifest @@ -16,6 +16,7 @@ + @@ -40,6 +41,7 @@ + diff --git a/vsintegration/Vsix/VisualFSharpOpenSource/VisualFSharpOpenSource.csproj b/vsintegration/Vsix/VisualFSharpOpenSource/VisualFSharpOpenSource.csproj index 7ee4ca18cb4..0a81bf8fb74 100644 --- a/vsintegration/Vsix/VisualFSharpOpenSource/VisualFSharpOpenSource.csproj +++ b/vsintegration/Vsix/VisualFSharpOpenSource/VisualFSharpOpenSource.csproj @@ -311,6 +311,10 @@ false True + + {25555554-522d-4cf7-97e4-ba940f0b18f3} + FSharp.DependencyManager.Paket + From 5729d674b1788d3f84f57066011db31e1582d9f9 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 14 Mar 2017 11:16:17 +0100 Subject: [PATCH 02/38] Add default resolvers --- src/fsharp/CompileOps.fs | 22 +++++--- src/fsharp/DependencyManager.Integration.fs | 52 ++++++++++++++++--- src/fsharp/DependencyManager.Integration.fsi | 4 +- .../PaketDependencyManager.fsi | 2 +- .../ReferenceLoading.PaketHandler.fs | 4 +- src/fsharp/fsi/fsi.fs | 7 ++- 6 files changed, 69 insertions(+), 22 deletions(-) diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 7ace63cdd0f..60f3a003b18 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -4940,16 +4940,22 @@ module ScriptPreprocessClosure = let packageManagerTextLines = packageManagerLines |> List.map fst match DependencyManagerIntegration.resolve packageManager tcConfig.Value.implicitIncludeDir scriptName m packageManagerTextLines with | None -> () // error already reported - | Some (additionalIncludeFolders,loadScript,loadScriptText) -> - loadScripts.Add loadScript |> ignore + | Some (loadScript,additionalIncludeFolders) -> // This may incrementally update tcConfig too with new #r references // New package text is ignored on this second phase - let tcConfigB = tcConfig.Value.CloneOfOriginalBuilder - for folder in additionalIncludeFolders do - tcConfigB.AddIncludePath(m,folder,"") - tcConfig := TcConfig.Create(tcConfigB, validate=false) - - yield! loop (ClosureSource(loadScript,m,loadScriptText,true)) ] + + 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)) = diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs index 02e555f7367..73f20cafa2d 100644 --- a/src/fsharp/DependencyManager.Integration.fs +++ b/src/fsharp/DependencyManager.Integration.fs @@ -23,6 +23,7 @@ module ReflectionHelper = |> Seq.tryFind (fun a -> a.GetType().Name = attributeName) |> function | Some _ -> true | _ -> false with | _ -> false + let getAttributeNamed (theType: Type) attributeName = try theType.GetCustomAttributes false @@ -60,7 +61,7 @@ type internal IDependencyManagerProvider = abstract Name : string abstract ToolName: string abstract Key: string - abstract ResolveDependencies : targetFramework: string * scriptDir: string * scriptName: string * packageManagerTextLines: string seq -> string * string list + abstract ResolveDependencies : targetFramework: string * scriptDir: string * scriptName: string * packageManagerTextLines: string seq -> string option * string list type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyInfo, toolNameProperty: PropertyInfo, keyProperty: PropertyInfo, resolveDeps: MethodInfo) = let instance = Activator.CreateInstance(theType) :?> IDisposable @@ -69,8 +70,7 @@ type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyIn let keyProperty = keyProperty.GetValue >> string static member InstanceMaker (theType: System.Type) = if not (ReflectionHelper.implements theType) then None - else - // maybe CE might be better + else match ReflectionHelper.getAttributeNamed theType "FSharpDependencyManagerAttribute" with | None -> None | Some _ -> @@ -106,16 +106,54 @@ let enumerateDependencyManagerAssembliesFromCurrentAssemblyLocation () = |> Seq.choose (fun path -> try Assembly.LoadFrom path |> Some with | _ -> 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, _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, _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, _scriptName: string, _packageManagerTextLines: string seq) = + None,[] + + interface System.IDisposable with + member __.Dispose() = () + let registeredDependencyManagers = lazy ( + let defaultProviders = + [new ProjectDependencyManager() :> IDependencyManagerProvider + new RefDependencyManager() :> IDependencyManagerProvider + new ImplDependencyManager() :> IDependencyManagerProvider] - let managers = + let loadedProviders = enumerateDependencyManagerAssembliesFromCurrentAssemblyLocation() |> Seq.collect (fun a -> a.GetTypes()) |> Seq.choose ReflectionDependencyManagerProvider.InstanceMaker |> Seq.map (fun maker -> maker ()) - // TODO: handle conflicting keys - managers + defaultProviders + |> Seq.append loadedProviders |> Seq.map (fun pm -> pm.Key, pm) |> Map.ofSeq ) @@ -151,7 +189,7 @@ let resolve (packageManager:IDependencyManagerProvider) implicitIncludeDir fileN fileName, packageManagerTextLines) - Some(additionalIncludeFolders,loadScript,File.ReadAllText(loadScript)) + Some(loadScript,additionalIncludeFolders) with e -> if e.InnerException <> null then errorR(Error(FSComp.SR.packageManagerError(e.InnerException.Message),m)) diff --git a/src/fsharp/DependencyManager.Integration.fsi b/src/fsharp/DependencyManager.Integration.fsi index c53625a2d20..6ea4f46ceb9 100644 --- a/src/fsharp/DependencyManager.Integration.fsi +++ b/src/fsharp/DependencyManager.Integration.fsi @@ -10,7 +10,7 @@ type IDependencyManagerProvider = abstract Name : string abstract ToolName: string abstract Key: string - abstract ResolveDependencies : string * string * string * string seq -> string * string list + abstract ResolveDependencies : string * string * string * string seq -> string option * string list val RegisteredDependencyManagers : unit -> Map val tryFindDependencyManagerInPath : range -> string -> IDependencyManagerProvider option @@ -18,4 +18,4 @@ val tryFindDependencyManagerByKey : range -> string -> IDependencyManagerProvide val removeDependencyManagerKey : string -> string -> string -val resolve : IDependencyManagerProvider -> string -> string -> range -> string seq -> (string list * string * string) option +val resolve : IDependencyManagerProvider -> string -> string -> range -> string seq -> (string option * string list) option diff --git a/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fsi b/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fsi index d36d8540da9..f761d8d32b9 100644 --- a/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fsi +++ b/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fsi @@ -8,4 +8,4 @@ type [] PaketDependencyManager = member Name : string member ToolName: string member Key: string - member ResolveDependencies : targetFramework: string * scriptDir: string * scriptName: string * dependencyManagerTextLines: string seq -> string * string list + member ResolveDependencies : targetFramework: string * scriptDir: string * scriptName: string * dependencyManagerTextLines: string seq -> string option * string list diff --git a/src/fsharp/FSharp.DependencyManager.Paket/ReferenceLoading.PaketHandler.fs b/src/fsharp/FSharp.DependencyManager.Paket/ReferenceLoading.PaketHandler.fs index f0a351a1215..3d84285a042 100644 --- a/src/fsharp/FSharp.DependencyManager.Paket/ReferenceLoading.PaketHandler.fs +++ b/src/fsharp/FSharp.DependencyManager.Paket/ReferenceLoading.PaketHandler.fs @@ -156,7 +156,7 @@ let ResolveDependenciesForLanguage(fileType,targetFramework:string,prioritizedSe (File.ReadAllLines(workingDirSpecFile.FullName) |> Array.toList) = packageManagerTextLines && File.Exists loadScript then - (loadScript,additionalIncludeFolders()) + (Some loadScript,additionalIncludeFolders()) else let toolPathOpt = // we try to resolve .paket/paket.exe any place up in the folder structure from current script @@ -212,7 +212,7 @@ let ResolveDependenciesForLanguage(fileType,targetFramework:string,prioritizedSe failwithf "Package resolution using '%s' failed, see directory '%s'.%s%s" toolPath workingDir Environment.NewLine msg else - (loadScript,additionalIncludeFolders()) + (Some loadScript,additionalIncludeFolders()) /// Resolve packages loaded into scripts using `paket:` in `#r` directives such as `#r @"paket: nuget AmazingNugetPackage"`. /// This function will throw if the resolution is not successful or the tool wasn't found diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 3a7dcab1027..89554ae366d 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -1250,10 +1250,13 @@ type internal FsiDynamicCompiler | Some packageManager -> match DependencyManagerIntegration.resolve packageManager tcConfigB.implicitIncludeDir "stdin.fsx" m packageManagerTextLines with | None -> () // error already reported - | Some (additionalIncludeFolders, loadScript,_loadScriptText) -> + | Some (loadScript,additionalIncludeFolders) -> for folder in additionalIncludeFolders do tcConfigB.AddIncludePath(m,folder,"") - istate := fsiDynamicCompiler.EvalSourceFiles (ctok, !istate, m, [loadScript], lexResourceManager, errorLogger) + + match loadScript with + | Some loadScript -> istate := fsiDynamicCompiler.EvalSourceFiles (ctok, !istate, m, [loadScript], lexResourceManager, errorLogger) + | None -> () !istate From 6ddf1bcb526c9a1e54d100a038d75a1d3ba25ecb Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 14 Mar 2017 15:51:09 +0100 Subject: [PATCH 03/38] Show proper error on unknown dependency manager --- .../Misc/UnknownDependencyManager/script1.fsx | 3 +++ tests/fsharpqa/Source/InteractiveSession/Misc/env.lst | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 tests/fsharpqa/Source/InteractiveSession/Misc/UnknownDependencyManager/script1.fsx 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..445c6a2af92 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/UnknownDependencyManager/script1.fsx @@ -0,0 +1,3 @@ +#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 From ce391359b47044e053164c1d2adbe6fb5bea0c40 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 14 Mar 2017 16:10:54 +0100 Subject: [PATCH 04/38] Show proper error on unknown dependency manager --- src/fsharp/CompileOps.fs | 6 +++-- src/fsharp/DependencyManager.Integration.fs | 22 ++++++++++++++----- src/fsharp/DependencyManager.Integration.fsi | 8 ++++++- src/fsharp/fsi/fsi.fs | 7 ++++-- .../Misc/UnknownDependencyManager/script1.fsx | 2 ++ 5 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 60f3a003b18..0b1eb6d4fac 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -4677,10 +4677,12 @@ let ProcessMetaCommandsFromInput | [path] -> matchedm<-m match DependencyManagerIntegration.tryFindDependencyManagerInPath m (path:string) with - | Some packageManager -> + | DependencyManagerIntegration.ReferenceType.RegisteredDependencyManager packageManager -> packageRequireF state (packageManager,m,path) - | None -> + | DependencyManagerIntegration.ReferenceType.Library path -> dllRequireF state (m,path) + | DependencyManagerIntegration.ReferenceType.UnknownType -> + state // error already reported | _ -> errorR(Error(FSComp.SR.buildInvalidHashrDirective(),m)) state diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs index 73f20cafa2d..0e78caa7963 100644 --- a/src/fsharp/DependencyManager.Integration.fs +++ b/src/fsharp/DependencyManager.Integration.fs @@ -63,6 +63,12 @@ type internal IDependencyManagerProvider = abstract Key: string abstract ResolveDependencies : targetFramework: string * scriptDir: 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 @@ -160,15 +166,21 @@ let registeredDependencyManagers = lazy ( let RegisteredDependencyManagers() = registeredDependencyManagers.Force() -let tryFindDependencyManagerInPath m (path:string) : IDependencyManagerProvider option = +let tryFindDependencyManagerInPath m (path:string) : ReferenceType = try - match RegisteredDependencyManagers() |> Seq.tryFind (fun kv -> path.StartsWith(kv.Value.Key + ":" )) with - | None -> None - | Some kv -> Some kv.Value + if path.Contains ":" then + let managers = RegisteredDependencyManagers() + match managers |> Seq.tryFind (fun kv -> path.StartsWith(kv.Value.Key + ":" )) with + | None -> + errorR(Error(FSComp.SR.packageManagerUnknown(path.Split(':').[0], String.Join(", ", managers |> Seq.map (fun pm -> pm.Value.Key)) ),m)) + ReferenceType.UnknownType + | Some kv -> ReferenceType.RegisteredDependencyManager kv.Value + else + ReferenceType.Library path with | e -> errorR(Error(FSComp.SR.packageManagerError(e.Message),m)) - None + ReferenceType.UnknownType let removeDependencyManagerKey (packageManagerKey:string) (path:string) = path.Substring(packageManagerKey.Length + 1).Trim() diff --git a/src/fsharp/DependencyManager.Integration.fsi b/src/fsharp/DependencyManager.Integration.fsi index 6ea4f46ceb9..101c4c37402 100644 --- a/src/fsharp/DependencyManager.Integration.fsi +++ b/src/fsharp/DependencyManager.Integration.fsi @@ -12,8 +12,14 @@ type IDependencyManagerProvider = abstract Key: string abstract ResolveDependencies : string * string * string * string seq -> string option * string list +[] +type ReferenceType = +| RegisteredDependencyManager of IDependencyManagerProvider +| Library of string +| UnknownType + val RegisteredDependencyManagers : unit -> Map -val tryFindDependencyManagerInPath : range -> string -> IDependencyManagerProvider option +val tryFindDependencyManagerInPath : range -> string -> ReferenceType val tryFindDependencyManagerByKey : range -> string -> IDependencyManagerProvider option val removeDependencyManagerKey : string -> string -> string diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 89554ae366d..5d2d892e2ce 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -1922,10 +1922,13 @@ type internal FsiInteractionProcessor | IHash (ParsedHashDirective(("reference" | "r"),[path],m),_) -> match DependencyManagerIntegration.tryFindDependencyManagerInPath m (path:string) with - | Some packageManager -> + | DependencyManagerIntegration.ReferenceType.RegisteredDependencyManager packageManager -> fsiDynamicCompiler.EvalDependencyManagerTextFragment(packageManager,m,path) istate,Completed None - | 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 = diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/UnknownDependencyManager/script1.fsx b/tests/fsharpqa/Source/InteractiveSession/Misc/UnknownDependencyManager/script1.fsx index 445c6a2af92..38c8173ec88 100644 --- a/tests/fsharpqa/Source/InteractiveSession/Misc/UnknownDependencyManager/script1.fsx +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/UnknownDependencyManager/script1.fsx @@ -1,3 +1,5 @@ +//Package manager key 'unk' was not registered. + #r "unk: blubblub" let x = 1 \ No newline at end of file From 185daa075ed40a74cfa5153e4b71a63c82be39cc Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 15 Mar 2017 10:03:18 +0100 Subject: [PATCH 05/38] Add to full vsix --- .../Vsix/VisualFSharpFull/Source.extension.vsixmanifest | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vsintegration/Vsix/VisualFSharpFull/Source.extension.vsixmanifest b/vsintegration/Vsix/VisualFSharpFull/Source.extension.vsixmanifest index b04ea3506a9..fc543aa3f54 100644 --- a/vsintegration/Vsix/VisualFSharpFull/Source.extension.vsixmanifest +++ b/vsintegration/Vsix/VisualFSharpFull/Source.extension.vsixmanifest @@ -16,6 +16,7 @@ + @@ -40,6 +41,7 @@ + From 367ebb13dcddb29ebd7f0353b9ab7bf4ac280536 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 15 Mar 2017 10:23:49 +0100 Subject: [PATCH 06/38] createPackageManagerUnknownError --- src/fsharp/CompileOps.fs | 3 +-- src/fsharp/DependencyManager.Integration.fs | 18 ++++++++++++------ src/fsharp/DependencyManager.Integration.fsi | 2 ++ src/fsharp/FSComp.txt | 2 +- src/fsharp/fsi/fsi.fs | 3 +-- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 0b1eb6d4fac..d3e7626f99c 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -4936,8 +4936,7 @@ module ScriptPreprocessClosure = | _ -> match DependencyManagerIntegration.tryFindDependencyManagerByKey m packageManagerKey with | None -> - let registeredKeys = String.Join(", ", DependencyManagerIntegration.RegisteredDependencyManagers() |> Seq.map (fun kv -> kv.Value.Key)) - errorR(Error(FSComp.SR.packageManagerUnknown(packageManagerKey, registeredKeys),m)) + errorR(DependencyManagerIntegration.createPackageManagerUnknownError packageManagerKey m) | Some packageManager -> let packageManagerTextLines = packageManagerLines |> List.map fst match DependencyManagerIntegration.resolve packageManager tcConfig.Value.implicitIncludeDir scriptName m packageManagerTextLines with diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs index 0e78caa7963..8d300ecc6f2 100644 --- a/src/fsharp/DependencyManager.Integration.fs +++ b/src/fsharp/DependencyManager.Integration.fs @@ -15,7 +15,6 @@ open Microsoft.FSharp.Compiler.ErrorLogger /// hardcoded to net461 as we don't have fsi on netcore let targetFramework = "net461" - module ReflectionHelper = let assemblyHasAttribute (theAssembly: Assembly) attributeName = try @@ -105,14 +104,17 @@ type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyIn member __.Dispose () = instance.Dispose() +let assemblySearchPath = + lazy( + let assemblyLocation = typeof.Assembly.Location + Path.GetDirectoryName assemblyLocation + ) + let enumerateDependencyManagerAssembliesFromCurrentAssemblyLocation () = - let assemblyLocation = typeof.Assembly.Location - let assemblySearchPath = Path.GetDirectoryName assemblyLocation - Directory.EnumerateFiles(assemblySearchPath,"*DependencyManager*.dll") + Directory.EnumerateFiles(assemblySearchPath.Force(),"*DependencyManager*.dll") |> Seq.choose (fun path -> try Assembly.LoadFrom path |> Some with | _ -> None) |> Seq.filter (fun a -> ReflectionHelper.assemblyHasAttribute a "FSharpDependencyManagerAttribute") - type ProjectDependencyManager() = interface IDependencyManagerProvider with member __.Name = "Project loader" @@ -166,13 +168,17 @@ let registeredDependencyManagers = lazy ( let RegisteredDependencyManagers() = registeredDependencyManagers.Force() +let createPackageManagerUnknownError packageManagerKey m = + let registeredKeys = String.Join(", ", RegisteredDependencyManagers() |> Seq.map (fun kv -> kv.Value.Key)) + Error(FSComp.SR.packageManagerUnknown(packageManagerKey, registeredKeys, assemblySearchPath.Force()),m) + let tryFindDependencyManagerInPath m (path:string) : ReferenceType = try if path.Contains ":" then let managers = RegisteredDependencyManagers() match managers |> Seq.tryFind (fun kv -> path.StartsWith(kv.Value.Key + ":" )) with | None -> - errorR(Error(FSComp.SR.packageManagerUnknown(path.Split(':').[0], String.Join(", ", managers |> Seq.map (fun pm -> pm.Value.Key)) ),m)) + errorR(createPackageManagerUnknownError (path.Split(':').[0]) m) ReferenceType.UnknownType | Some kv -> ReferenceType.RegisteredDependencyManager kv.Value else diff --git a/src/fsharp/DependencyManager.Integration.fsi b/src/fsharp/DependencyManager.Integration.fsi index 101c4c37402..3419a9e65f2 100644 --- a/src/fsharp/DependencyManager.Integration.fsi +++ b/src/fsharp/DependencyManager.Integration.fsi @@ -24,4 +24,6 @@ val tryFindDependencyManagerByKey : range -> string -> IDependencyManagerProvide val removeDependencyManagerKey : string -> string -> string +val createPackageManagerUnknownError : string -> range -> exn + val resolve : IDependencyManagerProvider -> string -> string -> range -> string seq -> (string option * string list) option diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index f74446837f2..1be3137b24e 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1333,7 +1333,7 @@ tcGlobalsSystemTypeNotFound,"The system type '%s' was required but no referenced 3213,typrelMemberHasMultiplePossibleDispatchSlots,"The member '%s' matches multiple overloads of the same method.\nPlease restrict it to one of the following:%s." 3214,methodIsNotStatic,"Method or object constructor '%s' is not static" 3215,parsUnexpectedSymbolEqualsInsteadOfIn,"Unexpected symbol '=' in expression. Did you intend to use 'for x in y .. z do' instead?" -3216,packageManagerUnknown,"Package manager key '%s' was not registered. Currently registered: %s" +3216,packageManagerUnknown,"Package manager key '%s' was not registered in '%s'. Currently registered: %s" 3217,packageManagerError,"%s" keywordDescriptionAbstract,"Indicates a method that either has no implementation in the type in which it is declared or that is virtual and has a default implementation." keyworkDescriptionAnd,"Used in mutually recursive bindings, in property declarations, and with multiple constraints on generic parameters." diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 5d2d892e2ce..ff83b240d24 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -1245,8 +1245,7 @@ type internal FsiDynamicCompiler let packageManagerTextLines = packageManagerLines |> List.map fst match DependencyManagerIntegration.tryFindDependencyManagerByKey m packageManagerKey with | None -> - let registeredKeys = String.Join(", ", DependencyManagerIntegration.RegisteredDependencyManagers() |> Seq.map (fun kv -> kv.Value.Key)) - errorR(Error(FSComp.SR.packageManagerUnknown(packageManagerKey, registeredKeys),m)) + errorR(DependencyManagerIntegration.createPackageManagerUnknownError packageManagerKey m) | Some packageManager -> match DependencyManagerIntegration.resolve packageManager tcConfigB.implicitIncludeDir "stdin.fsx" m packageManagerTextLines with | None -> () // error already reported From 2259dc67792dad2411cfa75cdf5f28f318faeedb Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 15 Mar 2017 10:32:05 +0100 Subject: [PATCH 07/38] fix order --- src/fsharp/DependencyManager.Integration.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs index 8d300ecc6f2..59e761cfd43 100644 --- a/src/fsharp/DependencyManager.Integration.fs +++ b/src/fsharp/DependencyManager.Integration.fs @@ -170,7 +170,7 @@ let RegisteredDependencyManagers() = registeredDependencyManagers.Force() let createPackageManagerUnknownError packageManagerKey m = let registeredKeys = String.Join(", ", RegisteredDependencyManagers() |> Seq.map (fun kv -> kv.Value.Key)) - Error(FSComp.SR.packageManagerUnknown(packageManagerKey, registeredKeys, assemblySearchPath.Force()),m) + Error(FSComp.SR.packageManagerUnknown(packageManagerKey, assemblySearchPath.Force(), registeredKeys),m) let tryFindDependencyManagerInPath m (path:string) : ReferenceType = try From edab5207d9a04220c35e84ed6dc1fb906d4aa3b2 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 15 Mar 2017 10:46:10 +0100 Subject: [PATCH 08/38] Multiple search paths --- src/fsharp/DependencyManager.Integration.fs | 15 ++++++++++----- src/fsharp/FSComp.txt | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs index 59e761cfd43..acad95279eb 100644 --- a/src/fsharp/DependencyManager.Integration.fs +++ b/src/fsharp/DependencyManager.Integration.fs @@ -104,14 +104,18 @@ type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyIn member __.Dispose () = instance.Dispose() -let assemblySearchPath = +let assemblySearchPaths = lazy( - let assemblyLocation = typeof.Assembly.Location - Path.GetDirectoryName assemblyLocation + [let assemblyLocation = typeof.Assembly.Location + yield Path.GetDirectoryName assemblyLocation + let executingAssembly = Assembly.GetExecutingAssembly().Location + yield Path.GetDirectoryName executingAssembly] + |> List.distinct ) let enumerateDependencyManagerAssembliesFromCurrentAssemblyLocation () = - Directory.EnumerateFiles(assemblySearchPath.Force(),"*DependencyManager*.dll") + assemblySearchPaths.Force() + |> Seq.collect (fun path -> Directory.EnumerateFiles(path,"*DependencyManager*.dll")) |> Seq.choose (fun path -> try Assembly.LoadFrom path |> Some with | _ -> None) |> Seq.filter (fun a -> ReflectionHelper.assemblyHasAttribute a "FSharpDependencyManagerAttribute") @@ -170,7 +174,8 @@ let RegisteredDependencyManagers() = registeredDependencyManagers.Force() let createPackageManagerUnknownError packageManagerKey m = let registeredKeys = String.Join(", ", RegisteredDependencyManagers() |> Seq.map (fun kv -> kv.Value.Key)) - Error(FSComp.SR.packageManagerUnknown(packageManagerKey, assemblySearchPath.Force(), registeredKeys),m) + let searchPaths = assemblySearchPaths.Force() + Error(FSComp.SR.packageManagerUnknown(packageManagerKey, String.Join(", ", searchPaths), registeredKeys),m) let tryFindDependencyManagerInPath m (path:string) : ReferenceType = try diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 1be3137b24e..69963698b96 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1333,7 +1333,7 @@ tcGlobalsSystemTypeNotFound,"The system type '%s' was required but no referenced 3213,typrelMemberHasMultiplePossibleDispatchSlots,"The member '%s' matches multiple overloads of the same method.\nPlease restrict it to one of the following:%s." 3214,methodIsNotStatic,"Method or object constructor '%s' is not static" 3215,parsUnexpectedSymbolEqualsInsteadOfIn,"Unexpected symbol '=' in expression. Did you intend to use 'for x in y .. z do' instead?" -3216,packageManagerUnknown,"Package manager key '%s' was not registered in '%s'. Currently registered: %s" +3216,packageManagerUnknown,"Package manager key '%s' was not registered in %s. Currently registered: %s" 3217,packageManagerError,"%s" keywordDescriptionAbstract,"Indicates a method that either has no implementation in the type in which it is declared or that is virtual and has a default implementation." keyworkDescriptionAnd,"Used in mutually recursive bindings, in property declarations, and with multiple constraints on generic parameters." From 1c20e1840f0c5e1ec7d6340b94f578cc7420f7ee Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 15 Mar 2017 11:01:17 +0100 Subject: [PATCH 09/38] add reference --- vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj b/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj index 6b684326f0a..6ac785d4312 100644 --- a/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj +++ b/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj @@ -312,6 +312,10 @@ false True + + {25555554-522d-4cf7-97e4-ba940f0b18f3} + FSharp.DependencyManager.Paket + @@ -323,4 +327,4 @@ - + \ No newline at end of file From 1d0308f7aa80e0e5892de559a82bff7918d73276 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 15 Mar 2017 12:06:07 +0100 Subject: [PATCH 10/38] Add AppDomain.CurrentDomain.BaseDirectory to searchpath --- src/fsharp/DependencyManager.Integration.fs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs index acad95279eb..c126c3056e3 100644 --- a/src/fsharp/DependencyManager.Integration.fs +++ b/src/fsharp/DependencyManager.Integration.fs @@ -109,7 +109,9 @@ let assemblySearchPaths = [let assemblyLocation = typeof.Assembly.Location yield Path.GetDirectoryName assemblyLocation let executingAssembly = Assembly.GetExecutingAssembly().Location - yield Path.GetDirectoryName executingAssembly] + yield Path.GetDirectoryName executingAssembly + let baseDir = AppDomain.CurrentDomain.BaseDirectory + yield baseDir ] |> List.distinct ) From ae1e974e2822c00e2ec10109f55d85614dafb439 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 21 Jun 2017 10:49:06 +0200 Subject: [PATCH 11/38] Do not touch sln --- FSharp.sln | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/FSharp.sln b/FSharp.sln index 44e4b6a400c..f4ac69591e4 100644 --- a/FSharp.sln +++ b/FSharp.sln @@ -3,10 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26403.7 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler", "src\fsharp\FSharp.Compiler\FSharp.Compiler.fsproj", "{2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}" - ProjectSection(ProjectDependencies) = postProject - {25555554-522D-4CF7-97E4-BA940F0B18F3} = {25555554-522D-4CF7-97E4-BA940F0B18F3} - EndProjectSection Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Private", "src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj", "{2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}" EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Server.Shared", "src\fsharp\FSharp.Compiler.Server.Shared\FSharp.Compiler.Server.Shared.fsproj", "{D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}" @@ -47,10 +43,6 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "HostedCompilerServer", "tes EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ILComparer", "tests\fsharpqa\testenv\src\ILComparer\ILComparer.fsproj", "{2E60864A-E3FF-4BCC-810F-DC7C34E6B236}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.LanguageService.Compiler", "src\fsharp\FSharp.LanguageService.Compiler\FSharp.LanguageService.Compiler.fsproj", "{A437A6EC-5323-47C2-8F86-E2CAC54FF152}" -EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.DependencyManager.Paket", "src\fsharp\FSharp.DependencyManager.Paket\FSharp.DependencyManager.Paket.fsproj", "{25555554-522D-4CF7-97E4-BA940F0B18F3}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -225,18 +217,6 @@ Global {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.Release|Any CPU.Build.0 = Release|Any CPU {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.Release|x86.ActiveCfg = Release|Any CPU {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.Release|x86.Build.0 = Release|Any CPU - {25555554-522D-4CF7-97E4-BA940F0B18F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {25555554-522D-4CF7-97E4-BA940F0B18F3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {25555554-522D-4CF7-97E4-BA940F0B18F3}.Debug|x86.ActiveCfg = Debug|Any CPU - {25555554-522D-4CF7-97E4-BA940F0B18F3}.Debug|x86.Build.0 = Debug|Any CPU - {25555554-522D-4CF7-97E4-BA940F0B18F3}.Proto|Any CPU.ActiveCfg = Proto|Any CPU - {25555554-522D-4CF7-97E4-BA940F0B18F3}.Proto|Any CPU.Build.0 = Proto|Any CPU - {25555554-522D-4CF7-97E4-BA940F0B18F3}.Proto|x86.ActiveCfg = Proto|Any CPU - {25555554-522D-4CF7-97E4-BA940F0B18F3}.Proto|x86.Build.0 = Proto|Any CPU - {25555554-522D-4CF7-97E4-BA940F0B18F3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {25555554-522D-4CF7-97E4-BA940F0B18F3}.Release|Any CPU.Build.0 = Release|Any CPU - {25555554-522D-4CF7-97E4-BA940F0B18F3}.Release|x86.ActiveCfg = Release|Any CPU - {25555554-522D-4CF7-97E4-BA940F0B18F3}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 387b82080b0facc16493225ef04111a8d40fc487 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 21 Jun 2017 10:49:21 +0200 Subject: [PATCH 12/38] Fsc-proto fix --- src/fsharp/Fsc-proto/Fsc-proto.fsproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/fsharp/Fsc-proto/Fsc-proto.fsproj b/src/fsharp/Fsc-proto/Fsc-proto.fsproj index a8006028692..881d525e189 100644 --- a/src/fsharp/Fsc-proto/Fsc-proto.fsproj +++ b/src/fsharp/Fsc-proto/Fsc-proto.fsproj @@ -419,6 +419,12 @@ IlxGen.fs + + Driver\DependencyManager.Integration.fsi + + + Driver\DependencyManager.Integration.fs + CompileOps.fsi From a41df7c1c44b13d254c8118240211a7c1f4147b6 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 21 Jun 2017 11:13:27 +0200 Subject: [PATCH 13/38] FSharp.Compiler.Private.fsproj fix --- .../FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index 61c8c2978b3..2a171171bce 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -652,6 +652,7 @@ {25555554-522d-4cf7-97e4-ba940f0b18f3} True + From 78f2dd876607d31630b001208918e9e8d47b3415 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 27 Jun 2017 16:35:46 +0200 Subject: [PATCH 14/38] Add integration hook into FCS --- fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index 6faf15a6593..e7129f69c49 100644 --- a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -457,6 +457,12 @@ CodeGen/IlxGen.fs + + Driver\DependencyManager.Integration.fsi + + + Driver\DependencyManager.Integration.fs + Driver/CompileOps.fsi From bc262d37f3c5a94de077220d913e11843e866e31 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 27 Jun 2017 16:57:27 +0200 Subject: [PATCH 15/38] Add integration hook into FCS --- fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index e7129f69c49..c5d3334c6b8 100644 --- a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -457,10 +457,10 @@ CodeGen/IlxGen.fs - + Driver\DependencyManager.Integration.fsi - + Driver\DependencyManager.Integration.fs From 02f4b6ce1a3cb1b4e48cb329ec9281fc0e7cf7f6 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 27 Jun 2017 16:59:08 +0200 Subject: [PATCH 16/38] Add integration hook into FCS --- fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index c5d3334c6b8..694e553302b 100644 --- a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -1,4 +1,4 @@ - + From b1e422dde4427b611dd6c7d6f17cf130356f4496 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 27 Jun 2017 20:53:13 +0200 Subject: [PATCH 17/38] Better error message in case of test error --- .../unittests/Tests.LanguageService.ErrorList.fs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/vsintegration/tests/unittests/Tests.LanguageService.ErrorList.fs b/vsintegration/tests/unittests/Tests.LanguageService.ErrorList.fs index 82a1e3a40ae..832688fc437 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.AddLine s + 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) = From 234fbff90df67bd1dc30b40ad578a149a1b8a10f Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 27 Jun 2017 20:58:25 +0200 Subject: [PATCH 18/38] exclude path names --- src/fsharp/DependencyManager.Integration.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs index c126c3056e3..7817dc83ff9 100644 --- a/src/fsharp/DependencyManager.Integration.fs +++ b/src/fsharp/DependencyManager.Integration.fs @@ -181,7 +181,7 @@ let createPackageManagerUnknownError packageManagerKey m = let tryFindDependencyManagerInPath m (path:string) : ReferenceType = try - if path.Contains ":" then + if path.Contains ": " then let managers = RegisteredDependencyManagers() match managers |> Seq.tryFind (fun kv -> path.StartsWith(kv.Value.Key + ":" )) with | None -> From 122b14d31982d6851cd0d0d69326882329be053c Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 27 Jun 2017 21:01:22 +0200 Subject: [PATCH 19/38] exclude path names --- src/fsharp/DependencyManager.Integration.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs index 7817dc83ff9..776903e5384 100644 --- a/src/fsharp/DependencyManager.Integration.fs +++ b/src/fsharp/DependencyManager.Integration.fs @@ -181,7 +181,7 @@ let createPackageManagerUnknownError packageManagerKey m = let tryFindDependencyManagerInPath m (path:string) : ReferenceType = try - if path.Contains ": " then + if path.Contains ":" && not (System.IO.Path.IsPathRooted path) then let managers = RegisteredDependencyManagers() match managers |> Seq.tryFind (fun kv -> path.StartsWith(kv.Value.Key + ":" )) with | None -> From d03b78259c4db005b6d9b06c5676b248f852855c Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 27 Jun 2017 21:07:14 +0200 Subject: [PATCH 20/38] fix build --- .../tests/unittests/Tests.LanguageService.ErrorList.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vsintegration/tests/unittests/Tests.LanguageService.ErrorList.fs b/vsintegration/tests/unittests/Tests.LanguageService.ErrorList.fs index 832688fc437..39e452e21b1 100644 --- a/vsintegration/tests/unittests/Tests.LanguageService.ErrorList.fs +++ b/vsintegration/tests/unittests/Tests.LanguageService.ErrorList.fs @@ -59,7 +59,7 @@ type UsingMSBuild() as this = for error in errorList do printfn "%A" error.Severity let s = error.ToString() - errorTexts.AddLine s + errorTexts.AppendLine s |> ignore printf "%s\n" s if num <> errorList.Length then From fc1d4b4ec32e56889b9ce60950493c4d137933f8 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 28 Jun 2017 08:58:14 +0200 Subject: [PATCH 21/38] Dedupe module names in fsi --- src/fsharp/CompileOps.fs | 8 ++++---- src/fsharp/fsi/fsi.fs | 9 ++++++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index d8f6f1cbe93..ca8855e5558 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -5080,8 +5080,8 @@ module ScriptPreprocessClosure = | _ -> closureFiles // Get all source files. - let sourceFiles = [ for (ClosureFile(filename,m,_,_,_,_)) in closureFiles -> (filename,m) ] - let sourceInputs = [ for (ClosureFile(filename,_,input,parseDiagnostics,metaDiagnostics,_nowarns)) in closureFiles -> ({ FileName=filename; SyntaxTree=input; ParseDiagnostics=parseDiagnostics; MetaCommandDiagnostics=metaDiagnostics }: LoadClosureInput) ] + let sourceFiles = [ for (ClosureFile(filename,m,_,_,_,_)) in closureFiles -> (filename,m) ] + let sourceInputs = [ for (ClosureFile(filename,_,input,parseDiagnostics,metaDiagnostics,_nowarns)) in closureFiles -> ({ FileName=filename; SyntaxTree=input; ParseDiagnostics=parseDiagnostics; MetaCommandDiagnostics=metaDiagnostics }: LoadClosureInput) ] let globalNoWarns = closureFiles |> List.collect (fun (ClosureFile(_,_,_,_,_,noWarns)) -> noWarns) // Resolve all references. @@ -5347,13 +5347,13 @@ let TypeCheckOneInputEventually // Check if we've already seen an implementation for this fragment if Zset.contains qualNameOfFile rootImpls then - errorR(Error(FSComp.SR.buildImplementationAlreadyGiven(qualNameOfFile.Text),m)) + errorR(Error(FSComp.SR.buildImplementationAlreadyGiven(qualNameOfFile.Text),m)) let tcImplEnv = tcState.tcsTcImplEnv // Typecheck the implementation file let! topAttrs, implFile, tcEnvAtEnd, createsGeneratedProvidedTypes = - TypeCheckOneImplFile (tcGlobals,tcState.tcsNiceNameGen,amap,tcState.tcsCcu,checkForErrors,tcConfig.conditionalCompilationDefines,tcSink) tcImplEnv rootSigOpt file + TypeCheckOneImplFile (tcGlobals,tcState.tcsNiceNameGen,amap,tcState.tcsCcu,checkForErrors,tcConfig.conditionalCompilationDefines,tcSink) tcImplEnv rootSigOpt file let hadSig = Option.isSome rootSigOpt let implFileSigType = SigTypeOfImplFile implFile diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index b0be5bd25d6..b1e03935ff1 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -1334,6 +1334,7 @@ type internal FsiDynamicCompiler member fsiDynamicCompiler.EvalSourceFiles(ctok, istate, m, sourceFiles, lexResourceManager, errorLogger: ErrorLogger) = let tcConfig = TcConfig.Create(tcConfigB,validate=false) + let moduleNamesDict = Dictionary>() match sourceFiles with | [] -> istate | _ -> @@ -1368,10 +1369,16 @@ type internal FsiDynamicCompiler input.FileName, parsedInput) |> List.unzip - errorLogger.AbortOnError(fsiConsoleOutput); + + errorLogger.AbortOnError(fsiConsoleOutput) if inputs |> List.exists Option.isNone then failwith "parse error" let inputs = List.map Option.get inputs let istate = (istate, sourceFiles, inputs) |||> List.fold2 (fun istate sourceFile input -> fsiDynamicCompiler.ProcessMetaCommandsFromInputAsInteractiveCommands(ctok, istate, sourceFile, input)) + + let inputs = + inputs + |> List.map (DeduplicateParsedInputModuleName moduleNamesDict) + fsiDynamicCompiler.EvalParsedSourceFiles (ctok, errorLogger, istate, inputs) From 58798c1e67c876ea990c686f89439e15fa2ca956 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 28 Jun 2017 10:44:14 +0200 Subject: [PATCH 22/38] Add mainScriptFile to interface - we might use it later --- src/fsharp/CompileOps.fs | 4 +-- src/fsharp/DependencyManager.Integration.fs | 17 ++++----- src/fsharp/DependencyManager.Integration.fsi | 4 +-- .../PaketDependencyManager.fs | 3 +- .../PaketDependencyManager.fsi | 3 +- .../ReferenceLoading.PaketHandler.fs | 36 +++++++++++-------- src/fsharp/fsi/fsi.fs | 2 +- 7 files changed, 40 insertions(+), 29 deletions(-) diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index ca8855e5558..da081a4ff7e 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -4971,7 +4971,7 @@ 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) = let tcConfig = ref origTcConfig let observedSources = Observed() @@ -4993,7 +4993,7 @@ module ScriptPreprocessClosure = errorR(DependencyManagerIntegration.createPackageManagerUnknownError packageManagerKey m) | Some packageManager -> let packageManagerTextLines = packageManagerLines |> List.map fst - match DependencyManagerIntegration.resolve packageManager tcConfig.Value.implicitIncludeDir scriptName m packageManagerTextLines with + 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 diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs index 776903e5384..51a9d5b0385 100644 --- a/src/fsharp/DependencyManager.Integration.fs +++ b/src/fsharp/DependencyManager.Integration.fs @@ -60,7 +60,7 @@ type internal IDependencyManagerProvider = abstract Name : string abstract ToolName: string abstract Key: string - abstract ResolveDependencies : targetFramework: string * scriptDir: string * scriptName: string * packageManagerTextLines: string seq -> string option * string list + abstract ResolveDependencies : targetFramework: string * scriptDir: string * mainScriptName: string * scriptName: string * packageManagerTextLines: string seq -> string option * string list [] type ReferenceType = @@ -88,7 +88,7 @@ type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyIn match ReflectionHelper.getInstanceProperty theType Array.empty "Key" with | None -> None | Some keyProperty -> - match ReflectionHelper.getInstanceMethod theType [|typeof;typeof;typeof;typeof;|] "ResolveDependencies" with + 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) @@ -97,8 +97,8 @@ type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyIn member __.Name = instance |> nameProperty member __.ToolName = instance |> toolNameProperty member __.Key = instance |> keyProperty - member __.ResolveDependencies(targetFramework, scriptDir, scriptName, packageManagerTextLines) = - let arguments = [|box targetFramework; box scriptDir; box scriptName; box packageManagerTextLines|] + 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() @@ -126,7 +126,7 @@ type ProjectDependencyManager() = member __.Name = "Project loader" member __.ToolName = "" member __.Key = "project" - member __.ResolveDependencies(_targetFramework:string, _scriptDir: string, _scriptName: string, _packageManagerTextLines: string seq) = + member __.ResolveDependencies(_targetFramework:string, _scriptDir: string, _mainScriptName: string, _scriptName: string, _packageManagerTextLines: string seq) = None,[] interface System.IDisposable with @@ -137,7 +137,7 @@ type RefDependencyManager() = member __.Name = "Ref library loader" member __.ToolName = "" member __.Key = "ref" - member __.ResolveDependencies(_targetFramework:string, _scriptDir: string, _scriptName: string, _packageManagerTextLines: string seq) = + member __.ResolveDependencies(_targetFramework:string, _scriptDir: string, _mainScriptName: string, _scriptName: string, _packageManagerTextLines: string seq) = None,[] interface System.IDisposable with @@ -148,7 +148,7 @@ type ImplDependencyManager() = member __.Name = "Impl library loader" member __.ToolName = "" member __.Key = "impl" - member __.ResolveDependencies(_targetFramework:string, _scriptDir: string, _scriptName: string, _packageManagerTextLines: string seq) = + member __.ResolveDependencies(_targetFramework:string, _scriptDir: string, _mainScriptName: string, _scriptName: string, _packageManagerTextLines: string seq) = None,[] interface System.IDisposable with @@ -205,12 +205,13 @@ let tryFindDependencyManagerByKey m (key:string) : IDependencyManagerProvider op errorR(Error(FSComp.SR.packageManagerError(e.Message),m)) None -let resolve (packageManager:IDependencyManagerProvider) implicitIncludeDir fileName m packageManagerTextLines = +let resolve (packageManager:IDependencyManagerProvider) implicitIncludeDir mainScriptName fileName m packageManagerTextLines = try let loadScript,additionalIncludeFolders = packageManager.ResolveDependencies( targetFramework, implicitIncludeDir, + mainScriptName, fileName, packageManagerTextLines) diff --git a/src/fsharp/DependencyManager.Integration.fsi b/src/fsharp/DependencyManager.Integration.fsi index 3419a9e65f2..7b4de99296a 100644 --- a/src/fsharp/DependencyManager.Integration.fsi +++ b/src/fsharp/DependencyManager.Integration.fsi @@ -10,7 +10,7 @@ type IDependencyManagerProvider = abstract Name : string abstract ToolName: string abstract Key: string - abstract ResolveDependencies : string * string * string * string seq -> string option * string list + abstract ResolveDependencies : string * string * string * string * string seq -> string option * string list [] type ReferenceType = @@ -26,4 +26,4 @@ val removeDependencyManagerKey : string -> string -> string val createPackageManagerUnknownError : string -> range -> exn -val resolve : IDependencyManagerProvider -> string -> string -> range -> string seq -> (string option * string list) option +val resolve : IDependencyManagerProvider -> string -> string -> string -> range -> string seq -> (string option * string list) option diff --git a/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fs b/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fs index 6e111f8488b..ca674e807bc 100644 --- a/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fs +++ b/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fs @@ -8,10 +8,11 @@ type [] PaketDependencyManager() = member __.Name = "Paket" member __.ToolName = "paket.exe" member __.Key = "paket" - member __.ResolveDependencies(targetFramework:string, scriptDir: string, scriptName: string, packageManagerTextLines: string seq) = + member __.ResolveDependencies(targetFramework:string, scriptDir: string, mainScriptName: string, scriptName: string, packageManagerTextLines: string seq) = ReferenceLoading.PaketHandler.ResolveDependencies( targetFramework, scriptDir, + mainScriptName, scriptName, packageManagerTextLines) diff --git a/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fsi b/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fsi index f761d8d32b9..625a66147df 100644 --- a/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fsi +++ b/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fsi @@ -2,10 +2,11 @@ type [] FSharpDependencyManagerAttribute = inherit System.Attribute new : unit -> FSharpDependencyManagerAttribute + type [] PaketDependencyManager = interface System.IDisposable new : unit -> PaketDependencyManager member Name : string member ToolName: string member Key: string - member ResolveDependencies : targetFramework: string * scriptDir: string * scriptName: string * dependencyManagerTextLines: string seq -> string option * string list + member ResolveDependencies : targetFramework: string * scriptDir: string * mainScriptName: string * scriptName: string * dependencyManagerTextLines: string seq -> string option * string list diff --git a/src/fsharp/FSharp.DependencyManager.Paket/ReferenceLoading.PaketHandler.fs b/src/fsharp/FSharp.DependencyManager.Paket/ReferenceLoading.PaketHandler.fs index 3d84285a042..222dec5b0af 100644 --- a/src/fsharp/FSharp.DependencyManager.Paket/ReferenceLoading.PaketHandler.fs +++ b/src/fsharp/FSharp.DependencyManager.Paket/ReferenceLoading.PaketHandler.fs @@ -98,10 +98,12 @@ let GetPaketLoadScriptLocation baseDir optionalFrameworkDir scriptName = /// A string given to paket command to fix the framework. /// List of directories which are checked first to resolve `paket.exe`. /// -/// filename for the script (not necessarily existing if interactive evaluation) +/// Filename for the main script (not necessarily existing if interactive evaluation) +/// Filename for the script (not necessarily existing if interactive evaluation) /// Package manager text lines from script, those are meant to be just the inner part, without `#r "paket:` prefix -let ResolveDependenciesForLanguage(fileType,targetFramework:string,prioritizedSearchPaths: string seq, scriptDir: string, scriptName: string,packageManagerTextLinesFromScript: string seq) = - let workingDir = Path.Combine(Path.GetTempPath(), "script-packages", string(abs(hash (scriptDir,scriptName)))) +let ResolveDependenciesForLanguage(fileType,targetFramework:string,prioritizedSearchPaths: string seq, scriptDir: string, _mainScriptName: string, scriptName: string, packageManagerTextLinesFromScript: string seq) = + let scriptHash = string(abs(hash (scriptDir,scriptName))) + let workingDir = Path.Combine(Path.GetTempPath(), "script-packages", scriptHash) let depsFileName = "paket.dependencies" let workingDirSpecFile = FileInfo(Path.Combine(workingDir,depsFileName)) if not (Directory.Exists workingDir) then @@ -147,16 +149,20 @@ let ResolveDependenciesForLanguage(fileType,targetFramework:string,prioritizedSe findSpecFile scriptDir /// hardcoded to load the "Main" group (implicit in paket) - let loadScript = GetPaketLoadScriptLocation workingDir (Some targetFramework) ("main.group." + fileType) - let additionalIncludeFolders() = + let loadScriptFileName = GetPaketLoadScriptLocation workingDir (Some targetFramework) ("main.group." + fileType) + let loadScriptFileInfo = FileInfo loadScriptFileName + let copiedScriptFileInfo = FileInfo(Path.Combine(loadScriptFileInfo.Directory.FullName,"main.group." + scriptHash + "." + fileType)) + + let additionalIncludeFolders() = [Path.Combine(workingDir,"paket-files")] |> List.filter Directory.Exists - + if workingDirSpecFile.Exists && (File.ReadAllLines(workingDirSpecFile.FullName) |> Array.toList) = packageManagerTextLines && - File.Exists loadScript - then - (Some loadScript,additionalIncludeFolders()) + loadScriptFileInfo.Exists && + copiedScriptFileInfo.Exists + then + (Some copiedScriptFileInfo.FullName,additionalIncludeFolders()) else let toolPathOpt = // we try to resolve .paket/paket.exe any place up in the folder structure from current script @@ -173,7 +179,7 @@ let ResolveDependenciesForLanguage(fileType,targetFramework:string,prioritizedSe scriptDir userProfile | Some toolPath -> - try File.Delete(loadScript) with _ -> () + try loadScriptFileInfo.Delete() with _ -> () let toolPath = if runningOnMono then "mono " + toolPath else toolPath File.WriteAllLines(workingDirSpecFile.FullName, packageManagerTextLines) let startInfo = @@ -212,13 +218,15 @@ let ResolveDependenciesForLanguage(fileType,targetFramework:string,prioritizedSe failwithf "Package resolution using '%s' failed, see directory '%s'.%s%s" toolPath workingDir Environment.NewLine msg else - (Some loadScript,additionalIncludeFolders()) + File.Copy(loadScriptFileInfo.FullName,copiedScriptFileInfo.FullName,true) + (Some copiedScriptFileInfo.FullName,additionalIncludeFolders()) /// Resolve packages loaded into scripts using `paket:` in `#r` directives such as `#r @"paket: nuget AmazingNugetPackage"`. /// This function will throw if the resolution is not successful or the tool wasn't found /// A string given to paket command to fix the framework. /// -/// filename for the script (not necessarily existing if interactive evaluation) +/// Filename for the main script (not necessarily existing if interactive evaluation) +/// Filename for the script (not necessarily existing if interactive evaluation) /// Package manager text lines from script, those are meant to be just the inner part, without `#r "paket:` prefix -let ResolveDependencies(targetFramework:string, scriptDir: string, scriptName: string,packageManagerTextLinesFromScript: string seq) = - ResolveDependenciesForLanguage("fsx",targetFramework,Seq.empty, scriptDir, scriptName,packageManagerTextLinesFromScript) +let ResolveDependencies(targetFramework:string, scriptDir: string, mainScriptName: string, scriptName: string, packageManagerTextLinesFromScript: string seq) = + ResolveDependenciesForLanguage("fsx",targetFramework,Seq.empty, scriptDir, mainScriptName, scriptName,packageManagerTextLinesFromScript) diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index b1e03935ff1..8004ff81daf 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -1309,7 +1309,7 @@ type internal FsiDynamicCompiler | None -> errorR(DependencyManagerIntegration.createPackageManagerUnknownError packageManagerKey m) | Some packageManager -> - match DependencyManagerIntegration.resolve packageManager tcConfigB.implicitIncludeDir "stdin.fsx" m packageManagerTextLines with + match DependencyManagerIntegration.resolve packageManager tcConfigB.implicitIncludeDir "stdin.fsx" "stdin.fsx" m packageManagerTextLines with | None -> () // error already reported | Some (loadScript,additionalIncludeFolders) -> for folder in additionalIncludeFolders do From 8ce1f872831bc9c429ebd2f09e74e569eb0748f7 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 28 Jun 2017 10:49:47 +0200 Subject: [PATCH 23/38] Update paket fsproj --- .../FSharp.DependencyManager.Paket.fsproj | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/fsharp/FSharp.DependencyManager.Paket/FSharp.DependencyManager.Paket.fsproj b/src/fsharp/FSharp.DependencyManager.Paket/FSharp.DependencyManager.Paket.fsproj index a2531eb83d1..5709a346d56 100644 --- a/src/fsharp/FSharp.DependencyManager.Paket/FSharp.DependencyManager.Paket.fsproj +++ b/src/fsharp/FSharp.DependencyManager.Paket/FSharp.DependencyManager.Paket.fsproj @@ -13,21 +13,14 @@ FSharp.DependencyManager.Paket EXTENSIONTYPING;$(DefineConstants) COMPILER;$(DefineConstants) - INCLUDE_METADATA_READER;$(DefineConstants) - INCLUDE_METADATA_WRITER;$(DefineConstants) $(NoWarn);62;9 {25555554-522D-4CF7-97E4-BA940F0B18F3} true + 0x06800000 $(OtherFlags) /warnon:1182 - - - $(NuGeReleaseVersion) - $(PackageVersionMajor)-$(PackageVersionMinor) - $(NuGetPerBuildPreReleaseVersion)-0 - @@ -62,6 +55,8 @@ {DED3BBD7-53F4-428A-8C9F-27968E768605} FSharp.Core + + From 91462b590bd7d0b8dc17fc3f7cfa873be0d2e98e Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 28 Jun 2017 11:35:09 +0200 Subject: [PATCH 24/38] No idea if that's good --- .../FSharp.DependencyManager.Paket.fsproj | 5 ++- .../project.json | 36 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/fsharp/FSharp.DependencyManager.Paket/project.json diff --git a/src/fsharp/FSharp.DependencyManager.Paket/FSharp.DependencyManager.Paket.fsproj b/src/fsharp/FSharp.DependencyManager.Paket/FSharp.DependencyManager.Paket.fsproj index 5709a346d56..fca194dbc71 100644 --- a/src/fsharp/FSharp.DependencyManager.Paket/FSharp.DependencyManager.Paket.fsproj +++ b/src/fsharp/FSharp.DependencyManager.Paket/FSharp.DependencyManager.Paket.fsproj @@ -1,4 +1,4 @@ - + @@ -50,6 +50,9 @@ + + + {DED3BBD7-53F4-428A-8C9F-27968E768605} diff --git a/src/fsharp/FSharp.DependencyManager.Paket/project.json b/src/fsharp/FSharp.DependencyManager.Paket/project.json new file mode 100644 index 00000000000..c50e8438f9d --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager.Paket/project.json @@ -0,0 +1,36 @@ +{ + "dependencies": { + "NETStandard.Library": "1.6.1", + "System.Collections.Immutable":"1.2.0", + "System.Diagnostics.Process": "4.3.0", + "System.Diagnostics.TraceSource": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Linq.Queryable": "4.3.0", + "System.Net.Requests": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Metadata": "1.4.2", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Loader": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Threading.Tasks.Parallel": "4.3.0", + "System.Threading.Thread": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "Microsoft.DiaSymReader.PortablePdb": "1.1.0", + "Microsoft.DiaSymReader": "1.1.0", + "System.ValueTuple": "4.3.1" + }, + "runtimes": { + "win7-x86": { }, + "win7-x64": { }, + "osx.10.11-x64": { }, + "ubuntu.14.04-x64": { } + }, + "frameworks": { + "netstandard1.6": { + "imports": "portable-net45+win8" + } + } +} + From 1bac5ba9a1823f78d32bab8802ed9247fb116a1c Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 28 Jun 2017 12:05:25 +0200 Subject: [PATCH 25/38] Do what enrico says --- src/fsharp/FSharp.DependencyManager.Paket/project.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fsharp/FSharp.DependencyManager.Paket/project.json b/src/fsharp/FSharp.DependencyManager.Paket/project.json index c50e8438f9d..d9581a10443 100644 --- a/src/fsharp/FSharp.DependencyManager.Paket/project.json +++ b/src/fsharp/FSharp.DependencyManager.Paket/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", From 9113f3394841faac1d81fdbde6b70042eb7560d7 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 28 Jun 2017 16:25:51 +0200 Subject: [PATCH 26/38] Revert "Dedupe module names in fsi" This reverts commit fc1d4b4ec32e56889b9ce60950493c4d137933f8. --- src/fsharp/CompileOps.fs | 8 ++++---- src/fsharp/fsi/fsi.fs | 9 +-------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index da081a4ff7e..439cd98b22e 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -5080,8 +5080,8 @@ module ScriptPreprocessClosure = | _ -> closureFiles // Get all source files. - let sourceFiles = [ for (ClosureFile(filename,m,_,_,_,_)) in closureFiles -> (filename,m) ] - let sourceInputs = [ for (ClosureFile(filename,_,input,parseDiagnostics,metaDiagnostics,_nowarns)) in closureFiles -> ({ FileName=filename; SyntaxTree=input; ParseDiagnostics=parseDiagnostics; MetaCommandDiagnostics=metaDiagnostics }: LoadClosureInput) ] + let sourceFiles = [ for (ClosureFile(filename,m,_,_,_,_)) in closureFiles -> (filename,m) ] + let sourceInputs = [ for (ClosureFile(filename,_,input,parseDiagnostics,metaDiagnostics,_nowarns)) in closureFiles -> ({ FileName=filename; SyntaxTree=input; ParseDiagnostics=parseDiagnostics; MetaCommandDiagnostics=metaDiagnostics }: LoadClosureInput) ] let globalNoWarns = closureFiles |> List.collect (fun (ClosureFile(_,_,_,_,_,noWarns)) -> noWarns) // Resolve all references. @@ -5347,13 +5347,13 @@ let TypeCheckOneInputEventually // Check if we've already seen an implementation for this fragment if Zset.contains qualNameOfFile rootImpls then - errorR(Error(FSComp.SR.buildImplementationAlreadyGiven(qualNameOfFile.Text),m)) + errorR(Error(FSComp.SR.buildImplementationAlreadyGiven(qualNameOfFile.Text),m)) let tcImplEnv = tcState.tcsTcImplEnv // Typecheck the implementation file let! topAttrs, implFile, tcEnvAtEnd, createsGeneratedProvidedTypes = - TypeCheckOneImplFile (tcGlobals,tcState.tcsNiceNameGen,amap,tcState.tcsCcu,checkForErrors,tcConfig.conditionalCompilationDefines,tcSink) tcImplEnv rootSigOpt file + TypeCheckOneImplFile (tcGlobals,tcState.tcsNiceNameGen,amap,tcState.tcsCcu,checkForErrors,tcConfig.conditionalCompilationDefines,tcSink) tcImplEnv rootSigOpt file let hadSig = Option.isSome rootSigOpt let implFileSigType = SigTypeOfImplFile implFile diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 8004ff81daf..0854f76edae 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -1334,7 +1334,6 @@ type internal FsiDynamicCompiler member fsiDynamicCompiler.EvalSourceFiles(ctok, istate, m, sourceFiles, lexResourceManager, errorLogger: ErrorLogger) = let tcConfig = TcConfig.Create(tcConfigB,validate=false) - let moduleNamesDict = Dictionary>() match sourceFiles with | [] -> istate | _ -> @@ -1369,16 +1368,10 @@ type internal FsiDynamicCompiler input.FileName, parsedInput) |> List.unzip - - errorLogger.AbortOnError(fsiConsoleOutput) + errorLogger.AbortOnError(fsiConsoleOutput); if inputs |> List.exists Option.isNone then failwith "parse error" let inputs = List.map Option.get inputs let istate = (istate, sourceFiles, inputs) |||> List.fold2 (fun istate sourceFile input -> fsiDynamicCompiler.ProcessMetaCommandsFromInputAsInteractiveCommands(ctok, istate, sourceFile, input)) - - let inputs = - inputs - |> List.map (DeduplicateParsedInputModuleName moduleNamesDict) - fsiDynamicCompiler.EvalParsedSourceFiles (ctok, errorLogger, istate, inputs) From 4bf8512658dea7cd4a2e16ec851b194a1f47fd0b Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 28 Jun 2017 16:35:13 +0200 Subject: [PATCH 27/38] cleanup --- src/fsharp/DependencyManager.Integration.fs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs index 51a9d5b0385..27b6a22a141 100644 --- a/src/fsharp/DependencyManager.Integration.fs +++ b/src/fsharp/DependencyManager.Integration.fs @@ -104,16 +104,14 @@ type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyIn member __.Dispose () = instance.Dispose() -let assemblySearchPaths = - lazy( - [let assemblyLocation = typeof.Assembly.Location - yield Path.GetDirectoryName assemblyLocation - let executingAssembly = Assembly.GetExecutingAssembly().Location - yield Path.GetDirectoryName executingAssembly - let baseDir = AppDomain.CurrentDomain.BaseDirectory - yield baseDir ] - |> List.distinct - ) +let assemblySearchPaths = lazy( + [ let assemblyLocation = typeof.Assembly.Location + yield Path.GetDirectoryName assemblyLocation + let executingAssembly = Assembly.GetExecutingAssembly().Location + yield Path.GetDirectoryName executingAssembly + let baseDir = AppDomain.CurrentDomain.BaseDirectory + yield baseDir ] + |> List.distinct) let enumerateDependencyManagerAssembliesFromCurrentAssemblyLocation () = assemblySearchPaths.Force() From 85f40ce7bc8bbe24aec20e3837406a759005b656 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 28 Jun 2017 16:35:26 +0200 Subject: [PATCH 28/38] Do what enrico says --- src/fsharp/FSharp.Compiler.Private/project.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fsharp/FSharp.Compiler.Private/project.json b/src/fsharp/FSharp.Compiler.Private/project.json index c50e8438f9d..d9581a10443 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", From 8d93812e942a938a732b339737a4916136ca761d Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 28 Jun 2017 16:44:19 +0200 Subject: [PATCH 29/38] cleanup --- .../FSharp.DependencyManager.Paket/PaketDependencyManager.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fs b/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fs index ca674e807bc..20226891fd4 100644 --- a/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fs +++ b/src/fsharp/FSharp.DependencyManager.Paket/PaketDependencyManager.fs @@ -1,8 +1,8 @@ namespace Microsoft.FSharp.DependencyManager.Paket -// used as a marker that compiler scans for, although there is no hard dependency, filtered by name +/// Used as a marker that compiler scans for, although there is no hard dependency, filtered by name. type FSharpDependencyManagerAttribute() = - inherit System.Attribute() + inherit System.Attribute() type [] PaketDependencyManager() = member __.Name = "Paket" From 62393b73a464b450a6166111a6e10941c47cf888 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 28 Jun 2017 16:47:47 +0200 Subject: [PATCH 30/38] Use the latest paket bootstrapper --- .../ReferenceLoading.PaketHandler.fs | 2 +- .../InteractiveSession/Paket/.paket/paket.exe | Bin 49664 -> 54272 bytes .../Paket/.paket/paket.exe.config | 6 ------ 3 files changed, 1 insertion(+), 7 deletions(-) delete mode 100644 tests/fsharpqa/Source/InteractiveSession/Paket/.paket/paket.exe.config diff --git a/src/fsharp/FSharp.DependencyManager.Paket/ReferenceLoading.PaketHandler.fs b/src/fsharp/FSharp.DependencyManager.Paket/ReferenceLoading.PaketHandler.fs index 222dec5b0af..b920ae69b61 100644 --- a/src/fsharp/FSharp.DependencyManager.Paket/ReferenceLoading.PaketHandler.fs +++ b/src/fsharp/FSharp.DependencyManager.Paket/ReferenceLoading.PaketHandler.fs @@ -2,7 +2,7 @@ // NOTE: this file is used by other parties integrating paket reference loading in scripting environments. // Do not add any reference to F# codebase other than FSharp.Core. -// This file should end up in paket repository instead of F#. +// This file should eventually end up in paket repository instead of F#. /// Paket invokation for In-Script reference loading module internal ReferenceLoading.PaketHandler diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/.paket/paket.exe b/tests/fsharpqa/Source/InteractiveSession/Paket/.paket/paket.exe index e24fa74fd060455605d91258d05eecb53f0cdf20..716fe25495b5362cc64d67449b76dc62ed0c1732 100644 GIT binary patch literal 54272 zcmc$H2Vh*q(f_{p?%oyYPP$W*s3Z2pS2Shv-YYzc*eW0mNY3xrsz8RE^C=52I(ds)

X46*f6Aqx5b?6*QCi#YykAy#l% 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 diff --git a/tests/fsharpqa/Source/InteractiveSession/Paket/.paket/paket.exe.config b/tests/fsharpqa/Source/InteractiveSession/Paket/.paket/paket.exe.config deleted file mode 100644 index 2fc733f95b1..00000000000 --- a/tests/fsharpqa/Source/InteractiveSession/Paket/.paket/paket.exe.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From c55762aecc058ddce58df9e6a7f94ac6b901321d Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Mon, 3 Jul 2017 09:10:44 +0200 Subject: [PATCH 31/38] Add files to FSharp.Compiler.Private.BuildFromSource.fsproj --- .../FSharp.Compiler.Private.BuildFromSource.fsproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.BuildFromSource.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.BuildFromSource.fsproj index eba37e12616..4e1e299ed38 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.BuildFromSource.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.BuildFromSource.fsproj @@ -450,6 +450,12 @@ CodeGen\IlxGen.fs + + Driver\DependencyManager.Integration.fsi + + + Driver\DependencyManager.Integration.fs + From 3d7b96812416f467d83cd1720552a50e46d90674 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Mon, 3 Jul 2017 09:11:31 +0200 Subject: [PATCH 32/38] Use FX_RESHAPED_REFLECTION --- src/fsharp/DependencyManager.Integration.fs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs index 27b6a22a141..2f6cf2f07fb 100644 --- a/src/fsharp/DependencyManager.Integration.fs +++ b/src/fsharp/DependencyManager.Integration.fs @@ -8,6 +8,11 @@ open System.Reflection open System.IO open Microsoft.FSharp.Compiler.ErrorLogger +#if FX_RESHAPED_REFLECTION + open PrimReflectionAdapters + open ReflectionAdapters +#endif + // 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 From 1ec3ffb03dfee97ade567a5e614b40af87ac6aff Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Mon, 3 Jul 2017 11:09:43 +0200 Subject: [PATCH 33/38] FX_RESHAPED_REFLECTION for build from source --- .../FSharp.Compiler.Private.BuildFromSource.fsproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.BuildFromSource.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.BuildFromSource.fsproj index 4e1e299ed38..ff221e4eae2 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.BuildFromSource.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.BuildFromSource.fsproj @@ -9,6 +9,7 @@ $(NoWarn);45;55;62;75;1204 true $(DefineConstants);EXTENSIONTYPING;COMPILER;BUILD_FROM_SOURCE + $(DefineConstants);FX_RESHAPED_REFLECTION $(OtherFlags) --warnon:1182 --maxerrors:20 --extraoptimizationloops:1 From a43de7e100b89e0403beee929705e1f3e6710cf7 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Mon, 3 Jul 2017 12:04:12 +0200 Subject: [PATCH 34/38] FX_RESHAPED_REFLECTION for build from source --- .../FSharp.Compiler.Private.BuildFromSource.fsproj | 1 + .../FSharp.Compiler.Private.netcore.nuspec | 1 + 2 files changed, 2 insertions(+) diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.BuildFromSource.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.BuildFromSource.fsproj index ff221e4eae2..ec3016511f7 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.BuildFromSource.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.BuildFromSource.fsproj @@ -638,6 +638,7 @@ + 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 8dfb2b6c252..f0c250998db 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 @@ + From f5f2cc74168258786a5eff0311a9a71404813f56 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 4 Jul 2017 09:13:33 +0200 Subject: [PATCH 35/38] work around FX_RESHAPED_REFLECTION --- src/fsharp/DependencyManager.Integration.fs | 7 ++++++- .../FSharp.Compiler.Private.BuildFromSource.fsproj | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs index 2f6cf2f07fb..b9dddd21814 100644 --- a/src/fsharp/DependencyManager.Integration.fs +++ b/src/fsharp/DependencyManager.Integration.fs @@ -112,7 +112,12 @@ type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyIn let assemblySearchPaths = lazy( [ let assemblyLocation = typeof.Assembly.Location yield Path.GetDirectoryName assemblyLocation - let executingAssembly = Assembly.GetExecutingAssembly().Location + let executingAssembly = +#if FX_RESHAPED_REFLECTION + typeof.GetTypeInfo().Assembly +#else + Assembly.GetExecutingAssembly().Location +#endif yield Path.GetDirectoryName executingAssembly let baseDir = AppDomain.CurrentDomain.BaseDirectory yield baseDir ] diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.BuildFromSource.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.BuildFromSource.fsproj index ec3016511f7..d58cdd045a6 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.BuildFromSource.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.BuildFromSource.fsproj @@ -8,8 +8,7 @@ FSharp.Compiler.Private $(NoWarn);45;55;62;75;1204 true - $(DefineConstants);EXTENSIONTYPING;COMPILER;BUILD_FROM_SOURCE - $(DefineConstants);FX_RESHAPED_REFLECTION + $(DefineConstants);EXTENSIONTYPING;COMPILER;BUILD_FROM_SOURCE;FX_RESHAPED_REFLECTION $(OtherFlags) --warnon:1182 --maxerrors:20 --extraoptimizationloops:1 @@ -616,6 +615,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", From 7890fac270f871b446d540bb4fcfcbfb42d8d8a0 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 4 Jul 2017 09:49:53 +0200 Subject: [PATCH 36/38] FX_RESHAPED_REFLECTION --- src/fsharp/DependencyManager.Integration.fs | 25 +++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs index b9dddd21814..a55d2c4596f 100644 --- a/src/fsharp/DependencyManager.Integration.fs +++ b/src/fsharp/DependencyManager.Integration.fs @@ -23,7 +23,11 @@ let targetFramework = "net461" module ReflectionHelper = let assemblyHasAttribute (theAssembly: Assembly) attributeName = try +#if FX_RESHAPED_REFLECTION + theAssembly.GetTypeInfo().GetCustomAttributes false +#else theAssembly.GetCustomAttributes false +#endif |> Seq.tryFind (fun a -> a.GetType().Name = attributeName) |> function | Some _ -> true | _ -> false with | _ -> false @@ -110,23 +114,36 @@ type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyIn let assemblySearchPaths = lazy( - [ let assemblyLocation = typeof.Assembly.Location + [ let assemblyLocation = +#if FX_RESHAPED_REFLECTION + typeof.GetTypeInfo().Assembly.Location +#else + typeof.Assembly.Location +#endif yield Path.GetDirectoryName assemblyLocation let executingAssembly = #if FX_RESHAPED_REFLECTION - typeof.GetTypeInfo().Assembly + typeof.GetTypeInfo().Assembly #else Assembly.GetExecutingAssembly().Location #endif yield Path.GetDirectoryName executingAssembly +#if FX_NO_APP_DOMAINS +#else let baseDir = AppDomain.CurrentDomain.BaseDirectory - yield baseDir ] + yield baseDir +#endif + ] |> List.distinct) let enumerateDependencyManagerAssembliesFromCurrentAssemblyLocation () = assemblySearchPaths.Force() |> Seq.collect (fun path -> Directory.EnumerateFiles(path,"*DependencyManager*.dll")) - |> Seq.choose (fun path -> try Assembly.LoadFrom path |> Some with | _ -> None) + |> Seq.choose (fun path -> + try + Some(AbstractIL.Internal.Library.Shim.FileSystem.AssemblyLoadFrom path) + with + | _ -> None) |> Seq.filter (fun a -> ReflectionHelper.assemblyHasAttribute a "FSharpDependencyManagerAttribute") type ProjectDependencyManager() = From 078962544060102ed147b76fb8c317c145a3ffbd Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 4 Jul 2017 10:15:12 +0200 Subject: [PATCH 37/38] FX_RESHAPED_REFLECTION --- src/fsharp/DependencyManager.Integration.fs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs index a55d2c4596f..466027c4d0b 100644 --- a/src/fsharp/DependencyManager.Integration.fs +++ b/src/fsharp/DependencyManager.Integration.fs @@ -23,18 +23,18 @@ let targetFramework = "net461" module ReflectionHelper = let assemblyHasAttribute (theAssembly: Assembly) attributeName = try -#if FX_RESHAPED_REFLECTION - theAssembly.GetTypeInfo().GetCustomAttributes false -#else - theAssembly.GetCustomAttributes false -#endif + CustomAttributeExtensions.GetCustomAttributes(theAssembly) |> Seq.tryFind (fun a -> a.GetType().Name = attributeName) |> function | Some _ -> true | _ -> false with | _ -> false let getAttributeNamed (theType: Type) attributeName = try +#if FX_RESHAPED_REFLECTION + theType.GetTypeInfo().GetCustomAttributes false +#else theType.GetCustomAttributes false +#endif |> Seq.tryFind (fun a -> a.GetType().Name = attributeName) with | _ -> None @@ -125,9 +125,9 @@ let assemblySearchPaths = lazy( #if FX_RESHAPED_REFLECTION typeof.GetTypeInfo().Assembly #else - Assembly.GetExecutingAssembly().Location + Assembly.GetExecutingAssembly() #endif - yield Path.GetDirectoryName executingAssembly + yield Path.GetDirectoryName(executingAssembly.Location) #if FX_NO_APP_DOMAINS #else let baseDir = AppDomain.CurrentDomain.BaseDirectory From f19544219a5a4a6ffee4d4a84a66303c396d080a Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 4 Jul 2017 13:31:46 +0200 Subject: [PATCH 38/38] Give warning if we can not load an extension --- src/fsharp/DependencyManager.Integration.fs | 48 +++++++++++--------- src/fsharp/DependencyManager.Integration.fsi | 3 -- src/fsharp/FSComp.txt | 1 + 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs index 466027c4d0b..dfaab7d560b 100644 --- a/src/fsharp/DependencyManager.Integration.fs +++ b/src/fsharp/DependencyManager.Integration.fs @@ -136,14 +136,16 @@ let assemblySearchPaths = lazy( ] |> List.distinct) -let enumerateDependencyManagerAssembliesFromCurrentAssemblyLocation () = +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 - | _ -> None) + | exn -> + warning(Error(FSComp.SR.couldNotLoadDependencyManagerExtenstion(path,exn.Message),m)) + None) |> Seq.filter (fun a -> ReflectionHelper.assemblyHasAttribute a "FSharpDependencyManagerAttribute") type ProjectDependencyManager() = @@ -179,35 +181,37 @@ type ImplDependencyManager() = interface System.IDisposable with member __.Dispose() = () -let registeredDependencyManagers = lazy ( - let defaultProviders = - [new ProjectDependencyManager() :> IDependencyManagerProvider - new RefDependencyManager() :> IDependencyManagerProvider - new ImplDependencyManager() :> IDependencyManagerProvider] +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() - |> Seq.collect (fun a -> a.GetTypes()) - |> Seq.choose ReflectionDependencyManagerProvider.InstanceMaker - |> Seq.map (fun maker -> maker ()) + 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 RegisteredDependencyManagers() = registeredDependencyManagers.Force() + defaultProviders + |> Seq.append loadedProviders + |> Seq.map (fun pm -> pm.Key, pm) + |> Map.ofSeq let createPackageManagerUnknownError packageManagerKey m = - let registeredKeys = String.Join(", ", RegisteredDependencyManagers() |> Seq.map (fun kv -> kv.Value.Key)) + 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() + let managers = RegisteredDependencyManagers m match managers |> Seq.tryFind (fun kv -> path.StartsWith(kv.Value.Key + ":" )) with | None -> errorR(createPackageManagerUnknownError (path.Split(':').[0]) m) @@ -224,7 +228,7 @@ let removeDependencyManagerKey (packageManagerKey:string) (path:string) = path.S let tryFindDependencyManagerByKey m (key:string) : IDependencyManagerProvider option = try - RegisteredDependencyManagers() |> Map.tryFind key + RegisteredDependencyManagers m |> Map.tryFind key with | e -> errorR(Error(FSComp.SR.packageManagerError(e.Message),m)) diff --git a/src/fsharp/DependencyManager.Integration.fsi b/src/fsharp/DependencyManager.Integration.fsi index 7b4de99296a..bde6e9c705f 100644 --- a/src/fsharp/DependencyManager.Integration.fsi +++ b/src/fsharp/DependencyManager.Integration.fsi @@ -18,12 +18,9 @@ type ReferenceType = | Library of string | UnknownType -val RegisteredDependencyManagers : unit -> Map 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 be9fbebaee2..cc3dae243ae 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1422,3 +1422,4 @@ notAFunctionButMaybeIndexerWithName,"This value is not a function and cannot be notAFunctionButMaybeIndexer,"This expression is not a function and cannot be applied. Did you intend to access the indexer via expr.[index] instead?" 3217,notAFunctionButMaybeIndexerErrorCode,"" notAFunctionButMaybeDeclaration,"This value is not a function and cannot be applied. Did you forget to terminate a declaration?" +3218,couldNotLoadDependencyManagerExtenstion,"The dependency manager extension %s could not be loaded. Message: %s" \ No newline at end of file