@@ -25,6 +25,7 @@ open JetBrains.ReSharper.Plugins.FSharp.Shim.AssemblyReader
25
25
open JetBrains.ReSharper .Plugins .FSharp .Util
26
26
open JetBrains.ReSharper .Psi
27
27
open JetBrains.ReSharper .Psi .CSharp
28
+ open JetBrains.ReSharper .Psi .Caches
28
29
open JetBrains.ReSharper .Psi .Modules
29
30
open JetBrains.ReSharper .Psi .Tree
30
31
open JetBrains.ReSharper .Psi .VB
@@ -36,6 +37,7 @@ module FcsCheckerService =
36
37
SourceText.ofString( document.GetText())
37
38
38
39
40
+ // add the project key?
39
41
type FcsProject =
40
42
{ OutputPath: VirtualFileSystemPath
41
43
ProjectOptions: FSharpProjectOptions
@@ -74,6 +76,57 @@ type FcsProject =
74
76
writer.WriteLine()
75
77
76
78
79
+ [<SolutionComponent>]
80
+ type FcsSnapshotCache ( fcsProjectProvider : IFcsProjectProvider , locks : IShellLocks ) =
81
+ let snapshots = Dictionary< FcsProjectKey, FSharpProjectSnapshot>()
82
+
83
+ let remove ( psiModule : IPsiModule ) =
84
+ let projectKey = FcsProjectKey.Create( psiModule)
85
+ snapshots.Remove( projectKey) |> ignore
86
+
87
+ match fcsProjectProvider.GetReferencedModule( projectKey) with
88
+ | None -> ()
89
+ | Some referencedModule ->
90
+
91
+ // todo: recursive update?
92
+ for referencingProject in referencedModule.ReferencingProjects do
93
+ snapshots.Remove( referencingProject) |> ignore
94
+
95
+ member this.GetProjectSnapshot ( projectKey : FcsProjectKey , options : FSharpProjectOptions ) =
96
+ // todo: use source files in file snapshots?
97
+ lock this ( fun _ ->
98
+ snapshots.GetOrCreateValue( projectKey, fun ( projectKey : FcsProjectKey ) ->
99
+ FSharpProjectSnapshot.FromOptions( options) .RunAsTask()
100
+ )
101
+ )
102
+
103
+ interface IPsiSourceFileCache with
104
+ member this.MarkAsDirty ( sourceFile ) =
105
+ locks.AssertWriteAccessAllowed()
106
+ remove sourceFile.PsiModule
107
+
108
+ member this.OnDocumentChange ( sourceFile , _ ) =
109
+ locks.AssertWriteAccessAllowed()
110
+ remove sourceFile.PsiModule
111
+
112
+ member this.OnPsiChange ( elementContainingChanges , _ ) =
113
+ if isNotNull elementContainingChanges then
114
+ locks.AssertWriteAccessAllowed()
115
+ remove ( elementContainingChanges.GetPsiModule())
116
+
117
+ member this.HasDirtyFiles = false
118
+ member this.UpToDate _ = true
119
+ member this.SyncUpdate _ = ()
120
+
121
+ member this.Build ( _ , _ ) = null
122
+ member this.Drop _ = ()
123
+ member this.Dump ( _ , _ ) = ()
124
+ member this.Load ( _ , _ ) = null
125
+ member this.Merge ( _ , _ ) = ()
126
+ member this.MergeLoaded _ = ()
127
+ member this.Save ( _ , _ ) = ()
128
+
129
+
77
130
[<RequireQualifiedAccess>]
78
131
type FcsProjectInvalidationType =
79
132
/// Used when invalidation is needed for a project still known to FCS.
@@ -88,14 +141,16 @@ type FcsProjectInvalidationType =
88
141
type FcsCheckerService ( lifetime : Lifetime , logger : ILogger , onSolutionCloseNotifier : OnSolutionCloseNotifier ,
89
142
settingsStore: ISettingsStore, locks: IShellLocks, configurations: RunsProducts.ProductConfigurations) =
90
143
91
- let checker =
92
- Environment.SetEnvironmentVariable( " FCS_CheckFileInProjectCacheSize" , " 20" )
144
+ let settingsStoreLive = settingsStore.BindToContextLive( lifetime, ContextRange.ApplicationWide)
93
145
94
- let settingsStoreLive = settingsStore.BindToContextLive( lifetime, ContextRange.ApplicationWide)
146
+ let getSettingProperty name =
147
+ let setting = SettingsUtil.getEntry< FSharpOptions> settingsStore name
148
+ settingsStoreLive.GetValueProperty( lifetime, setting, null )
95
149
96
- let getSettingProperty name =
97
- let setting = SettingsUtil.getEntry< FSharpOptions> settingsStore name
98
- settingsStoreLive.GetValueProperty( lifetime, setting, null )
150
+ let useTransparentCompiler = true //(getSettingProperty "UseTransparentCompiler").Value
151
+
152
+ let checker =
153
+ Environment.SetEnvironmentVariable( " FCS_CheckFileInProjectCacheSize" , " 20" )
99
154
100
155
let skipImpl = getSettingProperty " SkipImplementationAnalysis"
101
156
let analyzerProjectReferencesInParallel = getSettingProperty " ParallelProjectReferencesAnalysis"
@@ -106,7 +161,8 @@ type FcsCheckerService(lifetime: Lifetime, logger: ILogger, onSolutionCloseNotif
106
161
keepAllBackgroundResolutions = false ,
107
162
keepAllBackgroundSymbolUses = false ,
108
163
enablePartialTypeChecking = skipImpl.Value,
109
- parallelReferenceResolution = analyzerProjectReferencesInParallel.Value)
164
+ parallelReferenceResolution = analyzerProjectReferencesInParallel.Value,
165
+ useTransparentCompiler = useTransparentCompiler)
110
166
111
167
checker
112
168
@@ -174,8 +230,19 @@ type FcsCheckerService(lifetime: Lifetime, logger: ILogger, onSolutionCloseNotif
174
230
let source = FcsCheckerService.getSourceText sourceFile.Document
175
231
logger.Trace( " ParseAndCheckFile: start {0}, {1}" , path, opName)
176
232
233
+ let getParseAndCheckResults () =
234
+ if useTransparentCompiler then
235
+ let projectKey = FcsProjectKey.Create( psiModule)
236
+ let fcsSnapshotCache = sourceFile.GetSolution() .GetComponent< FcsSnapshotCache>()
237
+ let snapshot = fcsSnapshotCache.GetProjectSnapshot( projectKey, options)
238
+ match x.Checker.ParseAndCheckFileInProject( path, snapshot) .RunAsTask() with
239
+ | _, FSharpCheckFileAnswer.Aborted -> None
240
+ | parseFileResults, FSharpCheckFileAnswer.Succeeded checkFileResults -> Some( parseFileResults, checkFileResults)
241
+ else
242
+ x.Checker.ParseAndCheckDocument( path, source, options, allowStaleResults, opName) .RunAsTask()
243
+
177
244
// todo: don't cancel the computation when file didn't change
178
- match x.Checker.ParseAndCheckDocument ( path , source , options , allowStaleResults , opName ) .RunAsTask () with
245
+ match getParseAndCheckResults () with
179
246
| Some ( parseResults, checkResults) ->
180
247
logger.Trace( " ParseAndCheckFile: finish {0}, {1}" , path, opName)
181
248
Some { ParseResults = parseResults; CheckResults = checkResults }
0 commit comments