Skip to content

Commit d58159c

Browse files
authored
Add use refassemblies switch to fsi (#6585)
* Add support for fsi against ref assemblies * temp * working * Fix fsi
1 parent 22fc113 commit d58159c

21 files changed

+276
-77
lines changed

src/fsharp/CompileOps.fs

Lines changed: 49 additions & 32 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,16 @@ 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
3520+
//yield primaryReference
35143521

35153522
if not tcConfig.compilingFslib then
35163523
yield tcConfig.CoreLibraryDllReference()
35173524

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

35233530
if tcConfig.useFsiAuxLib then
@@ -4552,8 +4559,14 @@ type TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAssemblyResolu
45524559

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

45704583
// These are the DLLs we can search for well-known types
4571-
let sysCcus =
4584+
let sysCcus =
45724585
[| for ccu in frameworkTcImports.GetCcusInDeclOrder() do
45734586
//printfn "found sys ccu %s" ccu.AssemblyName
45744587
yield ccu |]
@@ -4913,8 +4926,8 @@ module private ScriptPreprocessClosure =
49134926
filename: string, codeContext,
49144927
useSimpleResolution, useFsiAuxLib,
49154928
basicReferences, applyCommandLineArgs,
4916-
assumeDotNetFramework, tryGetMetadataSnapshot,
4917-
reduceMemoryUsage) =
4929+
assumeDotNetFramework, useSdkRefs,
4930+
tryGetMetadataSnapshot, reduceMemoryUsage) =
49184931

49194932
let projectDir = Path.GetDirectoryName filename
49204933
let isInteractive = (codeContext = CodeContext.CompilationAndEvaluation)
@@ -4929,7 +4942,7 @@ module private ScriptPreprocessClosure =
49294942
applyCommandLineArgs tcConfigB
49304943

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

49354948
tcConfigB.resolutionEnvironment <-
@@ -4942,8 +4955,10 @@ module private ScriptPreprocessClosure =
49424955
// Indicates that there are some references not in basicReferencesForScriptLoadClosure which should
49434956
// be added conditionally once the relevant version of mscorlib.dll has been detected.
49444957
tcConfigB.implicitlyResolveAssemblies <- false
4958+
tcConfigB.useSdkRefs <- useSdkRefs
4959+
49454960
TcConfig.Create(tcConfigB, validate=true)
4946-
4961+
49474962
let ClosureSourceOfFilename(filename, m, inputCodePage, parseRequired) =
49484963
try
49494964
let filename = FileSystem.GetFullPathShim filename
@@ -5111,12 +5126,13 @@ module private ScriptPreprocessClosure =
51115126

51125127
/// Given source text, find the full load closure. Used from service.fs, when editing a script file
51135128
let GetFullClosureOfScriptText
5114-
(ctok, legacyReferenceResolver, defaultFSharpBinariesDir,
5115-
filename, sourceText,
5116-
codeContext, useSimpleResolution, useFsiAuxLib,
5117-
lexResourceManager: Lexhelp.LexResourceManager,
5129+
(ctok, legacyReferenceResolver, defaultFSharpBinariesDir,
5130+
filename, sourceText, codeContext,
5131+
useSimpleResolution, useFsiAuxLib, useSdkRefs,
5132+
lexResourceManager: Lexhelp.LexResourceManager,
51185133
applyCommmandLineArgs, assumeDotNetFramework,
5119-
tryGetMetadataSnapshot, reduceMemoryUsage) =
5134+
tryGetMetadataSnapshot, reduceMemoryUsage) =
5135+
51205136
// Resolve the basic references such as FSharp.Core.dll first, before processing any #I directives in the script
51215137
//
51225138
// This is tries to mimic the action of running the script in F# Interactive - the initial context for scripting is created
@@ -5126,7 +5142,7 @@ module private ScriptPreprocessClosure =
51265142
CreateScriptTextTcConfig(legacyReferenceResolver, defaultFSharpBinariesDir,
51275143
filename, codeContext, useSimpleResolution,
51285144
useFsiAuxLib, None, applyCommmandLineArgs, assumeDotNetFramework,
5129-
tryGetMetadataSnapshot, reduceMemoryUsage)
5145+
useSdkRefs, tryGetMetadataSnapshot, reduceMemoryUsage)
51305146

