Skip to content

Commit 028e1df

Browse files
authored
Pinvoke testing (#6594)
* Add support for fsi against ref assemblies * temp * working * unit test * feedback * Parens
1 parent 816efbd commit 028e1df

24 files changed

+347
-79
lines changed

eng/Build.ps1

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ param (
4646
[switch]$warnAsError = $true,
4747
[switch][Alias('test')]$testDesktop,
4848
[switch]$testCoreClr,
49+
[switch]$testFSharpCompiler,
4950
[switch]$testFSharpQA,
5051
[switch]$testFSharpCore,
5152
[switch]$testVs,
@@ -77,6 +78,7 @@ function Print-Usage() {
7778
Write-Host " -testAll Run all tests"
7879
Write-Host " -testDesktop Run tests against full .NET Framework"
7980
Write-Host " -testCoreClr Run tests against CoreCLR"
81+
Write-Host " -testFSharpCompiler Run F# Compiler unit tests"
8082
Write-Host " -testFSharpQA Run F# Cambridge tests"
8183
Write-Host " -testFSharpCore Run FSharpCore unit tests"
8284
Write-Host " -testVs Run F# editor unit tests"
@@ -279,16 +281,16 @@ try {
279281
}
280282

281283
if ($testFSharpCore) {
282-
Write-Host "Environment Variables"
283-
Get-Childitem Env:
284284
TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Core.UnitTests\FSharp.Core.UnitTests.fsproj" -targetFramework $desktopTargetFramework
285285
TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Core.UnitTests\FSharp.Core.UnitTests.fsproj" -targetFramework $coreclrTargetFramework
286286
}
287287

288+
if ($testFSharpCompiler) {
289+
TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.UnitTests\FSharp.Compiler.UnitTests.fsproj" -targetFramework $desktopTargetFramework
290+
TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.UnitTests\FSharp.Compiler.UnitTests.fsproj" -targetFramework $coreclrTargetFramework
291+
}
288292

289293
if ($testVs) {
290-
Write-Host "Environment Variables"
291-
Get-Childitem Env:
292294
TestUsingNUnit -testProject "$RepoRoot\vsintegration\tests\GetTypesVS.UnitTests\GetTypesVS.UnitTests.fsproj" -targetFramework $desktopTargetFramework
293295
TestUsingNUnit -testProject "$RepoRoot\vsintegration\tests\UnitTests\VisualFSharp.UnitTests.fsproj" -targetFramework $desktopTargetFramework
294296
}

src/fsharp/CompileOps.fs

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2141,6 +2141,7 @@ type TcConfigBuilder =
21412141

21422142
/// When false FSI will lock referenced assemblies requiring process restart, false = disable Shadow Copy false (*default*)
21432143
mutable shadowCopyReferences: bool
2144+
mutable useSdkRefs: bool
21442145

21452146
/// A function to call to try to get an object that acts as a snapshot of the metadata section of a .NET binary,
21462147
/// and from which we can read the metadata. Only used when metadataOnly=true.
@@ -2280,6 +2281,7 @@ type TcConfigBuilder =
22802281
exename = None
22812282
copyFSharpCore = CopyFSharpCoreFlag.No
22822283
shadowCopyReferences = false
2284+
useSdkRefs = true
22832285
tryGetMetadataSnapshot = (fun _ -> None)
22842286
internalTestSpanStackReferring = false
22852287
noConditionalErasure = false
@@ -2747,6 +2749,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) =
27472749
member x.emitDebugInfoInQuotations = data.emitDebugInfoInQuotations
27482750
member x.copyFSharpCore = data.copyFSharpCore
27492751
member x.shadowCopyReferences = data.shadowCopyReferences
2752+
member x.useSdkRefs = data.useSdkRefs
27502753
member x.tryGetMetadataSnapshot = data.tryGetMetadataSnapshot
27512754
member x.internalTestSpanStackReferring = data.internalTestSpanStackReferring
27522755
member x.noConditionalErasure = data.noConditionalErasure
@@ -2795,6 +2798,11 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) =
27952798
if Directory.Exists runtimeRootWPF then
27962799
yield runtimeRootWPF // PresentationCore.dll is in C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF
27972800

2801+
match getFrameworkRefsPackDirectory with
2802+
| Some path when Directory.Exists(path) ->
2803+
yield path
2804+
| _ -> ()
2805+
27982806
| ResolutionEnvironment.EditingOrCompilation _ ->
27992807
#if ENABLE_MONO_SUPPORT
28002808
if runningOnMono then
@@ -2857,13 +2865,14 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) =
28572865
///
28582866
/// Returning true may mean that the file is locked and/or placed into the
28592867
/// 'framework' reference set that is potentially shared across multiple compilations.
2860-
member tcConfig.IsSystemAssembly (filename: string) =
2861-
try
2862-
FileSystem.SafeExists filename &&
2868+
member tcConfig.IsSystemAssembly (filename: string) =
2869+
try
2870+
FileSystem.SafeExists filename &&
28632871
((tcConfig.GetTargetFrameworkDirectories() |> List.exists (fun clrRoot -> clrRoot = Path.GetDirectoryName filename)) ||
2864-
(systemAssemblies.Contains(fileNameWithoutExtension filename)))
2872+
(systemAssemblies.Contains (fileNameWithoutExtension filename)) ||
2873+
isInReferenceAssemblyPackDirectory filename)
28652874
with _ ->
2866-
false
2875+
false
28672876

