Skip to content

Commit 0bf1ac4

Browse files
committed
default resolver
1 parent 9e4727a commit 0bf1ac4

File tree

3 files changed

+150
-66
lines changed

3 files changed

+150
-66
lines changed

src/fsharp/ReferenceResolver.fs

Lines changed: 150 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,13 @@ type Resolver =
6565
logerror:(string->string->unit)
6666
-> ResolvedFile[]
6767

68-
let ScriptingNaiveResolver =
68+
let SimulatedMSBuildResolver =
6969
{ new Resolver with
7070
member __.HighestInstalledNetFrameworkVersion() = "v4.5"
7171
member __.DotNetFrameworkReferenceAssembliesRootDirectory =
72+
#if RESHAPED_MSBUILD
73+
""
74+
#else
7275
if System.Environment.OSVersion.Platform = System.PlatformID.Win32NT then
7376
let PF =
7477
match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with
@@ -77,10 +80,12 @@ let ScriptingNaiveResolver =
7780
PF + @"\Reference Assemblies\Microsoft\Framework\.NETFramework"
7881
else
7982
""
83+
#endif
8084

8185
member __.Resolve(resolutionEnvironment, references, targetFrameworkVersion, targetFrameworkDirectories, targetProcessorArchitecture,
8286
outputDirectory, fsharpCoreDir, explicitIncludeDirs, implicitIncludeDir, logMessage, logWarning, logError) =
8387

88+
#if !RESHAPED_MSBUILD
8489
let registrySearchPaths() =
8590
[ let registryKey = @"Software\Microsoft\.NetFramework";
8691
use key = Registry.LocalMachine.OpenSubKey(registryKey)
@@ -107,79 +112,126 @@ let ScriptingNaiveResolver =
107112
match subSubSubKey.GetValue(null) with
108113
| :? string as s -> yield s
109114
| _ -> () ]
115+
#endif
110116

111-
117+
let results = ResizeArray()
112118
let searchPaths =
113119
[ yield! targetFrameworkDirectories
114120
yield! explicitIncludeDirs
115121
yield fsharpCoreDir
116122
yield implicitIncludeDir
123+
#if !RESHAPED_MSBUILD
117124
if System.Environment.OSVersion.Platform = System.PlatformID.Win32NT then
118-
yield! registrySearchPaths() ]
125+
yield! registrySearchPaths()
126+
#endif
127+
]
119128

120-
[| for (baggage,r) in references do
129+
for (r, baggage) in references do
130+
//printfn "resolving %s" r
121131
let mutable found = false
122132
let success path =
123133
if not found then
134+
//printfn "resolved %s --> %s" r path
124135
found <- true
125-
[ { itemSpec = path; prepareToolTip = snd; baggage=baggage } ]
126-
else []
127-
if Path.IsPathRooted(r) then
128-
if FileSystem.SafeExists(r) then
129-
yield! success r
130-
else
131-
let isFileName =
132-
r.EndsWith("dll",StringComparison.InvariantCultureIgnoreCase) ||
133-
r.EndsWith("exe",StringComparison.InvariantCultureIgnoreCase)
134-
135-
let qual = if isFileName then r else try AssemblyName(r).Name + ".dll" with _ -> r + ".dll"
136-
137-
for searchPath in searchPaths do
138-
if not found then
139-
let trialPath = Path.Combine(searchPath,qual)
140-
if FileSystem.SafeExists(trialPath) then
141-
yield! success trialPath
142-
if not found then
143-
let ass = try Some (System.Reflection.Assembly.ReflectionOnlyLoad(r)) with _ -> None
144-
match ass with
145-
| None -> ()
146-
| Some ass -> yield! success ass.Location |] }
136+
results.Add { itemSpec = path; prepareToolTip = snd; baggage=baggage }
147137

