Skip to content

Commit db6b8cd

Browse files
dawedawe0101
andauthored
Add a version of TryGetRecentCheckResultsForFile with project snapshot (#16720)
* First stab at adding a version of TryGetRecentCheckResultsForFile that takes a snapshot instead of project options * use version type without defaultof<_> = null * take sourcetext out of project snapshot, kind of forces us to an async return but let's see if this is acceptable * format * - reuse ParseAndCheckFileInProject cache for TryGetRecentCheckResultsForFile - extend version of ParseAndCheckFileInProject cache with the check sum of the source code - add test * format * cleanup * use a new LruCache member GetAll to get rid of the dummy version * cleanup * Update src/Compiler/Service/TransparentCompiler.fs Co-authored-by: Petr Pokorny <[email protected]> * unify key creation * just use ProjectSnapShot.FileKey * to have it on record, push a version with "f.Version |> Md5Hasher.toString" as the second part of lastFileKey.Version * use FileKeyWithExtraFileSnapshotVersion for the ParseAndCheckFileInProject cache * replace FileSnapShot after edit in Test * add CustomOperation tryGetRecentCheckResults for tests * - Make API non-async and don't return hash - let tests run for background compiler, too * better fix for commandLineOptions order * Update src/Compiler/Service/FSharpProjectSnapshot.fs Co-authored-by: Petr Pokorny <[email protected]> * Update tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs Co-authored-by: Petr Pokorny <[email protected]> * Update tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs Co-authored-by: Petr Pokorny <[email protected]> * fix version predicate * let LruCache.GetAll(key: 'TKey) return a seq instead of a list * compare signatures in CustomOperation tryGetRecentCheckResults to tighten the tests --------- Co-authored-by: Petr Pokorny <[email protected]>
1 parent d071ddc commit db6b8cd

File tree

16 files changed

+237
-11
lines changed

16 files changed

+237
-11
lines changed

src/Compiler/Facilities/AsyncMemoize.fs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,15 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T
534534

535535
}
536536

537+
member _.TryGet(key: 'TKey, predicate: 'TVersion -> bool) : 'TValue option =
538+
let versionsAndJobs = cache.GetAll(key)
539+
540+
versionsAndJobs
541+
|> Seq.tryPick (fun (version, job) ->
542+
match predicate version, job with
543+
| true, Completed(completed, _) -> Some completed
544+
| _ -> None)
545+
537546
member _.Clear() = cache.Clear()
538547

539548
member _.Clear predicate = cache.Clear predicate

src/Compiler/Facilities/AsyncMemoize.fsi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T
6969

7070
member Get': key: 'TKey * computation: NodeCode<'TValue> -> NodeCode<'TValue>
7171

72+
member TryGet: key: 'TKey * predicate: ('TVersion -> bool) -> 'TValue option
73+
7274
member Event: IEvent<JobEvent * (string * 'TKey * 'TVersion)>
7375

7476
member OnEvent: ((JobEvent * (string * 'TKey * 'TVersion) -> unit) -> unit)