28682877
// This is not the complete set of search paths, it is just the set
28692878
// that is special to F# (as compared to MSBuild resolution)
@@ -3506,18 +3515,15 @@ type TcAssemblyResolutions(tcConfig: TcConfig, results: AssemblyResolution list,
35063515
TcConfig.TryResolveLibsUsingMSBuildRules (tcConfig, assemblyList, rangeStartup, ResolveAssemblyReferenceMode.ReportErrors)
35073516
TcAssemblyResolutions(tcConfig, resolved, unresolved @ knownUnresolved)
35083517

3509-
3510-
static member GetAllDllReferences (tcConfig: TcConfig) =
3511-
[
3518+
static member GetAllDllReferences (tcConfig: TcConfig) = [
35123519
let primaryReference = tcConfig.PrimaryAssemblyDllReference()
3513-
yield primaryReference
35143520

35153521
if not tcConfig.compilingFslib then
35163522
yield tcConfig.CoreLibraryDllReference()
35173523

35183524
let assumeDotNetFramework = primaryReference.SimpleAssemblyNameIs("mscorlib")
3519-
if tcConfig.framework then
3520-
for s in defaultReferencesForScriptsAndOutOfProjectSources assumeDotNetFramework do
3525+
if tcConfig.framework then
3526+
for s in defaultReferencesForScriptsAndOutOfProjectSources assumeDotNetFramework tcConfig.useSdkRefs do
35213527
yield AssemblyReference(rangeStartup, (if s.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) then s else s+".dll"), None)
35223528

35233529
if tcConfig.useFsiAuxLib then
@@ -4552,8 +4558,14 @@ type TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAssemblyResolu
45524558

45534559
// Note: TcImports are disposable - the caller owns this object and must dispose
45544560
let frameworkTcImports = new TcImports(tcConfigP, tcResolutions, None, None)
4555-
4556-
let primaryAssemblyReference = tcConfig.PrimaryAssemblyDllReference()
4561+
4562+
// Fetch the primaryAssembly from the referenced assemblies otherwise
4563+
let primaryAssemblyReference =
4564+
let path = frameworkDLLs |> List.tryFind(fun dll -> String.Compare(Path.GetFileNameWithoutExtension(dll.resolvedPath), tcConfig.primaryAssembly.Name, StringComparison.OrdinalIgnoreCase) = 0)
4565+
match path with
4566+
| Some p -> AssemblyReference(range0, p.resolvedPath, None)
4567+
| None -> tcConfig.PrimaryAssemblyDllReference()
4568+
45574569
let primaryAssemblyResolution = frameworkTcImports.ResolveAssemblyReference(ctok, primaryAssemblyReference, ResolveAssemblyReferenceMode.ReportErrors)
45584570
let! primaryAssem = frameworkTcImports.RegisterAndImportReferencedAssemblies(ctok, primaryAssemblyResolution)
45594571
let primaryScopeRef =
@@ -4568,7 +4580,7 @@ type TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAssemblyResolu
45684580
let! _assemblies = frameworkTcImports.RegisterAndImportReferencedAssemblies (ctok, tcResolutions.GetAssemblyResolutions())
45694581

45704582
// These are the DLLs we can search for well-known types
4571-
let sysCcus =
4583+
let sysCcus =
45724584
[| for ccu in frameworkTcImports.GetCcusInDeclOrder() do
45734585
//printfn "found sys ccu %s" ccu.AssemblyName
45744586
yield ccu |]
@@ -4913,8 +4925,8 @@ module private ScriptPreprocessClosure =
49134925
filename: string, codeContext,
49144926
useSimpleResolution, useFsiAuxLib,
49154927
basicReferences, applyCommandLineArgs,
4916-
assumeDotNetFramework, tryGetMetadataSnapshot,
4917-
reduceMemoryUsage) =
4928+
assumeDotNetFramework, useSdkRefs,
4929+
tryGetMetadataSnapshot, reduceMemoryUsage) =
49184930

