@@ -2188,17 +2188,17 @@ module Helpers =
21882188&& FSharpProjectOptions.UseSameProject( o1, o2)
21892189
21902190/// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. parsing
2191- let AreSameForParsing (( fileName1 : string , source1 : ISourceText , options1 ), ( fileName2 , source2 , options2 )) =
2192- fileName1= fileName2&& options1= options2&& source1.ContentEquals ( source2 )
2191+ let AreSameForParsing (( fileName1 : string , source1Hash : int , options1 ), ( fileName2 , source2Hash , options2 )) =
2192+ fileName1= fileName2&& options1= options2&& source1Hash = source2Hash
21932193
21942194let AreSimilarForParsing (( fileName1 , _ , _ ), ( fileName2 , _ , _ )) =
21952195 fileName1= fileName2
21962196
21972197/// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. checking
2198- let AreSameForChecking3 (( fileName1 : string , source1 : ISourceText , options1 : FSharpProjectOptions ), ( fileName2 , source2 , options2 )) =
2198+ let AreSameForChecking3 (( fileName1 : string , source1Hash : int , options1 : FSharpProjectOptions ), ( fileName2 , source2Hash , options2 )) =
21992199( fileName1= fileName2)
22002200&& FSharpProjectOptions.AreSameForChecking( options1, options2)
2201- && source1.ContentEquals ( source2 )
2201+ && source1Hash = source2Hash
22022202
22032203/// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. resource usage
22042204let AreSubsumable3 (( fileName1 : string , _ , o1 : FSharpProjectOptions ),( fileName2 : string , _ , o2 : FSharpProjectOptions )) =
@@ -2314,7 +2314,7 @@ module CompileHelpers =
23142314 System.Console.SetError error
23152315| None-> ()
23162316
2317-
2317+ type SourceTextHash = int
23182318type FileName = string
23192319type FilePath = string
23202320type ProjectPath = string
@@ -2460,7 +2460,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC
24602460
24612461// Also keyed on source. This can only be out of date if the antecedent is out of date
24622462let checkFileInProjectCache =
2463- MruCache< ParseCacheLockToken, FileName* ISourceText * FSharpProjectOptions, FSharpParseFileResults* FSharpCheckFileResults* FileVersion* DateTime>
2463+ MruCache< ParseCacheLockToken, FileName* SourceTextHash * FSharpProjectOptions, FSharpParseFileResults* FSharpCheckFileResults* FileVersion* DateTime>
24642464( keepStrongly= checkFileInProjectCacheSize,
24652465 areSame= AreSameForChecking3,
24662466 areSimilar= AreSubsumable3)
@@ -2511,13 +2511,14 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC
25112511
25122512member bc.ParseFile ( filename : string , sourceText : ISourceText , options : FSharpParsingOptions , userOpName : string ) =
25132513async {
2514- match parseCacheLock.AcquireLock( fun ltok -> parseFileCache.TryGet( ltok, ( filename, sourceText, options))) with
2514+ let hash = sourceText.GetHashCode()
2515+ match parseCacheLock.AcquireLock( fun ltok -> parseFileCache.TryGet( ltok, ( filename, hash, options))) with
25152516| Some res-> return res
25162517| None->
25172518 foregroundParseCount<- foregroundParseCount+ 1
25182519let parseErrors , parseTreeOpt , anyErrors = Parser.parseFile( sourceText, filename, options, userOpName)
25192520let res = FSharpParseFileResults( parseErrors, parseTreeOpt, anyErrors, options.SourceFiles)
2520- parseCacheLock.AcquireLock( fun ltok -> parseFileCache.Set( ltok, ( filename, sourceText , options), res))
2521+ parseCacheLock.AcquireLock( fun ltok -> parseFileCache.Set( ltok, ( filename, hash , options), res))
25212522return res
25222523}
25232524
@@ -2536,9 +2537,9 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC
25362537}
25372538)
25382539
2539- member bc.GetCachedCheckFileResult ( builder : IncrementalBuilder , filename , sourceText , options ) =
2540+ member bc.GetCachedCheckFileResult ( builder : IncrementalBuilder , filename , sourceText : ISourceText , options ) =
25402541// Check the cache. We can only use cached results when there is no work to do to bring the background builder up-to-date
2541- let cachedResults = parseCacheLock.AcquireLock( fun ltok -> checkFileInProjectCache.TryGet( ltok, ( filename, sourceText, options)))
2542+ let cachedResults = parseCacheLock.AcquireLock( fun ltok -> checkFileInProjectCache.TryGet( ltok, ( filename, sourceText.GetHashCode () , options)))
25422543
25432544match cachedResultswith
25442545// | Some (parseResults, checkResults, _, _) when builder.AreCheckResultsBeforeFileInProjectReady(filename) ->
@@ -2598,7 +2599,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC
25982599 tcPrior.TcState, loadClosure, tcPrior.TcErrors, reactorOps, ( fun () -> builder.IsAlive), textSnapshotInfo, userOpName)
25992600let parsingOptions = FSharpParsingOptions.FromTcConfig( tcPrior.TcConfig, Array.ofList builder.SourceFiles, options.UseScriptResolutionRules)
26002601let checkAnswer = MakeCheckFileAnswer( fileName, tcFileResult, options, builder, Array.ofList tcPrior.TcDependencyFiles, creationErrors, parseResults.Errors, tcErrors)
2601- bc.RecordTypeCheckFileInProjectResults( fileName, options, parsingOptions, parseResults, fileVersion, tcPrior.TimeStamp, Some checkAnswer, sourceText)
2602+ bc.RecordTypeCheckFileInProjectResults( fileName, options, parsingOptions, parseResults, fileVersion, tcPrior.TimeStamp, Some checkAnswer, sourceText.GetHashCode () )
26022603return checkAnswer
26032604finally
26042605let dummy = ref()
@@ -2614,7 +2615,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC
26142615}
26152616
26162617/// Type-check the result obtained by parsing, but only if the antecedent type checking context is available.
2617- member bc.CheckFileInProjectAllowingStaleCachedResults ( parseResults : FSharpParseFileResults , filename , fileVersion , sourceText , options , textSnapshotInfo : obj option , userOpName ) =
2618+ member bc.CheckFileInProjectAllowingStaleCachedResults ( parseResults : FSharpParseFileResults , filename , fileVersion , sourceText : ISourceText , options , textSnapshotInfo : obj option , userOpName ) =
26182619let execWithReactorAsync action = reactor.EnqueueAndAwaitOpAsync( userOpName, " CheckFileInProjectAllowingStaleCachedResults" , filename, action)
26192620async {
26202621try
@@ -2657,7 +2658,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC
26572658}
26582659
26592660/// Type-check the result obtained by parsing. Force the evaluation of the antecedent type checking context if needed.
2660- member bc.CheckFileInProject ( parseResults : FSharpParseFileResults , filename , fileVersion , sourceText , options , textSnapshotInfo , userOpName ) =
2661+ member bc.CheckFileInProject ( parseResults : FSharpParseFileResults , filename , fileVersion , sourceText : ISourceText , options , textSnapshotInfo , userOpName ) =
26612662let execWithReactorAsync action = reactor.EnqueueAndAwaitOpAsync( userOpName, " CheckFileInProject" , filename, action)
26622663async {
26632664try
@@ -2685,7 +2686,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC
26852686}
26862687
26872688/// Parses and checks the source file and returns untyped AST and check results.
2688- member bc.ParseAndCheckFileInProject ( filename : string , fileVersion , sourceText , options : FSharpProjectOptions , textSnapshotInfo , userOpName ) =
2689+ member bc.ParseAndCheckFileInProject ( filename : string , fileVersion , sourceText : ISourceText , options : FSharpProjectOptions , textSnapshotInfo , userOpName ) =
26892690let execWithReactorAsync action = reactor.EnqueueAndAwaitOpAsync( userOpName, " ParseAndCheckFileInProject" , filename, action)
26902691async {
26912692try
@@ -2772,7 +2773,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC
27722773match sourceTextwith
27732774| Some sourceText->
27742775 parseCacheLock.AcquireLock( fun ltok ->
2775- match checkFileInProjectCache.TryGet( ltok,( filename, sourceText, options)) with
2776+ match checkFileInProjectCache.TryGet( ltok,( filename, sourceText.GetHashCode () , options)) with
27762777| Some( a, b, c,_) -> Some( a, b, c)
27772778| None-> parseCacheLock.AcquireLock( fun ltok -> checkFileInProjectCachePossiblyStale.TryGet( ltok,( filename, options))))
27782779| None-> parseCacheLock.AcquireLock( fun ltok -> checkFileInProjectCachePossiblyStale.TryGet( ltok,( filename, options)))
@@ -3008,14 +3009,15 @@ type FSharpChecker(legacyReferenceResolver, projectCacheSize, keepAssemblyConten
30083009
30093010member ic.ReferenceResolver = legacyReferenceResolver
30103011
3011- member ic.MatchBraces ( filename , sourceText , options : FSharpParsingOptions , ? userOpName : string ) =
3012+ member ic.MatchBraces ( filename , sourceText : ISourceText , options : FSharpParsingOptions , ? userOpName : string ) =
30123013let userOpName = defaultArg userOpName" Unknown"
3014+ let hash = sourceText.GetHashCode()
30133015async {
3014- match braceMatchCache.TryGet( AssumeAnyCallerThreadWithoutEvidence(), ( filename, sourceText , options)) with
3016+ match braceMatchCache.TryGet( AssumeAnyCallerThreadWithoutEvidence(), ( filename, hash , options)) with
30153017| Some res-> return res
30163018| None->
30173019let res = Parser.matchBraces( sourceText, filename, options, userOpName)
3018- braceMatchCache.Set( AssumeAnyCallerThreadWithoutEvidence(), ( filename, sourceText , options), res)
3020+ braceMatchCache.Set( AssumeAnyCallerThreadWithoutEvidence(), ( filename, hash , options), res)
30193021return res
30203022}
30213023