148-
#if INTERACTIVE
149-
ScriptingNaiveResolver.DotNetFrameworkReferenceAssembliesRootDirectory
150-
ScriptingNaiveResolver.HighestInstalledNetFrameworkVersion()
138+
try
139+
if not found && Path.IsPathRooted(r) then
140+
if FileSystem.SafeExists(r) then
141+
success r
142+
with e -> logWarning "SR001" (e.ToString())
151143

152-
let fscoreDir =
153-
if System.Environment.OSVersion.Platform = System.PlatformID.Win32NT then // file references only valid on Windows
154-
let PF =
155-
match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with
156-
| null -> Environment.GetEnvironmentVariable("ProgramFiles") // if PFx86 is null, then we are 32-bit and just get PF
157-
| s -> s
158-
PF + @"\Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\4.4.0.0"
159-
else
160-
System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()
144+
#if !RESHAPED_MSBUILD
145+
// For this one we need to get the version search exactly right, without doing a load
146+
try
147+
if not found && r.StartsWith("FSharp.Core, Version=") && Environment.OSVersion.Platform = PlatformID.Win32NT then
148+
let n = AssemblyName(r)
149+
let fscoreDir0 =
150+
let PF =
151+
match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with
152+
| null -> Environment.GetEnvironmentVariable("ProgramFiles")
153+
| s -> s
154+
PF + @"\Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\" + n.Version.ToString()
155+
let trialPath = Path.Combine(fscoreDir0,n.Name + ".dll")
156+
if FileSystem.SafeExists(trialPath) then
157+
success trialPath
158+
with e -> logWarning "SR001" (e.ToString())
159+
#endif
161160

162-
let resolve s =
163-
ScriptingNaiveResolver.Resolve(ResolutionEnvironment.CompileTimeLike,[| for a in s -> ("", a) |],"v4.5.1", [ScriptingNaiveResolver.DotNetFrameworkReferenceAssembliesRootDirectory + @"\v4.5.1" ],"", "", fscoreDir,[],__SOURCE_DIRECTORY__,ignore, (fun _ _ -> ()), (fun _ _-> ()))
161+
let isFileName =
162+
r.EndsWith("dll",StringComparison.OrdinalIgnoreCase) ||
163+
r.EndsWith("exe",StringComparison.OrdinalIgnoreCase)
164164

165-
resolve ["System"; "mscorlib"; "mscorlib.dll"; "FSharp.Core"; "FSharp.Core.dll"; "Microsoft.SqlServer.Dmf.dll"; "Microsoft.SqlServer.Dmf" ]
165+
let qual = if isFileName then r else try AssemblyName(r).Name + ".dll" with _ -> r + ".dll"
166166

167-
resolve [ "FSharp.Core, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ]
167+
for searchPath in searchPaths do
168+
try
169+
if not found then
170+
let trialPath = Path.Combine(searchPath,qual)
171+
if FileSystem.SafeExists(trialPath) then
172+
success trialPath
173+
with e -> logWarning "SR001" (e.ToString())
174+
175+
#if !RESHAPED_MSBUILD
176+
try
177+
// Seach the GAC on Windows
178+
if not found && not isFileName && Environment.OSVersion.Platform = PlatformID.Win32NT then
179+
let n = AssemblyName(r)
180+
let netfx = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()
181+
let gac = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(netfx.TrimEnd('\\'))),"assembly")
182+
match n.Version, n.GetPublicKeyToken() with
183+
| null, _ | _,null ->
184+
let options =
185+
[ for gacdir in Directory.EnumerateDirectories(gac) do
186+
let assdir = Path.Combine(gacdir,n.Name)
187+
if Directory.Exists(assdir) then
188+
for tdir in Directory.EnumerateDirectories(assdir) do
189+
let trialPath = Path.Combine(tdir,qual)
190+
if FileSystem.SafeExists(trialPath) then
191+
yield trialPath ]
192+
//printfn "sorting GAC paths: %A" options
193+
options
194+
|> List.sort // puts latest version last
195+
|> List.tryLast
196+
|> function None -> () | Some p -> success p
197+
198+
| v,tok ->
199+
for gacdir in Directory.EnumerateDirectories(gac) do
200+
//printfn "searching GAC directory: %s" gacdir
201+
let assdir = Path.Combine(gacdir,n.Name)
202+
if Directory.Exists(assdir) then
203+
//printfn "searching GAC directory: %s" assdir
204+
205+
let tokText = String.concat "" [| for b in tok -> sprintf "%02x" b |]
206+
let verdir = Path.Combine(assdir,"v4.0_"+v.ToString()+"__"+tokText)
207+
//printfn "searching GAC directory: %s" verdir
208+
209+
if Directory.Exists(verdir) then
210+
let trialPath = Path.Combine(verdir,qual)
211+
//printfn "searching GAC: %s" trialPath
212+
if FileSystem.SafeExists(trialPath) then
213+
success trialPath
214+
with e -> logWarning "SR001" (e.ToString())
168215
#endif
169216