51315147
let resolutions0, _unresolvedReferences = GetAssemblyResolutionInformation(ctok, tcConfig)
51325148
let references0 = resolutions0 |> List.map (fun r->r.originalReference.Range, r.resolvedPath) |> Seq.distinct |> List.ofSeq
@@ -5135,7 +5151,8 @@ module private ScriptPreprocessClosure =
51355151
let tcConfig =
51365152
CreateScriptTextTcConfig(legacyReferenceResolver, defaultFSharpBinariesDir, filename,
51375153
codeContext, useSimpleResolution, useFsiAuxLib, Some references0,
5138-
applyCommmandLineArgs, assumeDotNetFramework, tryGetMetadataSnapshot, reduceMemoryUsage)
5154+
applyCommmandLineArgs, assumeDotNetFramework, useSdkRefs,
5155+
tryGetMetadataSnapshot, reduceMemoryUsage)
51395156

51405157
let closureSources = [ClosureSource(filename, range0, sourceText, true)]
51415158
let closureFiles, tcConfig = FindClosureFiles(closureSources, tcConfig, codeContext, lexResourceManager)
@@ -5161,15 +5178,15 @@ type LoadClosure with
51615178
/// 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
51625179
/// same arguments as the rest of the application.
51635180
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 =
5181+
(ctok, legacyReferenceResolver, defaultFSharpBinariesDir,
5182+
filename: string, sourceText: ISourceText, codeContext, useSimpleResolution: bool,
5183+
useFsiAuxLib, useSdkRefs, lexResourceManager: Lexhelp.LexResourceManager,
5184+
applyCommmandLineArgs, assumeDotNetFramework, tryGetMetadataSnapshot, reduceMemoryUsage) =
51685185