49194931
let projectDir = Path.GetDirectoryName filename
49204932
let isInteractive = (codeContext = CodeContext.CompilationAndEvaluation)
@@ -4929,7 +4941,7 @@ module private ScriptPreprocessClosure =
49294941
applyCommandLineArgs tcConfigB
49304942

49314943
match basicReferences with
4932-
| None -> (basicReferencesForScriptLoadClosure useFsiAuxLib assumeDotNetFramework) |> List.iter(fun f->tcConfigB.AddReferencedAssemblyByPath(range0, f)) // Add script references
4944+
| None -> (basicReferencesForScriptLoadClosure useFsiAuxLib useSdkRefs assumeDotNetFramework) |> List.iter(fun f->tcConfigB.AddReferencedAssemblyByPath(range0, f)) // Add script references
49334945
| Some rs -> for m, r in rs do tcConfigB.AddReferencedAssemblyByPath(m, r)
49344946

49354947
tcConfigB.resolutionEnvironment <-
@@ -4942,8 +4954,10 @@ module private ScriptPreprocessClosure =
49424954
// Indicates that there are some references not in basicReferencesForScriptLoadClosure which should
49434955
// be added conditionally once the relevant version of mscorlib.dll has been detected.
49444956
tcConfigB.implicitlyResolveAssemblies <- false
4957+
tcConfigB.useSdkRefs <- useSdkRefs
4958+
49454959
TcConfig.Create(tcConfigB, validate=true)
4946-
4960+
49474961
let ClosureSourceOfFilename(filename, m, inputCodePage, parseRequired) =
49484962
try
49494963
let filename = FileSystem.GetFullPathShim filename
@@ -5112,11 +5126,12 @@ module private ScriptPreprocessClosure =
51125126
/// Given source text, find the full load closure. Used from service.fs, when editing a script file
51135127
let GetFullClosureOfScriptText
51145128
(ctok, legacyReferenceResolver, defaultFSharpBinariesDir,
5115-
filename, sourceText,
5116-
codeContext, useSimpleResolution, useFsiAuxLib,
5129+
filename, sourceText, codeContext,
5130+
useSimpleResolution, useFsiAuxLib, useSdkRefs,
51175131
lexResourceManager: Lexhelp.LexResourceManager,
51185132
applyCommmandLineArgs, assumeDotNetFramework,
51195133
tryGetMetadataSnapshot, reduceMemoryUsage) =
5134+
51205135
// Resolve the basic references such as FSharp.Core.dll first, before processing any #I directives in the script
51215136
//
51225137
// This is tries to mimic the action of running the script in F# Interactive - the initial context for scripting is created
@@ -5126,7 +5141,7 @@ module private ScriptPreprocessClosure =
51265141
CreateScriptTextTcConfig(legacyReferenceResolver, defaultFSharpBinariesDir,
51275142
filename, codeContext, useSimpleResolution,
51285143
useFsiAuxLib, None, applyCommmandLineArgs, assumeDotNetFramework,
5129-
tryGetMetadataSnapshot, reduceMemoryUsage)
5144+
useSdkRefs, tryGetMetadataSnapshot, reduceMemoryUsage)
51305145

