@@ -2556,7 +2556,7 @@ type TcConfig private (data : TcConfigBuilder,validate:bool) =
25562556 else
25572557 // If the file doesn't exist, let reference resolution logic report the error later...
25582558 defaultCoreLibraryReference, if r.Range = rangeStartup then Some( filename) else None
2559- match data.referencedDLLs |> List.filter( fun assemblyReference -> assemblyReference.SimpleAssemblyNameIs libraryName) with
2559+ match data.referencedDLLs |> List.filter ( fun assemblyReference -> assemblyReference.SimpleAssemblyNameIs libraryName) with
25602560 | [ r] -> nameOfDll r
25612561 | [] ->
25622562 defaultCoreLibraryReference, None
@@ -2861,9 +2861,7 @@ type TcConfig private (data : TcConfigBuilder,validate:bool) =
28612861 else Some( m, path)
28622862 with e -> errorRecovery e m; None
28632863 tcConfig.loadedSources
2864- |> List.map resolveLoadedSource
2865- |> List.filter Option.isSome
2866- |> List.map Option.get
2864+ |> List.choose resolveLoadedSource
28672865 |> List.distinct
28682866
28692867 /// A closed set of assemblies where, for any subset S:
@@ -3061,10 +3059,7 @@ type TcConfig private (data : TcConfigBuilder,validate:bool) =
30613059 let resolvedAsFile =
30623060 groupedReferences
30633061 |> Array.map( fun ( _filename , maxIndexOfReference , references ) ->
3064- let assemblyResolution = references
3065- |> List.map tcConfig.TryResolveLibWithDirectories
3066- |> List.filter Option.isSome
3067- |> List.map Option.get
3062+ let assemblyResolution = references |> List.choose tcConfig.TryResolveLibWithDirectories
30683063 ( maxIndexOfReference, assemblyResolution))
30693064 |> Array.filter( fun ( _ , refs ) -> refs|> List.isEmpty|> not )
30703065
@@ -4876,10 +4871,12 @@ type CodeContext =
48764871module private ScriptPreprocessClosure =
48774872 open Internal.Utilities .Text .Lexing
48784873
4879- type ClosureDirective =
4880- | SourceFile of string * range * string // filename, range, source text
4881- | ClosedSourceFile of string * range * ParsedInput option * PhasedError list * PhasedError list * ( string * range ) list // filename, range, errors, warnings, nowarns
4874+ /// Represents an input to the closure finding process
4875+ type ClosureSource = ClosureSource of filename : string * referenceRange : range * sourceText : string * parseRequired : bool
48824876
4877+ /// Represents an output of the closure finding process
4878+ type ClosureFile = ClosureFile of string * range * ParsedInput option * PhasedError list * PhasedError list * ( string * range ) list // filename, range, errors, warnings, nowarns
4879+
48834880 type Observed () =
48844881 let seen = System.Collections.Generic.Dictionary<_, bool>()
48854882 member ob.SetSeen ( check ) =
@@ -4935,7 +4932,7 @@ module private ScriptPreprocessClosure =
49354932 tcConfigB.implicitlyResolveAssemblies <- false
49364933 TcConfig.Create( tcConfigB, validate= true )
49374934
4938- let SourceFileOfFilename ( filename , m , inputCodePage : int option ) : ClosureDirective list =
4935+ let ClosureSourceOfFilename ( filename , m , inputCodePage , parseRequired ) =
49394936 try
49404937 let filename = FileSystem.GetFullPathShim( filename)
49414938 use stream = FileSystem.FileStreamReadShim filename
@@ -4944,7 +4941,7 @@ module private ScriptPreprocessClosure =
49444941 | None -> new StreamReader( stream, true )
49454942 | Some n -> new StreamReader( stream, Encoding.GetEncodingShim( n))
49464943 let source = reader.ReadToEnd()
4947- [ SourceFile ( filename, m, source)]
4944+ [ ClosureSource ( filename, m, source, parseRequired )]
49484945 with e ->
49494946 errorRecovery e m
49504947 []
@@ -4968,84 +4965,92 @@ module private ScriptPreprocessClosure =
49684965 let tcConfigB = tcConfig.CloneOfOriginalBuilder
49694966 TcConfig.Create( tcConfigB, validate= false ), nowarns
49704967
4971- let FindClosureDirectives ( closureDirectives , tcConfig : TcConfig , codeContext , lexResourceManager : Lexhelp.LexResourceManager ) =
4968+ let FindClosureFiles ( closureSources , tcConfig : TcConfig , codeContext , lexResourceManager : Lexhelp.LexResourceManager ) =
49724969 let tcConfig = ref tcConfig
49734970
49744971 let observedSources = Observed()
4975- let rec FindClosure ( closureDirective : ClosureDirective ) : ClosureDirective list =
4976- match closureDirective with
4977- | ClosedSourceFile _ as csf -> [ csf]
4978- | SourceFile( filename, m, source) ->
4979- let errors = ref []
4980- let warnings = ref []
4981- let errorLogger =
4982- { new ErrorLogger( " FindClosure" ) with
4983- member x.ErrorSinkImpl ( e ) = errors := e :: ! errors
4984- member x.WarnSinkImpl ( e ) = warnings := e :: ! warnings
4985- member x.ErrorCount = (! errors). Length }
4986-
4987- use unwindEL = PushErrorLoggerPhaseUntilUnwind ( fun _ -> errorLogger)
4988- let pathOfMetaCommandSource = Path.GetDirectoryName( filename)
4989- match ParseScriptText( filename, source,! tcConfig, codeContext, lexResourceManager, errorLogger) with
4990- | Some( input) ->
4991- let tcConfigResult , noWarns = ApplyMetaCommandsFromInputToTcConfigAndGatherNoWarn ! tcConfig ( input, pathOfMetaCommandSource)
4992- tcConfig := tcConfigResult
4993-
4994- let AddFileIfNotSeen ( m , filename ) =
4995- if observedSources.HaveSeen( filename) then []
4996- else
4997- observedSources.SetSeen( filename)
4998- if IsScript( filename) then SourceFileOfFilename( filename, m, tcConfigResult.inputCodePage)
4999- else [ ClosedSourceFile( filename, m, None,[],[],[])] // Don't traverse into .fs leafs.
4972+ let rec loop ( ClosureSource ( filename , m , source , parseRequired )) =
4973+ [ if not ( observedSources.HaveSeen( filename)) then
4974+ observedSources.SetSeen( filename)
4975+ //printfn "visiting %s" filename
4976+ if IsScript( filename) || parseRequired then
4977+ let errors = ref []
4978+ let warnings = ref []
4979+ let errorLogger =
4980+ { new ErrorLogger( " FindClosure" ) with
4981+ member x.ErrorSinkImpl ( e ) = errors := e :: ! errors
4982+ member x.WarnSinkImpl ( e ) = warnings := e :: ! warnings
4983+ member x.ErrorCount = (! errors). Length }
4984+
4985+ use _unwindEL = PushErrorLoggerPhaseUntilUnwind ( fun _ -> errorLogger)
4986+ let pathOfMetaCommandSource = Path.GetDirectoryName( filename)
4987+ match ParseScriptText( filename, source,! tcConfig, codeContext, lexResourceManager, errorLogger) with
4988+ | Some parsedScriptAst ->
4989+ let preSources = (! tcConfig) .GetAvailableLoadedSources()
4990+
4991+ let tcConfigResult , noWarns = ApplyMetaCommandsFromInputToTcConfigAndGatherNoWarn ! tcConfig ( parsedScriptAst, pathOfMetaCommandSource)
4992+ tcConfig := tcConfigResult // We accumulate the tcConfig in order to collect assembly references
50004993
5001- let loadedSources = (! tcConfig) .GetAvailableLoadedSources() |> List.map AddFileIfNotSeen |> List.concat
5002- ( loadedSources |> List.map FindClosure |> List.concat)
5003- @ [ ClosedSourceFile( filename, m, Some( input),! errors,! warnings,! noWarns)]
5004- | None -> [ ClosedSourceFile( filename, m, None,! errors,! warnings,[])]
4994+ let postSources = (! tcConfig) .GetAvailableLoadedSources()
4995+ let sources = if preSources.Length < postSources.Length then postSources.[ preSources.Length..] else []
4996+
4997+ //for (_,subFile) in sources do
4998+ // printfn "visiting %s - has subsource of %s " filename subFile
4999+
5000+ for ( m, subFile) in sources do
5001+ if IsScript( subFile) then
5002+ for subSource in ClosureSourceOfFilename( subFile, m, tcConfigResult.inputCodePage, false ) do
5003+ yield ! loop subSource
5004+ else
5005+ yield ClosureFile( subFile, m, None, [], [], [])
5006+
5007+ //printfn "yielding source %s" filename
5008+ yield ClosureFile( filename, m, Some parsedScriptAst, ! errors, ! warnings, ! noWarns)
50055009
5006- closureDirectives |> List.map FindClosure |> List.concat, ! tcConfig
5010+ | None ->
5011+ //printfn "yielding source %s (failed parse)" filename
5012+ yield ClosureFile( filename, m, None, ! errors, ! warnings, [])
5013+ else
5014+ // Don't traverse into .fs leafs.
5015+ //printfn "yielding non-script source %s" filename
5016+ yield ClosureFile( filename, m, None, [], [], []) ]
5017+
5018+ closureSources |> List.map loop |> List.concat, ! tcConfig
50075019
50085020 /// Reduce the full directive closure into LoadClosure
5009- let GetLoadClosure ( rootFilename , closureDirectives ,( tcConfig : TcConfig ) ,codeContext ) =
5021+ let GetLoadClosure ( rootFilename , closureFiles , tcConfig : TcConfig , codeContext ) =
50105022
5011- // Mark the last file as isLastCompiland. closureDirectives is currently reversed.
5012- let closureDirectives =
5013- match closureDirectives with
5014- | ClosedSourceFile ( filename, m, Some( ParsedInput.ImplFile( ParsedImplFileInput( name, isScript, qualNameOfFile, scopedPragmas, hashDirectives, implFileFlags,_))), errs, warns, nowarns):: rest ->
5015- ClosedSourceFile ( filename, m, Some( ParsedInput.ImplFile( ParsedImplFileInput( name, isScript, qualNameOfFile, scopedPragmas, hashDirectives, implFileFlags,( true , tcConfig.target.IsExe)))), errs, warns, nowarns):: rest
5016- | x -> x
5023+ // Mark the last file as isLastCompiland.
5024+ let closureFiles =
5025+ match List.frontAndBack closureFiles with
5026+ | rest , ClosureFile ( filename, m, Some( ParsedInput.ImplFile( ParsedImplFileInput( name, isScript, qualNameOfFile, scopedPragmas, hashDirectives, implFileFlags,_))), errs, warns, nowarns) ->
5027+ rest @ [ ClosureFile ( filename, m, Some( ParsedInput.ImplFile( ParsedImplFileInput( name, isScript, qualNameOfFile, scopedPragmas, hashDirectives, implFileFlags,( true , tcConfig.target.IsExe)))), errs, warns, nowarns)]
5028+ | _ -> closureFiles
50175029
50185030 // Get all source files.
5019- let sourceFiles = ref []
5020- let sourceInputs = ref []
5021- let globalNoWarns = ref []
5022- for directive in List.rev closureDirectives do
5023- match directive with
5024- | ClosedSourceFile( filename, m, input,_,_, noWarns) ->
5025- let filename = FileSystem.GetFullPathShim( filename)
5026- sourceFiles := ( filename, m) :: ! sourceFiles
5027- globalNoWarns := (! globalNoWarns @ noWarns)
5028- sourceInputs := ( filename, input) :: ! sourceInputs
5029- | _ -> failwith " Unexpected"
5030-
5031+ let sourceFiles = [ for ( ClosureFile( filename, m,_,_,_,_)) in closureFiles -> ( filename, m) ]
5032+ let sourceInputs = [ for ( ClosureFile( filename,_, input,_,_,_)) in closureFiles -> ( filename, input) ]
5033+ let globalNoWarns = closureFiles |> List.collect ( fun ( ClosureFile ( _ , _ , _ , _ , _ , noWarns )) -> noWarns)
5034+
50315035 // Resolve all references.
5032- let resolutionErrors = ref []
5033- let resolutionWarnings = ref []
5034- let errorLogger =
5035- { new ErrorLogger( " GetLoadClosure" ) with
5036- member x.ErrorSinkImpl ( e ) = resolutionErrors := e :: ! resolutionErrors
5037- member x.WarnSinkImpl ( e ) = resolutionWarnings := e :: ! resolutionWarnings
5038- member x.ErrorCount = (! resolutionErrors). Length }
5036+ let references , unresolvedReferences , resolutionWarnings , resolutionErrors =
5037+ let resolutionErrors = ref []
5038+ let resolutionWarnings = ref []
5039+ let errorLogger =
5040+ { new ErrorLogger( " GetLoadClosure" ) with
5041+ member x.ErrorSinkImpl ( e ) = resolutionErrors := e :: ! resolutionErrors
5042+ member x.WarnSinkImpl ( e ) = resolutionWarnings := e :: ! resolutionWarnings
5043+ member x.ErrorCount = (! resolutionErrors). Length }
50395044
5040- let references , unresolvedReferences =
50415045 use unwindEL = PushErrorLoggerPhaseUntilUnwind ( fun _ -> errorLogger)
5042- GetAssemblyResolutionInformation( tcConfig)
5043- let references = references |> List.map ( fun ar -> ar.resolvedPath, ar)
5044-
5045- // Root errors and warnings
5046+ let references , unresolvedReferences = GetAssemblyResolutionInformation( tcConfig)
5047+ let references = references |> List.map ( fun ar -> ar.resolvedPath, ar)
5048+ references, unresolvedReferences, resolutionWarnings, resolutionErrors
5049+
5050+ // Root errors and warnings - look at the last item in the closureFiles list
50465051 let rootErrors , rootWarnings =
5047- match closureDirectives with
5048- | ClosedSourceFile (_,_,_, errors, warnings,_) :: _ -> errors @ ! resolutionErrors, warnings @ ! resolutionWarnings
5052+ match List.rev closureFiles with
5053+ | ClosureFile (_,_,_, errors, warnings,_) :: _ -> errors @ ! resolutionErrors, warnings @ ! resolutionWarnings
50495054 | _ -> [],[] // When no file existed.
50505055
50515056 let isRootRange exn =
@@ -5062,11 +5067,11 @@ module private ScriptPreprocessClosure =
50625067 let rootWarnings = rootWarnings |> List.filter isRootRange
50635068
50645069 let result : LoadClosure =
5065- { SourceFiles = List.groupByFirst ! sourceFiles
5070+ { SourceFiles = List.groupByFirst sourceFiles
50665071 References = List.groupByFirst references
50675072 UnresolvedReferences = unresolvedReferences
5068- Inputs = ! sourceInputs
5069- NoWarns = List.groupByFirst ! globalNoWarns
5073+ Inputs = sourceInputs
5074+ NoWarns = List.groupByFirst globalNoWarns
50705075 RootErrors = rootErrors
50715076 RootWarnings = rootWarnings}
50725077
@@ -5086,17 +5091,17 @@ module private ScriptPreprocessClosure =
50865091
50875092 let tcConfig = CreateScriptSourceTcConfig( filename, codeContext, useSimpleResolution, useFsiAuxLib, Some references0, applyCommmandLineArgs)
50885093
5089- let protoClosure = [ SourceFile ( filename, range0, source)]
5090- let finalClosure , tcConfig = FindClosureDirectives ( protoClosure , tcConfig, codeContext, lexResourceManager)
5091- GetLoadClosure( filename, finalClosure , tcConfig, codeContext)
5094+ let closureSources = [ ClosureSource ( filename, range0, source, true )]
5095+ let closureFiles , tcConfig = FindClosureFiles ( closureSources , tcConfig, codeContext, lexResourceManager)
5096+ GetLoadClosure( filename, closureFiles , tcConfig, codeContext)
50925097
50935098 /// Given source filename, find the full load closure
50945099 /// Used from fsi.fs and fsc.fs, for #load and command line
50955100 let GetFullClosureOfScriptFiles ( tcConfig : TcConfig , files :( string * range ) list , codeContext , _useDefaultScriptingReferences : bool , lexResourceManager : Lexhelp.LexResourceManager ) =
5096- let mainFile = fst ( List.head files)
5097- let protoClosure = files |> List.map ( fun ( filename , m ) -> SourceFileOfFilename ( filename, m, tcConfig.inputCodePage)) |> List.concat |> List.rev // Reverse to put them in the order they will be extracted later
5098- let finalClosure , tcConfig = FindClosureDirectives ( protoClosure , tcConfig, codeContext, lexResourceManager)
5099- GetLoadClosure( mainFile, finalClosure , tcConfig, codeContext)
5101+ let mainFile = fst ( List.last files)
5102+ let closureSources = files |> List.map ( fun ( filename , m ) -> ClosureSourceOfFilename ( filename, m, tcConfig.inputCodePage, true )) |> List.concat
5103+ let closureFiles , tcConfig = FindClosureFiles ( closureSources , tcConfig, codeContext, lexResourceManager)
5104+ GetLoadClosure( mainFile, closureFiles , tcConfig, codeContext)
51005105
51015106type LoadClosure with
51025107 // Used from service.fs, when editing a script file
0 commit comments