src/Compiler/Service/BackgroundCompiler.fs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ type internal IBackgroundCompiler =
179179
fileName: string * options: FSharpProjectOptions * sourceText: ISourceText option * userOpName: string ->
180180
(FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option
181181

182+
abstract member TryGetRecentCheckResultsForFile:
183+
fileName: string * projectSnapshot: FSharpProjectSnapshot * userOpName: string ->
184+
(FSharpParseFileResults * FSharpCheckFileResults) option
185+
182186
abstract member BeforeBackgroundFileCheck: IEvent<string * FSharpProjectOptions>
183187

184188
abstract member FileChecked: IEvent<string * FSharpProjectOptions>
@@ -1174,6 +1178,16 @@ type internal BackgroundCompiler
11741178
| None -> None
11751179
| None -> None
11761180

1181+
member _.TryGetRecentCheckResultsForFile(fileName: string, projectSnapshot: FSharpProjectSnapshot, userOpName: string) =
1182+
projectSnapshot.ProjectSnapshot.SourceFiles
1183+
|> List.tryFind (fun f -> f.FileName = fileName)
1184+
|> Option.bind (fun (f: FSharpFileSnapshot) ->
1185+
let options = projectSnapshot.ToOptions()
1186+
let sourceText = f.GetSource() |> Async.AwaitTask |> Async.RunSynchronously
1187+
1188+
self.TryGetRecentCheckResultsForFile(fileName, options, Some sourceText, userOpName)
1189+
|> Option.map (fun (parseFileResults, checkFileResults, _hash) -> (parseFileResults, checkFileResults)))
1190+
11771191
/// Parse and typecheck the whole project (the implementation, called recursively as project graph is evaluated)
11781192
member private _.ParseAndCheckProjectImpl(options, userOpName) =
11791193
node {
@@ -1732,3 +1746,11 @@ type internal BackgroundCompiler
17321746
userOpName: string
17331747
) : (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option =
17341748
self.TryGetRecentCheckResultsForFile(fileName, options, sourceText, userOpName)
1749+
1750+
member _.TryGetRecentCheckResultsForFile
1751+
(
1752+
fileName: string,
1753+
projectSnapshot: FSharpProjectSnapshot,
1754+
userOpName: string
1755+
) : (FSharpParseFileResults * FSharpCheckFileResults) option =
1756+
self.TryGetRecentCheckResultsForFile(fileName, projectSnapshot, userOpName)

src/Compiler/Service/BackgroundCompiler.fsi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ type internal IBackgroundCompiler =
169169
fileName: string * options: FSharpProjectOptions * sourceText: ISourceText option * userOpName: string ->
170170
(FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option
171171

172+
abstract TryGetRecentCheckResultsForFile:
173+
fileName: string * projectSnapshot: FSharpProjectSnapshot * userOpName: string ->
174+
(FSharpParseFileResults * FSharpCheckFileResults) option
175+
172176
abstract BeforeBackgroundFileCheck: IEvent<string * FSharpProjectOptions>
173177

174178
abstract FileChecked: IEvent<string * FSharpProjectOptions>

src/Compiler/Service/FSharpProjectSnapshot.fs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,12 @@ type internal ProjectSnapshotBase<'T when 'T :> IFileSnapshot>(projectCore: Proj
345345
member this.FileKey(fileName: string) = this.UpTo(fileName).LastFileKey
346346
member this.FileKey(index: FileIndex) = this.UpTo(index).LastFileKey
347347

348+
member this.FileKeyWithExtraFileSnapshotVersion(fileName: string) =
349+
let fileKey = this.FileKey fileName
350+
let fileSnapshot = this.SourceFiles |> Seq.find (fun f -> f.FileName = fileName)
351+
352+
fileKey.WithExtraVersion(fileSnapshot.Version |> Md5Hasher.toString)
353+
348354
/// Project snapshot with filenames and versions given as initial input
349355
and internal ProjectSnapshot = ProjectSnapshotBase<FSharpFileSnapshot>
350356

@@ -394,10 +400,10 @@ and internal ProjectCore
394400
let commandLineOptions =
395401
lazy
396402
(seq {
403+
yield! OtherOptions
404+
397405
for r in ReferencesOnDisk do
398406
$"-r:{r.Path}"
399-
400-
yield! OtherOptions
401407
}
402408
|> Seq.toList)
403409

src/Compiler/Service/TransparentCompiler.fs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ type internal CompilerCaches(sizeFactor: int) =
307307
this.AssemblyData.Clear(shouldClear)
308308
this.SemanticClassification.Clear(snd >> shouldClear)
309309
this.ItemKeyStore.Clear(snd >> shouldClear)
310-
this.ScriptClosure.Clear(snd >> shouldClear) // Todo check if correct predicate
310+
this.ScriptClosure.Clear(snd >> shouldClear)
311311

312312
type internal TransparentCompiler
313313
(
@@ -1472,9 +1472,8 @@ type internal TransparentCompiler
14721472

14731473
let ComputeParseAndCheckFileInProject (fileName: string) (projectSnapshot: ProjectSnapshot) =
14741474
caches.ParseAndCheckFileInProject.Get(
1475-
projectSnapshot.FileKey fileName,
1475+
projectSnapshot.FileKeyWithExtraFileSnapshotVersion fileName,
14761476
node {
1477-
14781477
use _ =
14791478
Activity.start "ComputeParseAndCheckFileInProject" [| Activity.Tags.fileName, fileName |> Path.GetFileName |]
14801479

@@ -1605,6 +1604,29 @@ type internal TransparentCompiler
16051604
}
16061605
)
16071606

1607+
let TryGetRecentCheckResultsForFile
1608+
(
1609+
fileName: string,
1610+
projectSnapshot: FSharpProjectSnapshot,
1611+
userOpName: string
1612+
) : (FSharpParseFileResults * FSharpCheckFileResults) option =
1613+
ignore userOpName
1614+
1615+
let cacheKey =
1616+
projectSnapshot.ProjectSnapshot.FileKeyWithExtraFileSnapshotVersion fileName
1617+
1618+
let version = cacheKey.GetVersion()
1619+
1620+
let parseFileResultsAndcheckFileAnswer =
1621+
caches.ParseAndCheckFileInProject.TryGet(
1622+
cacheKey.GetKey(),
1623+
(fun (_fullVersion, fileContentVersion) -> fileContentVersion = (snd version))
1624+
)
1625+
1626+
match parseFileResultsAndcheckFileAnswer with
1627+
| Some(parseFileResults, FSharpCheckFileAnswer.Succeeded checkFileResults) -> Some(parseFileResults, checkFileResults)
1628+
| _ -> None
1629+
16081630
let ComputeProjectExtras (bootstrapInfo: BootstrapInfo) (projectSnapshot: ProjectSnapshotWithSources) =
16091631
caches.ProjectExtras.Get(
16101632
projectSnapshot.SignatureKey,
@@ -2356,3 +2378,11 @@ type internal TransparentCompiler
23562378
userOpName: string
23572379
) : (FSharpParseFileResults * FSharpCheckFileResults * SourceTextHash) option =
23582380
backgroundCompiler.TryGetRecentCheckResultsForFile(fileName, options, sourceText, userOpName)
2381+
2382+
member this.TryGetRecentCheckResultsForFile
2383+
(
2384+
fileName: string,
2385+
projectSnapshot: FSharpProjectSnapshot,
2386+
userOpName: string
2387+
) : (FSharpParseFileResults * FSharpCheckFileResults) option =
2388+
TryGetRecentCheckResultsForFile(fileName, projectSnapshot, userOpName)

src/Compiler/Service/TransparentCompiler.fsi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ type internal CompilerCaches =
118118
member ParseAndCheckAllFilesInProject: AsyncMemoizeDisabled<obj, obj, obj>
119119

120120
member ParseAndCheckFileInProject:
121-
AsyncMemoize<(string * (string * string)), string, (FSharpParseFileResults * FSharpCheckFileAnswer)>
121+
AsyncMemoize<(string * (string * string)), string * string, (FSharpParseFileResults * FSharpCheckFileAnswer)>
122122

123123
member ParseAndCheckProject: AsyncMemoize<(string * string), string, FSharpCheckProjectResults>
124124

src/Compiler/Service/service.fs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,10 @@ type FSharpChecker
338338
let userOpName = defaultArg userOpName "Unknown"
339339
backgroundCompiler.TryGetRecentCheckResultsForFile(fileName, options, sourceText, userOpName)
340340

341+
member _.TryGetRecentCheckResultsForFile(fileName: string, projectSnapshot: FSharpProjectSnapshot, ?userOpName: string) =
342+
let userOpName = defaultArg userOpName "Unknown"
343+
backgroundCompiler.TryGetRecentCheckResultsForFile(fileName, projectSnapshot, userOpName)
344+
341345
member _.Compile(argv: string[], ?userOpName: string) =
342346
let _userOpName = defaultArg userOpName "Unknown"
343347
use _ = Activity.start "FSharpChecker.Compile" [| Activity.Tags.userOpName, _userOpName |]

src/Compiler/Service/service.fsi

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,11 @@ type public FSharpChecker =
422422
fileName: string * options: FSharpProjectOptions * ?sourceText: ISourceText * ?userOpName: string ->
423423
(FSharpParseFileResults * FSharpCheckFileResults (* hash *) * int64) option
424424

425+
[<Experimental("This FCS API is experimental and subject to change.")>]
426+
member TryGetRecentCheckResultsForFile:
427+
fileName: string * projectSnapshot: FSharpProjectSnapshot * ?userOpName: string ->
428+
(FSharpParseFileResults * FSharpCheckFileResults) option
429+
425430
/// This function is called when the entire environment is known to have changed for reasons not encoded in the ProjectOptions of any project/compilation.
426431
member InvalidateAll: unit -> unit
427432

src/Compiler/Utilities/LruCache.fs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,21 +198,27 @@ type internal LruCache<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'TVers
198198

199199
/// Returns an option of a value for given key and version, and also a list of all other versions for given key
200200
member this.GetAll(key, version) =
201-
this.TryGet(key, version),
201+
let others =
202+
this.GetAll(key) |> Seq.filter (fun (ver, _val) -> ver <> version) |> Seq.toList
202203

204+
this.TryGet(key, version), others
205+
206+
/// Returns a list of version * value pairs for a given key. The strongly held value is first in the list.
207+
member _.GetAll(key: 'TKey) : ('TVersion * 'TValue) seq =
203208
match dictionary.TryGetValue key with
204209
| false, _ -> []
205210
| true, versionDict ->
206211
versionDict.Values
207-
|> Seq.map (fun node -> node.Value)
208-
|> Seq.filter (p24 >> ((<>) version))
212+
|> Seq.map (_.Value)
213+
|> Seq.sortBy (function
214+
| _, _, _, Strong _ -> 0
215+
| _ -> 1)
209216
|> Seq.choose (function
210217
| _, ver, _, Strong v -> Some(ver, v)
211218
| _, ver, _, Weak r ->
212219
match r.TryGetTarget() with
213220
| true, x -> Some(ver, x)
214221
| _ -> None)
215-
|> Seq.toList
216222

217223
member _.Remove(key, version) =
218224
match dictionary.TryGetValue key with

0 commit comments

Comments
 (0)