51315146
let resolutions0, _unresolvedReferences = GetAssemblyResolutionInformation(ctok, tcConfig)
51325147
let references0 = resolutions0 |> List.map (fun r->r.originalReference.Range, r.resolvedPath) |> Seq.distinct |> List.ofSeq
@@ -5135,7 +5150,8 @@ module private ScriptPreprocessClosure =
51355150
let tcConfig =
51365151
CreateScriptTextTcConfig(legacyReferenceResolver, defaultFSharpBinariesDir, filename,
51375152
codeContext, useSimpleResolution, useFsiAuxLib, Some references0,
5138-
applyCommmandLineArgs, assumeDotNetFramework, tryGetMetadataSnapshot, reduceMemoryUsage)
5153+
applyCommmandLineArgs, assumeDotNetFramework, useSdkRefs,
5154+
tryGetMetadataSnapshot, reduceMemoryUsage)
51395155

51405156
let closureSources = [ClosureSource(filename, range0, sourceText, true)]
51415157
let closureFiles, tcConfig = FindClosureFiles(closureSources, tcConfig, codeContext, lexResourceManager)
@@ -5161,15 +5177,15 @@ type LoadClosure with
51615177
/// A temporary TcConfig is created along the way, is why this routine takes so many arguments. We want to be sure to use exactly the
51625178
/// same arguments as the rest of the application.
51635179
static member ComputeClosureOfScriptText
5164-
(ctok, legacyReferenceResolver, defaultFSharpBinariesDir,
5165-
filename: string, sourceText:ISourceText, codeContext, useSimpleResolution: bool,
5166-
useFsiAuxLib, lexResourceManager: Lexhelp.LexResourceManager,
5167-
applyCommmandLineArgs, assumeDotNetFramework, tryGetMetadataSnapshot, reduceMemoryUsage): LoadClosure =
5180+
(ctok, legacyReferenceResolver, defaultFSharpBinariesDir,
5181+
filename: string, sourceText: ISourceText, codeContext, useSimpleResolution: bool,
5182+
useFsiAuxLib, useSdkRefs, lexResourceManager: Lexhelp.LexResourceManager,
5183+
applyCommmandLineArgs, assumeDotNetFramework, tryGetMetadataSnapshot, reduceMemoryUsage) =
51685184

51695185
use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse
51705186
ScriptPreprocessClosure.GetFullClosureOfScriptText
51715187
(ctok, legacyReferenceResolver, defaultFSharpBinariesDir, filename, sourceText,
5172-
codeContext, useSimpleResolution, useFsiAuxLib, lexResourceManager,
5188+
codeContext, useSimpleResolution, useFsiAuxLib, useSdkRefs, lexResourceManager,
51735189
applyCommmandLineArgs, assumeDotNetFramework, tryGetMetadataSnapshot, reduceMemoryUsage)
51745190

51755191
/// Analyze a set of script files and find the closure of their references.
@@ -5178,8 +5194,7 @@ type LoadClosure with
51785194
lexResourceManager: Lexhelp.LexResourceManager) =
51795195
use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse
51805196
ScriptPreprocessClosure.GetFullClosureOfScriptFiles (ctok, tcConfig, files, codeContext, lexResourceManager)
5181-
5182-
5197+
51835198

