1
1
namespace JetBrains.ReSharper.Plugins.FSharp.Checker
2
2
3
+ #nowarn " 57"
4
+
3
5
open System
4
6
open System.Collections .Generic
7
+ open System.Threading .Tasks
5
8
open FSharp.Compiler .CodeAnalysis
6
9
open FSharp.Compiler .Text
7
10
open JetBrains.DataFlow
@@ -24,13 +27,13 @@ type ScriptFcsProjectProvider(lifetime: Lifetime, logger: ILogger, checkerServic
24
27
25
28
let scriptFcsProjects = Dictionary< VirtualFileSystemPath, FcsProject option>()
26
29
27
- let mutable defaultOptions : FSharpProjectOptions option option = None
30
+ let mutable defaultSnapshot : FSharpProjectSnapshot option option = None
28
31
29
32
let currentRequests = HashSet< VirtualFileSystemPath>()
30
33
let dirtyPaths = HashSet< VirtualFileSystemPath>()
31
34
32
- let optionsUpdated =
33
- new Signal< VirtualFileSystemPath * FSharpProjectOptions >( " ScriptFcsProjectProvider.optionsUpdated" )
35
+ let snapshotUpdated =
36
+ new Signal< VirtualFileSystemPath * FSharpProjectSnapshot >( " ScriptFcsProjectProvider.optionsUpdated" )
34
37
35
38
let isHeadless =
36
39
let var = Environment.GetEnvironmentVariable( " JET_HEADLESS_MODE" ) |> Option.ofObj |> Option.defaultValue " false"
@@ -63,60 +66,84 @@ type ScriptFcsProjectProvider(lifetime: Lifetime, logger: ILogger, checkerServic
63
66
IPropertyEx.FlowInto( languageVersion, lifetime, flags, getOtherFlags)
64
67
flags
65
68
66
- let getOptionsImpl ( path : VirtualFileSystemPath ) source =
69
+ let getSnapshotImpl ( path : VirtualFileSystemPath ) source : FSharpProjectSnapshot option =
67
70
let path = path.FullPath
68
71
let source = SourceText.ofString source
69
72
let targetNetFramework = not PlatformUtil.IsRunningOnCore && scriptSettings.TargetNetFramework.Value
70
73
71
74
let toolset = toolset.GetDotNetCoreToolset()
72
- let getScriptOptionsAsync =
75
+ let getScriptSnapshotAsync : Async < FSharpProjectSnapshot * FSharp.Compiler.Diagnostics.FSharpDiagnostic list > =
73
76
if isNotNull toolset && isNotNull toolset.Sdk then
74
77
let sdkRootFolder = toolset.Cli.NotNull( " cli" ) .SdkRootFolder.NotNull( " sdkRootFolder" )
75
78
let sdkFolderPath = sdkRootFolder / toolset.Sdk.NotNull( " sdk" ) .FolderName.NotNull( " sdkFolderName" )
76
- checkerService.Checker.GetProjectOptionsFromScript( path, source,
77
- otherFlags = otherFlags.Value.Value,
78
- assumeDotNetFramework = targetNetFramework,
79
- sdkDirOverride = sdkFolderPath.FullPath)
79
+ // TODO: GetProjectOptionsFromScript does not exists for Snapshot
80
+ Unchecked.defaultof< Async< FSharpProjectSnapshot * FSharp.Compiler.Diagnostics.FSharpDiagnostic list>>
81
+ // checkerService.Checker.GetProjectOptionsFromScript(path, source,
82
+ // otherFlags = otherFlags.Value.Value,
83
+ // assumeDotNetFramework = targetNetFramework,
84
+ // sdkDirOverride = sdkFolderPath.FullPath)
80
85
else
81
- checkerService.Checker.GetProjectOptionsFromScript( path, source,
82
- otherFlags = otherFlags.Value.Value,
83
- assumeDotNetFramework = targetNetFramework)
86
+ Unchecked.defaultof< Async< FSharpProjectSnapshot * FSharp.Compiler.Diagnostics.FSharpDiagnostic list>>
87
+ // checkerService.Checker.GetProjectOptionsFromScript(path, source,
88
+ // otherFlags = otherFlags.Value.Value,
89
+ // assumeDotNetFramework = targetNetFramework)
84
90
85
91
try
86
- let options , errors = getScriptOptionsAsync .RunAsTask()
92
+ let snapshot , errors = getScriptSnapshotAsync .RunAsTask()
87
93
if not errors.IsEmpty then
88
94
logErrors logger ( sprintf " Script options for %s " path) errors
89
- Some options
95
+ Some snapshot
90
96
with
91
97
| OperationCanceled -> reraise()
92
98
| exn ->
93
99
logger.Warn( " Error while getting script options for {0}: {1}" , path, exn.Message)
94
100
logger.LogExceptionSilently( exn)
95
101
None
96
102
97
- let getDefaultOptions ( path : VirtualFileSystemPath ) =
98
- let withPath ( options : FSharpProjectOptions option ) =
99
- match options with
100
- | Some options -> Some { options with SourceFiles = [| path.FullPath |] }
101
- | _ -> None
102
-
103
- match defaultOptions with
103
+ let getDefaultSnapshot ( path : VirtualFileSystemPath ) ( source : string ): ProjectSnapshot.FSharpProjectSnapshot option =
104
+ let withPath ( snapshot : FSharpProjectSnapshot option ) =
105
+ snapshot
106
+ |> Option.map ( fun snapshot ->
107
+ let name = path.Name
108
+ let version = string path.Info.ModificationTimeUtc.Ticks
109
+ let getSource () = SourceTextNew.ofString source |> Task.FromResult
110
+ let sourceFiles =
111
+ ProjectSnapshot.FSharpFileSnapshot.Create( name, version, getSource)
112
+ |> List.singleton
113
+
114
+ FSharpProjectSnapshot.Create(
115
+ snapshot.ProjectFileName,
116
+ snapshot.ProjectId,
117
+ sourceFiles,
118
+ snapshot.ReferencesOnDisk,
119
+ snapshot.OtherOptions,
120
+ snapshot.ReferencedProjects,
121
+ snapshot.IsIncompleteTypeCheckEnvironment,
122
+ snapshot.UseScriptResolutionRules,
123
+ snapshot.LoadTime,
124
+ snapshot.UnresolvedReferences,
125
+ snapshot.OriginalLoadReferences,
126
+ snapshot.Stamp
127
+ )
128
+ )
129
+
130
+ match defaultSnapshot with
104
131
| Some options -> withPath options
105
132
| _ ->
106
133
107
134
lock defaultOptionsLock ( fun _ ->
108
- match defaultOptions with
135
+ match defaultSnapshot with
109
136
| Some options -> withPath options
110
137
| _ ->
111
138
112
- let newOptions = getOptionsImpl path " "
113
- defaultOptions <- Some newOptions
139
+ let newOptions = getSnapshotImpl path " "
140
+ defaultSnapshot <- Some newOptions
114
141
newOptions
115
142
)
116
143
117
- let createFcsProject ( path : VirtualFileSystemPath ) options =
118
- options
119
- |> Option.map ( fun options ->
144
+ let createFcsProject ( path : VirtualFileSystemPath ) snapshot =
145
+ snapshot
146
+ |> Option.map ( fun snapshot ->
120
147
let parsingOptions =
121
148
{ FSharpParsingOptions.Default with
122
149
SourceFiles = [| path.FullPath |]
@@ -125,7 +152,7 @@ type ScriptFcsProjectProvider(lifetime: Lifetime, logger: ILogger, checkerServic
125
152
IsExe = true }
126
153
127
154
{ OutputPath = path
128
- ProjectOptions = options
155
+ ProjectSnapshot = snapshot
129
156
ParsingOptions = parsingOptions
130
157
FileIndices = dict [ path, 0 ]
131
158
ImplementationFilesWithSignatures = EmptySet.Instance
@@ -143,11 +170,11 @@ type ScriptFcsProjectProvider(lifetime: Lifetime, logger: ILogger, checkerServic
143
170
currentRequests.Add( path) |> ignore
144
171
dirtyPaths.Remove( path) |> ignore
145
172
let oldOptions = tryGetValue path scriptFcsProjects |> Option.bind id
146
- let newOptions = getOptionsImpl path source
173
+ let newSnapshot = getSnapshotImpl path source
147
174
148
175
scriptFcsProjects[ path] <-
149
- newOptions
150
- |> Option.map ( fun options ->
176
+ newSnapshot
177
+ |> Option.map ( fun snapshot ->
151
178
let parsingOptions =
152
179
{ FSharpParsingOptions.Default with
153
180
SourceFiles = [| path.FullPath |]
@@ -158,27 +185,27 @@ type ScriptFcsProjectProvider(lifetime: Lifetime, logger: ILogger, checkerServic
158
185
let indices = Dictionary()
159
186
160
187
{ OutputPath = path
161
- ProjectOptions = options
188
+ ProjectSnapshot = snapshot
162
189
ParsingOptions = parsingOptions
163
190
FileIndices = indices
164
191
ImplementationFilesWithSignatures = EmptySet.Instance
165
192
ReferencedModules = EmptySet.Instance }
166
193
)
167
194
168
- match oldOptions, newOptions with
169
- | Some oldOptions, Some newOptions ->
170
- let areEqualForChecking ( options1 : FSharpProjectOptions ) ( options2 : FSharpProjectOptions ) =
171
- let arrayEq a1 a2 =
172
- Array .length a1 = Array .length a2 && Array .forall2 (=) a1 a2
195
+ match oldOptions, newSnapshot with
196
+ | Some oldOptions, Some newSnapshot ->
197
+ let areEqualForChecking ( options1 : FSharpProjectSnapshot ) ( options2 : FSharpProjectSnapshot ) =
198
+ let listEq l1 l2 =
199
+ List .length l1 = List .length l2 && List .forall2 (=) l1 l2
173
200
174
- arrayEq options1.OtherOptions options2.OtherOptions &&
175
- arrayEq options1.SourceFiles options2.SourceFiles
201
+ listEq options1.OtherOptions options2.OtherOptions &&
202
+ listEq options1.SourceFiles options2.SourceFiles
176
203
177
- if not ( areEqualForChecking oldOptions.ProjectOptions newOptions ) then
178
- optionsUpdated .Fire(( path, newOptions ))
204
+ if not ( areEqualForChecking oldOptions.ProjectSnapshot newSnapshot ) then
205
+ snapshotUpdated .Fire(( path, newSnapshot ))
179
206
180
207
| _, Some newOptions ->
181
- optionsUpdated .Fire(( path, newOptions))
208
+ snapshotUpdated .Fire(( path, newOptions))
182
209
183
210
| _ -> ()
184
211
@@ -203,7 +230,7 @@ type ScriptFcsProjectProvider(lifetime: Lifetime, logger: ILogger, checkerServic
203
230
if isHeadless && allowRetry then
204
231
getFcsProject path source false
205
232
else
206
- getDefaultOptions path |> createFcsProject path
233
+ getDefaultSnapshot path source |> createFcsProject path
207
234
208
235
let getOptions path source : FSharpProjectSnapshot option =
209
236
getFcsProject path source true |> Option.map ( fun fcsProject -> fcsProject.ProjectSnapshot)
@@ -223,5 +250,5 @@ type ScriptFcsProjectProvider(lifetime: Lifetime, logger: ILogger, checkerServic
223
250
let source = sourceFile.Document.GetText()
224
251
getFcsProject path source true
225
252
226
- member this.OptionsUpdated = optionsUpdated
253
+ member this.SnapshotUpdated = snapshotUpdated
227
254
member this.SyncUpdate = isHeadless
0 commit comments