51695186
use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse
51705187
ScriptPreprocessClosure.GetFullClosureOfScriptText
5171-
(ctok, legacyReferenceResolver, defaultFSharpBinariesDir, filename, sourceText,
5172-
codeContext, useSimpleResolution, useFsiAuxLib, lexResourceManager,
5188+
(ctok, legacyReferenceResolver, defaultFSharpBinariesDir, filename, sourceText,
5189+
codeContext, useSimpleResolution, useFsiAuxLib, useSdkRefs, lexResourceManager,
51735190
applyCommmandLineArgs, assumeDotNetFramework, tryGetMetadataSnapshot, reduceMemoryUsage)
51745191

51755192
/// Analyze a set of script files and find the closure of their references.
@@ -5479,4 +5496,4 @@ let TypeCheckClosedInputSet (ctok, checkForErrors, tcConfig, tcImports, tcGlobal
54795496

54805497
// Existing public APIs delegate to newer implementations
54815498
let GetFSharpCoreLibraryName () = getFSharpCoreLibraryName
5482-
let DefaultReferencesForScriptsAndOutOfProjectSources assumeDotNetFramework = defaultReferencesForScriptsAndOutOfProjectSources assumeDotNetFramework
5499+
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.

src/fsharp/CompileOptions.fs

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,9 @@ let subSystemVersionSwitch (tcConfigB: TcConfigBuilder) (text: string) =
442442
| _ -> fail()
443443
| _ -> fail()
444444

445+
let SetUseSdkSwitch (tcConfigB: TcConfigBuilder) switch =
446+
tcConfigB.useSdkRefs <- (switch = OptionSwitch.On)
447+
445448
let (++) x s = x @ [s]
446449

447450
let SetTarget (tcConfigB: TcConfigBuilder)(s: string) =
@@ -544,18 +547,21 @@ let PrintOptionInfo (tcConfigB:TcConfigBuilder) =
544547
// OptionBlock: Input files
545548
//-------------------------
546549

547-
let inputFileFlagsBoth (tcConfigB : TcConfigBuilder) =
548-
[ CompilerOption("reference", tagFile, OptionString (fun s -> tcConfigB.AddReferencedAssemblyByPath (rangeStartup, s)), None,
549-
Some (FSComp.SR.optsReference()) )
550+
let inputFileFlagsBoth (tcConfigB: TcConfigBuilder) =
551+
[ CompilerOption("reference", tagFile, OptionString (fun s -> tcConfigB.AddReferencedAssemblyByPath (rangeStartup, s)), None, Some (FSComp.SR.optsReference()))
550552
]
551553

552-
let referenceFlagAbbrev (tcConfigB: TcConfigBuilder) =
553-
CompilerOption("r", tagFile, OptionString (fun s -> tcConfigB.AddReferencedAssemblyByPath (rangeStartup, s)), None,
554-
Some(FSComp.SR.optsShortFormOf("--reference")) )
555-
556-
let inputFileFlagsFsi tcConfigB = inputFileFlagsBoth tcConfigB
557-
let inputFileFlagsFsc tcConfigB = inputFileFlagsBoth tcConfigB
554+
let inputFileFlagsFsc tcConfigB = inputFileFlagsBoth tcConfigB
555+
556+
let inputFileFlagsFsiBase (_tcConfigB: TcConfigBuilder) =
557+
#if NETSTANDARD
558+
[ CompilerOption("usesdkrefs", tagNone, OptionSwitch (SetUseSdkSwitch _tcConfigB), None, Some (FSComp.SR.useSdkRefs())) ]
559+
#else
560+
List.empty<CompilerOption>
561+
#endif
558562

563+
let inputFileFlagsFsi (tcConfigB: TcConfigBuilder) =
564+
List.concat [ inputFileFlagsBoth tcConfigB; inputFileFlagsFsiBase tcConfigB]
559565

560566
// OptionBlock: Errors and warnings
561567
//---------------------------------
@@ -825,12 +831,6 @@ let libFlag (tcConfigB: TcConfigBuilder) =
825831
OptionStringList (fun s -> tcConfigB.AddIncludePath (rangeStartup, s, tcConfigB.implicitIncludeDir)), None,
826832
Some (FSComp.SR.optsLib()))
827833

828-
let libFlagAbbrev (tcConfigB: TcConfigBuilder) =
829-
CompilerOption
830-
("I", tagDirList,
831-
OptionStringList (fun s -> tcConfigB.AddIncludePath (rangeStartup, s, tcConfigB.implicitIncludeDir)), None,
832-
Some (FSComp.SR.optsShortFormOf("--lib")))
833-
834834
let codePageFlag (tcConfigB: TcConfigBuilder) =
835835
CompilerOption
836836
("codepage", tagInt,
@@ -1395,8 +1395,10 @@ let abbreviatedFlagsBoth tcConfigB =
13951395
CompilerOption("O", tagNone, OptionSwitch (SetOptimizeSwitch tcConfigB), None, Some(FSComp.SR.optsShortFormOf("--optimize[+|-]")))
13961396
CompilerOption("g", tagNone, OptionSwitch (SetDebugSwitch tcConfigB None), None, Some(FSComp.SR.optsShortFormOf("--debug")))
13971397
CompilerOption("i", tagString, OptionUnit (fun () -> tcConfigB.printSignature <- true), None, Some(FSComp.SR.optsShortFormOf("--sig")))
1398-
referenceFlagAbbrev tcConfigB (* -r <dll> *)
1399-
libFlagAbbrev tcConfigB (* -I <dir> *)
1398+
CompilerOption("r", tagFile, OptionString (fun s -> tcConfigB.AddReferencedAssemblyByPath (rangeStartup, s)),
1399+
None, Some(FSComp.SR.optsShortFormOf("--reference")))
1400+
CompilerOption("I", tagDirList, OptionStringList (fun s -> tcConfigB.AddIncludePath (rangeStartup, s, tcConfigB.implicitIncludeDir)),
1401+
None, Some (FSComp.SR.optsShortFormOf("--lib")))
14001402
]
14011403

14021404
let abbreviatedFlagsFsi tcConfigB = abbreviatedFlagsBoth tcConfigB

0 commit comments

Comments
 (0)