@@ -58,10 +58,10 @@ type InteractiveChecker internal (tcConfig, tcGlobals, tcImports, tcInitialState
5858
5959 static member Create ( references : string [], readAllBytes : string -> byte [], defines : string [], optimize : bool ) =
6060
61- let GetSignatureData (( filename : string ), ilScopeRef , ( ilModule : ILModuleDef option ), ( bytes : byte [])) =
62- TastPickle.unpickleObjWithDanglingCcus filename ilScopeRef ilModule TastPickle.unpickleCcuInfo bytes
63- let GetOptimizationData (( filename : string ), ilScopeRef , ( ilModule : ILModuleDef option ), ( bytes : byte [])) =
64- TastPickle.unpickleObjWithDanglingCcus filename ilScopeRef ilModule Optimizer.u_ CcuOptimizationInfo bytes
61+ let GetSignatureData (( fileName : string ), ilScopeRef , ( ilModule : ILModuleDef option ), ( bytes : byte [])) =
62+ TastPickle.unpickleObjWithDanglingCcus fileName ilScopeRef ilModule TastPickle.unpickleCcuInfo bytes
63+ let GetOptimizationData (( fileName : string ), ilScopeRef , ( ilModule : ILModuleDef option ), ( bytes : byte [])) =
64+ TastPickle.unpickleObjWithDanglingCcus fileName ilScopeRef ilModule Optimizer.u_ CcuOptimizationInfo bytes
6565
6666 let tcConfig = TcConfig ( optimize, defines = Array.toList defines)
6767 let tcImports = TcImports ()
@@ -233,9 +233,9 @@ type InteractiveChecker internal (tcConfig, tcGlobals, tcImports, tcInitialState
233233 let entityOpt = ( Some ccu.Contents, nsname) ||> List.fold findEntity
234234 match entityOpt with
235235 | Some ns ->
236- match Map.tryFind tname ns.ModuleOrNamespaceType.TypesByMangledName with
237- | Some _ -> true
238- | None -> false
236+ match Map.tryFind tname ns.ModuleOrNamespaceType.TypesByMangledName with
237+ | Some _ -> true
238+ | None -> false
239239 | None -> false
240240
241241 // Search for a type
@@ -281,8 +281,9 @@ type InteractiveChecker internal (tcConfig, tcGlobals, tcImports, tcInitialState
281281
282282 // dictionary for de-duplicating module names
283283 let moduleNamesDict = ConcurrentDictionary< string, Set< string>>()
284- // parse and type check caches
285- let parseCache = ConcurrentDictionary< string * int * FSharpParsingOptions, FSharpParseFileResults>( HashIdentity.Structural)
284+ // parse cache, keyed on file name and source hash
285+ let parseCache = ConcurrentDictionary< string * int, FSharpParseFileResults>( HashIdentity.Structural)
286+ // type check cache, keyed on file name
286287 let checkCache = ConcurrentDictionary< string, TcResult * TcState>( HashIdentity.Structural)
287288
288289 InteractiveChecker ( tcConfig, tcGlobals, tcImports, tcInitialState, ctok, reactorOps, moduleNamesDict, parseCache, checkCache)
@@ -294,141 +295,179 @@ type InteractiveChecker internal (tcConfig, tcGlobals, tcImports, tcInitialState
294295 let access = tcState.TcEnvFromImpls.AccessRights
295296 let dependencyFiles = parseResults |> Seq.map ( fun x -> x.DependencyFiles) |> Array.concat
296297 let details = ( tcGlobals, tcImports, tcState.Ccu, tcState.CcuSig, symbolUses, topAttrsOpt, assemblyDataOpt, assemblyRef, access, tcImplFilesOpt, dependencyFiles)
297- FSharpCheckProjectResults ( projectFileName, Some tcConfig, true , errors, Some details)
298+ let keepAssemblyContents = true
299+ FSharpCheckProjectResults ( projectFileName, Some tcConfig, keepAssemblyContents, errors, Some details)
298300
299301 member private x.ClearStaleCache ( fileName : string , parsingOptions : FSharpParsingOptions ) =
300302 let fileIndex = parsingOptions.SourceFiles |> Array.findIndex ((=) fileName)
301- let _ , staleCheckKeys = parsingOptions.SourceFiles |> Array.splitAt fileIndex
302- let staleParseKeys = parseCache.Keys |> Seq.filter ( fun ( fname , _ , _ ) -> fname = fileName ) |> Seq.toArray
303+ let staleParseKeys = parseCache.Keys |> Seq.filter ( fun ( n , _ ) -> n = fileName ) |> Seq.toArray
304+ let staleCheckKeys = parsingOptions.SourceFiles |> Array.skip fileIndex
303305 staleParseKeys |> Array.iter ( fun key -> parseCache.Remove( key) |> ignore)
304306 staleCheckKeys |> Array.iter ( fun key -> checkCache.Remove( key) |> ignore)
305307
306- member private x.ParseScript ( fileName : string , source : string , parsingOptions : FSharpParsingOptions ) =
307- let parseCacheKey = fileName, hash source, parsingOptions
308+ member private x.ParseFile ( fileName : string , source : string , parsingOptions : FSharpParsingOptions ) =
309+ let parseCacheKey = fileName, hash source
308310 parseCache.GetOrAdd( parseCacheKey, fun _ ->
309311 x.ClearStaleCache( fileName, parsingOptions)
310312 let parseErrors , parseTreeOpt , anyErrors = Parser.parseFile ( source, fileName, parsingOptions, userOpName)
311313 let parseTreeOpt = parseTreeOpt |> Option.map ( DeduplicateParsedInputModuleName moduleNamesDict)
312314 let dependencyFiles = [||] // interactions have no dependencies
313315 FSharpParseFileResults ( parseErrors, parseTreeOpt, anyErrors, dependencyFiles) )
314316
317+ // member private x.CheckFile (source: string, projectFileName: string, parseResults: FSharpParseFileResults, tcState: TcState) =
318+ // let fileName = parseResults.FileName
319+ // let loadClosure = None
320+ // let backgroundErrors = [||]
321+ // let checkAlive () = true
322+ // let textSnapshotInfo = None
323+ // let tcResults = Parser.CheckOneFile(
324+ // parseResults, source, fileName, projectFileName, tcConfig, tcGlobals, tcImports, tcState,
325+ // loadClosure, backgroundErrors, reactorOps, checkAlive, textSnapshotInfo, userOpName)
326+ // match tcResults with
327+ // | tcErrors, Parser.TypeCheckAborted.No scope ->
328+ // let errors = Array.append parseResults.Errors tcErrors
329+ // let checkResults = FSharpCheckFileResults (fileName, errors, Some scope, parseResults.DependencyFiles, None, reactorOps, true)
330+ // FSharpCheckFileAnswer.Succeeded checkResults
331+ // | _ ->
332+ // FSharpCheckFileAnswer.Aborted
333+
334+ member private x.CheckFile ( projectFileName : string , parseResults : FSharpParseFileResults , tcState : TcState ) =
335+ match parseResults.ParseTree with
336+ | Some input ->
337+ let capturingErrorLogger = CompilationErrorLogger( " TypeCheckFile" , tcConfig.errorSeverityOptions)
338+ let errorLogger = GetErrorLoggerFilteringByScopedPragmas( false , GetScopedPragmasForInput( input), capturingErrorLogger)
339+ use _errorScope = new CompilationGlobalsScope ( errorLogger, BuildPhase.TypeCheck)
340+
341+ let sink = TcResultsSinkImpl( tcGlobals)
342+ let tcSink = TcResultsSink.WithSink sink
343+ let checkForErrors () = parseResults.ParseHadErrors || errorLogger.ErrorCount > 0
344+ let prefixPathOpt = None
345+ let ( tcEnvAtEnd , topAttrs , implFile , ccuSigForFile ), tcState =
346+ TypeCheckOneInputEventually ( checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt, tcSink, tcState, input)
347+ |> Eventually.force ctok
348+
349+ let fileName = parseResults.FileName
350+ checkCache.[ fileName] <- (( tcEnvAtEnd, topAttrs, implFile, ccuSigForFile), tcState)
351+
352+ let loadClosure = None
353+ let checkAlive () = true
354+ let textSnapshotInfo = None
355+ let keepAssemblyContents = true
356+
357+ let tcErrors = ErrorHelpers.CreateErrorInfos ( tcConfig.errorSeverityOptions, false , fileName, ( capturingErrorLogger.GetErrors()))
358+ let errors = Array.append parseResults.Errors tcErrors
359+
360+ let scope = TypeCheckInfo ( tcConfig, tcGlobals, ccuSigForFile, tcState.Ccu, tcImports, tcEnvAtEnd.AccessRights,
361+ projectFileName, fileName, sink.GetResolutions(), sink.GetSymbolUses(), tcEnvAtEnd.NameEnv,
362+ loadClosure, reactorOps, checkAlive, textSnapshotInfo, implFile, sink.GetOpenDeclarations())
363+ FSharpCheckFileResults ( fileName, errors, Some scope, parseResults.DependencyFiles, None, reactorOps, keepAssemblyContents)
364+ |> Some
365+ | None ->
366+ None
367+
315368 member private x.TypeCheckClosedInputSet ( ctok , checkForErrors , tcConfig , tcImports , tcGlobals , prefixPathOpt , tcState , inputs ) =
316- // tcEnvAtEndOfLastFile is the environment when incrementally adding definitions
317369 let fileNameOf = function
318370 | ParsedInput.SigFile ( ParsedSigFileInput( fileName,_,_,_,_)) -> fileName
319371 | ParsedInput.ImplFile ( ParsedImplFileInput( fileName,_,_,_,_,_,_)) -> fileName
320372 let cachedTypeCheck tcState ( input : ParsedInput ) =
321373 let checkCacheKey = fileNameOf input
322374 checkCache.GetOrAdd( checkCacheKey, fun _ ->
323375 TypeCheckOneInput ( ctok, checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt) tcState input)
324- let results , tcState = ( tcState, inputs) ||> List.mapFold cachedTypeCheck
325- let ( tcEnvAtEndOfLastFile , topAttrs , implFiles , _ ), tcState = TypeCheckMultipleInputsFinish( results, tcState)
376+ let results , tcState = ( tcState, inputs) ||> List.mapFold cachedTypeCheck
377+ let ( tcEnvAtEndOfLastFile , topAttrs , implFiles , _ccuSigsForFiles ), tcState =
378+ TypeCheckMultipleInputsFinish( results, tcState)
326379 let tcState , declaredImpls = TypeCheckClosedInputSetFinish ( implFiles, tcState)
327380 tcState, topAttrs, declaredImpls, tcEnvAtEndOfLastFile
328381
329382 member x.ClearCache () =
330383 parseCache.Clear()
331384 checkCache.Clear()
332385
333- member x.ParseAndCheckScript ( projectFileName , filename : string , source : string ) =
334- let parsingOptions = FSharpParsingOptions.FromTcConfig( tcConfig, [| filename |], true )
335- let parseResults = x.ParseScript ( filename, source, parsingOptions)
386+ member x.ParseAndCheckScript ( projectFileName : string , fileName : string , source : string ) =
387+ let fileNames = [| fileName |]
388+ let parsingOptions = FSharpParsingOptions.FromTcConfig( tcConfig, fileNames, false )
389+ let parseResults = x.ParseFile ( fileName, source, parsingOptions)
336390 let loadClosure = None
337391 let backgroundErrors = [||]
338- let checkAlive = fun () -> true
392+ let checkAlive () = true
339393 let textSnapshotInfo = None
340394 let tcState = tcInitialState
341395 let tcResults = Parser.CheckOneFile(
342- parseResults, source, filename , projectFileName, tcConfig, tcGlobals, tcImports, tcState,
396+ parseResults, source, fileName , projectFileName, tcConfig, tcGlobals, tcImports, tcState,
343397 loadClosure, backgroundErrors, reactorOps, checkAlive, textSnapshotInfo, userOpName)
344398 match tcResults with
345399 | tcErrors, Parser.TypeCheckAborted.No scope ->
346400 let errors = Array.append parseResults.Errors tcErrors
347401 let tcImplFilesOpt = match scope.ImplementationFile with Some x -> Some [ x] | None -> None
348- let typeCheckResults = FSharpCheckFileResults ( filename , errors, Some scope, parseResults.DependencyFiles, None, reactorOps, true )
402+ let typeCheckResults = FSharpCheckFileResults ( fileName , errors, Some scope, parseResults.DependencyFiles, None, reactorOps, true )
349403 let symbolUses = [ scope.ScopeSymbolUses]
350404 let projectResults = x.MakeProjectResults ( projectFileName, [| parseResults|], tcState, errors, symbolUses, None, tcImplFilesOpt)
351405 parseResults, typeCheckResults, projectResults
352406 | _ ->
353407 failwith " unexpected aborted"
354408
355- member x.ParseAndCheckProject ( projectFileName , fileNames : string [], sources : string []) =
356- use errorScope = new ErrorScope()
357-
409+ member x.ParseAndCheckProject ( projectFileName : string , fileNames : string [], sources : string []) =
358410 // parse files
359- let parsingOptions = FSharpParsingOptions.FromTcConfig( tcConfig, fileNames, true )
360- let parseScript ( filename , source ) = x.ParseScript ( filename , source, parsingOptions)
361- let parseResults = Array.zip fileNames sources |> Array.map parseScript
411+ let parsingOptions = FSharpParsingOptions.FromTcConfig( tcConfig, fileNames, false )
412+ let parseFile ( fileName , source ) = x.ParseFile ( fileName , source, parsingOptions)
413+ let parseResults = Array.zip fileNames sources |> Array.map parseFile
362414 let parseHadErrors = parseResults |> Array.exists ( fun p -> p.ParseHadErrors)
363- let inputs = parseResults |> Array.choose ( fun p -> p.ParseTree) |> Array.toList
415+ let parsedInputs = parseResults |> Array.choose ( fun p -> p.ParseTree) |> Array.toList
364416
365417 // type check files
366- let checkForErrors () = parseHadErrors
418+ use errorScope = new ErrorScope()
419+ let hasTypedErrors () = errorScope.Diagnostics |> List.exists ( fun e -> e.Severity = FSharpErrorSeverity.Error)
420+ let checkForErrors () = parseHadErrors || hasTypedErrors ()
367421 let prefixPathOpt = None
368422 let tcState , topAttrs , tcImplFiles , _tcEnvAtEnd =
369- x.TypeCheckClosedInputSet ( ctok, checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt, tcInitialState, inputs )
423+ x.TypeCheckClosedInputSet ( ctok, checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt, tcInitialState, parsedInputs )
370424
371425 // make project results
372426 let parseErrors = parseResults |> Array.collect ( fun p -> p.Errors)
373- let tcErrors = errorScope.Diagnostics |> List.toArray
374- let errors = Array.append parseErrors tcErrors
427+ let typedErrors = errorScope.Diagnostics |> List.toArray
428+ let errors = Array.append parseErrors typedErrors
375429 let symbolUses = [] //TODO:
376430 let projectResults = x.MakeProjectResults ( projectFileName, parseResults, tcState, errors, symbolUses, Some topAttrs, Some tcImplFiles)
377431
378432 projectResults
379433
380- // // TODO:
381- // member __.GetParseResults (fileName) =
382- // parseResults, typeCheckResults
383-
384- // // this version is too memory-inefficient
385- // member x.ParseAndCheckProjectFiles (projectFileName, fileNames: string[], sources: string[]) =
386- // use errorScope = new ErrorScope()
387- // let sink = TcResultsSinkImpl(tcGlobals)
388-
389- // let typeCheckOneInput (ctok, checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt) tcSink tcState input =
390- // //// 'use' ensures that the warning handler is restored at the end
391- // //use unwindEL = PushErrorLoggerPhaseUntilUnwind(fun oldLogger ->
392- // // GetErrorLoggerFilteringByScopedPragmas(false, GetScopedPragmasForInput(input), oldLogger) )
393- // //use unwindBP = PushThreadBuildPhaseUntilUnwind BuildPhase.TypeCheck
394- // TypeCheckOneInputEventually (checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt, tcSink, tcState, input)
395- // |> Eventually.force ctok
396-
397- // let makeTcResult (tcState: TcState) (parseRes: FSharpParseFileResults, (tcEnvAtEnd: TcEnv, _topAttrs, implFile, ccuSigForFile)) =
398- // let filename = parseRes.FileName
399- // let loadClosure = None
400- // let checkAlive = fun () -> true
401- // let textSnapshotInfo = None
402- // let tcErrors = errorScope.Diagnostics |> List.filter (fun e -> e.FileName = filename) |> List.toArray
403- // let errors = Array.append parseRes.Errors tcErrors
404- // let scope = TypeCheckInfo(tcConfig, tcGlobals, ccuSigForFile, tcState.Ccu, tcImports, tcEnvAtEnd.AccessRights,
405- // projectFileName, filename, sink.GetResolutions(), sink.GetSymbolUses(), tcEnvAtEnd.NameEnv,
406- // loadClosure, reactorOps, checkAlive, textSnapshotInfo, implFile, sink.GetOpenDeclarations())
407- // FSharpCheckFileResults (filename, errors, Some scope, parseRes.DependencyFiles, None, reactorOps, true)
408-
409- // // parse files
410- // let parsingOptions = FSharpParsingOptions.FromTcConfig(tcConfig, fileNames, true)
411- // let parseScript (filename, source) = x.ParseScript(filename, source, parsingOptions)
412- // let parseResults = Array.zip fileNames sources |> Array.map parseScript
413- // let parseHadErrors = parseResults |> Array.exists (fun p -> p.ParseHadErrors)
414- // let inputs = parseResults |> Array.choose (fun p -> p.ParseTree) |> Array.toList
415-
416- // // type check files
417- // let checkForErrors() = parseHadErrors
418- // let prefixPathOpt = None
419- // let tcSink = TcResultsSink.WithSink sink
420- // let tcOneInput = typeCheckOneInput (ctok, checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt) tcSink
421- // let tcResults, tcState = (tcInitialState, inputs) ||> List.mapFold tcOneInput
422- // let (_tcEnvAtEnd, topAttrs, implFiles, _ccuSigsForFiles), tcState = TypeCheckMultipleInputsFinish(tcResults, tcState)
423- // let tcState, tcImplFiles = TypeCheckClosedInputSetFinish (implFiles, tcState)
424-
425- // let typeCheckResults = tcResults |> List.toArray |> Array.zip parseResults |> Array.map (makeTcResult tcState)
426-
427- // // make project results
428- // let parseErrors = parseResults |> Array.collect (fun p -> p.Errors)
429- // let tcErrors = errorScope.Diagnostics |> List.toArray
430- // let errors = Array.append parseErrors tcErrors
431- // let symbolUses = [sink.GetSymbolUses()]
432- // let projectResults = x.MakeProjectResults (projectFileName, parseResults, tcState, errors, symbolUses, Some topAttrs, Some tcImplFiles)
433-
434- // parseResults, typeCheckResults, projectResults
434+ member x.ParseAndCheckFileInProject ( fileName : string , projectFileName : string , fileNames : string [], sources : string []) =
435+ // get files before file
436+ let fileIndex = fileNames |> Array.findIndex ((=) fileName)
437+ let fileNamesBeforeFile = fileNames |> Array.take fileIndex
438+ let sourcesBeforeFile = sources |> Array.take fileIndex
439+
440+ // parse files before file
441+ let parsingOptions = FSharpParsingOptions.FromTcConfig( tcConfig, fileNames, false )
442+ let parseFile ( fileName , source ) = x.ParseFile( fileName, source, parsingOptions)
443+ let parseResults = Array.zip fileNamesBeforeFile sourcesBeforeFile |> Array.map parseFile
444+ let parseHadErrors = parseResults |> Array.exists ( fun p -> p.ParseHadErrors)
445+ let parsedInputs = parseResults |> Array.choose ( fun p -> p.ParseTree) |> Array.toList
446+
447+ // type check files before file
448+ use errorScope = new ErrorScope()
449+ let hasTypedErrors () = errorScope.Diagnostics |> List.exists ( fun e -> e.Severity = FSharpErrorSeverity.Error)
450+ let checkForErrors () = parseHadErrors || hasTypedErrors ()
451+ let prefixPathOpt = None
452+ let tcState , topAttrs , tcImplFiles , _tcEnvAtEnd =
453+ x.TypeCheckClosedInputSet ( ctok, checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt, tcInitialState, parsedInputs)
454+
455+ // parse and type check file
456+ let parseFileResults = parseFile ( fileName, sources.[ fileIndex])
457+ let checkFileResults = x.CheckFile ( projectFileName, parseFileResults, tcState)
458+ let ( _tcEnvAtEndFile , topAttrsFile , implFile , _ccuSigForFile ), tcState = checkCache.[ fileName]
459+
460+ // collect errors
461+ let parseErrorsBefore = parseResults |> Array.collect ( fun p -> p.Errors)
462+ let typedErrorsBefore = errorScope.Diagnostics |> List.toArray
463+ let newErrors = match checkFileResults with | Some res -> res.Errors | None -> [||]
464+ let errors = [| yield ! parseErrorsBefore; yield ! typedErrorsBefore; yield ! newErrors |]
465+
466+ // make partial project results
467+ let parseResults = Array.append parseResults [| parseFileResults |]
468+ let tcImplFiles = List.append tcImplFiles ( Option.toList implFile)
469+ let topAttrs = CombineTopAttrs topAttrsFile topAttrs
470+ let symbolUses = [] //TODO:
471+ let projectResults = x.MakeProjectResults ( projectFileName, parseResults, tcState, errors, symbolUses, Some topAttrs, Some tcImplFiles)
472+
473+ parseFileResults, checkFileResults, projectResults
0 commit comments