From c47c3674a946dc52afe763e15f5b90f7612130c1 Mon Sep 17 00:00:00 2001 From: Kevin Ransom Date: Tue, 23 Jul 2019 17:13:05 -0700 Subject: [PATCH] Dependency Manager --- .gitignore | 1 - FSharp.sln | 51 ++- FSharpTests.Directory.Build.targets | 10 +- VisualFSharp.sln | 14 + eng/Versions.props | 4 + .../FSharp.Compiler.Service.fsproj | 11 + fcs/samples/FscExe/FscMain.fs | 4 - scripts/dotnet-install.ps1 | 2 +- src/fsharp/CompileOps.fs | 255 +++++++---- src/fsharp/CompileOps.fsi | 14 +- src/fsharp/CompileOptions.fs | 19 +- src/fsharp/CompileOptions.fsi | 1 + src/fsharp/DependencyManager.Integration.fs | 183 ++++++++ src/fsharp/DependencyManager.Integration.fsi | 24 ++ src/fsharp/ExtensionTyping.fs | 104 +---- src/fsharp/FSComp.txt | 3 + src/fsharp/FSharp.Build/FSharp.Build.fsproj | 10 +- .../Microsoft.FSharp.NetSdk.props | 6 + .../Microsoft.FSharp.NetSdk.targets | 57 ++- .../FSharp.Build/Microsoft.FSharp.Targets | 6 +- .../FSharp.Compiler.Private.fsproj | 20 +- .../FSharp.Compiler.Private.netcore.nuspec | 1 + .../Microsoft.FSharp.Compiler.nuspec | 13 +- .../FSharp.DependencyManager/.gitignore | 1 + .../FSDependencyManager.txt | 2 + .../FSharp.DependencyManager.Utilities.fs | 403 ++++++++++++++++++ .../FSharp.DependencyManager.fs | 152 +++++++ .../FSharp.DependencyManager.fsproj | 84 ++++ .../xlf/FSDependencyManager.txt.cs.xlf | 12 + .../xlf/FSDependencyManager.txt.de.xlf | 12 + .../xlf/FSDependencyManager.txt.en.xlf | 12 + .../xlf/FSDependencyManager.txt.es.xlf | 12 + .../xlf/FSDependencyManager.txt.fr.xlf | 12 + .../xlf/FSDependencyManager.txt.it.xlf | 12 + .../xlf/FSDependencyManager.txt.ja.xlf | 12 + .../xlf/FSDependencyManager.txt.ko.xlf | 12 + .../xlf/FSDependencyManager.txt.pl.xlf | 12 + .../xlf/FSDependencyManager.txt.pt-BR.xlf | 12 + .../xlf/FSDependencyManager.txt.ru.xlf | 12 + .../xlf/FSDependencyManager.txt.tr.xlf | 12 + .../xlf/FSDependencyManager.txt.zh-Hans.xlf | 12 + .../xlf/FSDependencyManager.txt.zh-Hant.xlf | 12 + src/fsharp/fsc/App.config | 12 +- src/fsharp/fsc/fsc.fsproj | 8 + src/fsharp/fsi/App.config | 2 +- src/fsharp/fsi/fsi.fs | 104 ++++- src/fsharp/fsi/fsi.fsproj | 15 + src/fsharp/fsiAnyCpu/fsiAnyCpu.fsproj | 1 + src/fsharp/service/service.fs | 2 +- src/fsharp/service/service.fsi | 2 +- src/fsharp/xlf/FSComp.txt.cs.xlf | 20 + src/fsharp/xlf/FSComp.txt.de.xlf | 20 + src/fsharp/xlf/FSComp.txt.es.xlf | 20 + src/fsharp/xlf/FSComp.txt.fr.xlf | 20 + src/fsharp/xlf/FSComp.txt.it.xlf | 20 + src/fsharp/xlf/FSComp.txt.ja.xlf | 20 + src/fsharp/xlf/FSComp.txt.ko.xlf | 20 + src/fsharp/xlf/FSComp.txt.pl.xlf | 20 + src/fsharp/xlf/FSComp.txt.pt-BR.xlf | 20 + src/fsharp/xlf/FSComp.txt.ru.xlf | 20 + src/fsharp/xlf/FSComp.txt.tr.xlf | 20 + src/fsharp/xlf/FSComp.txt.zh-Hans.xlf | 20 + src/fsharp/xlf/FSComp.txt.zh-Hant.xlf | 20 + src/utils/CompilerLocationUtils.fs | 138 +++++- .../Misc/UnknownDependencyManager/script1.fsx | 6 + .../Source/InteractiveSession/Misc/env.lst | 3 + vsintegration/Directory.Build.targets | 2 + .../Utils/LanguageServiceProfiling/Options.fs | 1 - .../VisualFSharpFull/VisualFSharpFull.csproj | 11 +- .../Tests.LanguageService.ErrorList.fs | 16 +- 70 files changed, 1927 insertions(+), 279 deletions(-) create mode 100644 src/fsharp/DependencyManager.Integration.fs create mode 100644 src/fsharp/DependencyManager.Integration.fsi create mode 100644 src/fsharp/FSharp.DependencyManager/.gitignore create mode 100644 src/fsharp/FSharp.DependencyManager/FSDependencyManager.txt create mode 100644 src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs create mode 100644 src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fs create mode 100644 src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fsproj create mode 100644 src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.cs.xlf create mode 100644 src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.de.xlf create mode 100644 src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.en.xlf create mode 100644 src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.es.xlf create mode 100644 src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.fr.xlf create mode 100644 src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.it.xlf create mode 100644 src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.ja.xlf create mode 100644 src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.ko.xlf create mode 100644 src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.pl.xlf create mode 100644 src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.pt-BR.xlf create mode 100644 src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.ru.xlf create mode 100644 src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.tr.xlf create mode 100644 src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.zh-Hans.xlf create mode 100644 src/fsharp/FSharp.DependencyManager/xlf/FSDependencyManager.txt.zh-Hant.xlf create mode 100644 tests/fsharpqa/Source/InteractiveSession/Misc/UnknownDependencyManager/script1.fsx 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..afa7434153c 100644 --- a/FSharp.sln +++ b/FSharp.sln @@ -5,22 +5,32 @@ 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}" +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}" EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Tests.FSharpSuite", "tests\fsharp\FSharp.Tests.FSharpSuite.fsproj", "{4E7B9500-6DEF-4C33-BF18-246F7E2C0BC6}" +EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Core.UnitTests", "tests\FSharp.Core.UnitTests\FSharp.Core.UnitTests.fsproj", "{88E2D422-6852-46E3-A740-83E391DC7973}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Compiler", "Compiler", "{3881429D-A97A-49EB-B7AE-A82BA5FE9C77}" @@ -38,6 +48,7 @@ EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.LanguageServer", "src\fsharp\FSharp.Compiler.LanguageServer\FSharp.Compiler.LanguageServer.fsproj", "{99B3F4A5-80B4-41D9-A073-117DB6D7DBBA}" 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}" +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 @@ -65,6 +76,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 +148,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 +268,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 +291,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 +301,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..01ab8ed78ab 100644 --- a/VisualFSharp.sln +++ b/VisualFSharp.sln @@ -153,6 +153,7 @@ EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Private.Scripting", "src\fsharp\FSharp.Compiler.Private.Scripting\FSharp.Compiler.Private.Scripting.fsproj", "{20B7BC36-CF51-4D75-9E13-66681C07977F}" 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}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.DependencyManager", "src\fsharp\FSharp.DependencyManager\FSharp.DependencyManager.fsproj", "{F0CB2C0F-4EBF-4E9C-A484-D9C30441757E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -896,6 +897,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 + {F0CB2C0F-4EBF-4E9C-A484-D9C30441757E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F0CB2C0F-4EBF-4E9C-A484-D9C30441757E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F0CB2C0F-4EBF-4E9C-A484-D9C30441757E}.Debug|x86.ActiveCfg = Debug|Any CPU + {F0CB2C0F-4EBF-4E9C-A484-D9C30441757E}.Debug|x86.Build.0 = Debug|Any CPU + {F0CB2C0F-4EBF-4E9C-A484-D9C30441757E}.Proto|Any CPU.ActiveCfg = Debug|Any CPU + {F0CB2C0F-4EBF-4E9C-A484-D9C30441757E}.Proto|Any CPU.Build.0 = Debug|Any CPU + {F0CB2C0F-4EBF-4E9C-A484-D9C30441757E}.Proto|x86.ActiveCfg = Debug|Any CPU + {F0CB2C0F-4EBF-4E9C-A484-D9C30441757E}.Proto|x86.Build.0 = Debug|Any CPU + {F0CB2C0F-4EBF-4E9C-A484-D9C30441757E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F0CB2C0F-4EBF-4E9C-A484-D9C30441757E}.Release|Any CPU.Build.0 = Release|Any CPU + {F0CB2C0F-4EBF-4E9C-A484-D9C30441757E}.Release|x86.ActiveCfg = Release|Any CPU + {F0CB2C0F-4EBF-4E9C-A484-D9C30441757E}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -968,6 +981,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} + {F0CB2C0F-4EBF-4E9C-A484-D9C30441757E} = {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 b631912fec1..f4bfd42cbda 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..8bd7cf8f50d 100644 --- a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -1,4 +1,6 @@  + + @@ -517,6 +519,15 @@ Driver\DotNetFrameworkDependencies.fs + + + Driver\DependencyManager.Integration.fsi + + 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 a873b8f2f1b..be0c4513989 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 //-------------------------------------------------------------------------- @@ -2028,9 +2027,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 @@ -2042,6 +2042,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 @@ -2196,6 +2197,7 @@ type TcConfigBuilder = implicitlyResolveAssemblies = true compilerToolPaths = [] referencedDLLs = [] + packageManagerLines = Map.empty projectReferences = [] knownUnresolvedReferences = [] loadedSources = [] @@ -2208,6 +2210,7 @@ type TcConfigBuilder = mlCompatibility = false checkOverflow = false showReferenceResolutions = false + outputDir = None outputFile = None platform = None prefer32Bit = false @@ -2407,18 +2410,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 @@ -2426,12 +2430,11 @@ type TcConfigBuilder = member tcConfigB.AddEmbeddedResource filename = tcConfigB.embedResources <- tcConfigB.embedResources ++ filename - member tcConfigB.AddCompilerToolsByPath (m:range, path) = - if FileSystem.IsInvalidPathShim(path) then - warning(Error(FSComp.SR.buildInvalidAssemblyName(path), m)) - elif not (tcConfigB.compilerToolPaths |> List.exists (fun text -> path = text)) then // NOTE: We keep same paths if range is different. + 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) - tcConfigB.compilerToolPaths <- tcConfigB.compilerToolPaths ++ (Option.defaultValue "" compilerToolPath) //AssemblyReference(m, path, projectReference) + if compilerToolPath.IsNone then + tcConfigB.compilerToolPaths <- tcConfigB.compilerToolPaths ++ path member tcConfigB.AddReferencedAssemblyByPath (m, path) = if FileSystem.IsInvalidPathShim path then @@ -2440,6 +2443,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) @@ -2704,6 +2714,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 @@ -2744,6 +2755,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 @@ -2887,13 +2899,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 @@ -4268,11 +4290,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, tcConfig.compilerToolPaths, 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 @@ -4812,14 +4841,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) = - + (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 = @@ -4842,15 +4870,22 @@ let ProcessMetaCommandsFromInput | _ -> errorR(Error(FSComp.SR.buildInvalidHashIDirective(), m)) state - | ParsedHashDirective("nowarn", numbers, m) -> - List.fold (fun state d -> nowarnF state (m, d)) state numbers - | ParsedHashDirective(("reference" | "r"), args, m) -> + | ParsedHashDirective("nowarn",numbers,m) -> + List.fold (fun state d -> nowarnF state (m,d)) state numbers + + | ParsedHashDirective(("reference" | "r"),args,m) -> if not canHaveScriptMetaCommands then errorR(HashReferenceNotAllowedInNonScript m) match args with | [path] -> matchedm<-m - dllRequireF state (m, path) + match DependencyManagerIntegration.tryFindDependencyManagerInPath tcConfig.compilerToolPaths tcConfig.outputDir m (path:string) with + | DependencyManagerIntegration.ReferenceType.RegisteredDependencyManager packageManager -> + packageRequireF state (packageManager,m,path) + | DependencyManagerIntegration.ReferenceType.Library path -> + dllRequireF state (m,path) + | DependencyManagerIntegration.ReferenceType.UnknownType -> + state // error already reported | _ -> errorR(Error(FSComp.SR.buildInvalidHashrDirective(), m)) state @@ -4927,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) //---------------------------------------------------------------------------- @@ -4951,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 = @@ -4971,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 @@ -4987,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 @@ -5087,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 () @@ -5103,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 @@ -5144,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) = @@ -5216,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 @@ -5229,7 +5319,7 @@ module private ScriptPreprocessClosure = OriginalLoadReferences = tcConfig.loadedSources ResolutionDiagnostics = resolutionDiagnostics AllRootFileDiagnostics = allRootDiagnostics - LoadClosureRootFileDiagnostics = loadClosureRootDiagnostics } + LoadClosureRootFileDiagnostics = loadClosureRootDiagnostics } result @@ -5264,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 @@ -5304,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 cadaa56d436..80e40f52197 100644 --- a/src/fsharp/CompileOps.fsi +++ b/src/fsharp/CompileOps.fsi @@ -271,9 +271,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 @@ -285,6 +287,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 @@ -408,7 +411,7 @@ type TcConfigBuilder = member TurnWarningOff: range * string -> unit member TurnWarningOn: range * string -> unit member AddIncludePath: range * string * string -> unit - member AddCompilerToolsByPath: range * string -> unit + member AddCompilerToolsByPath: string -> unit member AddReferencedAssemblyByPath: range * string -> unit member RemoveReferencedAssemblyByPath: range * string -> unit member AddEmbeddedSourceFile: string -> unit @@ -451,6 +454,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 @@ -687,8 +691,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 @@ -809,7 +813,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 8b81abee0bb..2d94bd78f90 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 @@ -560,23 +563,23 @@ let PrintOptionInfo (tcConfigB:TcConfigBuilder) = //------------------------- 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 (rangeStartup, s)), None, Some (FSComp.SR.optsCompilerTool())) + 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 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 (rangeStartup, s)), None, Some(FSComp.SR.optsShortFormOf("--compilertool"))) + CompilerOption("t", tagFile, OptionString (fun s -> tcConfigB.AddCompilerToolsByPath s), None, Some(FSComp.SR.optsShortFormOf("--compilertool"))) -let inputFileFlagsFsi tcConfigB = inputFileFlagsBoth tcConfigB 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 5c3e4047b1f..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 diff --git a/src/fsharp/DependencyManager.Integration.fs b/src/fsharp/DependencyManager.Integration.fs new file mode 100644 index 00000000000..e899bc7bcf7 --- /dev/null +++ b/src/fsharp/DependencyManager.Integration.fs @@ -0,0 +1,183 @@ +// 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 + +// 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 -> 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;|] 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) = + let arguments = [| box scriptDir; box mainScriptName; box scriptName; box packageManagerTextLines |] + 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 + let result, loadScripts, additionalIncludeFolders = + packageManager.ResolveDependencies(implicitIncludeDir, mainScriptName, fileName, packageManagerTextLines) + Some(result, loadScripts, additionalIncludeFolders) + 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..e61d37064cb --- /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 -> 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/ExtensionTyping.fs b/src/fsharp/ExtensionTyping.fs index 3d40b36bbea..9ffe6aa817d 100644 --- 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,36 +32,7 @@ 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. @@ -68,71 +42,7 @@ module internal ExtensionTyping = 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 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 we've found a design-time assembly, look for the public types with TypeProviderAttribute - - // =========================================================================================== - // CompilerTools can also TypeProvider design time tools - // TODO: Search xompilerToolPaths for designtime type provider - // =========================================================================================== - - ignore (compilerToolPaths) - - // =========================================================================================== - - 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 + let designTimeAssemblyOpt = getTypeProviderAssembly (runTimeAssemblyFileName, designTimeAssemblyNameString, compilerToolPaths, raiseError) match designTimeAssemblyOpt with | Some loadedDesignTimeAssembly -> diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 820ff4d47ea..3831657afe6 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1354,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." @@ -1464,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." 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/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 3c6cf662b98..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,7 +210,7 @@ this file. @(CompileBefore); @(Compile); @(CompileAfter); - @(CompilerToolsFscCompilerTools); + @(FscCompilerTools); @(_CoreCompileResourceInputs); @(ManifestNonResxWithNoCultureOnDisk); $(ApplicationIcon); @@ -279,7 +279,7 @@ this file. BaseAddress="$(BaseAddress)" ChecksumAlgorithm="$(PdbChecksumAlgorithm)" CodePage="$(CodePage)" - CompilerTools="$(FscCompilerTools)" + 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..3e74a2d936e 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,6 +516,12 @@ CodeGen\IlxGen.fs + + Driver\DependencyManager.Integration.fsi + + + Driver\DependencyManager.Integration.fs + @@ -641,6 +639,9 @@ Service/ServiceXmlDocParser.fs + + Service/SimulatedMSBuildReferenceResolver.fs + Service/ExternalSymbol.fsi @@ -706,6 +707,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..53918b80201 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,8 +50,16 @@ + + target="lib\netcoreapp2.1" /> + + + + + + + @@ -65,5 +75,6 @@ + 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..5353ff1be26 --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.Utilities.fs @@ -0,0 +1,403 @@ +// 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 = + + let private context = + try + match (Assembly.GetEntryAssembly()) with + | null -> + // No entry assembly therefore look for fsi.exe/fsc.exe alongside this assembly + let loadAssembly path = + let asm = Assembly.LoadFrom(path) + DependencyContext.Load(asm) + // If there is no entry assembly then we assume try fsi.exe, then fsc.exe` + let location = typeof.GetTypeInfo().Assembly.Location + let pathToFsiExe = Path.Combine(Path.GetDirectoryName(location), "fsi.exe") + if File.Exists(pathToFsiExe) then + loadAssembly pathToFsiExe |> Option.ofObj + else + let pathToFscExe = Path.Combine(Path.GetDirectoryName(location), "fsc.exe") + if File.Exists(pathToFscExe) then + loadAssembly pathToFscExe |> Option.ofObj + else + None + | asm -> DependencyContext.Load(asm) |> Option.ofObj + with _ -> None + + // Latest documentation about nuget tfms is here: https://docs.microsoft.com/en-us/nuget/schema/target-frameworks + let netCoreAppTFM = [| + 2.2m, ".NETCoreApp,Version=v2.2"; + 2.2m, ".NETStandard,Version=v2.2"; + 2.1m, ".NETCoreApp,Version=v2.1"; + 2.0m, ".NETStandard,Version=v2.0"; + 2.0m, ".NETCoreApp,Version=v2.0"; + 1.0m, ".NETStandard,Version=v1.6"; + 1.0m, ".NETStandard,Version=v1.5"; + 1.0m, ".NETStandard,Version=v1.4"; + 1.0m, ".NETStandard,Version=v1.3"; + 1.0m, ".NETStandard,Version=v1.2"; + 1.0m, ".NETStandard,Version=v1.1"; + 1.0m, ".NETStandard,Version=v1.0"; + |] + + let netDesktopTFM = [| + 0.472m, ".NETFramework,Version=v4.7.2"; + 0.471m, ".NETFramework,Version=v4.7.1"; + 0.47m, ".NETFramework,Version=v4.7"; + 0.47m, ".NETStandard,Version=v2.0"; + 0.462m, ".NETFramework,Version=v4.6.2"; + 0.462m, ".NETStandard,Version=v1.6"; + 0.461m, ".NETFramework,Version=v4.6.1"; + 0.461m, ".NETStandard,Version=v1.5"; + 0.46m, ".NETFramework,Version=v4.6"; + 0.46m, ".NETStandard,Version=v1.4"; + 0.452m, ".NETFramework,Version=v4.5.2"; + 0.452m, ".NETStandard,Version=v1.3"; + 0.451m, ".NETFramework,Version=v4.51"; + 0.451m, ".NETStandard,Version=v1.2"; + 0.45m, ".NETFramework,Version=v4.5"; + 0.45m, ".NETStandard,Version=v1.1"; + 0.45m, ".NETStandard,Version=v1.0"; + 0.40m, ".NETFramework,Version=v4"; + |] + + let desktopProductVersionMonikers = [| + // major, minor, build, revision, moniker + 4, 7, 3190, 0, 0.472m; + 4, 7, 2600, 0, 0.471m; + 4, 7, 2053, 0, 0.47m; + 4, 6, 1590, 0, 0.462m; + 4, 6, 1055, 0, 0.461m; + 4, 6 , 81, 0, 0.46m; + 4, 0, 30319, 34209, 0.452m; + 4, 0, 30319, 18408, 0.451m; + 4, 0, 30319, 17929, 0.45m; + 4, 0, 30319, 1, 0.40m; + |] + + let defaultMscorlibVersion = 4, 6, 1055, 0 // Probably needs configuring + let defaultFrameworkName = ".NETFramework,Version=v4.6.1" + let netCoreAppPrefix = ".NETCoreApp,Version=v" + let netStandardPrefix = ".NETStandard,Version=v" + + // Algorithm: + // This returns a prioritized the list of supported tfms for the executing application + // the first entry is the most appropriate. + // On windows desktop the windows tfm that matches the installed dotnet framework version is the best match, followed by the highest supported netstandard dll + // E.g. + // Priority search for net471 looks like: + // net471;netstandard2.0;net47;net462;netstandard1.6;net461;netstandard1.5;net46;netstandard1.4;net452;netstandard1.3;net451;netstandard1.2;net45;netstandard1.1;net40;netstandard1.0 + // Priority for .NetCoreApp 2.1 looks like: + // netstandard2.0;netstandard1.6;netstandard1.5;netstandard1.4;netstandard1.3;netstandard1.2;netstandard1.1;netstandard1.0 + let executionTFMs = + seq { + let netStandardsFromVersion version = + netCoreAppTFM |> Seq.filter(fun (ver,_) -> version >= ver) |> Seq.map(fun (_,moniker) -> moniker) |> Seq.toArray + + let netDesktopsFromVersion version = + netDesktopTFM |> Seq.filter(fun (ver,_) -> version >= ver) |> Seq.map(fun (_,moniker) -> moniker) |> Seq.toArray + + match context with + | Some ctxt -> + let target = ctxt.Target.Framework.ToString() + if target.StartsWith(netCoreAppPrefix) then + yield! (netStandardsFromVersion (Decimal.Parse(target.Substring(netCoreAppPrefix.Length)))) + elif target.StartsWith(netStandardPrefix) then + yield! (netStandardsFromVersion (Decimal.Parse(target.Substring(netStandardPrefix.Length)))) + | None -> + let fileMajorPart, fileMinorPart, fileBuildPart, filePrivatePart = + try + let attrOpt = typeof.GetTypeInfo().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 + for majorPart, minorPart, buildPart, privatePart, version in desktopProductVersionMonikers do + if fileMajorPart < majorPart then () + elif fileMajorPart > majorPart then + yield! (netDesktopsFromVersion version) + elif fileMinorPart < minorPart then () + elif fileMinorPart > minorPart then + yield! (netDesktopsFromVersion version) + elif fileBuildPart < buildPart then () + elif fileBuildPart = 30319 && filePrivatePart < privatePart then () + elif fileBuildPart = 30319 && filePrivatePart > privatePart then + yield! (netDesktopsFromVersion version) + elif fileBuildPart < buildPart then () + else + yield! (netDesktopsFromVersion version) + } |> Seq.distinct |> Seq.toArray + + let frameworkIdentifier, frameworkVersion = + let frameworkName = + match executionTFMs |> Array.tryHead with + | Some tfm -> new FrameworkName(tfm) + | None -> new FrameworkName(defaultFrameworkName) + frameworkName.Identifier, frameworkName.Version + + /// 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 = @" + + + $(TARGETFRAMEWORKIDENTIFIER) + v$(TARGETFRAMEWORKVERSION) + 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..9d83f61cb41 --- /dev/null +++ b/src/fsharp/FSharp.DependencyManager/FSharp.DependencyManager.fs @@ -0,0 +1,152 @@ +// 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) : 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("$(TARGETFRAMEWORKIDENTIFIER)", frameworkIdentifier) + .Replace("$(TARGETFRAMEWORKVERSION)", frameworkVersion.ToString()) + .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 \ No newline at end of file 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/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..23f0a790ac1 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)) @@ -1788,34 +1838,48 @@ type internal FsiInteractionProcessor istate |> InteractiveCatch errorLogger (fun istate -> match action with | IDefns ([ ],_) -> + let istate = fsiDynamicCompiler.CommitDependencyManagerText(ctok, istate, lexResourceManager, errorLogger) istate,Completed None + | IDefns ([ SynModuleDecl.DoExpr(_,expr,_)],_) -> + let istate = fsiDynamicCompiler.CommitDependencyManagerText(ctok, istate, lexResourceManager, errorLogger) fsiDynamicCompiler.EvalParsedExpression(ctok, errorLogger, istate, expr) + | IDefns (defs,_) -> + let istate = fsiDynamicCompiler.CommitDependencyManagerText(ctok, istate, lexResourceManager, errorLogger) fsiDynamicCompiler.EvalParsedDefinitions (ctok, errorLogger, istate, true, false, defs),Completed None | IHash (ParsedHashDirective("load",sourceFiles,m),_) -> + let istate = fsiDynamicCompiler.CommitDependencyManagerText(ctok, istate, lexResourceManager, errorLogger) fsiDynamicCompiler.EvalSourceFiles (ctok, istate, m, sourceFiles, lexResourceManager, errorLogger),Completed None - | IHash (ParsedHashDirective(("reference" | "r"),[path],m),_) -> - let resolutions,istate = fsiDynamicCompiler.EvalRequireReference(ctok, istate, m, path) - resolutions |> List.iter (fun ar -> - let format = - if tcConfig.shadowCopyReferences then - let resolvedPath = ar.resolvedPath.ToUpperInvariant() - let fileTime = File.GetLastWriteTimeUtc(resolvedPath) - match referencedAssemblies.TryGetValue resolvedPath with - | false, _ -> - referencedAssemblies.Add(resolvedPath, fileTime) - FSIstrings.SR.fsiDidAHashr(ar.resolvedPath) - | true, time when time <> fileTime -> - FSIstrings.SR.fsiDidAHashrWithStaleWarning(ar.resolvedPath) - | _ -> - FSIstrings.SR.fsiDidAHashr(ar.resolvedPath) - else - FSIstrings.SR.fsiDidAHashrWithLockWarning(ar.resolvedPath) - fsiConsoleOutput.uprintnfnn "%s" format) - istate,Completed None + | IHash (ParsedHashDirective(("reference" | "r"), [path], m), _) -> + match DependencyManagerIntegration.tryFindDependencyManagerInPath tcConfigB.compilerToolPaths tcConfigB.outputDir m (path:string) with + | DependencyManagerIntegration.ReferenceType.RegisteredDependencyManager packageManager -> + fsiDynamicCompiler.EvalDependencyManagerTextFragment(packageManager, m, path) + istate,Completed None + | DependencyManagerIntegration.ReferenceType.UnknownType -> + // error already reported + istate,Completed None + | DependencyManagerIntegration.ReferenceType.Library path -> + let resolutions,istate = fsiDynamicCompiler.EvalRequireReference(ctok, istate, m, path) + resolutions |> List.iter (fun ar -> + let format = + if tcConfig.shadowCopyReferences then + let resolvedPath = ar.resolvedPath.ToUpperInvariant() + let fileTime = File.GetLastWriteTimeUtc(resolvedPath) + match referencedAssemblies.TryGetValue resolvedPath with + | false, _ -> + referencedAssemblies.Add(resolvedPath, fileTime) + FSIstrings.SR.fsiDidAHashr(ar.resolvedPath) + | true, time when time <> fileTime -> + FSIstrings.SR.fsiDidAHashrWithStaleWarning(ar.resolvedPath) + | _ -> + FSIstrings.SR.fsiDidAHashr(ar.resolvedPath) + else + FSIstrings.SR.fsiDidAHashrWithLockWarning(ar.resolvedPath) + fsiConsoleOutput.uprintnfnn "%s" format) + istate,Completed None | IHash (ParsedHashDirective("I",[path],m),_) -> tcConfigB.AddIncludePath (m,path, tcConfig.implicitIncludeDir) @@ -2430,7 +2494,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..40e47daac0b 100644 --- a/src/fsharp/xlf/FSComp.txt.cs.xlf +++ b/src/fsharp/xlf/FSComp.txt.cs.xlf @@ -7232,6 +7232,26 @@ Neplatná mapa cest. Mapování musí být oddělená čárkami a používat formát cesta=zdrojováCesta. + + Reference an assembly or diretory containing a design time tool (Short form: -t) + Reference an assembly or diretory 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..8f6f10ef075 100644 --- a/src/fsharp/xlf/FSComp.txt.de.xlf +++ b/src/fsharp/xlf/FSComp.txt.de.xlf @@ -7232,6 +7232,26 @@ Ungültige Pfadzuordnung. Zuordnungen müssen durch Kommas getrennt werden und das Format 'path=sourcePath' aufweisen + + Reference an assembly or diretory containing a design time tool (Short form: -t) + Reference an assembly or diretory 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..ace695efe26 100644 --- a/src/fsharp/xlf/FSComp.txt.es.xlf +++ b/src/fsharp/xlf/FSComp.txt.es.xlf @@ -7232,6 +7232,26 @@ Mapa de ruta no válido. Las asignaciones deben estar separadas por comas y tener el formato "path=rutaOrigen" + + Reference an assembly or diretory containing a design time tool (Short form: -t) + Reference an assembly or diretory 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..d277428f94c 100644 --- a/src/fsharp/xlf/FSComp.txt.fr.xlf +++ b/src/fsharp/xlf/FSComp.txt.fr.xlf @@ -7232,6 +7232,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 diretory containing a design time tool (Short form: -t) + Reference an assembly or diretory 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..a8d164ef75f 100644 --- a/src/fsharp/xlf/FSComp.txt.it.xlf +++ b/src/fsharp/xlf/FSComp.txt.it.xlf @@ -7232,6 +7232,26 @@ Mapping di percorso non valido. I mapping devono essere delimitati da virgole e specificati in formato 'percorso=percorsoOrigine' + + Reference an assembly or diretory containing a design time tool (Short form: -t) + Reference an assembly or diretory 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..9e123e4fbb7 100644 --- a/src/fsharp/xlf/FSComp.txt.ja.xlf +++ b/src/fsharp/xlf/FSComp.txt.ja.xlf @@ -7232,6 +7232,26 @@ 無効なパス マップです。マッピングはコンマ区切りの 'path=sourcePath' 形式である必要があります + + Reference an assembly or diretory containing a design time tool (Short form: -t) + Reference an assembly or diretory 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..c4352b737f6 100644 --- a/src/fsharp/xlf/FSComp.txt.ko.xlf +++ b/src/fsharp/xlf/FSComp.txt.ko.xlf @@ -7232,6 +7232,26 @@ 잘못된 경로 맵입니다. 매핑은 쉼표로 구분되어야 하며 'path=sourcePath' 형식이어야 합니다. + + Reference an assembly or diretory containing a design time tool (Short form: -t) + Reference an assembly or diretory 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..e72b4195624 100644 --- a/src/fsharp/xlf/FSComp.txt.pl.xlf +++ b/src/fsharp/xlf/FSComp.txt.pl.xlf @@ -7232,6 +7232,26 @@ Nieprawidłowe mapowanie ścieżek. Mapowania muszą być rozdzielone przecinkami i mieć format „path=sourcePath” + + Reference an assembly or diretory containing a design time tool (Short form: -t) + Reference an assembly or diretory 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..79962f4b690 100644 --- a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf +++ b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf @@ -7232,6 +7232,26 @@ Mapa de caminho inválido. Os mapeamentos devem ser separados por vírgulas e do formato 'path=sourcePath' + + Reference an assembly or diretory containing a design time tool (Short form: -t) + Reference an assembly or diretory 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..c58bc13972a 100644 --- a/src/fsharp/xlf/FSComp.txt.ru.xlf +++ b/src/fsharp/xlf/FSComp.txt.ru.xlf @@ -7232,6 +7232,26 @@ Недействительная карта путей. Сопоставления должны быть разделены запятыми и должны иметь формат "path=исходный_путь" + + Reference an assembly or diretory containing a design time tool (Short form: -t) + Reference an assembly or diretory 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..7b42b3b34dd 100644 --- a/src/fsharp/xlf/FSComp.txt.tr.xlf +++ b/src/fsharp/xlf/FSComp.txt.tr.xlf @@ -7232,6 +7232,26 @@ Geçersiz yol eşlemesi. Eşlemeler virgülle ayrılmış ve 'path=sourcePath' biçiminde olmalıdır + + Reference an assembly or diretory containing a design time tool (Short form: -t) + Reference an assembly or diretory 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..67acd81a6ca 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf @@ -7232,6 +7232,26 @@ 路径映射无效。映射必须以逗号分隔,且采用 "path=sourcePath" 格式 + + Reference an assembly or diretory containing a design time tool (Short form: -t) + Reference an assembly or diretory 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..c8481cb4b54 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf @@ -7232,6 +7232,26 @@ 路徑對應無效。對應必須以逗號分隔,且格式應為 'path=sourcePath' + + Reference an assembly or diretory containing a design time tool (Short form: -t) + Reference an assembly or diretory 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/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/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 b3f8c1633f8..8777ce42fc4 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/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) =