From 44b518237994597009640bbf030cfd29283c026b Mon Sep 17 00:00:00 2001 From: KevinRansom Date: Wed, 16 Nov 2022 19:59:49 -0800 Subject: [PATCH 1/3] temp --- .../SimulatedMSBuildReferenceResolver.fs | 631 +++++++++--------- 1 file changed, 312 insertions(+), 319 deletions(-) diff --git a/src/Compiler/Facilities/SimulatedMSBuildReferenceResolver.fs b/src/Compiler/Facilities/SimulatedMSBuildReferenceResolver.fs index 21d3260c5c8..b34ad624073 100644 --- a/src/Compiler/Facilities/SimulatedMSBuildReferenceResolver.fs +++ b/src/Compiler/Facilities/SimulatedMSBuildReferenceResolver.fs @@ -2,340 +2,333 @@ module internal FSharp.Compiler.CodeAnalysis.SimulatedMSBuildReferenceResolver -open System -open System.IO -open System.Reflection -open Microsoft.Build.Utilities -open Internal.Utilities.Library -open FSharp.Compiler.IO + open System + open System.IO + open System.Reflection + open Microsoft.Build.Utilities + open Internal.Utilities.Library + open FSharp.Compiler.IO + + // ATTENTION!: the following code needs to be updated every time we are switching to the new MSBuild version because new .NET framework version was released + // 1. List of frameworks + // 2. DeriveTargetFrameworkDirectoriesFor45Plus + // 3. HighestInstalledRefAssembliesOrDotNETFramework + // 4. GetPathToDotNetFrameworkImlpementationAssemblies + [] + let private Net45 = "v4.5" + + [] + let private Net451 = "v4.5.1" + + [] + let private Net452 = "v4.5.2" // not available in Dev15 MSBuild version + + [] + let private Net46 = "v4.6" + + [] + let private Net461 = "v4.6.1" + + [] + let private Net462 = "v4.6.2" + + [] + let private Net47 = "v4.7" + + [] + let private Net471 = "v4.7.1" + + [] + let private Net472 = "v4.7.2" + + [] + let private Net48 = "v4.8" + + let SupportedDesktopFrameworkVersions = + [ Net48; Net472; Net471; Net47; Net462; Net461; Net46; Net452; Net451; Net45 ] + + let private SimulatedMSBuildResolver = + + /// Get the path to the .NET Framework implementation assemblies by using ToolLocationHelper.GetPathToDotNetFramework + /// This is only used to specify the "last resort" path for assembly resolution. + let GetPathToDotNetFrameworkImlpementationAssemblies v = + let v = + match v with + | Net45 -> Some TargetDotNetFrameworkVersion.Version45 + | Net451 -> Some TargetDotNetFrameworkVersion.Version451 + | Net452 -> Some TargetDotNetFrameworkVersion.Version452 + | Net46 -> Some TargetDotNetFrameworkVersion.Version46 + | Net461 -> Some TargetDotNetFrameworkVersion.Version461 + | Net462 -> Some TargetDotNetFrameworkVersion.Version462 + | Net47 -> Some TargetDotNetFrameworkVersion.Version47 + | Net471 -> Some TargetDotNetFrameworkVersion.Version471 + | Net472 -> Some TargetDotNetFrameworkVersion.Version472 + | Net48 -> Some TargetDotNetFrameworkVersion.Version48 + | _ -> + assert false + None -// ATTENTION!: the following code needs to be updated every time we are switching to the new MSBuild version because new .NET framework version was released -// 1. List of frameworks -// 2. DeriveTargetFrameworkDirectoriesFor45Plus -// 3. HighestInstalledRefAssembliesOrDotNETFramework -// 4. GetPathToDotNetFrameworkImlpementationAssemblies -[] -let private Net45 = "v4.5" - -[] -let private Net451 = "v4.5.1" - -[] -let private Net452 = "v4.5.2" // not available in Dev15 MSBuild version + match v with + | Some v -> + match ToolLocationHelper.GetPathToDotNetFramework v with + | null -> [] + | x -> [ x ] + | _ -> [] + + let GetPathToDotNetFrameworkReferenceAssemblies version = + ignore version + let r: string list = [] + r + + { new ILegacyReferenceResolver with + member x.HighestInstalledNetFrameworkVersion() = + + let root = x.DotNetFrameworkReferenceAssembliesRootDirectory + + let fwOpt = + SupportedDesktopFrameworkVersions + |> Seq.tryFind (fun fw -> FileSystem.DirectoryExistsShim(Path.Combine(root, fw))) + + match fwOpt with + | Some fw -> fw + | None -> "v4.5" + + member _.DotNetFrameworkReferenceAssembliesRootDirectory = + if Environment.OSVersion.Platform = PlatformID.Win32NT then + let PF = + match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with + | null -> Environment.GetEnvironmentVariable("ProgramFiles") // if PFx86 is null, then we are 32-bit and just get PF + | s -> s + + PF + @"\Reference Assemblies\Microsoft\Framework\.NETFramework" + else + "" + + member _.Resolve + ( + resolutionEnvironment, + references, + targetFrameworkVersion, + targetFrameworkDirectories, + targetProcessorArchitecture, + fsharpCoreDir, + explicitIncludeDirs, + implicitIncludeDir, + logMessage, + logWarningOrError + ) = + + + let results = ResizeArray() + + let searchPaths = + [ + yield! targetFrameworkDirectories + yield! explicitIncludeDirs + yield fsharpCoreDir + yield implicitIncludeDir + yield! GetPathToDotNetFrameworkReferenceAssemblies targetFrameworkVersion + yield! GetPathToDotNetFrameworkImlpementationAssemblies targetFrameworkVersion + ] + + for r, baggage in references do + //printfn "resolving %s" r + let mutable found = false + + let success path = + if not found then + //printfn "resolved %s --> %s" r path + found <- true -[] -let private Net46 = "v4.6" + results.Add + { + itemSpec = path + prepareToolTip = snd + baggage = baggage + } -[] -let private Net461 = "v4.6.1" + try + if not found && FileSystem.IsPathRootedShim r then + if FileSystem.FileExistsShim r then success r + with e -> + logWarningOrError false "SR001" (e.ToString()) -[] -let private Net462 = "v4.6.2" + // For this one we need to get the version search exactly right, without doing a load + try + if not found + && r.StartsWithOrdinal("FSharp.Core, Version=") + && Environment.OSVersion.Platform = PlatformID.Win32NT then + let n = AssemblyName r -[] -let private Net47 = "v4.7" + let fscoreDir0 = + let PF = + match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with + | null -> Environment.GetEnvironmentVariable("ProgramFiles") + | s -> s -[] -let private Net471 = "v4.7.1" + PF + + @"\Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\" + + n.Version.ToString() -[] -let private Net472 = "v4.7.2" + let trialPath = Path.Combine(fscoreDir0, n.Name + ".dll") -[] -let private Net48 = "v4.8" + if FileSystem.FileExistsShim trialPath then + success trialPath + with e -> + logWarningOrError false "SR001" (e.ToString()) -let SupportedDesktopFrameworkVersions = - [ Net48; Net472; Net471; Net47; Net462; Net461; Net46; Net452; Net451; Net45 ] + let isFileName = + r.EndsWith("dll", StringComparison.OrdinalIgnoreCase) + || r.EndsWith("exe", StringComparison.OrdinalIgnoreCase) -let private SimulatedMSBuildResolver = + let qual = + if isFileName then + r + else + try + AssemblyName(r).Name + ".dll" + with _ -> + r + ".dll" - /// Get the path to the .NET Framework implementation assemblies by using ToolLocationHelper.GetPathToDotNetFramework - /// This is only used to specify the "last resort" path for assembly resolution. - let GetPathToDotNetFrameworkImlpementationAssemblies v = - let v = - match v with - | Net45 -> Some TargetDotNetFrameworkVersion.Version45 - | Net451 -> Some TargetDotNetFrameworkVersion.Version451 - | Net452 -> Some TargetDotNetFrameworkVersion.Version452 - | Net46 -> Some TargetDotNetFrameworkVersion.Version46 - | Net461 -> Some TargetDotNetFrameworkVersion.Version461 - | Net462 -> Some TargetDotNetFrameworkVersion.Version462 - | Net47 -> Some TargetDotNetFrameworkVersion.Version47 - | Net471 -> Some TargetDotNetFrameworkVersion.Version471 - | Net472 -> Some TargetDotNetFrameworkVersion.Version472 - | Net48 -> Some TargetDotNetFrameworkVersion.Version48 - | _ -> - assert false - None - - match v with - | Some v -> - match ToolLocationHelper.GetPathToDotNetFramework v with - | null -> [] - | x -> [ x ] - | _ -> [] - - let GetPathToDotNetFrameworkReferenceAssemblies version = -#if NETSTANDARD - ignore version - let r: string list = [] - r -#else - match Microsoft.Build.Utilities.ToolLocationHelper.GetPathToStandardLibraries(".NETFramework", version, "") with - | null - | "" -> [] - | x -> [ x ] -#endif - - { new ILegacyReferenceResolver with - member x.HighestInstalledNetFrameworkVersion() = - - let root = x.DotNetFrameworkReferenceAssembliesRootDirectory - - let fwOpt = - SupportedDesktopFrameworkVersions - |> Seq.tryFind (fun fw -> FileSystem.DirectoryExistsShim(Path.Combine(root, fw))) - - match fwOpt with - | Some fw -> fw - | None -> "v4.5" - - member _.DotNetFrameworkReferenceAssembliesRootDirectory = - if Environment.OSVersion.Platform = PlatformID.Win32NT then - let PF = - match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with - | null -> Environment.GetEnvironmentVariable("ProgramFiles") // if PFx86 is null, then we are 32-bit and just get PF - | s -> s - - PF + @"\Reference Assemblies\Microsoft\Framework\.NETFramework" - else - "" - - member _.Resolve - ( - resolutionEnvironment, - references, - targetFrameworkVersion, - targetFrameworkDirectories, - targetProcessorArchitecture, - fsharpCoreDir, - explicitIncludeDirs, - implicitIncludeDir, - logMessage, - logWarningOrError - ) = - - - let results = ResizeArray() - - let searchPaths = - [ - yield! targetFrameworkDirectories - yield! explicitIncludeDirs - yield fsharpCoreDir - yield implicitIncludeDir - yield! GetPathToDotNetFrameworkReferenceAssemblies targetFrameworkVersion - yield! GetPathToDotNetFrameworkImlpementationAssemblies targetFrameworkVersion - ] - - for r, baggage in references do - //printfn "resolving %s" r - let mutable found = false - - let success path = - if not found then - //printfn "resolved %s --> %s" r path - found <- true - - results.Add - { - itemSpec = path - prepareToolTip = snd - baggage = baggage - } - - try - if not found && FileSystem.IsPathRootedShim r then - if FileSystem.FileExistsShim r then success r - with e -> - logWarningOrError false "SR001" (e.ToString()) - - // For this one we need to get the version search exactly right, without doing a load - try - if not found - && r.StartsWithOrdinal("FSharp.Core, Version=") - && Environment.OSVersion.Platform = PlatformID.Win32NT then - let n = AssemblyName r - - let fscoreDir0 = - let PF = - match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with - | null -> Environment.GetEnvironmentVariable("ProgramFiles") - | s -> s - - PF - + @"\Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\" - + n.Version.ToString() - - let trialPath = Path.Combine(fscoreDir0, n.Name + ".dll") - - if FileSystem.FileExistsShim trialPath then - success trialPath - with e -> - logWarningOrError false "SR001" (e.ToString()) - - let isFileName = - r.EndsWith("dll", StringComparison.OrdinalIgnoreCase) - || r.EndsWith("exe", StringComparison.OrdinalIgnoreCase) - - let qual = - if isFileName then - r - else + for searchPath in searchPaths do try - AssemblyName(r).Name + ".dll" - with _ -> - r + ".dll" + if not found then + let trialPath = Path.Combine(searchPath, qual) - for searchPath in searchPaths do - try - if not found then - let trialPath = Path.Combine(searchPath, qual) + if FileSystem.FileExistsShim trialPath then + success trialPath + with e -> + logWarningOrError false "SR001" (e.ToString()) - if FileSystem.FileExistsShim trialPath then - success trialPath + try + // Search the GAC on Windows + if not found + && not isFileName + && Environment.OSVersion.Platform = PlatformID.Win32NT then + let n = AssemblyName r + let netFx = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory() + + let gac = + Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(netFx.TrimEnd('\\'))), "assembly") + + match n.Version, n.GetPublicKeyToken() with + | null, _ + | _, null -> + let options = + [ + if FileSystem.DirectoryExistsShim gac then + for gacDir in FileSystem.EnumerateDirectoriesShim gac do + let assemblyDir = Path.Combine(gacDir, n.Name) + + if FileSystem.DirectoryExistsShim assemblyDir then + for tdir in FileSystem.EnumerateDirectoriesShim assemblyDir do + let trialPath = Path.Combine(tdir, qual) + if FileSystem.FileExistsShim trialPath then yield trialPath + ] + //printfn "sorting GAC paths: %A" options + options + |> List.sort // puts latest version last + |> List.tryLast + |> function + | None -> () + | Some p -> success p + + | v, tok -> + if FileSystem.DirectoryExistsShim gac then + for gacDir in Directory.EnumerateDirectories gac do + //printfn "searching GAC directory: %s" gacDir + let assemblyDir = Path.Combine(gacDir, n.Name) + + if FileSystem.DirectoryExistsShim assemblyDir then + //printfn "searching GAC directory: %s" assemblyDir + + let tokText = String.concat "" [| for b in tok -> sprintf "%02x" b |] + let verDir = Path.Combine(assemblyDir, "v4.0_" + v.ToString() + "__" + tokText) + //printfn "searching GAC directory: %s" verDir + + if FileSystem.DirectoryExistsShim verDir then + let trialPath = Path.Combine(verDir, qual) + //printfn "searching GAC: %s" trialPath + if FileSystem.FileExistsShim trialPath then + success trialPath with e -> logWarningOrError false "SR001" (e.ToString()) - try - // Search the GAC on Windows - if not found - && not isFileName - && Environment.OSVersion.Platform = PlatformID.Win32NT then - let n = AssemblyName r - let netFx = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory() - - let gac = - Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(netFx.TrimEnd('\\'))), "assembly") - - match n.Version, n.GetPublicKeyToken() with - | null, _ - | _, null -> - let options = - [ - if FileSystem.DirectoryExistsShim gac then - for gacDir in FileSystem.EnumerateDirectoriesShim gac do - let assemblyDir = Path.Combine(gacDir, n.Name) - - if FileSystem.DirectoryExistsShim assemblyDir then - for tdir in FileSystem.EnumerateDirectoriesShim assemblyDir do - let trialPath = Path.Combine(tdir, qual) - if FileSystem.FileExistsShim trialPath then yield trialPath - ] - //printfn "sorting GAC paths: %A" options - options - |> List.sort // puts latest version last - |> List.tryLast - |> function - | None -> () - | Some p -> success p - - | v, tok -> - if FileSystem.DirectoryExistsShim gac then - for gacDir in Directory.EnumerateDirectories gac do - //printfn "searching GAC directory: %s" gacDir - let assemblyDir = Path.Combine(gacDir, n.Name) - - if FileSystem.DirectoryExistsShim assemblyDir then - //printfn "searching GAC directory: %s" assemblyDir - - let tokText = String.concat "" [| for b in tok -> sprintf "%02x" b |] - let verDir = Path.Combine(assemblyDir, "v4.0_" + v.ToString() + "__" + tokText) - //printfn "searching GAC directory: %s" verDir - - if FileSystem.DirectoryExistsShim verDir then - let trialPath = Path.Combine(verDir, qual) - //printfn "searching GAC: %s" trialPath - if FileSystem.FileExistsShim trialPath then - success trialPath - with e -> - logWarningOrError false "SR001" (e.ToString()) - - results.ToArray() - } - |> LegacyReferenceResolver - -let internal getResolver () = SimulatedMSBuildResolver - -#if INTERACTIVE -// Some manual testing -SimulatedMSBuildResolver.DotNetFrameworkReferenceAssembliesRootDirectory -SimulatedMSBuildResolver.HighestInstalledNetFrameworkVersion() - -let fscoreDir = - if System.Environment.OSVersion.Platform = System.PlatformID.Win32NT then // file references only valid on Windows - let PF = - match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with - | null -> Environment.GetEnvironmentVariable("ProgramFiles") // if PFx86 is null, then we are 32-bit and just get PF - | s -> s - - PF + @"\Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\4.4.0.0" - else - System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory() - -let resolve s = - SimulatedMSBuildResolver.Resolve( - ResolutionEnvironment.EditingOrCompilation, - [| for a in s -> (a, "") |], - "v4.5.1", + results.ToArray() + } + |> LegacyReferenceResolver + + let internal getResolver () = SimulatedMSBuildResolver + + #if INTERACTIVE + // Some manual testing + SimulatedMSBuildResolver.DotNetFrameworkReferenceAssembliesRootDirectory + SimulatedMSBuildResolver.HighestInstalledNetFrameworkVersion() + + let fscoreDir = + if System.Environment.OSVersion.Platform = System.PlatformID.Win32NT then // file references only valid on Windows + let PF = + match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with + | null -> Environment.GetEnvironmentVariable("ProgramFiles") // if PFx86 is null, then we are 32-bit and just get PF + | s -> s + + PF + @"\Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\4.4.0.0" + else + System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory() + + let resolve s = + SimulatedMSBuildResolver.Resolve( + ResolutionEnvironment.EditingOrCompilation, + [| for a in s -> (a, "") |], + "v4.5.1", + [ + SimulatedMSBuildResolver.DotNetFrameworkReferenceAssembliesRootDirectory + + @"\v4.5.1" + ], + "", + "", + fscoreDir, + [], + __SOURCE_DIRECTORY__, + ignore, + (fun _ _ -> ()), + (fun _ _ -> ()) + ) + + // Resolve partial name to something on search path + resolve [ "FSharp.Core" ] + + // Resolve DLL name to something on search path + resolve [ "FSharp.Core.dll" ] + + // Resolve from reference assemblies + resolve [ "System"; "mscorlib"; "mscorlib.dll" ] + + // Resolve from Registry AssemblyFolders + resolve [ "Microsoft.SqlServer.Dmf.dll"; "Microsoft.SqlServer.Dmf" ] + + // Resolve exact version of FSharp.Core + resolve + [ + "FSharp.Core, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" + ] + + // Resolve from GAC: + resolve + [ + "EventViewer, Version=6.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" + ] + + // Resolve from GAC: + resolve [ "EventViewer" ] + + resolve + [ + "Microsoft.SharePoint.Client, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" + ] + + resolve [ - SimulatedMSBuildResolver.DotNetFrameworkReferenceAssembliesRootDirectory - + @"\v4.5.1" - ], - "", - "", - fscoreDir, - [], - __SOURCE_DIRECTORY__, - ignore, - (fun _ _ -> ()), - (fun _ _ -> ()) - ) - -// Resolve partial name to something on search path -resolve [ "FSharp.Core" ] - -// Resolve DLL name to something on search path -resolve [ "FSharp.Core.dll" ] - -// Resolve from reference assemblies -resolve [ "System"; "mscorlib"; "mscorlib.dll" ] - -// Resolve from Registry AssemblyFolders -resolve [ "Microsoft.SqlServer.Dmf.dll"; "Microsoft.SqlServer.Dmf" ] - -// Resolve exact version of FSharp.Core -resolve - [ - "FSharp.Core, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" - ] - -// Resolve from GAC: -resolve - [ - "EventViewer, Version=6.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" - ] - -// Resolve from GAC: -resolve [ "EventViewer" ] - -resolve - [ - "Microsoft.SharePoint.Client, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" - ] - -resolve - [ - "Microsoft.SharePoint.Client, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" - ] -#endif + "Microsoft.SharePoint.Client, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" + ] + #endif From e9aab413c6870d4cd9bc1ed4ea68b69e6505203d Mon Sep 17 00:00:00 2001 From: KevinRansom Date: Wed, 16 Nov 2022 23:47:53 -0800 Subject: [PATCH 2/3] remove msbuild dependence from fcs --- eng/Versions.props | 4 +- src/Compiler/FSComp.txt | 4 -- src/Compiler/FSharp.Compiler.Service.fsproj | 5 -- src/Compiler/FSharp.Compiler.Service.nuspec | 3 -- src/Compiler/Facilities/ReferenceResolver.fs | 4 +- src/Compiler/Facilities/ReferenceResolver.fsi | 10 ++-- .../SimulatedMSBuildReferenceResolver.fs | 31 +++--------- src/Compiler/xlf/FSComp.txt.cs.xlf | 20 -------- src/Compiler/xlf/FSComp.txt.de.xlf | 20 -------- src/Compiler/xlf/FSComp.txt.es.xlf | 20 -------- src/Compiler/xlf/FSComp.txt.fr.xlf | 20 -------- src/Compiler/xlf/FSComp.txt.it.xlf | 20 -------- src/Compiler/xlf/FSComp.txt.ja.xlf | 20 -------- src/Compiler/xlf/FSComp.txt.ko.xlf | 20 -------- src/Compiler/xlf/FSComp.txt.pl.xlf | 20 -------- src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 20 -------- src/Compiler/xlf/FSComp.txt.ru.xlf | 20 -------- src/Compiler/xlf/FSComp.txt.tr.xlf | 20 -------- src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 20 -------- src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 20 -------- .../LegacyMSBuildReferenceResolver.fs | 16 ++++-- .../LegacyMSBuildReferenceResolver.fsi | 0 src/LegacyMSBuildResolver/LegacyResolver.txt | 7 +++ .../xlf/LegacyResolver.txt.cs.xlf | 27 ++++++++++ .../xlf/LegacyResolver.txt.de.xlf | 27 ++++++++++ .../xlf/LegacyResolver.txt.es.xlf | 27 ++++++++++ .../xlf/LegacyResolver.txt.fr.xlf | 27 ++++++++++ .../xlf/LegacyResolver.txt.it.xlf | 27 ++++++++++ .../xlf/LegacyResolver.txt.ja.xlf | 27 ++++++++++ .../xlf/LegacyResolver.txt.ko.xlf | 27 ++++++++++ .../xlf/LegacyResolver.txt.pl.xlf | 27 ++++++++++ .../xlf/LegacyResolver.txt.pt-BR.xlf | 27 ++++++++++ .../xlf/LegacyResolver.txt.ru.xlf | 27 ++++++++++ .../xlf/LegacyResolver.txt.tr.xlf | 27 ++++++++++ .../xlf/LegacyResolver.txt.zh-Hans.xlf | 27 ++++++++++ .../xlf/LegacyResolver.txt.zh-Hant.xlf | 27 ++++++++++ src/fsc/fsc.targets | 8 +++ src/fsi/fsi.targets | 11 +++++ ...erService.SurfaceArea.netstandard.expected | 49 ++++++++++++++++++- .../HostedCompilerServer.fsproj | 11 +++++ .../src/FSharp.Editor/FSharp.Editor.fsproj | 5 ++ 41 files changed, 469 insertions(+), 310 deletions(-) rename src/{Compiler/Legacy => LegacyMSBuildResolver}/LegacyMSBuildReferenceResolver.fs (97%) rename src/{Compiler/Legacy => LegacyMSBuildResolver}/LegacyMSBuildReferenceResolver.fsi (100%) create mode 100644 src/LegacyMSBuildResolver/LegacyResolver.txt create mode 100644 src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.cs.xlf create mode 100644 src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.de.xlf create mode 100644 src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.es.xlf create mode 100644 src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.fr.xlf create mode 100644 src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.it.xlf create mode 100644 src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ja.xlf create mode 100644 src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ko.xlf create mode 100644 src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.pl.xlf create mode 100644 src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.pt-BR.xlf create mode 100644 src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ru.xlf create mode 100644 src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.tr.xlf create mode 100644 src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.zh-Hans.xlf create mode 100644 src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.zh-Hant.xlf diff --git a/eng/Versions.props b/eng/Versions.props index 59553717f2f..979442cba5e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -31,9 +31,9 @@ 6.0.0.0 - 42 + 43 7 - 100 + 102 $(FSRevisionVersion) $(FCSMajorVersion).$(FCSMinorVersion).$(FCSBuildVersion) $(FCSMajorVersion).$(FCSMinorVersion).$(FCSBuildVersion).$(FCSRevisionVersion) diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 53cfa341667..2fca7afeb60 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -962,10 +962,6 @@ typeInfoFromFirst,"from %s" typeInfoFromNext,"also from %s" typeInfoGeneratedProperty,"generated property" typeInfoGeneratedType,"generated type" -assemblyResolutionFoundByAssemblyFoldersKey,"Found by AssemblyFolders registry key" -assemblyResolutionFoundByAssemblyFoldersExKey,"Found by AssemblyFoldersEx registry key" -assemblyResolutionNetFramework,".NET Framework" -assemblyResolutionGAC,"Global Assembly Cache" 1089,recursiveClassHierarchy,"Recursive class hierarchy in type '%s'" 1090,InvalidRecursiveReferenceToAbstractSlot,"Invalid recursive reference to an abstract slot" 1091,eventHasNonStandardType,"The event '%s' has a non-standard type. If this event is declared in another CLI language, you may need to access this event using the explicit %s and %s methods for the event. If this event is declared in F#, make the type of the event an instantiation of either 'IDelegateEvent<_>' or 'IEvent<_,_>'." diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj index e7468b34086..eedb771f0f3 100644 --- a/src/Compiler/FSharp.Compiler.Service.fsproj +++ b/src/Compiler/FSharp.Compiler.Service.fsproj @@ -461,8 +461,6 @@ - - @@ -492,9 +490,6 @@ - - - diff --git a/src/Compiler/FSharp.Compiler.Service.nuspec b/src/Compiler/FSharp.Compiler.Service.nuspec index c7b55ebb613..a60bdb81021 100644 --- a/src/Compiler/FSharp.Compiler.Service.nuspec +++ b/src/Compiler/FSharp.Compiler.Service.nuspec @@ -6,9 +6,6 @@ - - - diff --git a/src/Compiler/Facilities/ReferenceResolver.fs b/src/Compiler/Facilities/ReferenceResolver.fs index d4eeb29871d..7e825741942 100644 --- a/src/Compiler/Facilities/ReferenceResolver.fs +++ b/src/Compiler/Facilities/ReferenceResolver.fs @@ -2,7 +2,7 @@ namespace FSharp.Compiler.CodeAnalysis -exception internal LegacyResolutionFailure +exception LegacyResolutionFailure [] type LegacyResolutionEnvironment = @@ -28,7 +28,7 @@ type LegacyResolvedFile = sprintf "LegacyResolvedFile(%s)" this.itemSpec [] -type internal ILegacyReferenceResolver = +type ILegacyReferenceResolver = /// Get the "v4.5.1"-style moniker for the highest installed .NET Framework version. /// This is the value passed back to Resolve if no explicit "mscorlib" has been given. /// diff --git a/src/Compiler/Facilities/ReferenceResolver.fsi b/src/Compiler/Facilities/ReferenceResolver.fsi index 619c21d423c..8371775f956 100644 --- a/src/Compiler/Facilities/ReferenceResolver.fsi +++ b/src/Compiler/Facilities/ReferenceResolver.fsi @@ -4,17 +4,17 @@ namespace FSharp.Compiler.CodeAnalysis open System -exception internal LegacyResolutionFailure +exception LegacyResolutionFailure [] -type internal LegacyResolutionEnvironment = +type LegacyResolutionEnvironment = /// Indicates a script or source being edited or compiled. Uses reference assemblies (not implementation assemblies). | EditingOrCompilation of isEditing: bool /// Indicates a script or source being dynamically compiled and executed. Uses implementation assemblies. | CompilationAndEvaluation -type internal LegacyResolvedFile = +type LegacyResolvedFile = { /// Item specification. itemSpec: string @@ -27,7 +27,7 @@ type internal LegacyResolvedFile = } [] -type internal ILegacyReferenceResolver = +type ILegacyReferenceResolver = /// Get the "v4.5.1"-style moniker for the highest installed .NET Framework version. /// This is the value passed back to Resolve if no explicit "mscorlib" has been given. /// @@ -59,5 +59,5 @@ type internal ILegacyReferenceResolver = // outside FSharp.Compiler.Service [] type LegacyReferenceResolver = - internal new: impl: ILegacyReferenceResolver -> LegacyReferenceResolver + new: impl: ILegacyReferenceResolver -> LegacyReferenceResolver member internal Impl: ILegacyReferenceResolver diff --git a/src/Compiler/Facilities/SimulatedMSBuildReferenceResolver.fs b/src/Compiler/Facilities/SimulatedMSBuildReferenceResolver.fs index b34ad624073..b3492cb81ac 100644 --- a/src/Compiler/Facilities/SimulatedMSBuildReferenceResolver.fs +++ b/src/Compiler/Facilities/SimulatedMSBuildReferenceResolver.fs @@ -5,7 +5,6 @@ module internal FSharp.Compiler.CodeAnalysis.SimulatedMSBuildReferenceResolver open System open System.IO open System.Reflection - open Microsoft.Build.Utilities open Internal.Utilities.Library open FSharp.Compiler.IO @@ -51,29 +50,14 @@ module internal FSharp.Compiler.CodeAnalysis.SimulatedMSBuildReferenceResolver /// Get the path to the .NET Framework implementation assemblies by using ToolLocationHelper.GetPathToDotNetFramework /// This is only used to specify the "last resort" path for assembly resolution. - let GetPathToDotNetFrameworkImlpementationAssemblies v = - let v = - match v with - | Net45 -> Some TargetDotNetFrameworkVersion.Version45 - | Net451 -> Some TargetDotNetFrameworkVersion.Version451 - | Net452 -> Some TargetDotNetFrameworkVersion.Version452 - | Net46 -> Some TargetDotNetFrameworkVersion.Version46 - | Net461 -> Some TargetDotNetFrameworkVersion.Version461 - | Net462 -> Some TargetDotNetFrameworkVersion.Version462 - | Net47 -> Some TargetDotNetFrameworkVersion.Version47 - | Net471 -> Some TargetDotNetFrameworkVersion.Version471 - | Net472 -> Some TargetDotNetFrameworkVersion.Version472 - | Net48 -> Some TargetDotNetFrameworkVersion.Version48 - | _ -> - assert false - None - - match v with - | Some v -> - match ToolLocationHelper.GetPathToDotNetFramework v with + let GetPathToDotNetFrameworkImlpementationAssemblies _ = + let isDesktop = typeof.Assembly.GetName().Name = "mscorlib" + if isDesktop then + match System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory() with | null -> [] | x -> [ x ] - | _ -> [] + else + [] let GetPathToDotNetFrameworkReferenceAssemblies version = ignore version @@ -91,7 +75,8 @@ module internal FSharp.Compiler.CodeAnalysis.SimulatedMSBuildReferenceResolver match fwOpt with | Some fw -> fw - | None -> "v4.5" + | None -> Net45 + member _.DotNetFrameworkReferenceAssembliesRootDirectory = if Environment.OSVersion.Platform = PlatformID.Win32NT then diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index 2afccb1fd40..9f1b557acbe 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -5662,26 +5662,6 @@ generovaný typ - - Found by AssemblyFolders registry key - Nalezené klíčem registru AssemblyFolders - - - - Found by AssemblyFoldersEx registry key - Nalezené klíčem registru AssemblyFoldersEx - - - - .NET Framework - .NET Framework - - - - Global Assembly Cache - Globální mezipaměť sestavení - - Recursive class hierarchy in type '{0}' Rekurzivní hierarchie tříd u typu {0} diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index b0eec3044bc..fad70824e36 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -5662,26 +5662,6 @@ Generierter Typ - - Found by AssemblyFolders registry key - Von AssemblyFolders-Registrierungsschlüssel gefunden - - - - Found by AssemblyFoldersEx registry key - Von AssemblyFoldersEx-Registrierungsschlüssel gefunden - - - - .NET Framework - .NET Framework - - - - Global Assembly Cache - Globaler Assemblycache - - Recursive class hierarchy in type '{0}' Rekursive Klassenhierarchie in Typ "{0}". diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 89d57eacb65..5402a968afd 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -5662,26 +5662,6 @@ tipo generado - - Found by AssemblyFolders registry key - Encontrado por la clave del Registro AssemblyFolders. - - - - Found by AssemblyFoldersEx registry key - Encontrado por la clave del Registro AssemblyFoldersEx. - - - - .NET Framework - .NET Framework - - - - Global Assembly Cache - Caché global de ensamblados - - Recursive class hierarchy in type '{0}' Jerarquía de clases recursiva en el tipo '{0}'. diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 2db2d58f88f..aadf83ade0e 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -5662,26 +5662,6 @@ type généré - - Found by AssemblyFolders registry key - Trouvée par la clé de Registre AssemblyFolders - - - - Found by AssemblyFoldersEx registry key - Trouvée par la clé de Registre AssemblyFoldersEx - - - - .NET Framework - .NET Framework - - - - Global Assembly Cache - Global Assembly Cache - - Recursive class hierarchy in type '{0}' Hiérarchie de classes récursive dans le type '{0}' diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 66011450a6b..8b681eb4a16 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -5662,26 +5662,6 @@ tipo generato - - Found by AssemblyFolders registry key - Trovata mediante la chiave del Registro di sistema AssemblyFolders - - - - Found by AssemblyFoldersEx registry key - Trovata mediante chiave del Registro di sistema AssemblyFoldersEx - - - - .NET Framework - .NET Framework - - - - Global Assembly Cache - Global Assembly Cache - - Recursive class hierarchy in type '{0}' Gerarchia di classi ricorsiva nel tipo '{0}' diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 0ba2173b8fc..4b6c944481a 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -5662,26 +5662,6 @@ 生成された型 - - Found by AssemblyFolders registry key - AssemblyFolders レジストリ キーによって検出されました - - - - Found by AssemblyFoldersEx registry key - AssemblyFoldersEx レジストリ キーによって検出されました - - - - .NET Framework - .NET Framework - - - - Global Assembly Cache - グローバル アセンブリ キャッシュ - - Recursive class hierarchy in type '{0}' 型 '{0}' の再帰的クラス階層 diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index e97d0cf2eb2..40973f9e1a9 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -5662,26 +5662,6 @@ 생성된 형식 - - Found by AssemblyFolders registry key - AssemblyFolders 레지스트리 키로 찾았습니다. - - - - Found by AssemblyFoldersEx registry key - AssemblyFoldersEx 레지스트리 키로 찾았습니다. - - - - .NET Framework - .NET Framework - - - - Global Assembly Cache - 전역 어셈블리 캐시 - - Recursive class hierarchy in type '{0}' '{0}' 형식에 재귀적 클래스 계층 구조가 있습니다. diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index d39b72ca26f..9b4b9dab2eb 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -5662,26 +5662,6 @@ wygenerowany typ - - Found by AssemblyFolders registry key - Znalezione przez klucz rejestru AssemblyFolders - - - - Found by AssemblyFoldersEx registry key - Znalezione przez klucz rejestru AssemblyFoldersEx - - - - .NET Framework - .NET Framework - - - - Global Assembly Cache - Globalna pamięć podręczna zestawów - - Recursive class hierarchy in type '{0}' Cykliczna hierarchia klas w typie „{0}” diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 09d70721f8a..3307d01761c 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -5662,26 +5662,6 @@ tipo gerado - - Found by AssemblyFolders registry key - Localizada pela chave de registro AssemblyFolders - - - - Found by AssemblyFoldersEx registry key - Localizada pela chave de registro AssemblyFoldersEx - - - - .NET Framework - .NET Framework - - - - Global Assembly Cache - Cache de Assembly Global - - Recursive class hierarchy in type '{0}' Hierarquia de classe recursiva no tipo '{0}' diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 01249439e53..d9de5f772a1 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -5662,26 +5662,6 @@ созданный тип - - Found by AssemblyFolders registry key - Найдено по разделу реестра AssemblyFolders - - - - Found by AssemblyFoldersEx registry key - Найдено по разделу реестра AssemblyFoldersEx - - - - .NET Framework - .NET Framework - - - - Global Assembly Cache - Глобальный кэш сборок - - Recursive class hierarchy in type '{0}' Рекурсивная иерархия классов в типе "{0}" diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 113d6a42396..3cd9f827dc1 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -5662,26 +5662,6 @@ oluşturulan tür - - Found by AssemblyFolders registry key - AssemblyFolders kayıt defteri anahtarı ile bulunur - - - - Found by AssemblyFoldersEx registry key - AssemblyFoldersEx kayıt defteri anahtarı ile bulunur - - - - .NET Framework - .NET Framework - - - - Global Assembly Cache - Genel Bütünleştirilmiş Kod Önbelleği - - Recursive class hierarchy in type '{0}' '{0}' türünde özyinelemeli sınıf hiyerarşisi diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index b6a766f9cd5..d733d0c1038 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -5662,26 +5662,6 @@ 生成的类型 - - Found by AssemblyFolders registry key - 已由 AssemblyFolders 注册表项找到 - - - - Found by AssemblyFoldersEx registry key - 已由 AssemblyFoldersEx 注册表项找到 - - - - .NET Framework - .NET Framework - - - - Global Assembly Cache - 全局程序集缓存 - - Recursive class hierarchy in type '{0}' 类型“{0}”中的递归类层次结构 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index f404d766e1c..1d7aec7be9d 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -5662,26 +5662,6 @@ 產生的類型 - - Found by AssemblyFolders registry key - 依 AssemblyFolders 登錄機碼找到 - - - - Found by AssemblyFoldersEx registry key - 依 AssemblyFoldersEx 登錄機碼找到 - - - - .NET Framework - .NET Framework - - - - Global Assembly Cache - 全域組件快取 - - Recursive class hierarchy in type '{0}' 類型 '{0}' 中有遞迴的類別階層 diff --git a/src/Compiler/Legacy/LegacyMSBuildReferenceResolver.fs b/src/LegacyMSBuildResolver/LegacyMSBuildReferenceResolver.fs similarity index 97% rename from src/Compiler/Legacy/LegacyMSBuildReferenceResolver.fs rename to src/LegacyMSBuildResolver/LegacyMSBuildReferenceResolver.fs index 516695e7e18..39afa0a84d3 100644 --- a/src/Compiler/Legacy/LegacyMSBuildReferenceResolver.fs +++ b/src/LegacyMSBuildResolver/LegacyMSBuildReferenceResolver.fs @@ -16,6 +16,12 @@ module FSharp.Compiler.CodeAnalysis.LegacyMSBuildReferenceResolver member this.GetPropertyValue(propName) = this.GetType().GetProperty(propName, BindingFlags.Public).GetValue(this, null) + /// Match on the nullness of an argument. + let inline (|Null|NonNull|) (x: 'T) : Choice = + match x with + | null -> Null + | v -> NonNull v + /// Get the Reference Assemblies directory for the .NET Framework on Window. let DotNetFrameworkReferenceAssembliesRootDirectory = // ProgramFilesX86 is correct for both x86 and x64 architectures @@ -184,15 +190,15 @@ module FSharp.Compiler.CodeAnalysis.LegacyMSBuildReferenceResolver | AssemblyFolders -> lineIfExists resolvedPath + lineIfExists fusionName - + FSComp.SR.assemblyResolutionFoundByAssemblyFoldersKey() + + LegacyResolver.SR.assemblyResolutionFoundByAssemblyFoldersKey() | AssemblyFoldersEx -> lineIfExists resolvedPath + lineIfExists fusionName - + FSComp.SR.assemblyResolutionFoundByAssemblyFoldersExKey() + + LegacyResolver.SR.assemblyResolutionFoundByAssemblyFoldersExKey() | TargetFrameworkDirectory -> lineIfExists resolvedPath + lineIfExists fusionName - + FSComp.SR.assemblyResolutionNetFramework() + + LegacyResolver.SR.assemblyResolutionNetFramework() | Unknown -> // Unknown when resolved by plain directory search without help from MSBuild resolver. lineIfExists resolvedPath @@ -201,7 +207,7 @@ module FSharp.Compiler.CodeAnalysis.LegacyMSBuildReferenceResolver lineIfExists fusionName | GlobalAssemblyCache -> lineIfExists fusionName - + lineIfExists (FSComp.SR.assemblyResolutionGAC()) + + lineIfExists (LegacyResolver.SR.assemblyResolutionGAC()) + lineIfExists redist | Path _ -> lineIfExists resolvedPath @@ -315,6 +321,8 @@ module FSharp.Compiler.CodeAnalysis.LegacyMSBuildReferenceResolver prepareToolTip = TooltipForResolvedFrom(resolvedFrom, fusionName, redist) baggage = p.GetMetadata("Baggage") } |] + resolvedFiles + |> Array.iter(fun f -> printf $"XXXX: {f.itemSpec}") resolvedFiles let getResolver () = diff --git a/src/Compiler/Legacy/LegacyMSBuildReferenceResolver.fsi b/src/LegacyMSBuildResolver/LegacyMSBuildReferenceResolver.fsi similarity index 100% rename from src/Compiler/Legacy/LegacyMSBuildReferenceResolver.fsi rename to src/LegacyMSBuildResolver/LegacyMSBuildReferenceResolver.fsi diff --git a/src/LegacyMSBuildResolver/LegacyResolver.txt b/src/LegacyMSBuildResolver/LegacyResolver.txt new file mode 100644 index 00000000000..1aac6347541 --- /dev/null +++ b/src/LegacyMSBuildResolver/LegacyResolver.txt @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------- +# use a completely new error number and keep messages in their surrounding groups +# ------------------------------------------------------------------------------- +assemblyResolutionFoundByAssemblyFoldersKey,"Found by AssemblyFolders registry key" +assemblyResolutionFoundByAssemblyFoldersExKey,"Found by AssemblyFoldersEx registry key" +assemblyResolutionNetFramework,".NET Framework" +assemblyResolutionGAC,"Global Assembly Cache" \ No newline at end of file diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.cs.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.cs.xlf new file mode 100644 index 00000000000..fe16dc84f65 --- /dev/null +++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.cs.xlf @@ -0,0 +1,27 @@ + + + + + + Found by AssemblyFoldersEx registry key + Found by AssemblyFoldersEx registry key + + + + Found by AssemblyFolders registry key + Found by AssemblyFolders registry key + + + + Global Assembly Cache + Global Assembly Cache + + + + .NET Framework + .NET Framework + + + + + \ No newline at end of file diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.de.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.de.xlf new file mode 100644 index 00000000000..0980cec838a --- /dev/null +++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.de.xlf @@ -0,0 +1,27 @@ + + + + + + Found by AssemblyFoldersEx registry key + Found by AssemblyFoldersEx registry key + + + + Found by AssemblyFolders registry key + Found by AssemblyFolders registry key + + + + Global Assembly Cache + Global Assembly Cache + + + + .NET Framework + .NET Framework + + + + + \ No newline at end of file diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.es.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.es.xlf new file mode 100644 index 00000000000..ae938d2cacd --- /dev/null +++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.es.xlf @@ -0,0 +1,27 @@ + + + + + + Found by AssemblyFoldersEx registry key + Found by AssemblyFoldersEx registry key + + + + Found by AssemblyFolders registry key + Found by AssemblyFolders registry key + + + + Global Assembly Cache + Global Assembly Cache + + + + .NET Framework + .NET Framework + + + + + \ No newline at end of file diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.fr.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.fr.xlf new file mode 100644 index 00000000000..7fe41477230 --- /dev/null +++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.fr.xlf @@ -0,0 +1,27 @@ + + + + + + Found by AssemblyFoldersEx registry key + Found by AssemblyFoldersEx registry key + + + + Found by AssemblyFolders registry key + Found by AssemblyFolders registry key + + + + Global Assembly Cache + Global Assembly Cache + + + + .NET Framework + .NET Framework + + + + + \ No newline at end of file diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.it.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.it.xlf new file mode 100644 index 00000000000..d20390cc87e --- /dev/null +++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.it.xlf @@ -0,0 +1,27 @@ + + + + + + Found by AssemblyFoldersEx registry key + Found by AssemblyFoldersEx registry key + + + + Found by AssemblyFolders registry key + Found by AssemblyFolders registry key + + + + Global Assembly Cache + Global Assembly Cache + + + + .NET Framework + .NET Framework + + + + + \ No newline at end of file diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ja.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ja.xlf new file mode 100644 index 00000000000..2f2fbca84a3 --- /dev/null +++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ja.xlf @@ -0,0 +1,27 @@ + + + + + + Found by AssemblyFoldersEx registry key + Found by AssemblyFoldersEx registry key + + + + Found by AssemblyFolders registry key + Found by AssemblyFolders registry key + + + + Global Assembly Cache + Global Assembly Cache + + + + .NET Framework + .NET Framework + + + + + \ No newline at end of file diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ko.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ko.xlf new file mode 100644 index 00000000000..a57ff6c0dc3 --- /dev/null +++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ko.xlf @@ -0,0 +1,27 @@ + + + + + + Found by AssemblyFoldersEx registry key + Found by AssemblyFoldersEx registry key + + + + Found by AssemblyFolders registry key + Found by AssemblyFolders registry key + + + + Global Assembly Cache + Global Assembly Cache + + + + .NET Framework + .NET Framework + + + + + \ No newline at end of file diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.pl.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.pl.xlf new file mode 100644 index 00000000000..49133a8479c --- /dev/null +++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.pl.xlf @@ -0,0 +1,27 @@ + + + + + + Found by AssemblyFoldersEx registry key + Found by AssemblyFoldersEx registry key + + + + Found by AssemblyFolders registry key + Found by AssemblyFolders registry key + + + + Global Assembly Cache + Global Assembly Cache + + + + .NET Framework + .NET Framework + + + + + \ No newline at end of file diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.pt-BR.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.pt-BR.xlf new file mode 100644 index 00000000000..fbfa95dbf16 --- /dev/null +++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.pt-BR.xlf @@ -0,0 +1,27 @@ + + + + + + Found by AssemblyFoldersEx registry key + Found by AssemblyFoldersEx registry key + + + + Found by AssemblyFolders registry key + Found by AssemblyFolders registry key + + + + Global Assembly Cache + Global Assembly Cache + + + + .NET Framework + .NET Framework + + + + + \ No newline at end of file diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ru.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ru.xlf new file mode 100644 index 00000000000..c01f76a7296 --- /dev/null +++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ru.xlf @@ -0,0 +1,27 @@ + + + + + + Found by AssemblyFoldersEx registry key + Found by AssemblyFoldersEx registry key + + + + Found by AssemblyFolders registry key + Found by AssemblyFolders registry key + + + + Global Assembly Cache + Global Assembly Cache + + + + .NET Framework + .NET Framework + + + + + \ No newline at end of file diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.tr.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.tr.xlf new file mode 100644 index 00000000000..3131d7674af --- /dev/null +++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.tr.xlf @@ -0,0 +1,27 @@ + + + + + + Found by AssemblyFoldersEx registry key + Found by AssemblyFoldersEx registry key + + + + Found by AssemblyFolders registry key + Found by AssemblyFolders registry key + + + + Global Assembly Cache + Global Assembly Cache + + + + .NET Framework + .NET Framework + + + + + \ No newline at end of file diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.zh-Hans.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.zh-Hans.xlf new file mode 100644 index 00000000000..7791accdff9 --- /dev/null +++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.zh-Hans.xlf @@ -0,0 +1,27 @@ + + + + + + Found by AssemblyFoldersEx registry key + Found by AssemblyFoldersEx registry key + + + + Found by AssemblyFolders registry key + Found by AssemblyFolders registry key + + + + Global Assembly Cache + Global Assembly Cache + + + + .NET Framework + .NET Framework + + + + + \ No newline at end of file diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.zh-Hant.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.zh-Hant.xlf new file mode 100644 index 00000000000..52a305821cf --- /dev/null +++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.zh-Hant.xlf @@ -0,0 +1,27 @@ + + + + + + Found by AssemblyFoldersEx registry key + Found by AssemblyFoldersEx registry key + + + + Found by AssemblyFolders registry key + Found by AssemblyFolders registry key + + + + Global Assembly Cache + Global Assembly Cache + + + + .NET Framework + .NET Framework + + + + + \ No newline at end of file diff --git a/src/fsc/fsc.targets b/src/fsc/fsc.targets index af1998e9bbe..6dccff1eae3 100644 --- a/src/fsc/fsc.targets +++ b/src/fsc/fsc.targets @@ -28,6 +28,11 @@ + + LegacyResolver.txt + + + {{FSCoreVersion}} @@ -46,6 +51,9 @@ + + + diff --git a/src/fsi/fsi.targets b/src/fsi/fsi.targets index 23ee6e76bfc..e553c55cf1c 100644 --- a/src/fsi/fsi.targets +++ b/src/fsi/fsi.targets @@ -32,6 +32,11 @@ + + LegacyResolver.txt + + + @@ -54,4 +59,10 @@ + + + + + + \ No newline at end of file diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected index 52360afde2a..5c85f5131fa 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -2191,9 +2191,54 @@ FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: Boolean Equals(Syste FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: Int32 GetHashCode() FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: Int32 GetHashCode(System.Collections.IEqualityComparer) FSharp.Compiler.CodeAnalysis.FSharpUnresolvedReferencesSet: System.String ToString() -FSharp.Compiler.CodeAnalysis.LegacyMSBuildReferenceResolver -FSharp.Compiler.CodeAnalysis.LegacyMSBuildReferenceResolver: FSharp.Compiler.CodeAnalysis.LegacyReferenceResolver getResolver() +FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver +FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver: FSharp.Compiler.CodeAnalysis.LegacyResolvedFile[] Resolve(FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment, System.Tuple`2[System.String,System.String][], System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String], System.String, System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String], System.String, Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Core.FSharpFunc`2[System.Boolean,Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Core.FSharpFunc`2[System.String,Microsoft.FSharp.Core.Unit]]]) +FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver: System.String DotNetFrameworkReferenceAssembliesRootDirectory +FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver: System.String HighestInstalledNetFrameworkVersion() +FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver: System.String get_DotNetFrameworkReferenceAssembliesRootDirectory() FSharp.Compiler.CodeAnalysis.LegacyReferenceResolver +FSharp.Compiler.CodeAnalysis.LegacyReferenceResolver: Void .ctor(FSharp.Compiler.CodeAnalysis.ILegacyReferenceResolver) +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment+EditingOrCompilation: Boolean get_isEditing() +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment+EditingOrCompilation: Boolean isEditing +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment+Tags: Int32 CompilationAndEvaluation +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment+Tags: Int32 EditingOrCompilation +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: Boolean Equals(FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment) +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: Boolean Equals(System.Object) +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: Boolean Equals(System.Object, System.Collections.IEqualityComparer) +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: Boolean IsCompilationAndEvaluation +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: Boolean IsEditingOrCompilation +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: Boolean get_IsCompilationAndEvaluation() +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: Boolean get_IsEditingOrCompilation() +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment CompilationAndEvaluation +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment NewEditingOrCompilation(Boolean) +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment get_CompilationAndEvaluation() +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment+EditingOrCompilation +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment+Tags +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: Int32 CompareTo(FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment) +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: Int32 CompareTo(System.Object) +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: Int32 CompareTo(System.Object, System.Collections.IComparer) +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: Int32 GetHashCode() +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: Int32 GetHashCode(System.Collections.IEqualityComparer) +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: Int32 Tag +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: Int32 get_Tag() +FSharp.Compiler.CodeAnalysis.LegacyResolutionEnvironment: System.String ToString() +FSharp.Compiler.CodeAnalysis.LegacyResolutionFailure +FSharp.Compiler.CodeAnalysis.LegacyResolutionFailure: Boolean Equals(System.Object) +FSharp.Compiler.CodeAnalysis.LegacyResolutionFailure: Boolean Equals(System.Object, System.Collections.IEqualityComparer) +FSharp.Compiler.CodeAnalysis.LegacyResolutionFailure: Int32 GetHashCode() +FSharp.Compiler.CodeAnalysis.LegacyResolutionFailure: Int32 GetHashCode(System.Collections.IEqualityComparer) +FSharp.Compiler.CodeAnalysis.LegacyResolutionFailure: System.String get_Message() +FSharp.Compiler.CodeAnalysis.LegacyResolutionFailure: Void .ctor() +FSharp.Compiler.CodeAnalysis.LegacyResolvedFile +FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`2[System.String,System.String],System.String] get_prepareToolTip() +FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`2[System.String,System.String],System.String] prepareToolTip +FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: System.String ToString() +FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: System.String baggage +FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: System.String get_baggage() +FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: System.String get_itemSpec() +FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: System.String itemSpec +FSharp.Compiler.CodeAnalysis.LegacyResolvedFile: Void .ctor(System.String, Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`2[System.String,System.String],System.String], System.String) FSharp.Compiler.CompilerEnvironment FSharp.Compiler.CompilerEnvironment: Boolean IsCheckerSupportedSubcategory(System.String) FSharp.Compiler.CompilerEnvironment: Boolean IsCompilable(System.String) diff --git a/tests/fsharpqa/testenv/src/HostedCompilerServer/HostedCompilerServer.fsproj b/tests/fsharpqa/testenv/src/HostedCompilerServer/HostedCompilerServer.fsproj index a697caba11a..e417791c80d 100644 --- a/tests/fsharpqa/testenv/src/HostedCompilerServer/HostedCompilerServer.fsproj +++ b/tests/fsharpqa/testenv/src/HostedCompilerServer/HostedCompilerServer.fsproj @@ -15,6 +15,11 @@ + + LegacyResolver.txt + + + @@ -24,4 +29,10 @@ + + + + + + diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index db217723e13..d27151bf5e5 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -22,6 +22,11 @@ true Microsoft.VisualStudio.FSharp.Editor.SR + + LegacyResolver.txt + + + From c0fc10b7512a060d7b84d934686a5f8377765ec3 Mon Sep 17 00:00:00 2001 From: KevinRansom Date: Thu, 17 Nov 2022 09:29:13 -0800 Subject: [PATCH 3/3] remove temp diagnostic --- .../LegacyMSBuildReferenceResolver.fs | 756 +++++++++++------- 1 file changed, 449 insertions(+), 307 deletions(-) diff --git a/src/LegacyMSBuildResolver/LegacyMSBuildReferenceResolver.fs b/src/LegacyMSBuildResolver/LegacyMSBuildReferenceResolver.fs index 39afa0a84d3..977372d675a 100644 --- a/src/LegacyMSBuildResolver/LegacyMSBuildReferenceResolver.fs +++ b/src/LegacyMSBuildResolver/LegacyMSBuildReferenceResolver.fs @@ -2,282 +2,381 @@ module FSharp.Compiler.CodeAnalysis.LegacyMSBuildReferenceResolver - open System - open System.IO - open System.Reflection - open Internal.Utilities.Library - open Microsoft.Build.Tasks - open Microsoft.Build.Utilities - open Microsoft.Build.Framework - open FSharp.Compiler.IO - - // Reflection wrapper for properties - type Object with - member this.GetPropertyValue(propName) = - this.GetType().GetProperty(propName, BindingFlags.Public).GetValue(this, null) - - /// Match on the nullness of an argument. - let inline (|Null|NonNull|) (x: 'T) : Choice = - match x with - | null -> Null - | v -> NonNull v - - /// Get the Reference Assemblies directory for the .NET Framework on Window. - let DotNetFrameworkReferenceAssembliesRootDirectory = - // ProgramFilesX86 is correct for both x86 and x64 architectures - // (the reference assemblies are always in the 32-bit location, which is PF(x86) on an x64 machine) - let PF = - match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with - | Null -> Environment.GetEnvironmentVariable("ProgramFiles") // if PFx86 is null, then we are 32-bit and just get PF - | NonNull s -> s - PF + @"\Reference Assemblies\Microsoft\Framework\.NETFramework" - - /// When targeting .NET 2.0-3.5 on Windows, we expand the {WindowsFramework} and {ReferenceAssemblies} paths manually - let internal ReplaceVariablesForLegacyFxOnWindows(dirs: string list) = - let windowsFramework = Environment.GetEnvironmentVariable("windir")+ @"\Microsoft.NET\Framework" - let referenceAssemblies = DotNetFrameworkReferenceAssembliesRootDirectory - dirs |> List.map(fun d -> d.Replace("{WindowsFramework}",windowsFramework).Replace("{ReferenceAssemblies}",referenceAssemblies)) - - // ATTENTION!: the following code needs to be updated every time we are switching to the new MSBuild version because new .NET framework version was released - // 1. List of frameworks - // 2. DeriveTargetFrameworkDirectoriesFor45Plus - // 3. HighestInstalledRefAssembliesOrDotNETFramework - // 4. GetPathToDotNetFrameworkImlpementationAssemblies - [] - let private Net45 = "v4.5" - - [] - let private Net451 = "v4.5.1" - - [] - let private Net452 = "v4.5.2" // not available in Dev15 MSBuild version - - [] - let private Net46 = "v4.6" - - [] - let private Net461 = "v4.6.1" - - [] - let private Net462 = "v4.6.2" - - [] - let private Net47 = "v4.7" - - [] - let private Net471 = "v4.7.1" - - [] - let private Net472 = "v4.7.2" - - [] - let private Net48 = "v4.8" - - let SupportedDesktopFrameworkVersions = [ Net48; Net472; Net471; Net47; Net462; Net461; Net46; Net452; Net451; Net45 ] - - /// Get the path to the .NET Framework implementation assemblies by using ToolLocationHelper.GetPathToDotNetFramework - /// This is only used to specify the "last resort" path for assembly resolution. - let GetPathToDotNetFrameworkImlpementationAssemblies v : string list = - let v = - match v with - | Net45 -> Some TargetDotNetFrameworkVersion.Version45 - | Net451 -> Some TargetDotNetFrameworkVersion.Version451 - | Net452 -> Some TargetDotNetFrameworkVersion.Version452 - | Net46 -> Some TargetDotNetFrameworkVersion.Version46 - | Net461 -> Some TargetDotNetFrameworkVersion.Version461 - | Net462 -> Some TargetDotNetFrameworkVersion.Version462 - | Net47 -> Some TargetDotNetFrameworkVersion.Version47 - | Net471 -> Some TargetDotNetFrameworkVersion.Version471 - | Net472 -> Some TargetDotNetFrameworkVersion.Version472 - | Net48 -> Some TargetDotNetFrameworkVersion.Version48 - | _ -> assert false; None +open System +open System.IO +open System.Reflection +open Internal.Utilities.Library +open Microsoft.Build.Tasks +open Microsoft.Build.Utilities +open Microsoft.Build.Framework +open FSharp.Compiler.IO + +// Reflection wrapper for properties +type Object with + + member this.GetPropertyValue(propName) = + this.GetType().GetProperty(propName, BindingFlags.Public).GetValue(this, null) + +/// Match on the nullness of an argument. +let inline (|Null|NonNull|) (x: 'T) : Choice = + match x with + | null -> Null + | v -> NonNull v + +/// Get the Reference Assemblies directory for the .NET Framework on Window. +let DotNetFrameworkReferenceAssembliesRootDirectory = + // ProgramFilesX86 is correct for both x86 and x64 architectures + // (the reference assemblies are always in the 32-bit location, which is PF(x86) on an x64 machine) + let PF = + match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with + | Null -> Environment.GetEnvironmentVariable("ProgramFiles") // if PFx86 is null, then we are 32-bit and just get PF + | NonNull s -> s + + PF + @"\Reference Assemblies\Microsoft\Framework\.NETFramework" + +/// When targeting .NET 2.0-3.5 on Windows, we expand the {WindowsFramework} and {ReferenceAssemblies} paths manually +let internal ReplaceVariablesForLegacyFxOnWindows (dirs: string list) = + let windowsFramework = + Environment.GetEnvironmentVariable("windir") + @"\Microsoft.NET\Framework" + + let referenceAssemblies = DotNetFrameworkReferenceAssembliesRootDirectory + + dirs + |> List.map (fun d -> + d + .Replace("{WindowsFramework}", windowsFramework) + .Replace("{ReferenceAssemblies}", referenceAssemblies)) + +// ATTENTION!: the following code needs to be updated every time we are switching to the new MSBuild version because new .NET framework version was released +// 1. List of frameworks +// 2. DeriveTargetFrameworkDirectoriesFor45Plus +// 3. HighestInstalledRefAssembliesOrDotNETFramework +// 4. GetPathToDotNetFrameworkImlpementationAssemblies +[] +let private Net45 = "v4.5" + +[] +let private Net451 = "v4.5.1" + +[] +let private Net452 = "v4.5.2" // not available in Dev15 MSBuild version + +[] +let private Net46 = "v4.6" + +[] +let private Net461 = "v4.6.1" + +[] +let private Net462 = "v4.6.2" + +[] +let private Net47 = "v4.7" + +[] +let private Net471 = "v4.7.1" + +[] +let private Net472 = "v4.7.2" + +[] +let private Net48 = "v4.8" + +let SupportedDesktopFrameworkVersions = + [ Net48; Net472; Net471; Net47; Net462; Net461; Net46; Net452; Net451; Net45 ] + +/// Get the path to the .NET Framework implementation assemblies by using ToolLocationHelper.GetPathToDotNetFramework +/// This is only used to specify the "last resort" path for assembly resolution. +let GetPathToDotNetFrameworkImlpementationAssemblies v : string list = + let v = match v with - | Some v -> - match ToolLocationHelper.GetPathToDotNetFramework v with - | Null -> [] - | NonNull x -> [x] - | _ -> [] - - let GetPathToDotNetFrameworkReferenceAssemblies version = + | Net45 -> Some TargetDotNetFrameworkVersion.Version45 + | Net451 -> Some TargetDotNetFrameworkVersion.Version451 + | Net452 -> Some TargetDotNetFrameworkVersion.Version452 + | Net46 -> Some TargetDotNetFrameworkVersion.Version46 + | Net461 -> Some TargetDotNetFrameworkVersion.Version461 + | Net462 -> Some TargetDotNetFrameworkVersion.Version462 + | Net47 -> Some TargetDotNetFrameworkVersion.Version47 + | Net471 -> Some TargetDotNetFrameworkVersion.Version471 + | Net472 -> Some TargetDotNetFrameworkVersion.Version472 + | Net48 -> Some TargetDotNetFrameworkVersion.Version48 + | _ -> + assert false + None + + match v with + | Some v -> + match ToolLocationHelper.GetPathToDotNetFramework v with + | Null -> [] + | NonNull x -> [ x ] + | _ -> [] + +let GetPathToDotNetFrameworkReferenceAssemblies version = #if NETSTANDARD - ignore version - let r : string list = [] - r + ignore version + let r: string list = [] + r #else - match Microsoft.Build.Utilities.ToolLocationHelper.GetPathToStandardLibraries(".NETFramework",version,"") with - | Null | "" -> [] - | NonNull x -> [x] + match Microsoft.Build.Utilities.ToolLocationHelper.GetPathToStandardLibraries(".NETFramework", version, "") with + | Null + | "" -> [] + | NonNull x -> [ x ] #endif - /// Use MSBuild to determine the version of the highest installed set of reference assemblies, failing that grab the highest installed framework version - let HighestInstalledRefAssembliesOrDotNETFramework () = - let getHighestInstalledDotNETFramework () = +/// Use MSBuild to determine the version of the highest installed set of reference assemblies, failing that grab the highest installed framework version +let HighestInstalledRefAssembliesOrDotNETFramework () = + let getHighestInstalledDotNETFramework () = + try + if + box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version48)) + <> null + then + Net48 + elif + box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version472)) + <> null + then + Net472 + elif + box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version471)) + <> null + then + Net471 + elif + box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version47)) + <> null + then + Net47 + elif + box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version462)) + <> null + then + Net462 + elif + box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version461)) + <> null + then + Net461 + elif + box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version461)) + <> null + then + Net461 + elif + box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version46)) + <> null + then + Net46 + elif + box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version452)) + <> null + then + Net452 + elif + box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version451)) + <> null + then + Net451 + elif + box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version45)) + <> null + then + Net45 + else + Net45 // version is 4.5 assumed since this code is running. + with _ -> + Net45 + + // 1. First look to see if we can find the highest installed set of dotnet reference assemblies, if yes then select that framework + // 2. Otherwise ask msbuild for the highestinstalled framework + let checkFrameworkForReferenceAssemblies (dotNetVersion: string) = + if not (String.IsNullOrEmpty(dotNetVersion)) then try - if box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version48)) <> null then Net48 - elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version472)) <> null then Net472 - elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version471)) <> null then Net471 - elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version47)) <> null then Net47 - elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version462)) <> null then Net462 - elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version461)) <> null then Net461 - elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version461)) <> null then Net461 - elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version46)) <> null then Net46 - elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version452)) <> null then Net452 - elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version451)) <> null then Net451 - elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version45)) <> null then Net45 - else Net45 // version is 4.5 assumed since this code is running. - with _ -> Net45 - - // 1. First look to see if we can find the highest installed set of dotnet reference assemblies, if yes then select that framework - // 2. Otherwise ask msbuild for the highestinstalled framework - let checkFrameworkForReferenceAssemblies (dotNetVersion:string) = - if not (String.IsNullOrEmpty(dotNetVersion)) then - try - let v = if dotNetVersion.StartsWith("v") then dotNetVersion.Substring(1) else dotNetVersion - let frameworkName = System.Runtime.Versioning.FrameworkName(".NETFramework", Version(v)) - match ToolLocationHelper.GetPathToReferenceAssemblies(frameworkName) |> Seq.tryHead with - | Some p -> FileSystem.DirectoryExistsShim(p) - | None -> false - with _ -> false - else false - match SupportedDesktopFrameworkVersions |> Seq.tryFind(fun v -> checkFrameworkForReferenceAssemblies v) with - | Some v -> v - | None -> getHighestInstalledDotNETFramework() - - /// Derive the target framework directories. - let DeriveTargetFrameworkDirectories (targetFrameworkVersion:string, logMessage) = - - let targetFrameworkVersion = - if not(targetFrameworkVersion.StartsWith("v",StringComparison.Ordinal)) then "v"+targetFrameworkVersion - else targetFrameworkVersion - - let result = GetPathToDotNetFrameworkReferenceAssemblies(targetFrameworkVersion) |> Array.ofList - logMessage (sprintf "Derived target framework directories for version %s are: %s" targetFrameworkVersion (String.Join(",", result))) - result - - /// Describes the location where the reference was found, used only for debug and tooltip output - type ResolvedFrom = - | AssemblyFolders - | AssemblyFoldersEx - | TargetFrameworkDirectory - | RawFileName - | GlobalAssemblyCache - | Path of string - | Unknown - - /// Decode the ResolvedFrom code from MSBuild. - let DecodeResolvedFrom(resolvedFrom:string) : ResolvedFrom = - match resolvedFrom with - | "{RawFileName}" -> RawFileName - | "{GAC}" -> GlobalAssemblyCache - | "{TargetFrameworkDirectory}" -> TargetFrameworkDirectory - | "{AssemblyFolders}" -> AssemblyFolders - | r when r.Length >= 10 && "{Registry:" = r.Substring(0,10) -> AssemblyFoldersEx - | r -> ResolvedFrom.Path r - - let TooltipForResolvedFrom(resolvedFrom, fusionName, redist) = - fun (originalReference,resolvedPath) -> + let v = + if dotNetVersion.StartsWith("v") then + dotNetVersion.Substring(1) + else + dotNetVersion + + let frameworkName = + System.Runtime.Versioning.FrameworkName(".NETFramework", Version(v)) + + match ToolLocationHelper.GetPathToReferenceAssemblies(frameworkName) |> Seq.tryHead with + | Some p -> FileSystem.DirectoryExistsShim(p) + | None -> false + with _ -> + false + else + false + + match + SupportedDesktopFrameworkVersions + |> Seq.tryFind (fun v -> checkFrameworkForReferenceAssemblies v) + with + | Some v -> v + | None -> getHighestInstalledDotNETFramework () + +/// Derive the target framework directories. +let DeriveTargetFrameworkDirectories (targetFrameworkVersion: string, logMessage) = + + let targetFrameworkVersion = + if not (targetFrameworkVersion.StartsWith("v", StringComparison.Ordinal)) then + "v" + targetFrameworkVersion + else + targetFrameworkVersion + + let result = + GetPathToDotNetFrameworkReferenceAssemblies(targetFrameworkVersion) + |> Array.ofList + + logMessage (sprintf "Derived target framework directories for version %s are: %s" targetFrameworkVersion (String.Join(",", result))) + result + +/// Describes the location where the reference was found, used only for debug and tooltip output +type ResolvedFrom = + | AssemblyFolders + | AssemblyFoldersEx + | TargetFrameworkDirectory + | RawFileName + | GlobalAssemblyCache + | Path of string + | Unknown + +/// Decode the ResolvedFrom code from MSBuild. +let DecodeResolvedFrom (resolvedFrom: string) : ResolvedFrom = + match resolvedFrom with + | "{RawFileName}" -> RawFileName + | "{GAC}" -> GlobalAssemblyCache + | "{TargetFrameworkDirectory}" -> TargetFrameworkDirectory + | "{AssemblyFolders}" -> AssemblyFolders + | r when r.Length >= 10 && "{Registry:" = r.Substring(0, 10) -> AssemblyFoldersEx + | r -> ResolvedFrom.Path r + +let TooltipForResolvedFrom (resolvedFrom, fusionName, redist) = + fun (originalReference, resolvedPath) -> let originalReferenceName = originalReference let resolvedPath = // Don't show the resolved path if it is identical to what was referenced. - if originalReferenceName = resolvedPath then String.Empty - else resolvedPath + if originalReferenceName = resolvedPath then + String.Empty + else + resolvedPath let lineIfExists text = - if String.IsNullOrEmpty text then "" - else text.Trim(' ')+"\n" + if String.IsNullOrEmpty text then + "" + else + text.Trim(' ') + "\n" - match resolvedFrom with + match resolvedFrom with | AssemblyFolders -> lineIfExists resolvedPath + lineIfExists fusionName - + LegacyResolver.SR.assemblyResolutionFoundByAssemblyFoldersKey() - | AssemblyFoldersEx -> + + LegacyResolver.SR.assemblyResolutionFoundByAssemblyFoldersKey () + | AssemblyFoldersEx -> lineIfExists resolvedPath + lineIfExists fusionName - + LegacyResolver.SR.assemblyResolutionFoundByAssemblyFoldersExKey() - | TargetFrameworkDirectory -> + + LegacyResolver.SR.assemblyResolutionFoundByAssemblyFoldersExKey () + | TargetFrameworkDirectory -> lineIfExists resolvedPath + lineIfExists fusionName - + LegacyResolver.SR.assemblyResolutionNetFramework() + + LegacyResolver.SR.assemblyResolutionNetFramework () | Unknown -> // Unknown when resolved by plain directory search without help from MSBuild resolver. - lineIfExists resolvedPath - + lineIfExists fusionName - | RawFileName -> - lineIfExists fusionName - | GlobalAssemblyCache -> + lineIfExists resolvedPath + lineIfExists fusionName + | RawFileName -> lineIfExists fusionName + | GlobalAssemblyCache -> lineIfExists fusionName - + lineIfExists (LegacyResolver.SR.assemblyResolutionGAC()) + + lineIfExists (LegacyResolver.SR.assemblyResolutionGAC ()) + lineIfExists redist - | Path _ -> - lineIfExists resolvedPath - + lineIfExists fusionName - - /// Perform assembly resolution by instantiating the ResolveAssembly task directly from the MSBuild SDK. - let ResolveCore(resolutionEnvironment: LegacyResolutionEnvironment, - references:(string*string)[], - targetFrameworkVersion: string, - targetFrameworkDirectories: string list, - targetProcessorArchitecture: string, - fsharpCoreDir: string, - explicitIncludeDirs: string list, - implicitIncludeDir: string, - allowRawFileName: bool, - logMessage: string -> unit, - logDiagnostic: bool -> string -> string -> unit) = - - let frameworkRegistryBase, assemblyFoldersSuffix, assemblyFoldersConditions = - "Software\Microsoft\.NetFramework", "AssemblyFoldersEx" , "" - if Array.isEmpty references then [| |] else + | Path _ -> lineIfExists resolvedPath + lineIfExists fusionName + +/// Perform assembly resolution by instantiating the ResolveAssembly task directly from the MSBuild SDK. +let ResolveCore + ( + resolutionEnvironment: LegacyResolutionEnvironment, + references: (string * string)[], + targetFrameworkVersion: string, + targetFrameworkDirectories: string list, + targetProcessorArchitecture: string, + fsharpCoreDir: string, + explicitIncludeDirs: string list, + implicitIncludeDir: string, + allowRawFileName: bool, + logMessage: string -> unit, + logDiagnostic: bool -> string -> string -> unit + ) = + + let frameworkRegistryBase, assemblyFoldersSuffix, assemblyFoldersConditions = + "Software\Microsoft\.NetFramework", "AssemblyFoldersEx", "" + + if Array.isEmpty references then + [||] + else let mutable backgroundException = false - let protect f = - if not backgroundException then - try f() - with _ -> backgroundException <- true - - let engine = - { new IBuildEngine with - member _.BuildProjectFile(projectFileName, targetNames, globalProperties, targetOutputs) = true - member _.LogCustomEvent(e) = protect (fun () -> logMessage e.Message) - member _.LogErrorEvent(e) = protect (fun () -> logDiagnostic true e.Code e.Message) - member _.LogMessageEvent(e) = protect (fun () -> logMessage e.Message) - member _.LogWarningEvent(e) = protect (fun () -> logDiagnostic false e.Code e.Message) - member _.ColumnNumberOfTaskNode with get() = 1 - member _.LineNumberOfTaskNode with get() = 1 - member _.ContinueOnError with get() = true - member _.ProjectFileOfTaskNode with get() = "" } + let protect f = + if not backgroundException then + try + f () + with _ -> + backgroundException <- true + + let engine = + { new IBuildEngine with + member _.BuildProjectFile(projectFileName, targetNames, globalProperties, targetOutputs) = true + + member _.LogCustomEvent(e) = + protect (fun () -> logMessage e.Message) + + member _.LogErrorEvent(e) = + protect (fun () -> logDiagnostic true e.Code e.Message) + + member _.LogMessageEvent(e) = + protect (fun () -> logMessage e.Message) + + member _.LogWarningEvent(e) = + protect (fun () -> logDiagnostic false e.Code e.Message) + + member _.ColumnNumberOfTaskNode = 1 + member _.LineNumberOfTaskNode = 1 + member _.ContinueOnError = true + member _.ProjectFileOfTaskNode = "" + } // Derive the target framework directory if none was supplied. let targetFrameworkDirectories = - if targetFrameworkDirectories=[] then DeriveTargetFrameworkDirectories(targetFrameworkVersion, logMessage) - else targetFrameworkDirectories |> Array.ofList - + if targetFrameworkDirectories = [] then + DeriveTargetFrameworkDirectories(targetFrameworkVersion, logMessage) + else + targetFrameworkDirectories |> Array.ofList // Filter for null and zero length - let references = references |> Array.filter(fst >> String.IsNullOrEmpty >> not) + let references = references |> Array.filter (fst >> String.IsNullOrEmpty >> not) // Determine the set of search paths for the resolution - let searchPaths = + let searchPaths = - let explicitIncludeDirs = explicitIncludeDirs |> List.filter(String.IsNullOrEmpty >> not) + let explicitIncludeDirs = + explicitIncludeDirs |> List.filter (String.IsNullOrEmpty >> not) - let registry = sprintf "{Registry:%s,%s,%s%s}" frameworkRegistryBase targetFrameworkVersion assemblyFoldersSuffix assemblyFoldersConditions + let registry = + sprintf "{Registry:%s,%s,%s%s}" frameworkRegistryBase targetFrameworkVersion assemblyFoldersSuffix assemblyFoldersConditions - [| // When compiling scripts using fsc.exe, for some reason we have always historically put TargetFrameworkDirectory first + [| // When compiling scripts using fsc.exe, for some reason we have always historically put TargetFrameworkDirectory first // It is unclear why. This is the only place we look at the 'isdifference between ResolutionEnvironment.EditingOrCompilation and ResolutionEnvironment.EditingTime. match resolutionEnvironment with | LegacyResolutionEnvironment.EditingOrCompilation false -> yield "{TargetFrameworkDirectory}" | LegacyResolutionEnvironment.EditingOrCompilation true | LegacyResolutionEnvironment.CompilationAndEvaluation -> () - // Quick-resolve straight to file name first - if allowRawFileName then + // Quick-resolve straight to file name first + if allowRawFileName then yield "{RawFileName}" - yield! explicitIncludeDirs // From -I, #I - yield fsharpCoreDir // Location of explicit reference to FSharp.Core, otherwise location of fsc.exe - yield implicitIncludeDir // Usually the project directory + yield! explicitIncludeDirs // From -I, #I + yield fsharpCoreDir // Location of explicit reference to FSharp.Core, otherwise location of fsc.exe + yield implicitIncludeDir // Usually the project directory match resolutionEnvironment with | LegacyResolutionEnvironment.EditingOrCompilation true @@ -288,87 +387,130 @@ module FSharp.Compiler.CodeAnalysis.LegacyMSBuildReferenceResolver yield "{AssemblyFolders}" yield "{GAC}" // use path to implementation assemblies as the last resort - yield! GetPathToDotNetFrameworkImlpementationAssemblies targetFrameworkVersion - |] - - let assemblies = - [| for referenceName,baggage in references -> - let item = TaskItem(referenceName) :> ITaskItem - item.SetMetadata("Baggage", baggage) - item |] - let rar = - ResolveAssemblyReference(BuildEngine=engine, TargetFrameworkDirectories=targetFrameworkDirectories, - FindRelatedFiles=false, FindDependencies=false, FindSatellites=false, - FindSerializationAssemblies=false, Assemblies=assemblies, - SearchPaths=searchPaths, - AllowedAssemblyExtensions= [| ".dll" ; ".exe" |]) + yield! GetPathToDotNetFrameworkImlpementationAssemblies targetFrameworkVersion + |] + + let assemblies = + [| + for referenceName, baggage in references -> + let item = TaskItem(referenceName) :> ITaskItem + item.SetMetadata("Baggage", baggage) + item + |] + + let rar = + ResolveAssemblyReference( + BuildEngine = engine, + TargetFrameworkDirectories = targetFrameworkDirectories, + FindRelatedFiles = false, + FindDependencies = false, + FindSatellites = false, + FindSerializationAssemblies = false, + Assemblies = assemblies, + SearchPaths = searchPaths, + AllowedAssemblyExtensions = [| ".dll"; ".exe" |] + ) + rar.TargetProcessorArchitecture <- targetProcessorArchitecture let targetedRuntimeVersionValue = typeof.Assembly.ImageRuntimeVersion rar.TargetedRuntimeVersion <- targetedRuntimeVersionValue rar.CopyLocalDependenciesWhenParentReferenceInGac <- true - + let succeeded = rar.Execute() - if not succeeded then + if not succeeded then raise LegacyResolutionFailure - let resolvedFiles = - [| for p in rar.ResolvedFiles -> + [| + for p in rar.ResolvedFiles -> let resolvedFrom = DecodeResolvedFrom(p.GetMetadata("ResolvedFrom")) let fusionName = p.GetMetadata("FusionName") - let redist = p.GetMetadata("Redist") - { itemSpec = p.ItemSpec - prepareToolTip = TooltipForResolvedFrom(resolvedFrom, fusionName, redist) - baggage = p.GetMetadata("Baggage") } |] - - resolvedFiles - |> Array.iter(fun f -> printf $"XXXX: {f.itemSpec}") - resolvedFiles - - let getResolver () = - { new ILegacyReferenceResolver with - member _.HighestInstalledNetFrameworkVersion() = HighestInstalledRefAssembliesOrDotNETFramework() - member _.DotNetFrameworkReferenceAssembliesRootDirectory = DotNetFrameworkReferenceAssembliesRootDirectory - - /// Perform the resolution on rooted and unrooted paths, and then combine the results. - member _.Resolve(resolutionEnvironment, references, targetFrameworkVersion, targetFrameworkDirectories, targetProcessorArchitecture, - fsharpCoreDir, explicitIncludeDirs, implicitIncludeDir, logMessage, logDiagnostic) = - - // The {RawFileName} target is 'dangerous', in the sense that is uses Directory.GetCurrentDirectory() to resolve unrooted file paths. - // It is unreliable to use this mutable global state inside Visual Studio. As a result, we partition all references into a "rooted" set - // (which contains e.g. C:\MyDir\MyAssem.dll) and "unrooted" (everything else). We only allow "rooted" to use {RawFileName}. Note that - // unrooted may still find 'local' assemblies by virtue of the fact that "implicitIncludeDir" is one of the places searched during - // assembly resolution. - let references = - [| for fileName, baggage as data in references -> - // However, MSBuild will not resolve 'relative' paths, even when e.g. implicitIncludeDir is part of the search. As a result, - // if we have an unrooted path + file name, we'll assume this is relative to the project directory and root it. - if FileSystem.IsPathRootedShim(fileName) then - data // fine, e.g. "C:\Dir\foo.dll" - elif not(fileName.Contains("\\") || fileName.Contains("/")) then - data // fine, e.g. "System.Transactions.dll" - else - // We have a 'relative path', e.g. "bin/Debug/foo.exe" or "..\Yadda\bar.dll" - // turn it into an absolute path based at implicitIncludeDir - (Path.Combine(implicitIncludeDir, fileName), baggage) |] - - let rooted, unrooted = references |> Array.partition (fst >> FileSystem.IsPathRootedShim) - - let rootedResults = - ResolveCore - (resolutionEnvironment, rooted, targetFrameworkVersion, - targetFrameworkDirectories, targetProcessorArchitecture, - fsharpCoreDir, explicitIncludeDirs, implicitIncludeDir, - true, logMessage, logDiagnostic) - - let unrootedResults = - ResolveCore - (resolutionEnvironment, unrooted, targetFrameworkVersion, - targetFrameworkDirectories, targetProcessorArchitecture, - fsharpCoreDir, explicitIncludeDirs, implicitIncludeDir, - false, logMessage, logDiagnostic) - - // now unify the two sets of results - Array.concat [| rootedResults; unrootedResults |] - } - |> LegacyReferenceResolver + let redist = p.GetMetadata("Redist") + + { + itemSpec = p.ItemSpec + prepareToolTip = TooltipForResolvedFrom(resolvedFrom, fusionName, redist) + baggage = p.GetMetadata("Baggage") + } + |] + +let getResolver () = + { new ILegacyReferenceResolver with + member _.HighestInstalledNetFrameworkVersion() = + HighestInstalledRefAssembliesOrDotNETFramework() + + member _.DotNetFrameworkReferenceAssembliesRootDirectory = + DotNetFrameworkReferenceAssembliesRootDirectory + + /// Perform the resolution on rooted and unrooted paths, and then combine the results. + member _.Resolve + ( + resolutionEnvironment, + references, + targetFrameworkVersion, + targetFrameworkDirectories, + targetProcessorArchitecture, + fsharpCoreDir, + explicitIncludeDirs, + implicitIncludeDir, + logMessage, + logDiagnostic + ) = + + // The {RawFileName} target is 'dangerous', in the sense that is uses Directory.GetCurrentDirectory() to resolve unrooted file paths. + // It is unreliable to use this mutable global state inside Visual Studio. As a result, we partition all references into a "rooted" set + // (which contains e.g. C:\MyDir\MyAssem.dll) and "unrooted" (everything else). We only allow "rooted" to use {RawFileName}. Note that + // unrooted may still find 'local' assemblies by virtue of the fact that "implicitIncludeDir" is one of the places searched during + // assembly resolution. + let references = + [| + for fileName, baggage as data in references -> + // However, MSBuild will not resolve 'relative' paths, even when e.g. implicitIncludeDir is part of the search. As a result, + // if we have an unrooted path + file name, we'll assume this is relative to the project directory and root it. + if FileSystem.IsPathRootedShim(fileName) then + data // fine, e.g. "C:\Dir\foo.dll" + elif not (fileName.Contains("\\") || fileName.Contains("/")) then + data // fine, e.g. "System.Transactions.dll" + else + // We have a 'relative path', e.g. "bin/Debug/foo.exe" or "..\Yadda\bar.dll" + // turn it into an absolute path based at implicitIncludeDir + (Path.Combine(implicitIncludeDir, fileName), baggage) + |] + + let rooted, unrooted = + references |> Array.partition (fst >> FileSystem.IsPathRootedShim) + + let rootedResults = + ResolveCore( + resolutionEnvironment, + rooted, + targetFrameworkVersion, + targetFrameworkDirectories, + targetProcessorArchitecture, + fsharpCoreDir, + explicitIncludeDirs, + implicitIncludeDir, + true, + logMessage, + logDiagnostic + ) + + let unrootedResults = + ResolveCore( + resolutionEnvironment, + unrooted, + targetFrameworkVersion, + targetFrameworkDirectories, + targetProcessorArchitecture, + fsharpCoreDir, + explicitIncludeDirs, + implicitIncludeDir, + false, + logMessage, + logDiagnostic + ) + + // now unify the two sets of results + Array.concat [| rootedResults; unrootedResults |] + } + |> LegacyReferenceResolver