217+
results.ToArray() }
218+
170219
let GetDefaultResolver(msbuildEnabled: bool, msbuildVersion: string option) =
171-
//let msbuildEnabled = msbuildEnabled && false
220+
#if RESHAPED_MSBUILD
221+
ignore msbuildVersion
222+
ignore msbuildEnabled
223+
#else
224+
let msbuildEnabled = msbuildEnabled && false
225+
let msbuildVersion = defaultArg msbuildVersion "12"
172226
let tryMSBuild v =
173-
if msbuildEnabled then
174-
// Detect if MSBuild v12 is on the machine, if so use the resolver from there
175-
let mb = try System.Reflection.Assembly.Load(sprintf "Microsoft.Build.Framework, Version=%s.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" v) |> Option.ofObj with _ -> None
176-
let ass = mb |> Option.bind (fun _ -> try System.Reflection.Assembly.Load(sprintf "FSharp.Compiler.Service.MSBuild.v%s" v) |> Option.ofObj with _ -> None)
227+
// Detect if MSBuild is on the machine, if so use the resolver from there
228+
let mb = try Assembly.Load(sprintf "Microsoft.Build.Framework, Version=%s.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" v) |> Option.ofObj with _ -> None
229+
let ass = mb |> Option.bind (fun _ -> try Assembly.Load(sprintf "FSharp.Compiler.Service.MSBuild.v%s" v) |> Option.ofObj with _ -> None)
177230
let ty = ass |> Option.bind (fun ass -> ass.GetType("Microsoft.FSharp.Compiler.MSBuildReferenceResolver") |> Option.ofObj)
178-
let obj = ty |> Option.bind (fun ty -> ty.InvokeMember("get_Resolver",System.Reflection.BindingFlags.Static ||| System.Reflection.BindingFlags.Public ||| System.Reflection.BindingFlags.InvokeMethod ||| System.Reflection.BindingFlags.NonPublic, null, null, [| |]) |> Option.ofObj)
231+
let obj = ty |> Option.bind (fun ty -> ty.InvokeMember("get_Resolver",BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.InvokeMethod ||| BindingFlags.NonPublic, null, null, [| |]) |> Option.ofObj)
179232
let resolver = obj |> Option.bind (fun obj -> match obj with :? Resolver as r -> Some r | _ -> None)
180233
resolver
181-
else None
182-
match tryMSBuild (defaultArg msbuildVersion "12") with
234+
match (if msbuildEnabled then tryMSBuild msbuildVersion else None) with
183235
| Some r -> r
184236
| None ->
185237
//match tryMSBuild "15" with
@@ -188,7 +240,53 @@ let GetDefaultResolver(msbuildEnabled: bool, msbuildVersion: string option) =
188240
//match tryMSBuild "14" with
189241
//| Some r -> r
190242
//| None ->
191-
match tryMSBuild "12" with
243+
match (if msbuildEnabled && msbuildVersion <> "12" then tryMSBuild "12" else None) with
192244
| Some r -> r
193245
| None ->
194-
ScriptingNaiveResolver
246+
#endif
247+
SimulatedMSBuildResolver
248+
249+
250+
#if INTERACTIVE
251+
// Some manual testing
252+
SimulatedMSBuildResolver.DotNetFrameworkReferenceAssembliesRootDirectory
253+
SimulatedMSBuildResolver.HighestInstalledNetFrameworkVersion()
254+
255+
let fscoreDir =
256+
if System.Environment.OSVersion.Platform = System.PlatformID.Win32NT then // file references only valid on Windows
257+
let PF =
258+
match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with
259+
| null -> Environment.GetEnvironmentVariable("ProgramFiles") // if PFx86 is null, then we are 32-bit and just get PF
260+
| s -> s
261+
PF + @"\Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\4.4.0.0"
262+
else
263+
System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()
264+
265+
let resolve s =
266+
SimulatedMSBuildResolver.Resolve(ResolutionEnvironment.CompileTimeLike,[| for a in s -> (a, "") |],"v4.5.1", [SimulatedMSBuildResolver.DotNetFrameworkReferenceAssembliesRootDirectory + @"\v4.5.1" ],"", "", fscoreDir,[],__SOURCE_DIRECTORY__,ignore, (fun _ _ -> ()), (fun _ _-> ()))
267+
268+
// Resolve partial name to something on search path
269+
resolve ["FSharp.Core" ]
270+
271+
// Resolve DLL name to something on search path
272+
resolve ["FSharp.Core.dll" ]
273+
274+
// Resolve from reference assemblies
275+
resolve ["System"; "mscorlib"; "mscorlib.dll" ]
276+
277+
// Resolve from Registry AssemblyFolders
278+
resolve ["Microsoft.SqlServer.Dmf.dll"; "Microsoft.SqlServer.Dmf" ]
279+
280+
// Resolve exact version of FSharp.Core
281+
resolve [ "FSharp.Core, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ]
282+
283+
// Resolve from GAC:
284+
resolve [ "EventViewer, Version=6.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" ]
285+
286+
// Resolve from GAC:
287+
resolve [ "EventViewer" ]
288+
289+
resolve [ "Microsoft.SharePoint.Client, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" ]
290+
resolve [ "Microsoft.SharePoint.Client, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" ]
291+
#endif
292+

tests/service/FSharp.Compiler.Service.Tests.fsproj

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,6 @@
9999
<Project>{887630a3-4b1d-40ea-b8b3-2d842e9c40db}</Project>
100100
<Private>True</Private>
101101
</ProjectReference>
102-
<ProjectReference Include="data\TestTP\TestTP.fsproj">
103-
<Name>TestTP</Name>
104-
<Project>{ff76bd3c-5e0a-4752-b6c3-044f6e15719b}</Project>
105-
<Private>True</Private>
106-
</ProjectReference>
107102
</ItemGroup>
108103
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
109104
<ItemGroup>

tests/service/ProjectAnalysisTests.fs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4510,15 +4510,6 @@ module Project35b =
45104510
let options = checker.GetProjectOptionsFromScript(fileName1, fileSource1) |> Async.RunSynchronously
45114511
#endif
45124512

4513-
[<Test>]
4514-
let ``Test project35b Dependency files for ParseFileInProject`` () =
4515-
// This is testing legacy functionality
4516-
let parseFileResults = checker.ParseFileInProject(Project35b.fileName1, Project35b.fileSource1, Project35b.options) |> Async.RunSynchronously
4517-
for d in parseFileResults.DependencyFiles do
4518-
printfn "ParseFileInProject dependency: %s" d
4519-
parseFileResults.DependencyFiles |> List.exists (fun s -> s.Contains "notexist.dll") |> shouldEqual true
4520-
parseFileResults.DependencyFiles |> List.exists (fun s -> s.Contains Project35b.fileName1) |> shouldEqual true
4521-
45224513
[<Test>]
45234514
let ``Test project35b Dependency files for ParseAndCheckFileInProject`` () =
45244515
let checkFileResults =

0 commit comments

Comments
 (0)