diff --git a/.gitignore b/.gitignore index ec2166b3fc3..f75c0e414fc 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,6 @@ artifacts/ # Patches that may have been generated by scripts. # (These aren't generally useful to commit directly; if anything, they should be applied.) scripts/*.patch - /fcs/FSharp.Compiler.Service/illex.fs /fcs/FSharp.Compiler.Service/ilpars.fs /fcs/FSharp.Compiler.Service/ilpars.fsi diff --git a/FSharp.sln b/FSharp.sln index 9b650e008ce..1f83d5a6394 100644 --- a/FSharp.sln +++ b/FSharp.sln @@ -5,18 +5,25 @@ VisualStudioVersion = 16.0.28729.10 MinimumVisualStudioVersion = 10.0.40219.1 Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Private", "src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj", "{2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}" EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Server.Shared", "src\fsharp\FSharp.Compiler.Server.Shared\FSharp.Compiler.Server.Shared.fsproj", "{D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}" +EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Core", "src\fsharp\FSharp.Core\FSharp.Core.fsproj", "{DED3BBD7-53F4-428A-8C9F-27968E768605}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{CFE3259A-2D30-4EB0-80D5-E8B5F3D01449}" EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Build", "src\fsharp\FSharp.Build\FSharp.Build.fsproj", "{702A7979-BCF9-4C41-853E-3ADFC9897890}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "fsc", "src\fsharp\fsc\fsc.fsproj", "{C94C257C-3C0A-4858-B5D8-D746498D1F08}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Fsc", "src\fsharp\fsc\fsc.fsproj", "{C94C257C-3C0A-4858-B5D8-D746498D1F08}" EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Interactive.Settings", "src\fsharp\FSharp.Compiler.Interactive.Settings\FSharp.Compiler.Interactive.Settings.fsproj", "{649FA588-F02E-457C-9FCF-87E46407481E}" EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "fsi", "src\fsharp\fsi\fsi.fsproj", "{D0E98C0D-490B-4C61-9329-0862F6E87645}" EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsiAnyCpu", "src\fsharp\fsiAnyCpu\fsiAnyCpu.fsproj", "{8B3E283D-B5FE-4055-9D80-7E3A32F3967B}" + ProjectSection(ProjectDependencies) = postProject + {649FA588-F02E-457C-9FCF-87E46407481E} = {649FA588-F02E-457C-9FCF-87E46407481E} + EndProjectSection +EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharpSuite.Tests", "tests\fsharp\FSharpSuite.Tests.fsproj", "{C163E892-5BF7-4B59-AA99-B0E8079C67C4}" EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.UnitTests", "tests\FSharp.Compiler.UnitTests\FSharp.Compiler.UnitTests.fsproj", "{A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}" @@ -39,6 +46,8 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.LanguageSer EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.LanguageServer.UnitTests", "tests\FSharp.Compiler.LanguageServer.UnitTests\FSharp.Compiler.LanguageServer.UnitTests.fsproj", "{C97819B0-B428-4B96-9CD7-497D2D1C738C}" EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.DependencyManager", "src\fsharp\FSharp.DependencyManager\FSharp.DependencyManager.fsproj", "{8B7BF62E-7D8C-4928-BE40-4E392A9EE851}" +EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Private.Scripting", "src\fsharp\FSharp.Compiler.Private.Scripting\FSharp.Compiler.Private.Scripting.fsproj", "{6771860A-614D-4FDD-A655-4C70EBCC91B0}" EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Private.Scripting.UnitTests", "tests\FSharp.Compiler.Private.Scripting.UnitTests\FSharp.Compiler.Private.Scripting.UnitTests.fsproj", "{4FEDF286-0252-4EBC-9E75-879CCA3B85DC}" @@ -65,6 +74,18 @@ Global {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Release|Any CPU.Build.0 = Release|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Release|x86.ActiveCfg = Release|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Release|x86.Build.0 = Release|Any CPU + {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Debug|x86.ActiveCfg = Debug|Any CPU + {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Debug|x86.Build.0 = Debug|Any CPU + {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Proto|Any CPU.ActiveCfg = Release|Any CPU + {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Proto|Any CPU.Build.0 = Release|Any CPU + {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Proto|x86.ActiveCfg = Release|Any CPU + {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Proto|x86.Build.0 = Release|Any CPU + {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Release|Any CPU.Build.0 = Release|Any CPU + {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Release|x86.ActiveCfg = Release|Any CPU + {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Release|x86.Build.0 = Release|Any CPU {DED3BBD7-53F4-428A-8C9F-27968E768605}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DED3BBD7-53F4-428A-8C9F-27968E768605}.Debug|Any CPU.Build.0 = Debug|Any CPU {DED3BBD7-53F4-428A-8C9F-27968E768605}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -125,6 +146,18 @@ Global {D0E98C0D-490B-4C61-9329-0862F6E87645}.Release|Any CPU.Build.0 = Release|Any CPU {D0E98C0D-490B-4C61-9329-0862F6E87645}.Release|x86.ActiveCfg = Release|Any CPU {D0E98C0D-490B-4C61-9329-0862F6E87645}.Release|x86.Build.0 = Release|Any CPU + {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Debug|x86.ActiveCfg = Debug|Any CPU + {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Debug|x86.Build.0 = Debug|Any CPU + {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Proto|Any CPU.ActiveCfg = Release|Any CPU + {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Proto|Any CPU.Build.0 = Release|Any CPU + {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Proto|x86.ActiveCfg = Release|Any CPU + {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Proto|x86.Build.0 = Release|Any CPU + {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Release|Any CPU.Build.0 = Release|Any CPU + {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Release|x86.ActiveCfg = Release|Any CPU + {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Release|x86.Build.0 = Release|Any CPU {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Debug|Any CPU.Build.0 = Debug|Any CPU {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -233,6 +266,18 @@ Global {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Release|Any CPU.Build.0 = Release|Any CPU {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Release|x86.ActiveCfg = Release|Any CPU {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Release|x86.Build.0 = Release|Any CPU + {8B7BF62E-7D8C-4928-BE40-4E392A9EE851}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8B7BF62E-7D8C-4928-BE40-4E392A9EE851}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8B7BF62E-7D8C-4928-BE40-4E392A9EE851}.Debug|x86.ActiveCfg = Debug|Any CPU + {8B7BF62E-7D8C-4928-BE40-4E392A9EE851}.Debug|x86.Build.0 = Debug|Any CPU + {8B7BF62E-7D8C-4928-BE40-4E392A9EE851}.Proto|Any CPU.ActiveCfg = Release|Any CPU + {8B7BF62E-7D8C-4928-BE40-4E392A9EE851}.Proto|Any CPU.Build.0 = Release|Any CPU + {8B7BF62E-7D8C-4928-BE40-4E392A9EE851}.Proto|x86.ActiveCfg = Release|Any CPU + {8B7BF62E-7D8C-4928-BE40-4E392A9EE851}.Proto|x86.Build.0 = Release|Any CPU + {8B7BF62E-7D8C-4928-BE40-4E392A9EE851}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8B7BF62E-7D8C-4928-BE40-4E392A9EE851}.Release|Any CPU.Build.0 = Release|Any CPU + {8B7BF62E-7D8C-4928-BE40-4E392A9EE851}.Release|x86.ActiveCfg = Release|Any CPU + {8B7BF62E-7D8C-4928-BE40-4E392A9EE851}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -244,6 +289,7 @@ Global {C94C257C-3C0A-4858-B5D8-D746498D1F08} = {3881429D-A97A-49EB-B7AE-A82BA5FE9C77} {649FA588-F02E-457C-9FCF-87E46407481E} = {B8DDA694-7939-42E3-95E5-265C2217C142} {D0E98C0D-490B-4C61-9329-0862F6E87645} = {B8DDA694-7939-42E3-95E5-265C2217C142} + {8B3E283D-B5FE-4055-9D80-7E3A32F3967B} = {B8DDA694-7939-42E3-95E5-265C2217C142} {C163E892-5BF7-4B59-AA99-B0E8079C67C4} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} {88E2D422-6852-46E3-A740-83E391DC7973} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} @@ -253,6 +299,7 @@ Global {C97819B0-B428-4B96-9CD7-497D2D1C738C} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} {6771860A-614D-4FDD-A655-4C70EBCC91B0} = {B8DDA694-7939-42E3-95E5-265C2217C142} {4FEDF286-0252-4EBC-9E75-879CCA3B85DC} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} + {8B7BF62E-7D8C-4928-BE40-4E392A9EE851} = {3881429D-A97A-49EB-B7AE-A82BA5FE9C77} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BD5177C7-1380-40E7-94D2-7768E1A8B1B8} diff --git a/FSharpTests.Directory.Build.targets b/FSharpTests.Directory.Build.targets index 8ae8c562556..3768b5c726d 100644 --- a/FSharpTests.Directory.Build.targets +++ b/FSharpTests.Directory.Build.targets @@ -1,6 +1,6 @@ - + - - <_CoreCompileResourceInputs Remove="@(_CoreCompileResourceInputs)" /> - - + + <_CoreCompileResourceInputs Remove="@(_CoreCompileResourceInputs)" /> + + diff --git a/VisualFSharp.sln b/VisualFSharp.sln index 2c0ef9ad73c..f2e9539283c 100644 --- a/VisualFSharp.sln +++ b/VisualFSharp.sln @@ -154,6 +154,8 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Private.Scr EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Private.Scripting.UnitTests", "tests\FSharp.Compiler.Private.Scripting.UnitTests\FSharp.Compiler.Private.Scripting.UnitTests.fsproj", "{09F56540-AFA5-4694-B7A6-0DBF6D4618C2}" EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.DependencyManager", "src\fsharp\FSharp.DependencyManager\FSharp.DependencyManager.fsproj", "{DFA30881-C0B1-4813-B087-C21B5AF9B77F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -896,6 +898,18 @@ Global {09F56540-AFA5-4694-B7A6-0DBF6D4618C2}.Release|Any CPU.Build.0 = Release|Any CPU {09F56540-AFA5-4694-B7A6-0DBF6D4618C2}.Release|x86.ActiveCfg = Release|Any CPU {09F56540-AFA5-4694-B7A6-0DBF6D4618C2}.Release|x86.Build.0 = Release|Any CPU + {DFA30881-C0B1-4813-B087-C21B5AF9B77F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DFA30881-C0B1-4813-B087-C21B5AF9B77F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DFA30881-C0B1-4813-B087-C21B5AF9B77F}.Debug|x86.ActiveCfg = Debug|Any CPU + {DFA30881-C0B1-4813-B087-C21B5AF9B77F}.Debug|x86.Build.0 = Debug|Any CPU + {DFA30881-C0B1-4813-B087-C21B5AF9B77F}.Proto|Any CPU.ActiveCfg = Debug|Any CPU + {DFA30881-C0B1-4813-B087-C21B5AF9B77F}.Proto|Any CPU.Build.0 = Debug|Any CPU + {DFA30881-C0B1-4813-B087-C21B5AF9B77F}.Proto|x86.ActiveCfg = Debug|Any CPU + {DFA30881-C0B1-4813-B087-C21B5AF9B77F}.Proto|x86.Build.0 = Debug|Any CPU + {DFA30881-C0B1-4813-B087-C21B5AF9B77F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DFA30881-C0B1-4813-B087-C21B5AF9B77F}.Release|Any CPU.Build.0 = Release|Any CPU + {DFA30881-C0B1-4813-B087-C21B5AF9B77F}.Release|x86.ActiveCfg = Release|Any CPU + {DFA30881-C0B1-4813-B087-C21B5AF9B77F}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -968,6 +982,7 @@ Global {79255A92-ED00-40BA-9D64-12FCC664A976} = {4C7B48D7-19AF-4AE7-9D1D-3BB289D5480D} {20B7BC36-CF51-4D75-9E13-66681C07977F} = {B8DDA694-7939-42E3-95E5-265C2217C142} {09F56540-AFA5-4694-B7A6-0DBF6D4618C2} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} + {DFA30881-C0B1-4813-B087-C21B5AF9B77F} = {3881429D-A97A-49EB-B7AE-A82BA5FE9C77} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {48EDBBBE-C8EE-4E3C-8B19-97184A487B37} diff --git a/eng/Versions.props b/eng/Versions.props index ba8c539aa9c..9737ac95daa 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -68,6 +68,7 @@ 1.5.0 4.3.0 + 4.3.0 4.0.0 4.3.0 4.3.0 @@ -88,6 +89,7 @@ 4.3.0 4.3.0 4.3.0 + 4.6.0 4.3.0 4.3.0 4.3.0 @@ -107,6 +109,8 @@ $(MicrosoftBuildOverallPackagesVersion) $(MicrosoftBuildOverallPackagesVersion) $(MicrosoftBuildOverallPackagesVersion) + 2.1.0 + 2.1.0 8.0.1 14.0.25420 diff --git a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index 04389899a26..50a3077291e 100644 --- a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -1,4 +1,5 @@ - + + @@ -517,6 +518,12 @@ Driver\DotNetFrameworkDependencies.fs + + Driver/DependencyManager.Integration.fsi + + + Driver/DependencyManager.Integration.fs + Driver/CompileOps.fsi diff --git a/fcs/samples/FscExe/FscMain.fs b/fcs/samples/FscExe/FscMain.fs index 26f26be63d1..7531ae9f3bd 100644 --- a/fcs/samples/FscExe/FscMain.fs +++ b/fcs/samples/FscExe/FscMain.fs @@ -266,10 +266,6 @@ module Driver = if runningOnMono && hasArgument "resident" argv then let argv = stripArgument "resident" argv - //if not (hasArgument "nologo" argv) then - // printfn "%s" (FSComp.SR.buildProductName(FSharpEnvironment.FSharpTeamVersionNumber)) - // printfn "%s" (FSComp.SR.optsCopyright()) - let fscServerExe = typeof.Assembly.Location let exitCodeOpt = FSharpResidentCompiler.FSharpCompilationServer.TryCompileUsingServer (fscServerExe, argv) match exitCodeOpt with diff --git a/scripts/dotnet-install.ps1 b/scripts/dotnet-install.ps1 index 9da0947d958..3dc96520540 100644 --- a/scripts/dotnet-install.ps1 +++ b/scripts/dotnet-install.ps1 @@ -188,7 +188,7 @@ function GetHTTPResponse([Uri] $Uri) } # Default timeout for HttpClient is 100s. For a 50 MB download this assumes 500 KB/s average, any less will time out # 10 minutes allows it to work over much slower connections. - $HttpClient.Timeout = New-TimeSpan -Minutes 20 + $HttpClient.Timeout = New-TimeSpan -Minutes 40 $Response = $HttpClient.GetAsync($Uri).Result if (($Response -eq $null) -or (-not ($Response.IsSuccessStatusCode))) { diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 1360e97e938..fb7d4ad4280 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -73,7 +73,6 @@ let FSharpScriptFileSuffixes = [".fsscript";".fsx"] let doNotRequireNamespaceOrModuleSuffixes = [".mli";".ml"] @ FSharpScriptFileSuffixes let FSharpLightSyntaxFileSuffixes: string list = [ ".fs";".fsscript";".fsx";".fsi" ] - //---------------------------------------------------------------------------- // ERROR REPORTING //-------------------------------------------------------------------------- @@ -2025,8 +2024,10 @@ 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 compilerToolPaths: string list mutable referencedDLLs: AssemblyReference list + mutable packageManagerLines: Map mutable projectReferences: IProjectReference list mutable knownUnresolvedReferences: UnresolvedAssemblyReference list reduceMemoryUsage: ReduceMemoryFlag @@ -2038,6 +2039,7 @@ type TcConfigBuilder = mutable mlCompatibility: bool mutable checkOverflow: bool mutable showReferenceResolutions: bool + mutable outputDir : string option mutable outputFile: string option mutable platform: ILPlatform option mutable prefer32Bit: bool @@ -2187,7 +2189,9 @@ type TcConfigBuilder = resolutionEnvironment = ResolutionEnvironment.EditingOrCompilation false framework = true implicitlyResolveAssemblies = true + compilerToolPaths = [] referencedDLLs = [] + packageManagerLines = Map.empty projectReferences = [] knownUnresolvedReferences = [] loadedSources = [] @@ -2200,6 +2204,7 @@ type TcConfigBuilder = mlCompatibility = false checkOverflow = false showReferenceResolutions = false + outputDir = None outputFile = None platform = None prefer32Bit = false @@ -2399,18 +2404,19 @@ type TcConfigBuilder = if ok && not (List.contains absolutePath tcConfigB.includes) then tcConfigB.includes <- tcConfigB.includes ++ absolutePath - member tcConfigB.AddLoadedSource(m, path, pathLoadedFrom) = - if FileSystem.IsInvalidPathShim path then - warning(Error(FSComp.SR.buildInvalidFilename path, m)) + member tcConfigB.AddLoadedSource(m, originalPath, pathLoadedFrom) = + if FileSystem.IsInvalidPathShim originalPath then + warning(Error(FSComp.SR.buildInvalidFilename originalPath, m)) else let path = - match TryResolveFileUsingPaths(tcConfigB.includes @ [pathLoadedFrom], m, path) with + match TryResolveFileUsingPaths(tcConfigB.includes @ [pathLoadedFrom], m, originalPath) with | Some path -> path | None -> - // File doesn't exist in the paths. Assume it will be in the load-ed from directory. - ComputeMakePathAbsolute pathLoadedFrom path - if not (List.contains path (List.map snd tcConfigB.loadedSources)) then - tcConfigB.loadedSources <- tcConfigB.loadedSources ++ (m, path) + // File doesn't exist in the paths. Assume it will be in the load-ed from directory. + ComputeMakePathAbsolute pathLoadedFrom originalPath + if not (List.contains path (List.map (fun (_, _, path) -> path) tcConfigB.loadedSources)) then + tcConfigB.loadedSources <- tcConfigB.loadedSources ++ (m, originalPath, path) + member tcConfigB.AddEmbeddedSourceFile (file) = tcConfigB.embedSourceList <- tcConfigB.embedSourceList ++ file @@ -2418,6 +2424,12 @@ type TcConfigBuilder = member tcConfigB.AddEmbeddedResource filename = tcConfigB.embedResources <- tcConfigB.embedResources ++ filename + member tcConfigB.AddCompilerToolsByPath (path) = + if not (tcConfigB.compilerToolPaths |> List.exists (fun text -> path = text)) then // NOTE: We keep same paths if range is different. + let compilerToolPath = tcConfigB.compilerToolPaths |> List.tryPick (fun text -> if text = path then Some text else None) + if compilerToolPath.IsNone then + tcConfigB.compilerToolPaths <- tcConfigB.compilerToolPaths ++ path + member tcConfigB.AddReferencedAssemblyByPath (m, path) = if FileSystem.IsInvalidPathShim path then warning(Error(FSComp.SR.buildInvalidAssemblyName(path), m)) @@ -2425,6 +2437,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 ++ (false, path, m)) tcConfigB.packageManagerLines + | _ -> tcConfigB.packageManagerLines <- Map.add packageManager.Key [false, path, m] tcConfigB.packageManagerLines + member tcConfigB.RemoveReferencedAssemblyByPath (m, path) = tcConfigB.referencedDLLs <- tcConfigB.referencedDLLs |> List.filter (fun ar -> not (Range.equals ar.Range m) || ar.Text <> path) @@ -2673,6 +2692,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = member x.light = data.light member x.conditionalCompilationDefines = data.conditionalCompilationDefines member x.loadedSources = data.loadedSources + member x.compilerToolPaths = data.compilerToolPaths member x.referencedDLLs = data.referencedDLLs member x.knownUnresolvedReferences = data.knownUnresolvedReferences member x.clrRoot = clrRootValue @@ -2685,6 +2705,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = member x.mlCompatibility = data.mlCompatibility member x.checkOverflow = data.checkOverflow member x.showReferenceResolutions = data.showReferenceResolutions + member x.outputDir = data.outputDir member x.outputFile = data.outputFile member x.platform = data.platform member x.prefer32Bit = data.prefer32Bit @@ -2725,6 +2746,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 @@ -2868,13 +2890,23 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = member tcConfig.GetAvailableLoadedSources() = use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parameter - let resolveLoadedSource (m, path) = + let resolveLoadedSource (m, originalPath, path) = try - if not(FileSystem.SafeExists path) then - error(LoadedSourceNotFoundIgnoring(path, m)) - None - else Some(m, path) + if not(FileSystem.SafeExists(path)) then + 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 @@ -3126,8 +3158,8 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = else resultingResolutions, unresolvedReferences |> List.map (fun (name, _, r) -> (name, r)) |> List.map UnresolvedAssemblyReference - member tcConfig.PrimaryAssemblyDllReference() = primaryAssemblyReference + member tcConfig.CoreLibraryDllReference() = fslibReference @@ -4249,11 +4281,18 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse tcImportsStrong.AttachDisposeTypeProviderAction(fun () -> systemRuntimeContainsTypeRef := (fun _ -> raise (System.ObjectDisposedException("The type provider has been disposed")))) fun arg -> systemRuntimeContainsTypeRef.Value arg - let providers = - [ for designTimeAssemblyName in designTimeAssemblyNames do - yield! ExtensionTyping.GetTypeProvidersOfAssembly(fileNameOfRuntimeAssembly, ilScopeRefOfRuntimeAssembly, designTimeAssemblyName, typeProviderEnvironment, - tcConfig.isInvalidationSupported, tcConfig.isInteractive, systemRuntimeContainsType, primaryAssemblyVersion, m) ] - + let providers = [ + for designTimeAssemblyName in designTimeAssemblyNames do + yield! ExtensionTyping.GetTypeProvidersOfAssembly(fileNameOfRuntimeAssembly, + ilScopeRefOfRuntimeAssembly, + designTimeAssemblyName, + typeProviderEnvironment, + tcConfig.isInvalidationSupported, + tcConfig.isInteractive, + systemRuntimeContainsType, + primaryAssemblyVersion, + tcConfig.compilerToolPaths, + m) ] // Note, type providers are disposable objects. The TcImports owns the provider objects - when/if it is disposed, the providers are disposed. // We ignore all exceptions from provider disposal. for provider in providers do @@ -4536,7 +4575,6 @@ and [] TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAsse member tcImports.RegisterAndImportReferencedAssemblies (ctok, nms: AssemblyResolution list) = cancellable { CheckDisposed() - let! results = nms |> Cancellable.each (fun nm -> cancellable { @@ -4794,14 +4832,13 @@ 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, - loadSourceF: 'state -> range * string -> unit) - (tcConfig: TcConfigBuilder, inp, pathOfMetaCommandSource, state0) = - +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) = + use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse let canHaveScriptMetaCommands = @@ -4824,18 +4861,34 @@ let ProcessMetaCommandsFromInput | _ -> errorR(Error(FSComp.SR.buildInvalidHashIDirective(), m)) state - | ParsedHashDirective("nowarn", numbers, m) -> - List.fold (fun state d -> nowarnF state (m, d)) state numbers - | ParsedHashDirective(("reference" | "r"), args, m) -> - if not canHaveScriptMetaCommands then + | 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 args with + | [path] -> + matchedm <- m + match DependencyManagerIntegration.tryFindDependencyManagerInPath tcConfig.compilerToolPaths tcConfig.outputDir m (path:string) with + | DependencyManagerIntegration.ReferenceType.RegisteredDependencyManager packageManager -> + if tcConfig.langVersion.SupportsFeature(LanguageFeature.PackageManagement) then + packageRequireF state (packageManager,m,path) + else + errorR(Error(FSComp.SR.packageManagementRequiresVFive(), m)) + state + + // #r "Assembly" + | DependencyManagerIntegration.ReferenceType.Library path -> + dllRequireF state (m,path) + + | DependencyManagerIntegration.ReferenceType.UnknownType -> + state // error already reported + | _ -> errorR(Error(FSComp.SR.buildInvalidHashrDirective(), m)) state + | ParsedHashDirective("load", args, m) -> if not canHaveScriptMetaCommands then errorR(HashDirectiveNotAllowedInNonScript m) @@ -4909,19 +4962,21 @@ let ProcessMetaCommandsFromInput let ApplyNoWarnsToTcConfig (tcConfig: TcConfig, inp: ParsedInput, pathOfMetaCommandSource) = // Clone let tcConfigB = tcConfig.CloneOfOriginalBuilder - let addNoWarn = fun () (m, s) -> tcConfigB.TurnWarningOff(m, s) - let addReferencedAssemblyByPath = fun () (_m, _s) -> () - let addLoadedSource = fun () (_m, _s) -> () - ProcessMetaCommandsFromInput (addNoWarn, addReferencedAssemblyByPath, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ()) + let addNoWarn = fun () (m,s) -> tcConfigB.TurnWarningOff(m, s) + let addReferencedAssemblyByPath = fun () (_m,_s) -> () + let addDependencyManagerText = fun () (_prefix,_m,_s) -> () + let addLoadedSource = fun () (_m,_s) -> () + ProcessMetaCommandsFromInput (addNoWarn, addReferencedAssemblyByPath, addDependencyManagerText, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ()) TcConfig.Create(tcConfigB, validate=false) let ApplyMetaCommandsFromInputToTcConfig (tcConfig: TcConfig, inp: ParsedInput, pathOfMetaCommandSource) = // Clone let tcConfigB = tcConfig.CloneOfOriginalBuilder let getWarningNumber = fun () _ -> () - let addReferencedAssemblyByPath = fun () (m, s) -> tcConfigB.AddReferencedAssemblyByPath(m, s) - let addLoadedSource = fun () (m, s) -> tcConfigB.AddLoadedSource(m, s, pathOfMetaCommandSource) - ProcessMetaCommandsFromInput (getWarningNumber, addReferencedAssemblyByPath, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ()) + let addReferencedAssemblyByPath = fun () (m,s) -> tcConfigB.AddReferencedAssemblyByPath(m,s) + let addDependencyManagerText = fun () (packageManager, m,s) -> tcConfigB.AddDependencyManagerText(packageManager,m,s) + let addLoadedSource = fun () (m,s) -> tcConfigB.AddLoadedSource(m,s,pathOfMetaCommandSource) + ProcessMetaCommandsFromInput (getWarningNumber, addReferencedAssemblyByPath, addDependencyManagerText, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ()) TcConfig.Create(tcConfigB, validate=false) //---------------------------------------------------------------------------- @@ -4933,7 +4988,6 @@ let GetAssemblyResolutionInformation(ctok, tcConfig: TcConfig) = let assemblyList = TcAssemblyResolutions.GetAllDllReferences tcConfig let resolutions = TcAssemblyResolutions.ResolveAssemblyReferences (ctok, tcConfig, assemblyList, []) resolutions.GetAssemblyResolutions(), resolutions.GetUnresolvedReferences() - [] type LoadClosureInput = @@ -4953,7 +5007,7 @@ type LoadClosure = /// The list of all sources in the closure with inputs when available Inputs: LoadClosureInput list /// The #load, including those that didn't resolve - OriginalLoadReferences: (range * string) list + OriginalLoadReferences: (range * string * string) list /// The #nowarns NoWarns: (string * range list) list /// Diagnostics seen while processing resolutions @@ -4969,9 +5023,9 @@ type CodeContext = | CompilationAndEvaluation // in fsi.exe | Compilation // in fsc.exe | Editing // in VS - -module private ScriptPreprocessClosure = + +module ScriptPreprocessClosure = open Internal.Utilities.Text.Lexing /// Represents an input to the closure finding process @@ -5069,11 +5123,12 @@ module private ScriptPreprocessClosure = let tcConfigB = tcConfig.CloneOfOriginalBuilder let nowarns = ref [] - let getWarningNumber = fun () (m, s) -> nowarns := (s, m) :: !nowarns - let addReferencedAssemblyByPath = fun () (m, s) -> tcConfigB.AddReferencedAssemblyByPath(m, s) - let addLoadedSource = fun () (m, s) -> tcConfigB.AddLoadedSource(m, s, pathOfMetaCommandSource) + let getWarningNumber = fun () (m,s) -> nowarns := (s,m) :: !nowarns + let addReferencedAssemblyByPath = fun () (m,s) -> tcConfigB.AddReferencedAssemblyByPath(m,s) + let addDependencyManagerText = fun () (packageManagerPrefix,m,s) -> tcConfigB.AddDependencyManagerText(packageManagerPrefix,m,s) + let addLoadedSource = fun () (m,s) -> tcConfigB.AddLoadedSource(m,s,pathOfMetaCommandSource) try - ProcessMetaCommandsFromInput (getWarningNumber, addReferencedAssemblyByPath, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ()) + ProcessMetaCommandsFromInput (getWarningNumber, addReferencedAssemblyByPath, addDependencyManagerText, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ()) with ReportedError _ -> // Recover by using whatever did end up in the tcConfig () @@ -5085,40 +5140,89 @@ 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, sourceText, 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 tcConfig.Value.compilerToolPaths tcConfig.Value.outputDir m packageManagerKey with + | None -> + errorR(DependencyManagerIntegration.createPackageManagerUnknownError tcConfig.Value.compilerToolPaths tcConfig.Value.outputDir packageManagerKey m) + | Some packageManager -> + let inline snd3 (_, b, _) = b + let packageManagerTextLines = packageManagerLines |> List.map snd3 + + match DependencyManagerIntegration.resolve packageManager tcConfig.Value.implicitIncludeDir mainFile scriptName m packageManagerTextLines with + | None -> () // error already reported + | Some (succeeded, generatedScripts, additionalIncludeFolders) -> //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + // This may incrementally update tcConfig too with new #r references + // New package text is ignored on this second phase + match succeeded with + | true -> + // Resolution produced no errors + if not (isNil additionalIncludeFolders) then + let tcConfigB = tcConfig.Value.CloneOfOriginalBuilder + for folder in additionalIncludeFolders do + tcConfigB.AddIncludePath(m, folder, "") + tcConfigB.packageManagerLines <- tcConfigB.packageManagerLines |> Map.map(fun _ l -> l |> List.map(fun (_, p, m) -> true, p, m)) + tcConfig := TcConfig.Create(tcConfigB, validate=false) + for script in generatedScripts do + let scriptText = File.ReadAllText script + loadScripts.Add script |> ignore + let iSourceText = SourceText.ofString scriptText + yield! loop (ClosureSource(script, m, iSourceText, true)) + | false -> + // Resolution produced errors update packagerManagerLines entries to note these failure + // failed resolutions will no longer be considered + let tcConfigB = tcConfig.Value.CloneOfOriginalBuilder + tcConfigB.packageManagerLines <- tcConfigB.packageManagerLines |> Map.map(fun _ l -> l |> List.filter(fun (tried, _, _) -> tried)) + tcConfig := TcConfig.Create(tcConfigB, validate=false)] + else [] + + and loop (ClosureSource(filename, m, sourceText, parseRequired)) = + [ if not (observedSources.HaveSeen(filename)) then observedSources.SetSeen(filename) //printfn "visiting %s" filename if IsScript filename || parseRequired then let parseResult, parseDiagnostics = - let errorLogger = CapturingErrorLogger("FindClosureParse") + let errorLogger = CapturingErrorLogger("FindClosureParse") use _unwindEL = PushErrorLoggerPhaseUntilUnwind (fun _ -> errorLogger) let result = ParseScriptText (filename, sourceText, !tcConfig, codeContext, lexResourceManager, errorLogger) result, errorLogger.Diagnostics match parseResult with - | Some parsedScriptAst -> - let errorLogger = CapturingErrorLogger("FindClosureMetaCommands") + | Some parsedScriptAst -> + let errorLogger = CapturingErrorLogger("FindClosureMetaCommands") use _unwindEL = PushErrorLoggerPhaseUntilUnwind (fun _ -> errorLogger) - let pathOfMetaCommandSource = Path.GetDirectoryName filename + let pathOfMetaCommandSource = Path.GetDirectoryName(filename) + let preSources = (!tcConfig).GetAvailableLoadedSources() let tcConfigResult, noWarns = ApplyMetaCommandsFromInputToTcConfigAndGatherNoWarn (!tcConfig, parsedScriptAst, pathOfMetaCommandSource) tcConfig := tcConfigResult // We accumulate the tcConfig in order to collect assembly references - + + yield! resolveDependencyManagerSources filename + let postSources = (!tcConfig).GetAvailableLoadedSources() let sources = if preSources.Length < postSources.Length then postSources.[preSources.Length..] else [] - //for (_, subFile) in sources do - // printfn "visiting %s - has subsource of %s " filename subFile - + yield! resolveDependencyManagerSources filename +#if DEBUG + for (_,subFile) in sources do + printfn "visiting %s - has subsource of %s " filename subFile +#endif for (m, subFile) in sources do if IsScript subFile then for subSource in ClosureSourceOfFilename(subFile, m, tcConfigResult.inputCodePage, false) do @@ -5126,18 +5230,22 @@ module private ScriptPreprocessClosure = else yield ClosureFile(subFile, m, None, [], [], []) - //printfn "yielding source %s" filename +#if DEBUG + printfn "yielding source %s" filename +#endif yield ClosureFile(filename, m, Some parsedScriptAst, parseDiagnostics, errorLogger.Diagnostics, !noWarns) | None -> - //printfn "yielding source %s (failed parse)" filename + printfn "yielding source %s (failed parse)" filename yield ClosureFile(filename, m, None, parseDiagnostics, [], []) else // Don't traverse into .fs leafs. - //printfn "yielding non-script source %s" filename + 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) = @@ -5198,11 +5306,11 @@ module private ScriptPreprocessClosure = let isThisFileName = (0 = String.Compare(rootFilename, m.FileName, StringComparison.OrdinalIgnoreCase)) isArgParameterWhileNotEditing || isThisFileName | None -> true - + // Filter out non-root errors and warnings let allRootDiagnostics = allRootDiagnostics |> List.filter (fst >> isRootRange) - let result: LoadClosure = + let result: LoadClosure = { SourceFiles = List.groupBy fst sourceFiles |> List.map (map2Of2 (List.map snd)) References = List.groupBy fst references |> List.map (map2Of2 (List.map snd)) UnresolvedReferences = unresolvedReferences @@ -5211,7 +5319,7 @@ module private ScriptPreprocessClosure = OriginalLoadReferences = tcConfig.loadedSources ResolutionDiagnostics = resolutionDiagnostics AllRootFileDiagnostics = allRootDiagnostics - LoadClosureRootFileDiagnostics = loadClosureRootDiagnostics } + LoadClosureRootFileDiagnostics = loadClosureRootDiagnostics } result @@ -5246,20 +5354,15 @@ module private ScriptPreprocessClosure = tryGetMetadataSnapshot, reduceMemoryUsage) let closureSources = [ClosureSource(filename, range0, sourceText, true)] - let closureFiles, tcConfig = FindClosureFiles(closureSources, tcConfig, codeContext, lexResourceManager) + let closureFiles, tcConfig = FindClosureFiles(filename, range0, closureSources, tcConfig, codeContext, lexResourceManager) GetLoadClosure(ctok, filename, closureFiles, tcConfig, codeContext) - + /// Given source filename, find the full load closure /// Used from fsi.fs and fsc.fs, for #load and command line - let GetFullClosureOfScriptFiles - (ctok, tcConfig: TcConfig, - files:(string*range) list, - codeContext, - lexResourceManager: Lexhelp.LexResourceManager) = - - let mainFile = fst (List.last files) - let closureSources = files |> List.collect (fun (filename, m) -> ClosureSourceOfFilename(filename, m, tcConfig.inputCodePage, true)) - let closureFiles, tcConfig = FindClosureFiles(closureSources, tcConfig, codeContext, lexResourceManager) + let GetFullClosureOfScriptFiles(ctok, tcConfig:TcConfig, files:(string*range) list,codeContext,lexResourceManager: Lexhelp.LexResourceManager) = + let mainFile, mainFileRange = List.last files + let closureSources = files |> List.collect (fun (filename, m) -> ClosureSourceOfFilename(filename, m,tcConfig.inputCodePage,true)) + let closureFiles,tcConfig = FindClosureFiles(mainFile, mainFileRange, closureSources, tcConfig, codeContext, lexResourceManager) GetLoadClosure(ctok, mainFile, closureFiles, tcConfig, codeContext) type LoadClosure with @@ -5286,8 +5389,6 @@ type LoadClosure with lexResourceManager: Lexhelp.LexResourceManager) = use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse ScriptPreprocessClosure.GetFullClosureOfScriptFiles (ctok, tcConfig, files, codeContext, lexResourceManager) - - //---------------------------------------------------------------------------- // Initial type checking environment diff --git a/src/fsharp/CompileOps.fsi b/src/fsharp/CompileOps.fsi index a34c84d92da..7e5f2b4a1db 100644 --- a/src/fsharp/CompileOps.fsi +++ b/src/fsharp/CompileOps.fsi @@ -268,9 +268,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 compilerToolPaths: string list mutable referencedDLLs: AssemblyReference list + mutable packageManagerLines: Map + mutable projectReferences: IProjectReference list mutable knownUnresolvedReferences: UnresolvedAssemblyReference list reduceMemoryUsage: ReduceMemoryFlag @@ -282,6 +284,7 @@ type TcConfigBuilder = mutable mlCompatibility:bool mutable checkOverflow:bool mutable showReferenceResolutions:bool + mutable outputDir: string option mutable outputFile: string option mutable platform: ILPlatform option mutable prefer32Bit: bool @@ -405,6 +408,7 @@ type TcConfigBuilder = member TurnWarningOff: range * string -> unit member TurnWarningOn: range * string -> unit member AddIncludePath: range * string * string -> unit + member AddCompilerToolsByPath: string -> unit member AddReferencedAssemblyByPath: range * string -> unit member RemoveReferencedAssemblyByPath: range * string -> unit member AddEmbeddedSourceFile: string -> unit @@ -435,6 +439,7 @@ type TcConfig = member conditionalCompilationDefines: string list member subsystemVersion: int * int member useHighEntropyVA: bool + member compilerToolPaths: string list member referencedDLLs: AssemblyReference list member reduceMemoryUsage: ReduceMemoryFlag member inputCodePage: int option @@ -443,6 +448,7 @@ type TcConfig = member mlCompatibility:bool member checkOverflow:bool member showReferenceResolutions:bool + member outputDir: string option member outputFile: string option member platform: ILPlatform option member prefer32Bit: bool @@ -679,8 +685,8 @@ val WriteOptimizationData: TcGlobals * filename: string * inMem: bool * CcuThunk val RequireDLL: CompilationThreadToken * TcImports * TcEnv * thisAssemblyName: string * referenceRange: range * file: string -> TcEnv * (ImportedBinary list * ImportedAssembly list) /// Processing # commands -val ProcessMetaCommandsFromInput: - (('T -> range * string -> 'T) * ('T -> range * string -> 'T) * ('T -> range * string -> unit)) +val ProcessMetaCommandsFromInput : + (('T -> range * string -> 'T) * ('T -> range * string -> 'T) * ('T -> DependencyManagerIntegration.IDependencyManagerProvider * range * string -> 'T) * ('T -> range * string -> unit)) -> TcConfigBuilder * Ast.ParsedInput * string * 'T -> 'T @@ -801,7 +807,7 @@ type LoadClosure = Inputs: LoadClosureInput list /// The original #load references, including those that didn't resolve - OriginalLoadReferences: (range * string) list + OriginalLoadReferences: (range * string * string) list /// The #nowarns NoWarns: (string * range list) list diff --git a/src/fsharp/CompileOptions.fs b/src/fsharp/CompileOptions.fs index c4595d2dc24..55cc51b1c41 100644 --- a/src/fsharp/CompileOptions.fs +++ b/src/fsharp/CompileOptions.fs @@ -6,6 +6,7 @@ module internal FSharp.Compiler.CompileOptions open Internal.Utilities open System +open System.IO open FSharp.Compiler open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL.IL @@ -502,8 +503,10 @@ let SetDebugSwitch (tcConfigB: TcConfigBuilder) (dtype: string option) (s: Optio let SetEmbedAllSourceSwitch (tcConfigB: TcConfigBuilder) switch = if (switch = OptionSwitch.On) then tcConfigB.embedAllSource <- true else tcConfigB.embedAllSource <- false -let setOutFileName tcConfigB s = - tcConfigB.outputFile <- Some s +let setOutFileName tcConfigB path = + let outputDir = Path.GetDirectoryName(path) + tcConfigB.outputDir <- Some outputDir + tcConfigB.outputFile <- Some path let setSignatureFile tcConfigB s = tcConfigB.printSignature <- true @@ -559,17 +562,24 @@ let PrintOptionInfo (tcConfigB:TcConfigBuilder) = // OptionBlock: Input files //------------------------- -let inputFileFlagsBoth (tcConfigB: TcConfigBuilder) = - [ CompilerOption("reference", tagFile, OptionString (fun s -> tcConfigB.AddReferencedAssemblyByPath (rangeStartup, s)), None, Some (FSComp.SR.optsReference())) +let inputFileFlagsBoth (tcConfigB : TcConfigBuilder) = [ + CompilerOption("reference", tagFile, OptionString (fun s -> tcConfigB.AddReferencedAssemblyByPath (rangeStartup, s)), None, Some (FSComp.SR.optsReference())) + CompilerOption("compilertool", tagFile, OptionString (fun s -> tcConfigB.AddCompilerToolsByPath s), None, Some (FSComp.SR.optsCompilerTool())) ] -let inputFileFlagsFsc tcConfigB = inputFileFlagsBoth tcConfigB +let referenceFlagAbbrev (tcConfigB : TcConfigBuilder) = + CompilerOption("r", tagFile, OptionString (fun s -> tcConfigB.AddReferencedAssemblyByPath (rangeStartup, s)), None, Some(FSComp.SR.optsShortFormOf("--reference"))) + +let compilerToolFlagAbbrev (tcConfigB : TcConfigBuilder) = + CompilerOption("t", tagFile, OptionString (fun s -> tcConfigB.AddCompilerToolsByPath s), None, Some(FSComp.SR.optsShortFormOf("--compilertool"))) + +let inputFileFlagsFsc tcConfigB = inputFileFlagsBoth tcConfigB let inputFileFlagsFsiBase (_tcConfigB: TcConfigBuilder) = #if NETSTANDARD - [ CompilerOption("usesdkrefs", tagNone, OptionSwitch (SetUseSdkSwitch _tcConfigB), None, Some (FSComp.SR.useSdkRefs())) ] + [ CompilerOption("usesdkrefs", tagNone, OptionSwitch (SetUseSdkSwitch _tcConfigB), None, Some (FSComp.SR.useSdkRefs())) ] #else - List.empty + List.empty #endif let inputFileFlagsFsi (tcConfigB: TcConfigBuilder) = diff --git a/src/fsharp/CompileOptions.fsi b/src/fsharp/CompileOptions.fsi index e6e010bff2c..0b6a4c84890 100644 --- a/src/fsharp/CompileOptions.fsi +++ b/src/fsharp/CompileOptions.fsi @@ -2,6 +2,7 @@ module internal FSharp.Compiler.CompileOptions +open System open FSharp.Compiler open FSharp.Compiler.AbstractIL.Internal.Library open FSharp.Compiler.CompileOps @@ -12,7 +13,7 @@ open FSharp.Compiler.TcGlobals //---------------------------------------------------------------------------- // Compiler Option Parser -//-------------------------------------------------------------------------- +//---------------------------------------------------------------------------- // For command-line options that can be suffixed with +/- [] @@ -89,7 +90,7 @@ val NormalizeAssemblyRefs : CompilationThreadToken * TcImports -> (AbstractIL.IL // Miscellany val ignoreFailureOnMono1_1_16 : (unit -> unit) -> unit val mutable enableConsoleColoring : bool -val DoWithColor : System.ConsoleColor -> (unit -> 'a) -> 'a +val DoWithColor : ConsoleColor -> (unit -> 'a) -> 'a val DoWithErrorColor : bool -> (unit -> 'a) -> 'a val ReportTime : TcConfig -> string -> unit val GetAbbrevFlagSet : TcConfigBuilder -> bool -> Set diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs new file mode 100644 index 00000000000..07b2c323eac --- /dev/null +++ b/src/fsharp/DependencyManager.Integration.fs @@ -0,0 +1,182 @@ +// 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 FSharp.Compiler.DependencyManagerIntegration + +open System +open System.Reflection +open System.IO +open FSharp.Compiler.ErrorLogger +open Internal.Utilities.FSharpEnvironment +open FSharp.Compiler.DotNetFrameworkDependencies + +// Contract strings +let dependencyManagerPattern = "*DependencyManager*.dll" +let dependencyManagerAttributeName= "DependencyManagerAttribute" +let resolveDependenciesMethodName = "ResolveDependencies" +let namePropertyName = "Name" +let keyPropertyName = "Key" + +module ReflectionHelper = + let assemblyHasAttribute (theAssembly: Assembly) attributeName = + try + CustomAttributeExtensions.GetCustomAttributes(theAssembly) + |> Seq.exists (fun a -> a.GetType().Name = attributeName) + with | _ -> false + + let getAttributeNamed (theType: Type) attributeName = + try + theType.GetTypeInfo().GetCustomAttributes false + |> Seq.tryFind (fun a -> a.GetType().Name = attributeName) + with | _ -> None + + let getInstanceProperty<'treturn> (theType: Type) propertyName = + try + let property = theType.GetProperty(propertyName, typeof<'treturn>) + if isNull property then + None + elif not (property.GetGetMethod().IsStatic) + && property.GetIndexParameters() = Array.empty + then + Some property + else + None + with | _ -> None + + let getInstanceMethod<'treturn> (theType: Type) (parameterTypes: Type array) methodName = + try + let theMethod = theType.GetMethod(methodName, parameterTypes) + if isNull theMethod then + None + else + Some theMethod + with | _ -> None + + let stripTieWrapper (e:Exception) = + match e with + | :? TargetInvocationException as e-> + e.InnerException + | _ -> e + +(* Shape of Dependency Manager contract, resolved using reflection *) +type internal IDependencyManagerProvider = + abstract Name : string + abstract Key: string + abstract ResolveDependencies : scriptDir: string * mainScriptName: string * scriptName: string * packageManagerTextLines: string seq * tfm: string -> bool * string list * string list + +[] +type ReferenceType = +| RegisteredDependencyManager of IDependencyManagerProvider +| Library of string +| UnknownType + +type ReflectionDependencyManagerProvider(theType: Type, nameProperty: PropertyInfo, keyProperty: PropertyInfo, resolveDeps: MethodInfo, outputDir: string option) = + let instance = Activator.CreateInstance(theType, [|outputDir :> obj|]) + let nameProperty = nameProperty.GetValue >> string + let keyProperty = keyProperty.GetValue >> string + + static member InstanceMaker (theType: System.Type, outputDir: string option) = + match ReflectionHelper.getAttributeNamed theType dependencyManagerAttributeName, + ReflectionHelper.getInstanceProperty theType namePropertyName, + ReflectionHelper.getInstanceProperty theType keyPropertyName, + ReflectionHelper.getInstanceMethod theType [| typeof; typeof; typeof; typeof; typeof |] resolveDependenciesMethodName + with + | None, _, _, _ -> None + | _, None, _, _ -> None + | _, _, None, _ -> None + | _, _, _, None -> None + | Some _, Some nameProperty, Some keyProperty, Some resolveDependenciesMethod -> + Some (fun () -> new ReflectionDependencyManagerProvider(theType, nameProperty, keyProperty, resolveDependenciesMethod, outputDir) :> IDependencyManagerProvider) + + interface IDependencyManagerProvider with + member __.Name = instance |> nameProperty + member __.Key = instance |> keyProperty + member __.ResolveDependencies(scriptDir, mainScriptName, scriptName, packageManagerTextLines, tfm) = + let arguments = [| box scriptDir; box mainScriptName; box scriptName; box packageManagerTextLines; box tfm |] + resolveDeps.Invoke(instance, arguments) :?> _ + +// Resolution Path = Location of FSharp.Compiler.Private.dll +let assemblySearchPaths = lazy ( + [ + let assemblyLocation = typeof.GetTypeInfo().Assembly.Location + yield Path.GetDirectoryName assemblyLocation + yield AppDomain.CurrentDomain.BaseDirectory + ]) + +let enumerateDependencyManagerAssemblies compilerTools m = + getCompilerToolsDesignTimeAssemblyPaths compilerTools + |> Seq.append (assemblySearchPaths.Force()) + |> Seq.collect (fun path -> + try + if Directory.Exists(path) then Directory.EnumerateFiles(path, dependencyManagerPattern) + else Seq.empty + with _ -> Seq.empty) + |> Seq.choose (fun path -> + try + Some(AbstractIL.Internal.Library.Shim.FileSystem.AssemblyLoadFrom path) + with + | e -> + let e = ReflectionHelper.stripTieWrapper e + warning(Error(FSComp.SR.couldNotLoadDependencyManagerExtension(path,e.Message),m)) + None) + |> Seq.filter (fun a -> ReflectionHelper.assemblyHasAttribute a dependencyManagerAttributeName) + +let registeredDependencyManagers = ref None + +let RegisteredDependencyManagers (compilerTools: string list) (outputDir: string option) m = + match !registeredDependencyManagers with + | Some managers -> managers + | None -> + let defaultProviders =[] + + let loadedProviders = + enumerateDependencyManagerAssemblies compilerTools m + |> Seq.collect (fun a -> a.GetTypes()) + |> Seq.choose (fun t -> ReflectionDependencyManagerProvider.InstanceMaker(t, outputDir)) + |> Seq.map (fun maker -> maker ()) + + defaultProviders + |> Seq.append loadedProviders + |> Seq.map (fun pm -> pm.Key, pm) + |> Map.ofSeq + +let createPackageManagerUnknownError (compilerTools: string list) (outputDir:string option) packageManagerKey m = + let registeredKeys = String.Join(", ", RegisteredDependencyManagers compilerTools outputDir m |> Seq.map (fun kv -> kv.Value.Key)) + let searchPaths = assemblySearchPaths.Force() + Error(FSComp.SR.packageManagerUnknown(packageManagerKey, String.Join(", ", searchPaths, compilerTools), registeredKeys),m) + +let tryFindDependencyManagerInPath (compilerTools:string list) (outputDir:string option) m (path:string) : ReferenceType = + try + if path.Contains ":" && not (System.IO.Path.IsPathRooted path) then + let managers = RegisteredDependencyManagers compilerTools outputDir m + match managers |> Seq.tryFind (fun kv -> path.StartsWith(kv.Value.Key + ":" )) with + | None -> + errorR(createPackageManagerUnknownError compilerTools outputDir (path.Split(':').[0]) m) + ReferenceType.UnknownType + | Some kv -> ReferenceType.RegisteredDependencyManager kv.Value + else + ReferenceType.Library path + with + | e -> + let e = ReflectionHelper.stripTieWrapper e + errorR(Error(FSComp.SR.packageManagerError(e.Message),m)) + ReferenceType.UnknownType + +let removeDependencyManagerKey (packageManagerKey:string) (path:string) = path.Substring(packageManagerKey.Length + 1).Trim() + +let tryFindDependencyManagerByKey (compilerTools: string list) (outputDir:string option) m (key:string) : IDependencyManagerProvider option = + try + RegisteredDependencyManagers compilerTools outputDir m |> Map.tryFind key + with + | e -> + let e = ReflectionHelper.stripTieWrapper e + errorR(Error(FSComp.SR.packageManagerError(e.Message), m)) + None + +let resolve (packageManager:IDependencyManagerProvider) implicitIncludeDir mainScriptName fileName m packageManagerTextLines = + try + Some(packageManager.ResolveDependencies(implicitIncludeDir, mainScriptName, fileName, packageManagerTextLines, executionTfm)) + with e -> + let e = ReflectionHelper.stripTieWrapper e + errorR(Error(FSComp.SR.packageManagerError(e.Message), m)) + None diff --git a/src/fsharp/DependencyManager.Integration.fsi b/src/fsharp/DependencyManager.Integration.fsi new file mode 100644 index 00000000000..fa68ac8840f --- /dev/null +++ b/src/fsharp/DependencyManager.Integration.fsi @@ -0,0 +1,24 @@ +// 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 FSharp.Compiler.DependencyManagerIntegration + +open FSharp.Compiler.Range +open System + +type IDependencyManagerProvider = + abstract Name : string + abstract Key: string + abstract ResolveDependencies : scriptDir: string * mainScriptName: string * scriptName: string * packageManagerTextLines: string seq * tfm: string -> bool * string list * string list + +[] +type ReferenceType = +| RegisteredDependencyManager of IDependencyManagerProvider +| Library of string +| UnknownType + +val tryFindDependencyManagerInPath: string list -> string option -> range -> string -> ReferenceType +val tryFindDependencyManagerByKey: string list -> string option -> range -> string -> IDependencyManagerProvider option +val removeDependencyManagerKey: string -> string -> string +val createPackageManagerUnknownError: string list -> string option -> string -> range -> exn +val resolve: IDependencyManagerProvider -> string -> string -> string -> range -> string seq -> (bool * string list * string list) option diff --git a/src/fsharp/DotNetFrameworkDependencies.fs b/src/fsharp/DotNetFrameworkDependencies.fs index 3d8e33082c3..a85f58bbf44 100644 --- a/src/fsharp/DotNetFrameworkDependencies.fs +++ b/src/fsharp/DotNetFrameworkDependencies.fs @@ -17,6 +17,7 @@ module internal FSharp.Compiler.DotNetFrameworkDependencies let frameworkDir = Path.GetDirectoryName(typeof.Assembly.Location) let getDefaultFSharpCoreReference = typeof.Assembly.Location let getFSharpCompilerLocation = Path.GetDirectoryName(typeof.Assembly.Location) + let isRunningOnCoreClr = (typeof.Assembly).FullName.StartsWith("System.Private.CoreLib", StringComparison.InvariantCultureIgnoreCase) // Use the ValueTuple that is executing with the compiler if it is from System.ValueTuple // or the System.ValueTuple.dll that sits alongside the compiler. (Note we always ship one with the compiler) @@ -78,14 +79,20 @@ module internal FSharp.Compiler.DotNetFrameworkDependencies | false, false -> String.Compare(suffix1, suffix2, StringComparison.InvariantCultureIgnoreCase) with _ -> 0 - let executionTfm = + // Tries to figure out the tfm for the compiler instance. + // On coreclr it uses the deps.json file + let netcoreTfm = let file = try - let depsJsonPath = Path.ChangeExtension(Assembly.GetEntryAssembly().Location, "deps.json") - if File.Exists(depsJsonPath) then - File.ReadAllText(depsJsonPath) - else - "" + let asm = Assembly.GetEntryAssembly() + match asm with + | null -> "" + | asm -> + let depsJsonPath = Path.ChangeExtension(asm.Location, "deps.json") + if File.Exists(depsJsonPath) then + File.ReadAllText(depsJsonPath) + else + "" with _ -> "" let tfmPrefix=".NETCoreApp,Version=v" @@ -101,12 +108,64 @@ module internal FSharp.Compiler.DotNetFrameworkDependencies else -1 match startPos, length with | -1, _ - | _, -1 -> None - | pos, length -> Some ("netcoreapp" + file.Substring(pos, length)) - + | _, -1 -> + if isRunningOnCoreClr then + // Running on coreclr but no deps.json was deployed with the host so default to 3.0 + Some "netcoreapp3.0" + else + // Running on desktop + None + | pos, length -> + // use value from the deps.json file + Some ("netcoreapp" + file.Substring(pos, length)) + + // Tries to figure out the tfm for the compiler instance on the Windows desktop. + // On full clr it uses the mscorlib version number + let getWindowsDesktopTfm () = + let defaultMscorlibVersion = 4,8,3815,0 + let desktopProductVersionMonikers = [| + // major, minor, build, revision, moniker + 4, 8, 3815, 0, "net48" + 4, 7, 3190, 0, "net472" + 4, 7, 2600, 0, "net471" + 4, 7, 2053, 0, "net47" + 4, 6, 1590, 0, "net462" + 4, 6, 1055, 0, "net461" + 4, 6, 81, 0, "net46" + 4, 0, 30319, 34209, "net452" + 4, 0, 30319, 18408, "net451" + 4, 0, 30319, 17929, "net45" + 4, 0, 30319, 1, "net4" + |] + + let majorPart, minorPart, buildPart, privatePart= + try + let attrOpt = typeof.Assembly.GetCustomAttributes(typeof) |> Seq.tryHead + match attrOpt with + | Some attr -> + let fv = (downcast attr : AssemblyFileVersionAttribute).Version.Split([|'.'|]) |> Array.map(fun e -> Int32.Parse(e)) + fv.[0], fv.[1], fv.[2], fv.[3] + | _ -> defaultMscorlibVersion + with _ -> defaultMscorlibVersion + + // Get the ProductVersion of this framework compare with table yield compatible monikers + let _, _, _, _, moniker = + desktopProductVersionMonikers + |> Array.find (fun (major, minor, build, revision, _) -> + (majorPart >= major) && + (minorPart >= minor) && + (buildPart >= build) && + (privatePart >= revision)) + moniker + + /// Gets the tfm E.g netcore3.0, net472 + let executionTfm = + match netcoreTfm with + | Some tfm -> tfm + | _ -> getWindowsDesktopTfm () let getFrameworkRefsPackDirectoryPath = - match executionTfm with + match netcoreTfm with | Some _ -> let appRefDir = Path.Combine(getFSharpCompilerLocation, "../../../packs/Microsoft.NETCore.App.Ref") if Directory.Exists(appRefDir) then @@ -123,7 +182,7 @@ module internal FSharp.Compiler.DotNetFrameworkDependencies | _ -> false let getFrameworkRefsPackDirectory = - match executionTfm, getFrameworkRefsPackDirectoryPath with + match netcoreTfm, getFrameworkRefsPackDirectoryPath with | Some tfm, Some appRefDir -> try let refDirs = Directory.GetDirectories(appRefDir) @@ -132,8 +191,6 @@ module internal FSharp.Compiler.DotNetFrameworkDependencies with | _ -> None | _ -> None - - let getDependenciesOf assemblyReferences = let assemblies = new Dictionary() diff --git a/src/fsharp/ExtensionTyping.fs b/src/fsharp/ExtensionTyping.fs old mode 100755 new mode 100644 index c075e0dbe96..9ffe6aa817d --- a/src/fsharp/ExtensionTyping.fs +++ b/src/fsharp/ExtensionTyping.fs @@ -17,11 +17,14 @@ module internal ExtensionTyping = open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.Diagnostics // dprintfn open FSharp.Compiler.AbstractIL.Internal.Library // frontAndBack + open Internal.Utilities.FSharpEnvironment type TypeProviderDesignation = TypeProviderDesignation of string - exception ProvidedTypeResolution of range * System.Exception - exception ProvidedTypeResolutionNoRange of System.Exception + exception ProvidedTypeResolution of range * System.Exception + exception ProvidedTypeResolutionNoRange of System.Exception + + let toolingCompatiblePaths() = toolingCompatiblePaths () /// Represents some of the configuration parameters passed to type provider components type ResolutionEnvironment = @@ -29,101 +32,18 @@ module internal ExtensionTyping = outputFile : string option showResolutionMessages : bool referencedAssemblies : string[] - temporaryFolder : string } - - - // Specify the tooling-compatible fragments of a path such as: - // typeproviders/fsharp41/net461/MyProvider.DesignTime.dll - // tools/fsharp41/net461/MyProvider.DesignTime.dll - // See https://github.com/Microsoft/visualfsharp/issues/3736 - - // Represents the FF#-compiler <-> type provider protocol. - // When the API or protocol updates, add a new version moniker to the front of the list here. - let toolingCompatibleTypeProviderProtocolMonikers() = - [ "fsharp41" ] - - // Detect the host tooling context - let toolingCompatibleVersions() = - if typeof.Assembly.GetName().Name = "mscorlib" then - [ "net461"; "net452"; "net451"; "net45"; "netstandard2.0"] - elif typeof.Assembly.GetName().Name = "System.Private.CoreLib" then - [ "netcoreapp2.0"; "netstandard2.0"] - else - System.Diagnostics.Debug.Assert(false, "Couldn't determine runtime tooling context, assuming it supports at least .NET Standard 2.0") - [ "netstandard2.0"] - - - let toolingCompatiblePaths() = - [ for protocol in toolingCompatibleTypeProviderProtocolMonikers() do - for netRuntime in toolingCompatibleVersions() do - yield Path.Combine("typeproviders", protocol, netRuntime) - yield Path.Combine("tools", protocol, netRuntime) - ] + temporaryFolder : string } /// Load a the design-time part of a type-provider into the host process, and look for types /// marked with the TypeProviderAttribute attribute. - let GetTypeProviderImplementationTypes (runTimeAssemblyFileName, designTimeAssemblyNameString, m: range) = + let GetTypeProviderImplementationTypes (runTimeAssemblyFileName, designTimeAssemblyNameString, m:range, compilerToolPaths:string list) = // Report an error, blaming the particular type provider component let raiseError (e: exn) = raise (TypeProviderError(FSComp.SR.etProviderHasWrongDesignerAssembly(typeof.Name, designTimeAssemblyNameString, e.Message), runTimeAssemblyFileName, m)) - // Find and load the designer assembly for the type provider component. - // - // We look in the directories stepping up from the location of the runtime assembly. - - let loadFromLocation designTimeAssemblyPath = - try - Some (FileSystem.AssemblyLoadFrom designTimeAssemblyPath) - with e -> - raiseError e + let designTimeAssemblyOpt = getTypeProviderAssembly (runTimeAssemblyFileName, designTimeAssemblyNameString, compilerToolPaths, raiseError) - let rec searchParentDirChain dir designTimeAssemblyName = - seq { - for subdir in toolingCompatiblePaths() do - let designTimeAssemblyPath = Path.Combine (dir, subdir, designTimeAssemblyName) - if FileSystem.SafeExists designTimeAssemblyPath then - yield loadFromLocation designTimeAssemblyPath - match Path.GetDirectoryName dir with - | s when s = "" || s = null || Path.GetFileName dir = "packages" || s = dir -> () - | parentDir -> yield! searchParentDirChain parentDir designTimeAssemblyName - } - - let loadFromParentDirRelativeToRuntimeAssemblyLocation designTimeAssemblyName = - let runTimeAssemblyPath = Path.GetDirectoryName runTimeAssemblyFileName - searchParentDirChain runTimeAssemblyPath designTimeAssemblyName - |> Seq.tryHead - |> function - | Some res -> res - | None -> - // The search failed, just load from the first location and report an error - let runTimeAssemblyPath = Path.GetDirectoryName runTimeAssemblyFileName - loadFromLocation (Path.Combine (runTimeAssemblyPath, designTimeAssemblyName)) - - let designTimeAssemblyOpt = - - if designTimeAssemblyNameString.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) then - loadFromParentDirRelativeToRuntimeAssemblyLocation designTimeAssemblyNameString - else - // Cover the case where the ".dll" extension has been left off and no version etc. has been used in the assembly - // string specification. The Name=FullName comparison is particularly strange, and was there to support - // design-time DLLs specified using "x.DesignTIme, Version= ..." long assembly names and GAC loads. - // These kind of design-time assembly specifications are no longer used to our knowledge so that comparison is basically legacy - // and will always succeed. - let name = System.Reflection.AssemblyName (Path.GetFileNameWithoutExtension designTimeAssemblyNameString) - if name.Name.Equals(name.FullName, StringComparison.OrdinalIgnoreCase) then - let designTimeAssemblyName = designTimeAssemblyNameString+".dll" - loadFromParentDirRelativeToRuntimeAssemblyLocation designTimeAssemblyName - else - // Load from the GAC using Assembly.Load. This is legacy since type provider design-time components are - // never in the GAC these days and "x.DesignTIme, Version= ..." specifications are never used. - try - let asmName = System.Reflection.AssemblyName designTimeAssemblyNameString - Some (FileSystem.AssemblyLoad asmName) - with e -> - raiseError e - - // If we've find a design-time assembly, look for the public types with TypeProviderAttribute match designTimeAssemblyOpt with | Some loadedDesignTimeAssembly -> try @@ -194,7 +114,8 @@ module internal ExtensionTyping = isInteractive: bool, systemRuntimeContainsType : string -> bool, systemRuntimeAssemblyVersion : System.Version, - m: range) = + compilerToolPaths: string list, + m:range) = let providerSpecs = try @@ -214,7 +135,7 @@ module internal ExtensionTyping = | Some designTimeAssemblyName, Some path when String.Compare(designTimeAssemblyName.Name, Path.GetFileNameWithoutExtension path, StringComparison.OrdinalIgnoreCase) = 0 -> () | Some _, _ -> - for t in GetTypeProviderImplementationTypes (runTimeAssemblyFileName, designTimeAssemblyNameString, m) do + for t in GetTypeProviderImplementationTypes (runTimeAssemblyFileName, designTimeAssemblyNameString, m, compilerToolPaths) do let resolver = CreateTypeProvider (t, runTimeAssemblyFileName, resolutionEnvironment, isInvalidationSupported, isInteractive, systemRuntimeContainsType, systemRuntimeAssemblyVersion, m) match box resolver with | null -> () @@ -223,7 +144,7 @@ module internal ExtensionTyping = () ] with :? TypeProviderError as tpe -> - tpe.Iter(fun e -> errorR(NumberedError((e.Number, e.ContextualErrorMessage), m)) ) + tpe.Iter(fun e -> errorR(NumberedError((e.Number, e.ContextualErrorMessage), m)) ) [] let providers = Tainted<_>.CreateAll providerSpecs diff --git a/src/fsharp/ExtensionTyping.fsi b/src/fsharp/ExtensionTyping.fsi index 5c679fe69e1..d6584d4188b 100755 --- a/src/fsharp/ExtensionTyping.fsi +++ b/src/fsharp/ExtensionTyping.fsi @@ -54,6 +54,7 @@ module internal ExtensionTyping = * isInteractive: bool * systemRuntimeContainsType : (string -> bool) * systemRuntimeAssemblyVersion : System.Version + * compilerToolsPath : string list * range -> Tainted list /// Given an extension type resolver, supply a human-readable name suitable for error messages. diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index a5559cf424f..d63334f7cec 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -846,6 +846,7 @@ optsNoOpt,"Only include optimization information essential for implementing inli optsNoInterface,"Don't add a resource to the generated assembly containing F#-specific metadata" optsSig,"Print the inferred interface of the assembly to a file" optsReference,"Reference an assembly (Short form: -r)" +optsCompilerTool,"Reference an assembly or directory containing a design time tool (Short form: -t)" optsWin32res,"Specify a Win32 resource file (.res)" optsWin32manifest,"Specify a Win32 manifest file" optsNowin32manifest,"Do not include the default Win32 manifest" @@ -1353,6 +1354,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 in %s. Currently registered: %s" +3217,packageManagerError,"%s" tcAnonRecdCcuMismatch,"Two anonymous record types are from different assemblies '%s' and '%s'" tcAnonRecdFieldNameMismatch,"Two anonymous record types have mismatched sets of field names '%s' and '%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." @@ -1463,6 +1466,7 @@ notAFunctionButMaybeDeclaration,"This value is not a function and cannot be appl 3243,parsInvalidAnonRecdExpr,"Invalid anonymous record expression" 3244,parsInvalidAnonRecdType,"Invalid anonymous record type" 3245,tcCopyAndUpdateNeedsRecordType,"The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record" +3246,couldNotLoadDependencyManagerExtension,"The dependency manager extension %s could not be loaded. Message: %s" 3250,expressionHasNoName,"Expression does not have a name." 3251,chkNoFirstClassNameOf,"Using the 'nameof' operator as a first-class function value is not permitted." 3246,tcAugmentationsCannotHaveAttributes,"Attributes cannot be applied to type extensions." @@ -1473,4 +1477,5 @@ fSharpBannerVersion,"%s for F# %s" optsLangVersion,"Display the allowed values for language version, specify language version such as 'latest' or 'preview'" optsSupportedLangVersions,"Supported language versions:" nativeResourceFormatError,"Stream does not begin with a null resource and is not in '.RES' format." -nativeResourceHeaderMalformed,"Resource header beginning at offset %s is malformed." \ No newline at end of file +nativeResourceHeaderMalformed,"Resource header beginning at offset %s is malformed." +3302,packageManagementRequiresVFive,"The package management feature requires language version 5.0 use /langversion:preview" diff --git a/src/fsharp/FSharp.Build/FSharp.Build.fsproj b/src/fsharp/FSharp.Build/FSharp.Build.fsproj index 76b9c7043e9..0a9d7e9e076 100644 --- a/src/fsharp/FSharp.Build/FSharp.Build.fsproj +++ b/src/fsharp/FSharp.Build/FSharp.Build.fsproj @@ -31,10 +31,10 @@ Microsoft.FSharp.NetSdk.props - {{FSharpCoreShippedPackageVersion}} - $(FSharpCoreShippedPackageVersion) - {{FSharpCorePreviewPackageVersion}} - $(FSharpCorePreviewPackageVersion) + {{FSharpCoreShippedVersion}} + $(FSharpCoreShippedVersion) + {{FSharpCorePreviewVersion}} + $(FSharpCorePreviewVersion) @@ -48,6 +48,8 @@ + + diff --git a/src/fsharp/FSharp.Build/Fsc.fs b/src/fsharp/FSharp.Build/Fsc.fs index 25bdfa38d3a..a6e262089b5 100644 --- a/src/fsharp/FSharp.Build/Fsc.fs +++ b/src/fsharp/FSharp.Build/Fsc.fs @@ -27,6 +27,7 @@ type public Fsc () as this = let mutable checksumAlgorithm: string = null let mutable codePage : string = null let mutable commandLineArgs : ITaskItem list = [] + let mutable compilerTools: ITaskItem [] = [||] let mutable debugSymbols = false let mutable debugType : string = null let mutable defineConstants : ITaskItem[] = [||] @@ -162,6 +163,12 @@ type public Fsc () as this = // VersionFile builder.AppendSwitchIfNotNull("--versionfile:", versionFile) + + // CompilerTools + if compilerTools <> null then + for item in compilerTools do + builder.AppendSwitchIfNotNull("--compilertool:", item.ItemSpec) + // References if references <> null then for item in references do @@ -276,6 +283,11 @@ type public Fsc () as this = with get() = codePage and set(s) = codePage <- s + // -r : Reference an F# or .NET assembly. + member fsc.CompilerTools + with get() = compilerTools + and set(a) = compilerTools <- a + // -g: Produce debug file. Disables optimizations if a -O flag is not given. member fsc.DebugSymbols with get() = debugSymbols diff --git a/src/fsharp/FSharp.Build/Microsoft.FSharp.NetSdk.props b/src/fsharp/FSharp.Build/Microsoft.FSharp.NetSdk.props index 1b40e6675ed..f8bae0ab9ab 100644 --- a/src/fsharp/FSharp.Build/Microsoft.FSharp.NetSdk.props +++ b/src/fsharp/FSharp.Build/Microsoft.FSharp.NetSdk.props @@ -98,4 +98,10 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and + + + true + + + diff --git a/src/fsharp/FSharp.Build/Microsoft.FSharp.NetSdk.targets b/src/fsharp/FSharp.Build/Microsoft.FSharp.NetSdk.targets index 282166c98d7..a6923d4c177 100644 --- a/src/fsharp/FSharp.Build/Microsoft.FSharp.NetSdk.targets +++ b/src/fsharp/FSharp.Build/Microsoft.FSharp.NetSdk.targets @@ -58,6 +58,25 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and $(RestoreSources); https://dotnet.myget.org/F/fsharp/api/v3/index.json + + + + + + + + + + + + Pkg$([System.String]::Copy('%(ResolvedCompileFileDefinitions.NugetPackageId)').Replace('.','_')) + $(%(EnhancedResolvedFile.PackageRootProperty))\content\%(ResolvedCompileFileDefinitions.FileName)%(ResolvedCompileFileDefinitions.Extension).fsx + + + + fsharp41 @@ -68,17 +87,43 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - <_ResolvedProjectOutputFiles - Include="%(_ResolvedProjectReferencePaths.RootDir)%(_ResolvedProjectReferencePaths.Directory)/**/*" - Exclude="%(_ResolvedProjectReferencePaths.RootDir)%(_ResolvedProjectReferencePaths.Directory)/**/FSharp.Core.dll;%(_ResolvedProjectReferencePaths.RootDir)%(_ResolvedProjectReferencePaths.Directory)/**/System.ValueTuple.dll" + <_ResolvedOutputFiles + Include="%(_ResolvedProjectReferencePaths.RootDir)%(_ResolvedProjectReferencePaths.Directory)/**/*" + Exclude="%(_ResolvedProjectReferencePaths.RootDir)%(_ResolvedProjectReferencePaths.Directory)/**/FSharp.Core.dll;%(_ResolvedProjectReferencePaths.RootDir)%(_ResolvedProjectReferencePaths.Directory)/**/System.ValueTuple.dll" Condition="'%(_ResolvedProjectReferencePaths.IsFSharpDesignTimeProvider)' == 'true'"> %(_ResolvedProjectReferencePaths.NearestTargetFramework) - + + + <_ResolvedOutputFiles + Include="@(BuiltProjectOutputGroupKeyOutput)" + Condition=" '$(IsFSharpDesignTimeProvider)' == 'true' and '%(BuiltProjectOutputGroupKeyOutput->Filename)%(BuiltProjectOutputGroupKeyOutput->Extension)' != 'FSharp.Core.dll' and '%(BuiltProjectOutputGroupKeyOutput->Filename)%(BuiltProjectOutputGroupKeyOutput->Extension)' != 'System.ValueTuple.dll' "> + $(TargetFramework) + - - $(FSharpToolsDirectory)/$(FSharpDesignTimeProtocol)/%(_ResolvedProjectOutputFiles.NearestTargetFramework)/%(_ResolvedProjectOutputFiles.FileName)%(_ResolvedProjectOutputFiles.Extension) + + $(FSharpToolsDirectory)/$(FSharpDesignTimeProtocol)/%(_ResolvedOutputFiles.NearestTargetFramework)/%(_ResolvedOutputFiles.FileName)%(_ResolvedOutputFiles.Extension) + + + + + + + + + + + + + Pkg$([System.String]::Copy('%(ResolvedCompileFileDefinitions.NugetPackageId)').Replace('.','_')) + $(%(FsxResolvedFile.PackageRootProperty)) + $(%(FsxResolvedFile.PackageRootProperty))\content\%(ResolvedCompileFileDefinitions.FileName)%(ResolvedCompileFileDefinitions.Extension).fsx + + + diff --git a/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets b/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets index 8421c8ea504..e0c253f4916 100644 --- a/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets +++ b/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets @@ -19,7 +19,7 @@ this file. $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - FSharp.Build.dll + $(MSBuildThisFileDirectory)FSharp.Build.dll @@ -210,6 +210,7 @@ this file. @(CompileBefore); @(Compile); @(CompileAfter); + @(FscCompilerTools); @(_CoreCompileResourceInputs); @(ManifestNonResxWithNoCultureOnDisk); $(ApplicationIcon); @@ -278,6 +279,7 @@ this file. BaseAddress="$(BaseAddress)" ChecksumAlgorithm="$(PdbChecksumAlgorithm)" CodePage="$(CodePage)" + CompilerTools="@(FscCompilerTools)" DebugSymbols="$(DebugSymbols)" DebugType="$(DebugType)" DefineConstants="$(DefineConstants)" diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index d8f5341a8a2..8710d929be5 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -16,14 +16,6 @@ true - - true - - - - true - - $(BaseOutputPath)\$(Configuration)\$(TargetFramework) @@ -224,7 +216,7 @@ AbsIL\ilmorph.fs - + AbsIL\ilsign.fs @@ -524,11 +516,16 @@ CodeGen\IlxGen.fs - Driver\DotNetFrameworkDependencies.fs + + Driver\DependencyManager.Integration.fsi + + + Driver\DependencyManager.Integration.fs + Driver\CompileOps.fsi @@ -641,6 +638,9 @@ Service/ServiceXmlDocParser.fs + + Service/SimulatedMSBuildReferenceResolver.fs + Service/ExternalSymbol.fsi @@ -706,6 +706,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 e8af5ff0e4a..9fb4c25cf40 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.netcore.nuspec +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.netcore.nuspec @@ -23,6 +23,7 @@ + diff --git a/src/fsharp/FSharp.Compiler.nuget/Microsoft.FSharp.Compiler.nuspec b/src/fsharp/FSharp.Compiler.nuget/Microsoft.FSharp.Compiler.nuspec index dd9293cd88c..6a9e32442cb 100644 --- a/src/fsharp/FSharp.Compiler.nuget/Microsoft.FSharp.Compiler.nuspec +++ b/src/fsharp/FSharp.Compiler.nuget/Microsoft.FSharp.Compiler.nuspec @@ -5,6 +5,8 @@ en-US + + @@ -48,6 +50,7 @@ + @@ -65,5 +68,7 @@ + diff --git a/src/fsharp/FSharp.DependencyManager/.gitignore b/src/fsharp/FSharp.DependencyManager/.gitignore new file mode 100644 index 00000000000..b6f8be69852 --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/.gitignore @@ -0,0 +1 @@ +FSharp.DependencyManager.nuget.props \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager/FSDependencyManager.txt b/src/fsharp/FSharp.DependencyManager/FSDependencyManager.txt new file mode 100644 index 00000000000..a163aafc0f8 --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/FSDependencyManager.txt @@ -0,0 +1,2 @@ +# FSharp.Build resource strings +notUsed,"Not used." \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs new file mode 100644 index 00000000000..0e1cfd90d3d --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs @@ -0,0 +1,267 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. +namespace FSharp.DependencyManager + +open System +open System.Collections +open System.Collections.Generic +open System.Diagnostics +open System.IO +open System.Reflection +open System.Runtime.CompilerServices +open System.Runtime.Versioning + +open Internal.Utilities.FSharpEnvironment + +open Microsoft.DotNet.PlatformAbstractions +open Microsoft.Extensions.DependencyModel + +#if !(NETSTANDARD || NETCOREAPP) +open Microsoft.Build.Evaluation +open Microsoft.Build.Framework +#endif + +[] +type DependencyManagerAttribute() = inherit System.Attribute() + +module Utilities = + + /// Return a string array delimited by commas + /// Note that a quoted string is not going to be mangled into pieces. + let trimChars = [| ' '; '\t'; '\''; '\"' |] + + let inline private isNotQuotedQuotation (text: string) n = n > 0 && text.[n-1] <> '\\' + + let getOptions text = + let split (option:string) = + let pos = option.IndexOf('=') + let stringAsOpt text = + if String.IsNullOrEmpty(text) then None + else Some text + let nameOpt = + if pos <= 0 then None + else stringAsOpt (option.Substring(0, pos).Trim(trimChars).ToLowerInvariant()) + let valueOpt = + let valueText = + if pos < 0 then option + else if pos < option.Length then + option.Substring(pos + 1) + else "" + stringAsOpt (valueText.Trim(trimChars)) + nameOpt,valueOpt + + let last = String.length text - 1 + let result = ResizeArray() + let mutable insideSQ = false + let mutable start = 0 + let isSeperator c = c = ',' + for i = 0 to last do + match text.[i], insideSQ with + | c, false when isSeperator c -> // split when seeing a separator + result.Add(text.Substring(start, i - start)) + insideSQ <- false + start <- i + 1 + | _, _ when i = last -> + result.Add(text.Substring(start, i - start + 1)) + | c, true when isSeperator c -> // keep reading if a separator is inside quotation + insideSQ <- true + | '\'', _ when isNotQuotedQuotation text i -> // open or close quotation + insideSQ <- not insideSQ // keep reading + | _ -> () + + result |> Seq.map(fun option -> split option) + + // Path to the directory containing the fsharp compilers + let fsharpCompilerPath = Path.GetDirectoryName(typeof.GetTypeInfo().Assembly.Location) + + let isRunningOnCoreClr = + // We are running on dotnet core if the executing application has .runtimeconfig.json + let depsJsonPath = Path.ChangeExtension(Assembly.GetEntryAssembly().Location, "deps.json") + File.Exists(depsJsonPath) + + let isWindows = + match Environment.OSVersion.Platform with + | PlatformID.Unix -> false + | PlatformID.MacOSX -> false + | _ -> true + + let dotnet = + if isWindows then "dotnet.exe" else "dotnet" + + let sdks = "Sdks" + +#if !(NETSTANDARD || NETCOREAPP) + let msbuildExePath = + // Find msbuild.exe when invoked from desktop compiler. + // 1. Look relative to F# compiler location Normal retail build + // 2. Use VSAPPDIR Nightly when started from VS, or F5 + // 3. Use VSINSTALLDIR -- When app is run outside of VS, and + // is not copied relative to a vs install. + let vsRootFromVSAPPIDDIR = + let vsappiddir = Environment.GetEnvironmentVariable("VSAPPIDDIR") + if not (String.IsNullOrEmpty(vsappiddir)) then + Path.GetFullPath(Path.Combine(vsappiddir, "../..")) + else + null + + let roots = [| + Path.GetFullPath(Path.Combine(fsharpCompilerPath, "../../../../..")) + vsRootFromVSAPPIDDIR + Environment.GetEnvironmentVariable("VSINSTALLDIR") + |] + + let msbuildPath root = Path.GetFullPath(Path.Combine(root, "MSBuild/Current/Bin/MSBuild.exe")) + + let msbuildPathExists root = + if String.IsNullOrEmpty(root) then + false + else + File.Exists(msbuildPath root) + + let msbuildOption rootOpt = + match rootOpt with + | Some root -> Some (msbuildPath root) + | _ -> None + + roots |> Array.tryFind(fun root -> msbuildPathExists root) |> msbuildOption +#else + let dotnetHostPath = + if isRunningOnCoreClr then + match (Environment.GetEnvironmentVariable("DOTNET_HOST_PATH")) with + | value when not (String.IsNullOrEmpty(value)) -> Some value // Value set externally + | _ -> + let main = Process.GetCurrentProcess().MainModule + if main.ModuleName.StartsWith("dotnet") then + Some main.FileName + else + None + else + None +#endif + let executeBuild pathToExe arguments = + match pathToExe with + | Some path -> + let psi = ProcessStartInfo() + psi.FileName <- path + psi.RedirectStandardOutput <- false + psi.RedirectStandardError <- false + psi.Arguments <- arguments + psi.CreateNoWindow <- true + psi.UseShellExecute <- false + + use p = new Process() + p.StartInfo <- psi + p.Start() |> ignore + p.WaitForExit() + p.ExitCode = 0 + + | None -> false + + let buildProject projectPath binLogging = + + let binLoggingArguments = + match binLogging with + | true -> "-bl" + | _ -> "" + + let arguments prefix = + sprintf "%s -restore %s %c%s%c /t:FSI-PackageManagement" prefix binLoggingArguments '\"' projectPath '\"' + + let succeeded = +#if !(NETSTANDARD || NETCOREAPP) + // The Desktop build uses "msbuild" to build + executeBuild msbuildExePath (arguments "") +#else + // The coreclr uses "dotnet msbuild" to build + executeBuild dotnetHostPath (arguments "msbuild") +#endif + let outputFile = projectPath + ".fsx" + let resultOutFile = if succeeded && File.Exists(outputFile) then Some outputFile else None + succeeded, resultOutFile + + // Generate a project files for dependencymanager projects + let generateLibrarySource = @"// Generated dependencymanager library +namespace lib" + + let generateProjectBody = @" + + + $(TARGETFRAMEWORK) + false + + + + +$(PACKAGEREFERENCES) + + + + + + + + + + + + fsharp41 + tools + + + + + + + <_ResolvedOutputFiles + Include=""%(_ResolvedProjectReferencePaths.RootDir)%(_ResolvedProjectReferencePaths.Directory)/**/*"" + Exclude=""%(_ResolvedProjectReferencePaths.RootDir)%(_ResolvedProjectReferencePaths.Directory)/**/FSharp.Core.dll;%(_ResolvedProjectReferencePaths.RootDir)%(_ResolvedProjectReferencePaths.Directory)/**/System.ValueTuple.dll"" + Condition=""'%(_ResolvedProjectReferencePaths.IsFSharpDesignTimeProvider)' == 'true'""> + %(_ResolvedProjectReferencePaths.NearestTargetFramework) + + + <_ResolvedOutputFiles + Include=""@(BuiltProjectOutputGroupKeyOutput)"" + Condition=""'$(IsFSharpDesignTimeProvider)' == 'true' and '%(BuiltProjectOutputGroupKeyOutput->Filename)%(BuiltProjectOutputGroupKeyOutput->Extension)' != 'FSharp.Core.dll' and '%(BuiltProjectOutputGroupKeyOutput->Filename)%(BuiltProjectOutputGroupKeyOutput->Extension)' != 'System.ValueTuple.dll'""> + $(TargetFramework) + + + + $(FSharpToolsDirectory)/$(FSharpDesignTimeProtocol)/%(_ResolvedOutputFiles.NearestTargetFramework)/%(_ResolvedOutputFiles.FileName)%(_ResolvedOutputFiles.Extension) + + + + + + + + + Pkg$([System.String]::Copy('%(ResolvedCompileFileDefinitions.NugetPackageId)').Replace('.','_')) + $(%(FsxResolvedFile.PackageRootProperty)) + $(%(FsxResolvedFile.PackageRootProperty))\content\%(ResolvedCompileFileDefinitions.FileName)%(ResolvedCompileFileDefinitions.Extension).fsx + + + + + + + + + + + + + + + + + + + + + + + + + +" diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fs b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fs new file mode 100644 index 00000000000..3318487f9ac --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fs @@ -0,0 +1,151 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.DependencyManager + +open System +open System.Collections.Concurrent +open System.Diagnostics +open System.IO +open System.Reflection + +open FSharp.DependencyManager +open FSharp.DependencyManager.Utilities + +module Attributes = + [] + do () + + +type PackageReference = { Include:string; Version:string; RestoreSources:string; Script:string } + +type [] FSharpDependencyManager (outputDir:string option) = + + let key = "nuget" + let name = "MsBuild Nuget DependencyManager" + let scriptsPath = + let path = Path.Combine(Path.GetTempPath(), key, Process.GetCurrentProcess().Id.ToString()) + match outputDir with + | None -> path + | Some v -> Path.Combine(path, v) + let generatedScripts = new ConcurrentDictionary() + let deleteScripts () = + try + if Directory.Exists(scriptsPath) then + () //Directory.Delete(scriptsPath, true) + with | _ -> () + + let deleteAtExit = + try + if not (File.Exists(scriptsPath)) then + Directory.CreateDirectory(scriptsPath) |> ignore + true + with | _ -> false + + let emitFile filename (body:string) = + try + // Create a file to write to + use sw = File.CreateText(filename) + sw.WriteLine(body) + with | _ -> () + + let concat (s:string) (v:string) : string = + match String.IsNullOrEmpty(s), String.IsNullOrEmpty(v) with + | false, false -> s + ";" + v + | false, true -> s + | true, false -> v + | _ -> "" + + do if deleteAtExit then AppDomain.CurrentDomain.ProcessExit |> Event.add(fun _ -> deleteScripts () ) + + let formatPackageReference p = + let { Include=inc; Version=ver; RestoreSources=src; Script=script } = p + seq { + match not (String.IsNullOrEmpty(inc)), not (String.IsNullOrEmpty(ver)), not (String.IsNullOrEmpty(script)) with + | true, true, false -> yield sprintf @" true" inc ver + | true, true, true -> yield sprintf @" true" inc ver script + | true, false, false -> yield sprintf @" true" inc + | true, false, true -> yield sprintf @" true" inc script + | _ -> () + match not (String.IsNullOrEmpty(src)) with + | true -> yield sprintf @" %s" (concat "$(RestoreAdditionalProjectSources)" src) + | _ -> () + } + + member __.Name = name + + member __.Key = key + + member __.ResolveDependencies(_scriptDir:string, _mainScriptName:string, _scriptName:string, packageManagerTextLines:string seq, tfm: string) : bool * string list * string list = + + let packageReferences, binLogging = + let validatePackageName package packageName = + if String.Compare(packageName, package, StringComparison.OrdinalIgnoreCase) = 0 then + raise (ArgumentException(sprintf "PackageManager can not reference the System Package '%s'" packageName)) // @@@@@@@@@@@@@@@@@@@@@@@ Globalize me please + + let mutable binLogging = false + let references = [ + for line in packageManagerTextLines do + let options = getOptions line + let mutable found = false + let mutable packageReference = { Include = ""; Version = "*"; RestoreSources = ""; Script = "" } + for opt in options do + let addInclude v = + // TODO: Consider a comprehensive list of dotnet framework packages that are disallowed + validatePackageName v "mscorlib" + validatePackageName v "FSharp.Core" + validatePackageName v "System.ValueTuple" + validatePackageName v "NETStandard.Library" + found <- true + packageReference <- { packageReference with Include = v } + + let addScript v = packageReference <- { packageReference with Script = v } + match opt with + | Some "version", Some v -> + found <- true + packageReference <- { packageReference with Version = v } + | Some "restoresources", Some v -> + found <- true + packageReference <- { packageReference with RestoreSources = concat packageReference.RestoreSources v } + | Some "bl", Some v -> + binLogging <- + match v.ToLowerInvariant() with + | "true" -> true + | _ -> false + | Some "include", None -> + raise (ArgumentException(sprintf "%s requires a value" "Include")) // @@@@@@@@@@@@@@@@@@@@@@@ Globalize me please + | Some "version", None -> + raise (ArgumentException(sprintf "%s requires a value" "Version")) // @@@@@@@@@@@@@@@@@@@@@@@ Globalize me please + | Some "restoresources", None -> + raise (ArgumentException(sprintf "%s requires a value" "RestoreSources")) // @@@@@@@@@@@@@@@@@@@@@@@ Globalize me please + | Some "include", Some v -> addInclude v + | Some "script", Some v -> addScript v + | None, Some v -> addInclude v + | _ -> () + if found then yield! formatPackageReference packageReference + ] + references |> List.distinct |>String.concat Environment.NewLine, binLogging + + // Generate a project files + let generateAndBuildProjectArtifacts = + let writeFile path body = + if not (generatedScripts.ContainsKey(body.GetHashCode().ToString())) then + emitFile path body + + let fsProjectPath = Path.Combine(scriptsPath, "Project.fsproj") + + let generateProjBody = + generateProjectBody.Replace("$(TARGETFRAMEWORK)", tfm) + .Replace("$(PACKAGEREFERENCES)", packageReferences) + + writeFile (Path.Combine(scriptsPath, "Library.fs")) generateLibrarySource + writeFile fsProjectPath generateProjBody + + let succeeded, resultingFsx = buildProject fsProjectPath binLogging + let fsx = + match resultingFsx with + | Some fsx -> [fsx] + | None -> [] + + succeeded, fsx, List.empty + + generateAndBuildProjectArtifacts diff --git a/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fsproj b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fsproj new file mode 100644 index 00000000000..733367a7755 --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fsproj @@ -0,0 +1,84 @@ + + + + + + Library + net472;netstandard2.0 + netstandard2.0 + FSharp.DependencyManager + $(NoWarn);45;55;62;75;1204 + true + $(DefineConstants);COMPILER + $(DefineConstants);MSBUILD_AT_LEAST_15 + $(OtherFlags) --warnon:1182 --maxerrors:20 --extraoptimizationloops:1 + true + + + + + $(BaseOutputPath)\$(Configuration)\$(TargetFramework) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.cs.xlf b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.cs.xlf new file mode 100644 index 00000000000..1b2b7891240 --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.cs.xlf @@ -0,0 +1,12 @@ + + + + + + Not used. + Not used. + + + + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.de.xlf b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.de.xlf new file mode 100644 index 00000000000..fad4a92c190 --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.de.xlf @@ -0,0 +1,12 @@ + + + + + + Not used. + Not used. + + + + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.en.xlf b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.en.xlf new file mode 100644 index 00000000000..486faaceb83 --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.en.xlf @@ -0,0 +1,12 @@ + + + + + + Not used. + Not used. + + + + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.es.xlf b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.es.xlf new file mode 100644 index 00000000000..af7ece6ad9b --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.es.xlf @@ -0,0 +1,12 @@ + + + + + + Not used. + Not used. + + + + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.fr.xlf b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.fr.xlf new file mode 100644 index 00000000000..42aa351aa0c --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.fr.xlf @@ -0,0 +1,12 @@ + + + + + + Not used. + Not used. + + + + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.it.xlf b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.it.xlf new file mode 100644 index 00000000000..da872e4f39d --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.it.xlf @@ -0,0 +1,12 @@ + + + + + + Not used. + Not used. + + + + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.ja.xlf b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.ja.xlf new file mode 100644 index 00000000000..e9e3444fcfb --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.ja.xlf @@ -0,0 +1,12 @@ + + + + + + Not used. + Not used. + + + + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.ko.xlf b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.ko.xlf new file mode 100644 index 00000000000..13f0865b931 --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.ko.xlf @@ -0,0 +1,12 @@ + + + + + + Not used. + Not used. + + + + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.pl.xlf b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.pl.xlf new file mode 100644 index 00000000000..e9718434a10 --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.pl.xlf @@ -0,0 +1,12 @@ + + + + + + Not used. + Not used. + + + + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.pt-BR.xlf b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.pt-BR.xlf new file mode 100644 index 00000000000..6fb3374c226 --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.pt-BR.xlf @@ -0,0 +1,12 @@ + + + + + + Not used. + Not used. + + + + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.ru.xlf b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.ru.xlf new file mode 100644 index 00000000000..98624d79969 --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.ru.xlf @@ -0,0 +1,12 @@ + + + + + + Not used. + Not used. + + + + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.tr.xlf b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.tr.xlf new file mode 100644 index 00000000000..a94d8e068e4 --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.tr.xlf @@ -0,0 +1,12 @@ + + + + + + Not used. + Not used. + + + + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.zh-Hans.xlf b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.zh-Hans.xlf new file mode 100644 index 00000000000..44e599a4143 --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.zh-Hans.xlf @@ -0,0 +1,12 @@ + + + + + + Not used. + Not used. + + + + + \ No newline at end of file diff --git a/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.zh-Hant.xlf b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.zh-Hant.xlf new file mode 100644 index 00000000000..83fa3521e6b --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.zh-Hant.xlf @@ -0,0 +1,12 @@ + + + + + + Not used. + Not used. + + + + + \ No newline at end of file diff --git a/src/fsharp/LanguageFeatures.fs b/src/fsharp/LanguageFeatures.fs index fa35a465dc9..b387b6b7f1d 100644 --- a/src/fsharp/LanguageFeatures.fs +++ b/src/fsharp/LanguageFeatures.fs @@ -26,6 +26,7 @@ type LanguageFeature = | NameOf = 6 | ImplicitYield = 7 | OpenStaticClasses = 8 + | PackageManagement = 9 | LanguageVersion46 = 0x10046 | LanguageVersion47 = 0x10047 | LanguageVersion50 = 0x10050 @@ -58,6 +59,7 @@ type LanguageVersion (specifiedVersion) = LanguageFeature.NameOf, previewVersion LanguageFeature.ImplicitYield, languageVersion47 LanguageFeature.OpenStaticClasses, previewVersion + LanguageFeature.PackageManagement, previewVersion |] let specified = diff --git a/src/fsharp/LanguageFeatures.fsi b/src/fsharp/LanguageFeatures.fsi index 1610f1af181..a55d084976b 100644 --- a/src/fsharp/LanguageFeatures.fsi +++ b/src/fsharp/LanguageFeatures.fsi @@ -13,6 +13,7 @@ type LanguageFeature = | NameOf = 6 | ImplicitYield = 7 | OpenStaticClasses = 8 + | PackageManagement = 9 | LanguageVersion46 = 0x10046 | LanguageVersion47 = 0x10047 | LanguageVersion50 = 0x10050 diff --git a/src/fsharp/fsc/App.config b/src/fsharp/fsc/App.config index 3e0f05bbf95..c5ee96a1294 100644 --- a/src/fsharp/fsc/App.config +++ b/src/fsharp/fsc/App.config @@ -8,10 +8,10 @@ - - - - - + + + + + - + \ No newline at end of file diff --git a/src/fsharp/fsc/fsc.fsproj b/src/fsharp/fsc/fsc.fsproj index 7bddcb9dfd3..85559a81d0c 100644 --- a/src/fsharp/fsc/fsc.fsproj +++ b/src/fsharp/fsc/fsc.fsproj @@ -36,6 +36,7 @@ + @@ -44,6 +45,13 @@ + + + + + + + diff --git a/src/fsharp/fsi/App.config b/src/fsharp/fsi/App.config index 43f1fdd57ed..94ab5a37ace 100644 --- a/src/fsharp/fsi/App.config +++ b/src/fsharp/fsi/App.config @@ -11,6 +11,6 @@ - + diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 1b8ad8ee312..034037c66ca 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -962,6 +962,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) @@ -1251,6 +1253,53 @@ 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 @ [false, path, m]) tcConfigB.packageManagerLines + | _ -> tcConfigB.packageManagerLines <- Map.add packageManager.Key [false, path, m] tcConfigB.packageManagerLines + + needsPackageResolution <- true + + member fsiDynamicCompiler.CommitDependencyManagerText (ctok, istate: FsiDynamicCompilerState, lexResourceManager, errorLogger) = + if not needsPackageResolution then istate else + needsPackageResolution <- false + + tcConfigB.packageManagerLines |> Seq.fold(fun istate kv -> + let inline snd3 (_, b, _) = b + let packageManagerKey, packageManagerLines = kv.Key, kv.Value + match packageManagerLines with + | [] -> istate + | (_, _, m)::_ -> + match DependencyManagerIntegration.tryFindDependencyManagerByKey tcConfigB.compilerToolPaths tcConfigB.outputDir m packageManagerKey with + | None -> + errorR(DependencyManagerIntegration.createPackageManagerUnknownError tcConfigB.compilerToolPaths tcConfigB.outputDir packageManagerKey m) + istate + | Some packageManager -> + let packageManagerTextLines = packageManagerLines |> List.map snd3 + let removeErrorLinesFromScript () = + tcConfigB.packageManagerLines <- tcConfigB.packageManagerLines |> Map.map(fun _ l -> l |> List.filter(fun (tried, _, _) -> tried)) + try + match DependencyManagerIntegration.resolve packageManager tcConfigB.implicitIncludeDir "stdin.fsx" "stdin.fsx" m packageManagerTextLines with + | None -> istate // error already reported + | Some (succeeded, generatedScripts, additionalIncludeFolders) -> //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + if succeeded then + tcConfigB.packageManagerLines <- tcConfigB.packageManagerLines |> Map.map(fun _ l -> l |> List.map(fun (_, p, m) -> true, p, m)) + else + removeErrorLinesFromScript () + for folder in additionalIncludeFolders do + tcConfigB.AddIncludePath(m, folder, "") + if generatedScripts.Length > 0 then + fsiDynamicCompiler.EvalSourceFiles(ctok, istate, m, generatedScripts, lexResourceManager, errorLogger) + else istate + with _ -> + // An exception occured during processing, so remove the lines causing the error from the package manager list. + removeErrorLinesFromScript () + reraise () + ) istate + member fsiDynamicCompiler.ProcessMetaCommandsFromInputAsInteractiveCommands(ctok, istate, sourceFile, inp) = WithImplicitHome (tcConfigB, directoryName sourceFile) @@ -1258,6 +1307,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)) @@ -1785,37 +1835,57 @@ type internal FsiInteractionProcessor /// Execute a single parsed interaction. Called on the GUI/execute/main thread. let ExecInteraction (ctok, tcConfig:TcConfig, istate, action:ParsedFsiInteraction, errorLogger: ErrorLogger) = - istate |> InteractiveCatch errorLogger (fun istate -> + istate |> InteractiveCatch errorLogger (fun istate -> match action with | IDefns ([ ],_) -> + let istate = fsiDynamicCompiler.CommitDependencyManagerText(ctok, istate, lexResourceManager, errorLogger) istate,Completed None + | IDefns ([ SynModuleDecl.DoExpr(_,expr,_)],_) -> + let istate = fsiDynamicCompiler.CommitDependencyManagerText(ctok, istate, lexResourceManager, errorLogger) fsiDynamicCompiler.EvalParsedExpression(ctok, errorLogger, istate, expr) + | IDefns (defs,_) -> + let istate = fsiDynamicCompiler.CommitDependencyManagerText(ctok, istate, lexResourceManager, errorLogger) fsiDynamicCompiler.EvalParsedDefinitions (ctok, errorLogger, istate, true, false, defs),Completed None | IHash (ParsedHashDirective("load",sourceFiles,m),_) -> + let istate = fsiDynamicCompiler.CommitDependencyManagerText(ctok, istate, lexResourceManager, errorLogger) fsiDynamicCompiler.EvalSourceFiles (ctok, istate, m, sourceFiles, lexResourceManager, errorLogger),Completed None - | IHash (ParsedHashDirective(("reference" | "r"),[path],m),_) -> - let resolutions,istate = fsiDynamicCompiler.EvalRequireReference(ctok, istate, m, path) - resolutions |> List.iter (fun ar -> - let format = - if tcConfig.shadowCopyReferences then - let resolvedPath = ar.resolvedPath.ToUpperInvariant() - let fileTime = File.GetLastWriteTimeUtc(resolvedPath) - match referencedAssemblies.TryGetValue resolvedPath with - | false, _ -> - referencedAssemblies.Add(resolvedPath, fileTime) - FSIstrings.SR.fsiDidAHashr(ar.resolvedPath) - | true, time when time <> fileTime -> - FSIstrings.SR.fsiDidAHashrWithStaleWarning(ar.resolvedPath) - | _ -> - FSIstrings.SR.fsiDidAHashr(ar.resolvedPath) - else - FSIstrings.SR.fsiDidAHashrWithLockWarning(ar.resolvedPath) - fsiConsoleOutput.uprintnfnn "%s" format) - istate,Completed None + | IHash (ParsedHashDirective(("reference" | "r"), [path], m), _) -> + match DependencyManagerIntegration.tryFindDependencyManagerInPath tcConfigB.compilerToolPaths tcConfigB.outputDir m (path:string) with + | DependencyManagerIntegration.ReferenceType.RegisteredDependencyManager packageManager -> + if tcConfig.langVersion.SupportsFeature(LanguageFeature.PackageManagement) then + fsiDynamicCompiler.EvalDependencyManagerTextFragment(packageManager, m, path) + istate,Completed None + else + errorR(Error(FSComp.SR.packageManagementRequiresVFive(), m)) + istate, Completed None + + | DependencyManagerIntegration.ReferenceType.UnknownType -> + // error already reported + istate,Completed None + + | DependencyManagerIntegration.ReferenceType.Library path -> + let resolutions,istate = fsiDynamicCompiler.EvalRequireReference(ctok, istate, m, path) + resolutions |> List.iter (fun ar -> + let format = + if tcConfig.shadowCopyReferences then + let resolvedPath = ar.resolvedPath.ToUpperInvariant() + let fileTime = File.GetLastWriteTimeUtc(resolvedPath) + match referencedAssemblies.TryGetValue resolvedPath with + | false, _ -> + referencedAssemblies.Add(resolvedPath, fileTime) + FSIstrings.SR.fsiDidAHashr(ar.resolvedPath) + | true, time when time <> fileTime -> + FSIstrings.SR.fsiDidAHashrWithStaleWarning(ar.resolvedPath) + | _ -> + FSIstrings.SR.fsiDidAHashr(ar.resolvedPath) + else + FSIstrings.SR.fsiDidAHashrWithLockWarning(ar.resolvedPath) + fsiConsoleOutput.uprintnfnn "%s" format) + istate,Completed None | IHash (ParsedHashDirective("I",[path],m),_) -> tcConfigB.AddIncludePath (m,path, tcConfig.implicitIncludeDir) @@ -2430,7 +2500,7 @@ type FsiEvaluationSession (fsi: FsiEvaluationSessionHostConfig, argv:string[], i let fsiDynamicCompiler = FsiDynamicCompiler(fsi, timeReporter, tcConfigB, tcLockObject, outWriter, tcImports, tcGlobals, fsiOptions, fsiConsoleOutput, fsiCollectible, niceNameGen, resolveAssemblyRef) - let fsiInterruptController = FsiInterruptController(fsiOptions, fsiConsoleOutput) + let fsiInterruptController = FsiInterruptController(fsiOptions, fsiConsoleOutput) let uninstallMagicAssemblyResolution = MagicAssemblyResolution.Install(tcConfigB, tcImports, fsiDynamicCompiler, fsiConsoleOutput) diff --git a/src/fsharp/fsi/fsi.fsproj b/src/fsharp/fsi/fsi.fsproj index 5b4978679b2..f6fb546249c 100644 --- a/src/fsharp/fsi/fsi.fsproj +++ b/src/fsharp/fsi/fsi.fsproj @@ -33,6 +33,10 @@ + + + + @@ -47,6 +51,17 @@ + + + + + + + + + + + diff --git a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj index 92503aaea03..3bf0d326d34 100644 --- a/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj +++ b/src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj @@ -31,6 +31,7 @@ + diff --git a/src/fsharp/service/service.fs b/src/fsharp/service/service.fs index 7eac7390c29..faa4895619d 100644 --- a/src/fsharp/service/service.fs +++ b/src/fsharp/service/service.fs @@ -55,7 +55,7 @@ type FSharpProjectOptions = UseScriptResolutionRules : bool LoadTime : System.DateTime UnresolvedReferences : UnresolvedReferencesSet option - OriginalLoadReferences: (range * string) list + OriginalLoadReferences: (range * string * string) list ExtraProjectInfo : obj option Stamp : int64 option } diff --git a/src/fsharp/service/service.fsi b/src/fsharp/service/service.fsi index 9f81f8fccda..182714e8d64 100755 --- a/src/fsharp/service/service.fsi +++ b/src/fsharp/service/service.fsi @@ -54,7 +54,7 @@ type public FSharpProjectOptions = UnresolvedReferences : UnresolvedReferencesSet option /// Unused in this API and should be '[]' when used as user-specified input - OriginalLoadReferences: (range * string) list + OriginalLoadReferences: (range * string * string) list /// Extra information passed back on event trigger ExtraProjectInfo : obj option diff --git a/src/fsharp/xlf/FSComp.txt.cs.xlf b/src/fsharp/xlf/FSComp.txt.cs.xlf index 6504c33e5d1..acaa95f576c 100644 --- a/src/fsharp/xlf/FSComp.txt.cs.xlf +++ b/src/fsharp/xlf/FSComp.txt.cs.xlf @@ -22,6 +22,11 @@ Nerozpoznaná hodnota {0} pro parametr --langversion; seznam možností zobrazíte zadáním --langversion:? + + The package management feature requires language version 5.0 use /langversion:preview + The package management feature requires language version 5.0 use /langversion:preview + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. Neočekávaný symbol . v definici členu. Očekávalo se with, = nebo jiný token. @@ -7232,6 +7237,26 @@ Neplatná mapa cest. Mapování musí být oddělená čárkami a používat formát cesta=zdrojováCesta. + + Reference an assembly or directory containing a design time tool (Short form: -t) + Reference an assembly or directory containing a design time tool (Short form: -t) + + + + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + + + + {0} + {0} + + + + The dependency manager extension {0} could not be loaded. Message: {1} + The dependency manager extension {0} could not be loaded. Message: {1} + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.de.xlf b/src/fsharp/xlf/FSComp.txt.de.xlf index 1a062596c6a..bd0dd57d5ea 100644 --- a/src/fsharp/xlf/FSComp.txt.de.xlf +++ b/src/fsharp/xlf/FSComp.txt.de.xlf @@ -22,6 +22,11 @@ Unbekannter Wert "{0}" für "--langversion". Verwenden Sie "--langversion:?", um die vollständige Liste anzuzeigen. + + The package management feature requires language version 5.0 use /langversion:preview + The package management feature requires language version 5.0 use /langversion:preview + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. Unerwartetes Symbol "." in der Memberdefinition. Erwartet wurde "with", "=" oder ein anderes Token. @@ -7232,6 +7237,26 @@ Ungültige Pfadzuordnung. Zuordnungen müssen durch Kommas getrennt werden und das Format 'path=sourcePath' aufweisen + + Reference an assembly or directory containing a design time tool (Short form: -t) + Reference an assembly or directory containing a design time tool (Short form: -t) + + + + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + + + + {0} + {0} + + + + The dependency manager extension {0} could not be loaded. Message: {1} + The dependency manager extension {0} could not be loaded. Message: {1} + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.es.xlf b/src/fsharp/xlf/FSComp.txt.es.xlf index 3c43675bdf5..5764280f157 100644 --- a/src/fsharp/xlf/FSComp.txt.es.xlf +++ b/src/fsharp/xlf/FSComp.txt.es.xlf @@ -22,6 +22,11 @@ Valor no reconocido "{0}" para --langversion, use --langversion:? para una lista completa + + The package management feature requires language version 5.0 use /langversion:preview + The package management feature requires language version 5.0 use /langversion:preview + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. Símbolo inesperado "." en la definición de miembro. Se esperaba "with", "=" u otro token. @@ -159,7 +164,7 @@ All branches of a pattern match expression must return values of the same type as the first branch, which here is '{0}'. This branch returns a value of type '{1}'. - Todas las ramas de una expresión de coincidencia de patrón deben devolver valores del mismo tipo. La primera rama devolvió un valor de tipo "{0}", pero esta rama devolvió un valor de tipo "\{1 \}". + All branches of a pattern match expression must return values of the same type as the first branch, which here is '{0}'. This branch returns a value of type '{1}'. @@ -7232,6 +7237,26 @@ Mapa de ruta no válido. Las asignaciones deben estar separadas por comas y tener el formato "path=rutaOrigen" + + Reference an assembly or directory containing a design time tool (Short form: -t) + Reference an assembly or directory containing a design time tool (Short form: -t) + + + + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + + + + {0} + {0} + + + + The dependency manager extension {0} could not be loaded. Message: {1} + The dependency manager extension {0} could not be loaded. Message: {1} + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.fr.xlf b/src/fsharp/xlf/FSComp.txt.fr.xlf index b31bb3230fe..a6b1dfb42dc 100644 --- a/src/fsharp/xlf/FSComp.txt.fr.xlf +++ b/src/fsharp/xlf/FSComp.txt.fr.xlf @@ -22,6 +22,11 @@ Valeur non reconnue '{0}' pour --langversion use --langversion:? pour la liste complète + + The package management feature requires language version 5.0 use /langversion:preview + The package management feature requires language version 5.0 use /langversion:preview + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. Symbole '.' inattendu dans la définition du membre. 'with','=' ou autre jeton attendu. @@ -7232,6 +7237,26 @@ Mappage de chemin non valide. Les mappages doivent être séparés par des virgules et au format 'path=sourcePath' + + Reference an assembly or directory containing a design time tool (Short form: -t) + Reference an assembly or directory containing a design time tool (Short form: -t) + + + + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + + + + {0} + {0} + + + + The dependency manager extension {0} could not be loaded. Message: {1} + The dependency manager extension {0} could not be loaded. Message: {1} + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.it.xlf b/src/fsharp/xlf/FSComp.txt.it.xlf index bfa82141e58..3cba5dd8a96 100644 --- a/src/fsharp/xlf/FSComp.txt.it.xlf +++ b/src/fsharp/xlf/FSComp.txt.it.xlf @@ -22,6 +22,11 @@ Valore '{0}' non riconosciuto per --langversion. Per l'elenco completo usare --langversion:? + + The package management feature requires language version 5.0 use /langversion:preview + The package management feature requires language version 5.0 use /langversion:preview + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. Simbolo '.' imprevisto nella definizione di membro. È previsto 'with', '=' o un altro token. @@ -7232,6 +7237,26 @@ Mapping di percorso non valido. I mapping devono essere delimitati da virgole e specificati in formato 'percorso=percorsoOrigine' + + Reference an assembly or directory containing a design time tool (Short form: -t) + Reference an assembly or directory containing a design time tool (Short form: -t) + + + + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + + + + {0} + {0} + + + + The dependency manager extension {0} could not be loaded. Message: {1} + The dependency manager extension {0} could not be loaded. Message: {1} + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.ja.xlf b/src/fsharp/xlf/FSComp.txt.ja.xlf index 41c714765e4..52a0775c440 100644 --- a/src/fsharp/xlf/FSComp.txt.ja.xlf +++ b/src/fsharp/xlf/FSComp.txt.ja.xlf @@ -22,6 +22,11 @@ --langversion の値 '{0}' が認識されません。完全なリストについては、--langversion:? を使用してください + + The package management feature requires language version 5.0 use /langversion:preview + The package management feature requires language version 5.0 use /langversion:preview + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. メンバー定義に予期しない記号 '.' があります。'with'、'=' またはその他のトークンが必要です。 @@ -7232,6 +7237,26 @@ 無効なパス マップです。マッピングはコンマ区切りの 'path=sourcePath' 形式である必要があります + + Reference an assembly or directory containing a design time tool (Short form: -t) + Reference an assembly or directory containing a design time tool (Short form: -t) + + + + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + + + + {0} + {0} + + + + The dependency manager extension {0} could not be loaded. Message: {1} + The dependency manager extension {0} could not be loaded. Message: {1} + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.ko.xlf b/src/fsharp/xlf/FSComp.txt.ko.xlf index d5e39b707f6..85d54c8612f 100644 --- a/src/fsharp/xlf/FSComp.txt.ko.xlf +++ b/src/fsharp/xlf/FSComp.txt.ko.xlf @@ -22,6 +22,11 @@ 전체 목록에 대한 --langversion use --langversion:?의 인식할 수 없는 값 '{0}'입니다. + + The package management feature requires language version 5.0 use /langversion:preview + The package management feature requires language version 5.0 use /langversion:preview + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. 멤버 정의의 예기치 않은 기호 '.'입니다. 'with', '=' 또는 기타 토큰이 필요합니다. @@ -7232,6 +7237,26 @@ 잘못된 경로 맵입니다. 매핑은 쉼표로 구분되어야 하며 'path=sourcePath' 형식이어야 합니다. + + Reference an assembly or directory containing a design time tool (Short form: -t) + Reference an assembly or directory containing a design time tool (Short form: -t) + + + + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + + + + {0} + {0} + + + + The dependency manager extension {0} could not be loaded. Message: {1} + The dependency manager extension {0} could not be loaded. Message: {1} + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.pl.xlf b/src/fsharp/xlf/FSComp.txt.pl.xlf index f6adb36605b..f8baf0166a4 100644 --- a/src/fsharp/xlf/FSComp.txt.pl.xlf +++ b/src/fsharp/xlf/FSComp.txt.pl.xlf @@ -22,6 +22,11 @@ Nierozpoznana wartość „{0}” dla parametru –langversion; podaj parametr –langversion:?, aby uzyskać pełną listę + + The package management feature requires language version 5.0 use /langversion:preview + The package management feature requires language version 5.0 use /langversion:preview + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. Nieoczekiwany symbol „.” w definicji składowej. Oczekiwano ciągu „with”, znaku „=” lub innego tokenu. @@ -7232,6 +7237,26 @@ Nieprawidłowe mapowanie ścieżek. Mapowania muszą być rozdzielone przecinkami i mieć format „path=sourcePath” + + Reference an assembly or directory containing a design time tool (Short form: -t) + Reference an assembly or directory containing a design time tool (Short form: -t) + + + + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + + + + {0} + {0} + + + + The dependency manager extension {0} could not be loaded. Message: {1} + The dependency manager extension {0} could not be loaded. Message: {1} + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf index fb7ecf72ed9..e32cf949c63 100644 --- a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf +++ b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf @@ -22,6 +22,11 @@ Valor não reconhecido '{0}' para --langversion use --langversion:? para a lista completa + + The package management feature requires language version 5.0 use /langversion:preview + The package management feature requires language version 5.0 use /langversion:preview + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. Símbolo inesperado '.' na definição de membro. Esperado 'com', '=' ou outro token. @@ -7232,6 +7237,26 @@ Mapa de caminho inválido. Os mapeamentos devem ser separados por vírgulas e do formato 'path=sourcePath' + + Reference an assembly or directory containing a design time tool (Short form: -t) + Reference an assembly or directory containing a design time tool (Short form: -t) + + + + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + + + + {0} + {0} + + + + The dependency manager extension {0} could not be loaded. Message: {1} + The dependency manager extension {0} could not be loaded. Message: {1} + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.ru.xlf b/src/fsharp/xlf/FSComp.txt.ru.xlf index 9e23c9d63da..90106eda122 100644 --- a/src/fsharp/xlf/FSComp.txt.ru.xlf +++ b/src/fsharp/xlf/FSComp.txt.ru.xlf @@ -22,6 +22,11 @@ Не удалось распознать значение "{0}" для параметра --langversion. Для получения полного списка допустимых значений выполните команду use --langversion:? + + The package management feature requires language version 5.0 use /langversion:preview + The package management feature requires language version 5.0 use /langversion:preview + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. Неожиданный символ "." в определении члена. Ожидаемые инструкции: "with", "=" или другие токены. @@ -7232,6 +7237,26 @@ Недействительная карта путей. Сопоставления должны быть разделены запятыми и должны иметь формат "path=исходный_путь" + + Reference an assembly or directory containing a design time tool (Short form: -t) + Reference an assembly or directory containing a design time tool (Short form: -t) + + + + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + + + + {0} + {0} + + + + The dependency manager extension {0} could not be loaded. Message: {1} + The dependency manager extension {0} could not be loaded. Message: {1} + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.tr.xlf b/src/fsharp/xlf/FSComp.txt.tr.xlf index 7a1b995890f..77b4d7bfdb5 100644 --- a/src/fsharp/xlf/FSComp.txt.tr.xlf +++ b/src/fsharp/xlf/FSComp.txt.tr.xlf @@ -22,6 +22,11 @@ --langversion için '{0}' değeri tanınmıyor. Tam liste için --langversion:? kullanın + + The package management feature requires language version 5.0 use /langversion:preview + The package management feature requires language version 5.0 use /langversion:preview + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. Üye tanımında '.' sembolü beklenmiyordu. 'with', '=' veya başka bir belirteç bekleniyordu. @@ -7232,6 +7237,26 @@ Geçersiz yol eşlemesi. Eşlemeler virgülle ayrılmış ve 'path=sourcePath' biçiminde olmalıdır + + Reference an assembly or directory containing a design time tool (Short form: -t) + Reference an assembly or directory containing a design time tool (Short form: -t) + + + + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + + + + {0} + {0} + + + + The dependency manager extension {0} could not be loaded. Message: {1} + The dependency manager extension {0} could not be loaded. Message: {1} + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf index 6b9a080dcc2..b3a9e8e3543 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf @@ -22,6 +22,11 @@ --langversion 的值“{0}”无法识别,使用 --langversion:? 获取完整列表。 + + The package management feature requires language version 5.0 use /langversion:preview + The package management feature requires language version 5.0 use /langversion:preview + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. 成员定义中有意外的符号 "."。预期 "with"、"+" 或其他标记。 @@ -7232,6 +7237,26 @@ 路径映射无效。映射必须以逗号分隔,且采用 "path=sourcePath" 格式 + + Reference an assembly or directory containing a design time tool (Short form: -t) + Reference an assembly or directory containing a design time tool (Short form: -t) + + + + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + + + + {0} + {0} + + + + The dependency manager extension {0} could not be loaded. Message: {1} + The dependency manager extension {0} could not be loaded. Message: {1} + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf index f9dd3cc6ddc..71aef5083ec 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf @@ -22,6 +22,11 @@ 對 --langversion 為無法識別的值 '{0}',對完整清單使用 --langversion:? + + The package management feature requires language version 5.0 use /langversion:preview + The package management feature requires language version 5.0 use /langversion:preview + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. 成員定義中的非預期符號 '.'。預期為 'with'、'=' 或其他語彙基元。 @@ -7232,6 +7237,26 @@ 路徑對應無效。對應必須以逗號分隔,且格式應為 'path=sourcePath' + + Reference an assembly or directory containing a design time tool (Short form: -t) + Reference an assembly or directory containing a design time tool (Short form: -t) + + + + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + Package manager key '{0}' was not registered in {1}. Currently registered: {2} + + + + {0} + {0} + + + + The dependency manager extension {0} could not be loaded. Message: {1} + The dependency manager extension {0} could not be loaded. Message: {1} + + \ No newline at end of file diff --git a/src/utils/CompilerLocationUtils.fs b/src/utils/CompilerLocationUtils.fs index 95aa5c5a31e..e1c7ad85e03 100644 --- a/src/utils/CompilerLocationUtils.fs +++ b/src/utils/CompilerLocationUtils.fs @@ -1,11 +1,14 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. namespace Internal.Utilities + open System +open System.Diagnostics open System.IO open System.Reflection -open Microsoft.Win32 open System.Runtime.InteropServices +open Microsoft.Win32 +open Microsoft.FSharp.Core #nowarn "44" // ConfigurationSettings is obsolete but the new stuff is horribly complicated. @@ -25,7 +28,7 @@ module internal FSharpEnvironment = let versionOf<'t> = typeof<'t>.Assembly.GetName().Version.ToString() - let FSharpCoreLibRunningVersion = + let FSharpCoreLibRunningVersion = try match versionOf with | null -> None | "" -> None @@ -163,7 +166,7 @@ module internal FSharpEnvironment = if String.IsNullOrEmpty(locationFromAppConfig) then None else - let exeAssemblyFolder = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + let exeAssemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) let locationFromAppConfig = locationFromAppConfig.Replace("{exepath}", exeAssemblyFolder) System.Diagnostics.Debug.Print(sprintf "Using path %s" locationFromAppConfig) Some locationFromAppConfig @@ -176,9 +179,10 @@ module internal FSharpEnvironment = // - default F# binaries directory in service.fs (REVIEW: check this) // - default location of fsi.exe in FSharp.VS.FSI.dll (REVIEW: check this) // - default F# binaries directory in (project system) Project.fs - let BinFolderOfDefaultFSharpCompiler(probePoint:string option) = + let BinFolderOfDefaultFSharpCompiler(probePoint:string option) = #if FX_NO_WIN_REGISTRY ignore probePoint + #if FX_NO_APP_DOMAINS Some System.AppContext.BaseDirectory #else @@ -190,15 +194,17 @@ module internal FSharpEnvironment = try // FSharp.Compiler support setting an appkey for compiler location. I've never seen this used. let result = tryAppConfig "fsharp-compiler-location" - match result with - | Some _ -> result + match result with + | Some _ -> result | None -> let safeExists f = (try File.Exists(f) with _ -> false) + // Look in the probePoint if given, e.g. look for a compiler alongside of FSharp.Build.dll match probePoint with | Some p when safeExists (Path.Combine(p,"FSharp.Core.dll")) -> Some p | _ -> + // We let you set FSHARP_COMPILER_BIN. I've rarely seen this used and its not documented in the install instructions. let result = System.Environment.GetEnvironmentVariable("FSHARP_COMPILER_BIN") if not (String.IsNullOrEmpty(result)) then @@ -206,18 +212,17 @@ module internal FSharpEnvironment = else // For the prototype compiler, we can just use the current domain tryCurrentDomain() - with e -> - None + with e -> None // Apply the given function to the registry entry corresponding to the subkey. // The reg key is disposed at the end of the scope. let useKey subkey f = let key = Registry.LocalMachine.OpenSubKey subkey - try f key - finally - match key with - | null -> () + try f key + finally + match key with + | null -> () | _ -> key.Dispose() // Check if the framework version 4.5 or above is installed at the given key entry @@ -243,3 +248,112 @@ module internal FSharpEnvironment = major > 4 || (major = 4 && IsNetFx45OrAboveInstalled) #endif + + // Specify the tooling-compatible fragments of a path such as: + // typeproviders/fsharp41/net461/MyProvider.DesignTime.dll + // tools/fsharp41/net461/MyProvider.DesignTime.dll + // See https://github.com/Microsoft/visualfsharp/issues/3736 + + // Represents the F#-compiler <-> type provider protocol. + // When the API or protocol updates, add a new version moniker to the front of the list here. + let toolingCompatibleTypeProviderProtocolMonikers() = + [ "fsharp41" ] + + // Detect the host tooling context + let toolingCompatibleVersions = + if typeof.Assembly.GetName().Name = "mscorlib" then + [| "net48"; "net472"; "net471";"net47";"net462";"net461"; "net452"; "net451"; "net45"; "netstandard2.0" |] + elif typeof.Assembly.GetName().Name = "System.Private.CoreLib" then + [| "netcoreapp3.0"; "netstandard2.1"; "netcoreapp2.2"; "netcoreapp2.1"; "netstandard2.0" |] + else + System.Diagnostics.Debug.Assert(false, "Couldn't determine runtime tooling context, assuming it supports at least .NET Standard 2.0") + [| "netstandard2.0" |] + + let toolPaths = [| "tools"; "typeproviders" |] + + let toolingCompatiblePaths() = [ + for toolPath in toolPaths do + for protocol in toolingCompatibleTypeProviderProtocolMonikers() do + for netRuntime in toolingCompatibleVersions do + yield Path.Combine(toolPath, protocol, netRuntime) + ] + + let rec searchToolPaths path compilerToolPaths = + seq { + let searchToolPath path = + seq { + yield path + for toolPath in toolingCompatiblePaths() do + yield Path.Combine (path, toolPath) + } + + for toolPath in compilerToolPaths do + yield! searchToolPath toolPath + + match path with + | None -> () + | Some path -> yield! searchToolPath path + } + + let getTypeProviderAssembly (runTimeAssemblyFileName: string, designTimeAssemblyName: string, compilerToolPaths: string list, raiseError) = + // Find and load the designer assembly for the type provider component. + // We look in the directories stepping up from the location of the runtime assembly. + let loadFromLocation designTimeAssemblyPath = + try + printfn "Using: %s" designTimeAssemblyPath + Some (Assembly.UnsafeLoadFrom designTimeAssemblyPath) + with e -> + raiseError e + + let rec searchParentDirChain path assemblyName = + seq { + match path with + | None -> () + | Some (p:string) -> + match Path.GetDirectoryName(p) with + | s when s = "" || s = null || Path.GetFileName(p) = "packages" || s = p -> () + | parentDir -> yield! searchParentDirChain (Some parentDir) assemblyName + + for p in searchToolPaths path compilerToolPaths do + let fileName = Path.Combine (p, assemblyName) + if File.Exists fileName then yield fileName + } + + let loadFromParentDirRelativeToRuntimeAssemblyLocation designTimeAssemblyName = + let runTimeAssemblyPath = Path.GetDirectoryName runTimeAssemblyFileName + let paths = searchParentDirChain (Some runTimeAssemblyPath) designTimeAssemblyName + paths + |> Seq.iter(function res -> printfn ">>>> %s" res) + paths + |> Seq.tryHead + |> function + | Some res -> loadFromLocation res + | None -> + // The search failed, just load from the first location and report an error + let runTimeAssemblyPath = Path.GetDirectoryName runTimeAssemblyFileName + loadFromLocation (Path.Combine (runTimeAssemblyPath, designTimeAssemblyName)) + + printfn "=============== S T A R T ==========================================" + if designTimeAssemblyName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) then + loadFromParentDirRelativeToRuntimeAssemblyLocation designTimeAssemblyName + else + // Cover the case where the ".dll" extension has been left off and no version etc. has been used in the assembly + // string specification. The Name=FullName comparison is particularly strange, and was there to support + // design-time DLLs specified using "x.DesignTIme, Version= ..." long assembly names and GAC loads. + // These kind of design-time assembly specifications are no longer used to our knowledge so that comparison is basically legacy + // and will always succeed. + let name = AssemblyName (Path.GetFileNameWithoutExtension designTimeAssemblyName) + if name.Name.Equals(name.FullName, StringComparison.OrdinalIgnoreCase) then + let designTimeFileName = designTimeAssemblyName + ".dll" + loadFromParentDirRelativeToRuntimeAssemblyLocation designTimeFileName + else + // Load from the GAC using Assembly.Load. This is legacy since type provider design-time components are + // never in the GAC these days and "x.DesignTIme, Version= ..." specifications are never used. + try + let name = AssemblyName designTimeAssemblyName + Some (Assembly.Load (name)) + with e -> + raiseError e + + let getCompilerToolsDesignTimeAssemblyPaths compilerToolPaths = + searchToolPaths None compilerToolPaths diff --git a/tests/FSharp.Compiler.UnitTests/ProductVersion.fs b/tests/FSharp.Compiler.UnitTests/ProductVersion.fs index 84d05f43e32..1da55436d25 100644 --- a/tests/FSharp.Compiler.UnitTests/ProductVersion.fs +++ b/tests/FSharp.Compiler.UnitTests/ProductVersion.fs @@ -85,31 +85,3 @@ module ProductVersionTest = let ``should zero starting from first invalid version part`` () = for (v, expected) in invalidValues() do v |> productVersionToILVersionInfo |> Assert.areEqual expected - -module TypeProviderDesignTimeComponentLoading = - - - [] - let ``check tooling paths for type provider design time component loading`` () = - let expected = - [ -#if NET472 // only available on net472 - Path.Combine("typeproviders", "fsharp41", "net461") - Path.Combine("tools", "fsharp41", "net461") - Path.Combine("typeproviders", "fsharp41", "net452") - Path.Combine("tools", "fsharp41", "net452") - Path.Combine("typeproviders", "fsharp41", "net451") - Path.Combine("tools", "fsharp41", "net451") - Path.Combine("typeproviders", "fsharp41", "net45") - Path.Combine("tools", "fsharp41", "net45") -#else // only available on netcoreapp2.0 - Path.Combine("typeproviders", "fsharp41", "netcoreapp2.0") - Path.Combine("tools", "fsharp41", "netcoreapp2.0") -#endif // available in both - Path.Combine("typeproviders", "fsharp41", "netstandard2.0") - Path.Combine("tools", "fsharp41", "netstandard2.0") - ] - let actual = FSharp.Compiler.ExtensionTyping.toolingCompatiblePaths() - printfn "actual = %A" actual - printfn "expected = %A" expected - Assert.True((expected=actual)) diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/help/help40.437.1033.bsl b/tests/fsharpqa/Source/CompilerOptions/fsc/help/help40.437.1033.bsl index 5c4045831d7..2ef3abcd84a 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsc/help/help40.437.1033.bsl +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/help/help40.437.1033.bsl @@ -1,4 +1,4 @@ -Microsoft (R) F# Compiler version 10.2.3 for F# 4.5 +Microsoft (R) F# Compiler version 10.6.0.0 for F# 4.7 Copyright (c) Microsoft Corporation. All Rights Reserved. @@ -42,6 +42,9 @@ Copyright (c) Microsoft Corporation. All Rights Reserved. - INPUT FILES - --reference: Reference an assembly (Short form: -r) +--compilertool: Reference an assembly or directory + containing a design time tool (Short + form: -t) - RESOURCES - diff --git a/tests/fsharpqa/Source/CompilerOptions/fsi/exename/help40.437.1033.bsl b/tests/fsharpqa/Source/CompilerOptions/fsi/exename/help40.437.1033.bsl index 8a9d6d418ab..cf97598d925 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsi/exename/help40.437.1033.bsl +++ b/tests/fsharpqa/Source/CompilerOptions/fsi/exename/help40.437.1033.bsl @@ -8,6 +8,9 @@ Usage: fsharpi [script.fsx []] --load: #load the given file on startup --reference: Reference an assembly (Short form: -r) +--compilertool: Reference an assembly or directory + containing a design time tool (Short + form: -t) -- ... Treat remaining arguments as command line arguments, accessed using fsi.CommandLineArgs diff --git a/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40-nologo.437.1033.bsl b/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40-nologo.437.1033.bsl index 041e86b8287..230f23f0f92 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40-nologo.437.1033.bsl +++ b/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40-nologo.437.1033.bsl @@ -8,6 +8,9 @@ Usage: fsi.exe [script.fsx []] --load: #load the given file on startup --reference: Reference an assembly (Short form: -r) +--compilertool: Reference an assembly or directory + containing a design time tool (Short + form: -t) -- ... Treat remaining arguments as command line arguments, accessed using fsi.CommandLineArgs diff --git a/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40.437.1033.bsl b/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40.437.1033.bsl index 24fbfc4de40..9e8af92856a 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40.437.1033.bsl +++ b/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40.437.1033.bsl @@ -10,6 +10,9 @@ Usage: fsi.exe [script.fsx []] --load: #load the given file on startup --reference: Reference an assembly (Short form: -r) +--compilertool: Reference an assembly or directory + containing a design time tool (Short + form: -t) -- ... Treat remaining arguments as command line arguments, accessed using fsi.CommandLineArgs 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..2c30ed8ff15 --- /dev/null +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/UnknownDependencyManager/script1.fsx @@ -0,0 +1,6 @@ +//Package manager key 'unk' was not registered +//Processing of a script fragment has stopped because an exception has been raised + +#r "unk: blubblub" + +let x = 1 \ No newline at end of file diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/env.lst b/tests/fsharpqa/Source/InteractiveSession/Misc/env.lst index 13803307162..f18e59e67d6 100644 --- a/tests/fsharpqa/Source/InteractiveSession/Misc/env.lst +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/env.lst @@ -165,3 +165,6 @@ NOMONO SOURCE=Regressions01.fs COMPILE_ONLY=1 FSIMODE=PIPE SCFLAGS="--nologo" SOURCE=..\\Misc\\ccc\\RelativeHashRResolution03_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo --simpleresolution --noframework -r:\"%FSCOREDLLPATH%\"" # RelativeHashRResolution03_fscrelativesimple SOURCE=..\\Misc\\aaa\\bbb\\RelativeHashRResolution04_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo --simpleresolution --noframework -r:\"%FSCOREDLLPATH%\"" # RelativeHashRResolution04_fscrelativesimple SOURCE=..\\Misc\\aaa\\bbb\\RelativeHashRResolution05_1.fsx COMPILE_ONLY=1 SCFLAGS="--nologo --simpleresolution --noframework -r:\"%FSCOREDLLPATH%\"" # RelativeHashRResolution05_fscrelativesimple + +# dependency managers +SOURCE="UnknownDependencyManager\\script1.fsx" COMPILE_ONLY=1 FSIMODE=FEED SCFLAGS="--nologo" # with unknown manager \ No newline at end of file diff --git a/tests/fsharpqa/Source/comparer.fsx b/tests/fsharpqa/Source/comparer.fsx index 26bff8cb785..3832c61c73b 100644 --- a/tests/fsharpqa/Source/comparer.fsx +++ b/tests/fsharpqa/Source/comparer.fsx @@ -17,7 +17,14 @@ let f2 = File2List fn2 let mutable i = 0 let compare (f1:string[]) (f2:string[]) = - if f1.Length <> f2.Length then failwithf "Help text did not match. f1.Length = %d, f2.Length = %d, Check you have right fsi on path. fsi = %s, PATH=%s" f1.Length f2.Length arg0 path + if f1.Length <> f2.Length then + printfn "First" + f1 |> Array.iter (fun a -> printfn "%s" a) + printfn "Second" + f2 |> Array.iter (fun a -> printfn "%s" a) + + printfn "Files different lengths" + failwithf "Help text did not match.\nf1.Length = %d, f2.Length = %d, Check you have right fsi on path.\nfsi = %s,\nPATH=%s" f1.Length f2.Length arg0 path (f1, f2) ||> Array.forall2 (fun (a:string) (b:string) -> let replace (sourcepattern:string) (replacement:string) (str:string) : string = diff --git a/vsintegration/Directory.Build.targets b/vsintegration/Directory.Build.targets index bc5c6d7195c..3b8426ebd21 100644 --- a/vsintegration/Directory.Build.targets +++ b/vsintegration/Directory.Build.targets @@ -7,6 +7,8 @@ + + diff --git a/vsintegration/Utils/LanguageServiceProfiling/Options.fs b/vsintegration/Utils/LanguageServiceProfiling/Options.fs index 23a3ac25596..0662f09dd7d 100644 --- a/vsintegration/Utils/LanguageServiceProfiling/Options.fs +++ b/vsintegration/Utils/LanguageServiceProfiling/Options.fs @@ -189,7 +189,6 @@ let FCS (repositoryDir: string) : Options = @"src\fsharp\service\ServiceParamInfoLocations.fs" @"src\fsharp\service\ServiceUntypedParse.fsi" @"src\fsharp\service\ServiceUntypedParse.fs" - @"src\utils\reshapedmsbuild.fs" @"src\fsharp\SimulatedMSBuildReferenceResolver.fs" @"src\fsharp\service\FSharpCheckerResults.fsi" @"src\fsharp\service\FSharpCheckerResults.fs" diff --git a/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj b/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj index 68b8b5e1122..1d2074f907b 100644 --- a/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj +++ b/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj @@ -84,6 +84,16 @@ True TargetFramework=$(DependencyTargetFramework) + + FSharp.DependencyManager + BuiltProjectOutputGroup%3bGetCopyToOutputDirectoryItems%3b + DebugSymbolsProjectOutputGroup%3b + true + All + 2 + True + TargetFramework=net472 + {DED3BBD7-53F4-428A-8C9F-27968E768605} FSharp.Core @@ -282,5 +292,4 @@ - diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf index b071e0c5f72..5340031907e 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf index 4184f3edc59..2ca4bd450e9 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf index 4b1a5e0d904..394481ad696 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf index 99d34699194..821545638e2 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf index 8902030751c..dd58cb9a119 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf index de4d65e71f8..c0221174d97 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf index e7191ac3c4a..6f540b54250 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf index 6936b8e97f5..f912b6b4c78 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf index fefd197867e..5a2b75dce09 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf index 355d363084e..2b5303d91de 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf index 86ac32f4b37..73a72b806a2 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf index 0537632d5fc..474f99a3dcd 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf index 17c64ffefb9..16b7339b2a4 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorList.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorList.fs index 8c22810bb06..be8401a6135 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorList.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorList.fs @@ -62,13 +62,19 @@ type UsingMSBuild() as this = member private this.VerifyErrorListCountAtOpenProject(fileContents : string, num : int) = let (solution, project, file) = this.CreateSingleFileProject(fileContents) let errorList = GetErrors(project) + let errorTexts = new System.Text.StringBuilder() for error in errorList do printfn "%A" error.Severity - printf "%s\n" (error.ToString()) - if (num = errorList.Length) then - () - else - failwithf "The error list number is not the expected %d" num + let s = error.ToString() + errorTexts.AppendLine s |> ignore + printf "%s\n" s + + if num <> errorList.Length then + failwithf "The error list number is not the expected %d but %d%s%s" + num + errorList.Length + System.Environment.NewLine + (errorTexts.ToString()) //Verify the warning list Count member private this.VerifyWarningListCountAtOpenProject(fileContents : string, expectedNum : int, ?addtlRefAssy : list) =