51845199
//----------------------------------------------------------------------------
51855200
// Initial type checking environment
@@ -5479,4 +5494,4 @@ let TypeCheckClosedInputSet (ctok, checkForErrors, tcConfig, tcImports, tcGlobal
54795494

54805495
// Existing public APIs delegate to newer implementations
54815496
let GetFSharpCoreLibraryName () = getFSharpCoreLibraryName
5482-
let DefaultReferencesForScriptsAndOutOfProjectSources assumeDotNetFramework = defaultReferencesForScriptsAndOutOfProjectSources assumeDotNetFramework
5497+
let DefaultReferencesForScriptsAndOutOfProjectSources assumeDotNetFramework = defaultReferencesForScriptsAndOutOfProjectSources assumeDotNetFramework false

src/fsharp/CompileOps.fsi

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ type TcConfigBuilder =
361361
mutable exename: string option
362362
mutable copyFSharpCore: CopyFSharpCoreFlag
363363
mutable shadowCopyReferences: bool
364+
mutable useSdkRefs: bool
364365

365366
/// A function to call to try to get an object that acts as a snapshot of the metadata section of a .NET binary,
366367
/// and from which we can read the metadata. Only used when metadataOnly=true.
@@ -371,6 +372,7 @@ type TcConfigBuilder =
371372

372373
/// Prevent erasure of conditional attributes and methods so tooling is able analyse them.
373374
mutable noConditionalErasure: bool
375+
374376
}
375377

376378
static member Initial: TcConfigBuilder
@@ -394,11 +396,9 @@ type TcConfigBuilder =
394396
member RemoveReferencedAssemblyByPath: range * string -> unit
395397
member AddEmbeddedSourceFile: string -> unit
396398
member AddEmbeddedResource: string -> unit
397-
398-
static member SplitCommandLineResourceInfo: string -> string * string * ILResourceAccess
399399

400+
static member SplitCommandLineResourceInfo: string -> string * string * ILResourceAccess
400401

401-
402402
[<Sealed>]
403403
// Immutable TcConfig
404404
type TcConfig =
@@ -531,6 +531,8 @@ type TcConfig =
531531

532532
member copyFSharpCore: CopyFSharpCoreFlag
533533
member shadowCopyReferences: bool
534+
member useSdkRefs: bool
535+
534536
static member Create: TcConfigBuilder * validate: bool -> TcConfig
535537

536538
/// Represents a computation to return a TcConfig. Normally this is just a constant immutable TcConfig,
@@ -801,7 +803,7 @@ type LoadClosure =
801803
//
802804
/// A temporary TcConfig is created along the way, is why this routine takes so many arguments. We want to be sure to use exactly the
803805
/// same arguments as the rest of the application.
804-
static member ComputeClosureOfScriptText: CompilationThreadToken * legacyReferenceResolver: ReferenceResolver.Resolver * defaultFSharpBinariesDir: string * filename: string * sourceText: ISourceText * implicitDefines:CodeContext * useSimpleResolution: bool * useFsiAuxLib: bool * lexResourceManager: Lexhelp.LexResourceManager * applyCompilerOptions: (TcConfigBuilder -> unit) * assumeDotNetFramework: bool * tryGetMetadataSnapshot: ILReaderTryGetMetadataSnapshot * reduceMemoryUsage: ReduceMemoryFlag -> LoadClosure
806+
static member ComputeClosureOfScriptText: CompilationThreadToken * legacyReferenceResolver: ReferenceResolver.Resolver * defaultFSharpBinariesDir: string * filename: string * sourceText: ISourceText * implicitDefines:CodeContext * useSimpleResolution: bool * useFsiAuxLib: bool * useSdkRefs: bool * lexResourceManager: Lexhelp.LexResourceManager * applyCompilerOptions: (TcConfigBuilder -> unit) * assumeDotNetFramework: bool * tryGetMetadataSnapshot: ILReaderTryGetMetadataSnapshot * reduceMemoryUsage: ReduceMemoryFlag -> LoadClosure
805807

806808
/// Analyze a set of script files and find the closure of their references. The resulting references are then added to the given TcConfig.
807809
/// Used from fsi.fs and fsc.fs, for #load and command line.

0 commit comments

Comments
 (0)