Skip to content

Commit 05822f0

Browse files
committed
let's see if we still need this
1 parent 9547808 commit 05822f0

File tree

1 file changed

+149
-171
lines changed

1 file changed

+149
-171
lines changed

vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs

Lines changed: 149 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -49,190 +49,168 @@ type internal RoamingProfileStorageLocation(keyName: string) =
4949

5050
[<Composition.Shared>]
5151
[<ExportWorkspaceServiceFactory(typeof<IFSharpWorkspaceService>, ServiceLayer.Default)>]
52-
type internal FSharpWorkspaceServiceFactory [<Composition.ImportingConstructor>] (metadataAsSourceService: FSharpMetadataAsSourceService) =
52+
type internal FSharpWorkspaceServiceFactory
53+
[<Composition.ImportingConstructor>]
54+
(editorOptions: EditorOptions, metadataAsSourceService: FSharpMetadataAsSourceService) =
55+
56+
let tryGetMetadataSnapshot (workspace: VisualStudioWorkspace) (path, timeStamp) =
57+
try
58+
let md =
59+
LanguageServices.FSharpVisualStudioWorkspaceExtensions.GetMetadata(workspace, path, timeStamp)
60+
61+
let amd = (md :?> AssemblyMetadata)
62+
let mmd = amd.GetModules().[0]
63+
let mmr = mmd.GetMetadataReader()
64+
65+
// "lifetime is timed to Metadata you got from the GetMetadata(...). As long as you hold it strongly, raw
66+
// memory we got from metadata reader will be alive. Once you are done, just let everything go and
67+
// let finalizer handle resource rather than calling Dispose from Metadata directly. It is shared metadata.
68+
// You shouldn't dispose it directly."
69+
70+
let objToHold = box md
71+
72+
// We don't expect any ilread WeakByteFile to be created when working in Visual Studio
73+
// Debug.Assert((FSharp.Compiler.AbstractIL.ILBinaryReader.GetStatistics().weakByteFileCount = 0), "Expected weakByteFileCount to be zero when using F# in Visual Studio. Was there a problem reading a .NET binary?")
74+
75+
Some(objToHold, NativePtr.toNativeInt mmr.MetadataPointer, mmr.MetadataLength)
76+
with ex ->
77+
// We catch all and let the backup routines in the F# compiler find the error
78+
Assert.Exception(ex)
79+
None
80+
81+
let getSource (workspace: Workspace) filename =
82+
async {
83+
let! ct = Async.CancellationToken
84+
85+
match workspace.CurrentSolution.TryGetDocumentFromPath filename with
86+
| ValueSome document ->
87+
let! text = document.GetTextAsync(ct) |> Async.AwaitTask
88+
return Some(text.ToFSharpSourceText())
89+
| ValueNone -> return None
90+
}
91+
92+
let enableParallelReferenceResolution =
93+
editorOptions.LanguageServicePerformance.EnableParallelReferenceResolution
94+
95+
let enableLiveBuffers = editorOptions.Advanced.IsUseLiveBuffersEnabled
96+
97+
let enableInMemoryCrossProjectReferences =
98+
editorOptions.LanguageServicePerformance.EnableInMemoryCrossProjectReferences
99+
100+
let enableFastFindReferences =
101+
editorOptions.LanguageServicePerformance.EnableFastFindReferencesAndRename
102+
103+
let isInlineParameterNameHintsEnabled =
104+
editorOptions.Advanced.IsInlineParameterNameHintsEnabled
105+
106+
let isInlineTypeHintsEnabled = editorOptions.Advanced.IsInlineTypeHintsEnabled
107+
108+
let isInlineReturnTypeHintsEnabled =
109+
editorOptions.Advanced.IsInlineReturnTypeHintsEnabled
110+
111+
let enablePartialTypeChecking =
112+
editorOptions.LanguageServicePerformance.EnablePartialTypeChecking
113+
114+
// Default should be false
115+
let keepAllBackgroundResolutions =
116+
editorOptions.LanguageServicePerformance.KeepAllBackgroundResolutions
117+
118+
// Default should be false
119+
let keepAllBackgroundSymbolUses =
120+
editorOptions.LanguageServicePerformance.KeepAllBackgroundSymbolUses
121+
122+
// Default should be true
123+
let enableBackgroundItemKeyStoreAndSemanticClassification =
124+
editorOptions.LanguageServicePerformance.EnableBackgroundItemKeyStoreAndSemanticClassification
125+
126+
let useTransparentCompiler = editorOptions.Advanced.UseTransparentCompiler
127+
128+
// Default is false here
129+
let solutionCrawler = editorOptions.Advanced.SolutionBackgroundAnalysis
130+
131+
let create getSource tryGetMetadataSnapshot =
132+
133+
use _eventDuration =
134+
TelemetryReporter.ReportSingleEventWithDuration(
135+
TelemetryEvents.LanguageServiceStarted,
136+
[|
137+
nameof enableLiveBuffers, enableLiveBuffers
138+
nameof enableParallelReferenceResolution, enableParallelReferenceResolution
139+
nameof enableInMemoryCrossProjectReferences, enableInMemoryCrossProjectReferences
140+
nameof enableFastFindReferences, enableFastFindReferences
141+
nameof isInlineParameterNameHintsEnabled, isInlineParameterNameHintsEnabled
142+
nameof isInlineTypeHintsEnabled, isInlineTypeHintsEnabled
143+
nameof isInlineReturnTypeHintsEnabled, isInlineReturnTypeHintsEnabled
144+
nameof enablePartialTypeChecking, enablePartialTypeChecking
145+
nameof keepAllBackgroundResolutions, keepAllBackgroundResolutions
146+
nameof keepAllBackgroundSymbolUses, keepAllBackgroundSymbolUses
147+
nameof enableBackgroundItemKeyStoreAndSemanticClassification, enableBackgroundItemKeyStoreAndSemanticClassification
148+
"captureIdentifiersWhenParsing", enableFastFindReferences
149+
nameof useTransparentCompiler, useTransparentCompiler
150+
nameof solutionCrawler, solutionCrawler
151+
|],
152+
TelemetryThrottlingStrategy.NoThrottling
153+
)
53154

54-
// We have a lock just in case if multi-threads try to create a new IFSharpWorkspaceService -
55-
// but we only want to have a single instance of the FSharpChecker regardless if there are multiple instances of IFSharpWorkspaceService.
56-
// In VS, we only ever have a single IFSharpWorkspaceService, but for testing we may have multiple; we still only want a
57-
// single FSharpChecker instance shared across them.
58-
static let gate = obj ()
155+
let checker =
156+
FSharpChecker.Create(
157+
projectCacheSize = 5000, // We do not care how big the cache is. VS will actually tell FCS to clear caches, so this is fine.
158+
keepAllBackgroundResolutions = keepAllBackgroundResolutions,
159+
legacyReferenceResolver = LegacyMSBuildReferenceResolver.getResolver (),
160+
tryGetMetadataSnapshot = tryGetMetadataSnapshot,
161+
keepAllBackgroundSymbolUses = keepAllBackgroundSymbolUses,
162+
enableBackgroundItemKeyStoreAndSemanticClassification = enableBackgroundItemKeyStoreAndSemanticClassification,
163+
enablePartialTypeChecking = enablePartialTypeChecking,
164+
parallelReferenceResolution = enableParallelReferenceResolution,
165+
captureIdentifiersWhenParsing = enableFastFindReferences,
166+
documentSource =
167+
(if enableLiveBuffers then
168+
(DocumentSource.Custom(fun filename ->
169+
async {
170+
match! getSource filename with
171+
| Some source -> return Some(source :> ISourceText)
172+
| None -> return None
173+
}))
174+
else
175+
DocumentSource.FileSystem),
176+
useTransparentCompiler = useTransparentCompiler
177+
)
59178

60-
// We only ever want to have a single FSharpChecker.
61-
static let mutable checkerSingleton = None
179+
checker
62180

63181
interface IWorkspaceServiceFactory with
64-
member _.CreateService(workspaceServices) =
65182

183+
member _.CreateService(workspaceServices) =
66184
let workspace = workspaceServices.Workspace
185+
let getSource = getSource workspace
67186

68-
let tryGetMetadataSnapshot (path, timeStamp) =
187+
let tryGetMetadataSnapshot =
69188
match workspace with
70-
| :? VisualStudioWorkspace as workspace ->
71-
try
72-
let md =
73-
LanguageServices.FSharpVisualStudioWorkspaceExtensions.GetMetadata(workspace, path, timeStamp)
74-
75-
let amd = (md :?> AssemblyMetadata)
76-
let mmd = amd.GetModules().[0]
77-
let mmr = mmd.GetMetadataReader()
78-
79-
// "lifetime is timed to Metadata you got from the GetMetadata(...). As long as you hold it strongly, raw
80-
// memory we got from metadata reader will be alive. Once you are done, just let everything go and
81-
// let finalizer handle resource rather than calling Dispose from Metadata directly. It is shared metadata.
82-
// You shouldn't dispose it directly."
83-
84-
let objToHold = box md
85-
86-
// We don't expect any ilread WeakByteFile to be created when working in Visual Studio
87-
// Debug.Assert((FSharp.Compiler.AbstractIL.ILBinaryReader.GetStatistics().weakByteFileCount = 0), "Expected weakByteFileCount to be zero when using F# in Visual Studio. Was there a problem reading a .NET binary?")
88-
89-
Some(objToHold, NativePtr.toNativeInt mmr.MetadataPointer, mmr.MetadataLength)
90-
with ex ->
91-
// We catch all and let the backup routines in the F# compiler find the error
92-
Assert.Exception(ex)
93-
None
94-
| _ -> None
95-
96-
let getSource filename =
97-
async {
98-
let! ct = Async.CancellationToken
99-
100-
match workspace.CurrentSolution.TryGetDocumentFromPath filename with
101-
| ValueSome document ->
102-
let! text = document.GetTextAsync(ct) |> Async.AwaitTask
103-
return Some(text.ToFSharpSourceText())
104-
| ValueNone -> return None
105-
}
189+
| :? VisualStudioWorkspace as workspace -> tryGetMetadataSnapshot workspace
190+
| _ -> fun _ -> None
106191

107-
lock gate (fun () ->
108-
match checkerSingleton with
109-
| Some _ -> ()
110-
| _ ->
111-
let checker =
112-
lazy
113-
let editorOptions = workspace.Services.GetService<EditorOptions>()
114-
115-
let enableParallelReferenceResolution =
116-
editorOptions.LanguageServicePerformance.EnableParallelReferenceResolution
117-
118-
let enableLiveBuffers = editorOptions.Advanced.IsUseLiveBuffersEnabled
119-
120-
let enableInMemoryCrossProjectReferences =
121-
editorOptions.LanguageServicePerformance.EnableInMemoryCrossProjectReferences
122-
123-
let enableFastFindReferences =
124-
editorOptions.LanguageServicePerformance.EnableFastFindReferencesAndRename
125-
126-
let isInlineParameterNameHintsEnabled =
127-
editorOptions.Advanced.IsInlineParameterNameHintsEnabled
128-
129-
let isInlineTypeHintsEnabled = editorOptions.Advanced.IsInlineTypeHintsEnabled
130-
131-
let isInlineReturnTypeHintsEnabled =
132-
editorOptions.Advanced.IsInlineReturnTypeHintsEnabled
133-
134-
let enablePartialTypeChecking =
135-
editorOptions.LanguageServicePerformance.EnablePartialTypeChecking
136-
137-
// Default should be false
138-
let keepAllBackgroundResolutions =
139-
editorOptions.LanguageServicePerformance.KeepAllBackgroundResolutions
140-
141-
// Default should be false
142-
let keepAllBackgroundSymbolUses =
143-
editorOptions.LanguageServicePerformance.KeepAllBackgroundSymbolUses
144-
145-
// Default should be true
146-
let enableBackgroundItemKeyStoreAndSemanticClassification =
147-
editorOptions.LanguageServicePerformance.EnableBackgroundItemKeyStoreAndSemanticClassification
148-
149-
let useTransparentCompiler = editorOptions.Advanced.UseTransparentCompiler
150-
151-
// Default is false here
152-
let solutionCrawler = editorOptions.Advanced.SolutionBackgroundAnalysis
153-
154-
use _eventDuration =
155-
TelemetryReporter.ReportSingleEventWithDuration(
156-
TelemetryEvents.LanguageServiceStarted,
157-
[|
158-
nameof enableLiveBuffers, enableLiveBuffers
159-
nameof enableParallelReferenceResolution, enableParallelReferenceResolution
160-
nameof enableInMemoryCrossProjectReferences, enableInMemoryCrossProjectReferences
161-
nameof enableFastFindReferences, enableFastFindReferences
162-
nameof isInlineParameterNameHintsEnabled, isInlineParameterNameHintsEnabled
163-
nameof isInlineTypeHintsEnabled, isInlineTypeHintsEnabled
164-
nameof isInlineReturnTypeHintsEnabled, isInlineReturnTypeHintsEnabled
165-
nameof enablePartialTypeChecking, enablePartialTypeChecking
166-
nameof keepAllBackgroundResolutions, keepAllBackgroundResolutions
167-
nameof keepAllBackgroundSymbolUses, keepAllBackgroundSymbolUses
168-
nameof enableBackgroundItemKeyStoreAndSemanticClassification,
169-
enableBackgroundItemKeyStoreAndSemanticClassification
170-
"captureIdentifiersWhenParsing", enableFastFindReferences
171-
nameof useTransparentCompiler, useTransparentCompiler
172-
nameof solutionCrawler, solutionCrawler
173-
|],
174-
TelemetryThrottlingStrategy.NoThrottling
175-
)
176-
177-
let checker =
178-
FSharpChecker.Create(
179-
projectCacheSize = 5000, // We do not care how big the cache is. VS will actually tell FCS to clear caches, so this is fine.
180-
keepAllBackgroundResolutions = keepAllBackgroundResolutions,
181-
legacyReferenceResolver = LegacyMSBuildReferenceResolver.getResolver (),
182-
tryGetMetadataSnapshot = tryGetMetadataSnapshot,
183-
keepAllBackgroundSymbolUses = keepAllBackgroundSymbolUses,
184-
enableBackgroundItemKeyStoreAndSemanticClassification =
185-
enableBackgroundItemKeyStoreAndSemanticClassification,
186-
enablePartialTypeChecking = enablePartialTypeChecking,
187-
parallelReferenceResolution = enableParallelReferenceResolution,
188-
captureIdentifiersWhenParsing = enableFastFindReferences,
189-
documentSource =
190-
(if enableLiveBuffers then
191-
(DocumentSource.Custom(fun filename ->
192-
async {
193-
match! getSource filename with
194-
| Some source -> return Some(source :> ISourceText)
195-
| None -> return None
196-
}))
197-
else
198-
DocumentSource.FileSystem),
199-
useTransparentCompiler = useTransparentCompiler
200-
)
201-
202-
if enableLiveBuffers && not useTransparentCompiler then
203-
workspace.WorkspaceChanged.Add(fun args ->
204-
if args.DocumentId <> null then
205-
cancellableTask {
206-
let document = args.NewSolution.GetDocument(args.DocumentId)
207-
208-
let! _, _, _, options =
209-
document.GetFSharpCompilationOptionsAsync(nameof (workspace.WorkspaceChanged))
210-
211-
do! checker.NotifyFileChanged(document.FilePath, options)
212-
}
213-
|> CancellableTask.startAsTask CancellationToken.None
214-
|> ignore)
215-
216-
checker
217-
218-
checkerSingleton <- Some checker)
219-
220-
let optionsManager =
221-
lazy
222-
match checkerSingleton with
223-
| Some checker -> FSharpProjectOptionsManager(checker.Value, workspaceServices.Workspace)
224-
| _ -> failwith "Checker not set."
192+
let checker = create getSource tryGetMetadataSnapshot
225193

226-
{ new IFSharpWorkspaceService with
227-
member _.Checker =
228-
match checkerSingleton with
229-
| Some checker -> checker.Value
230-
| _ -> failwith "Checker not set."
194+
if enableLiveBuffers && not useTransparentCompiler then
195+
workspace.WorkspaceChanged.Add(fun args ->
196+
if args.DocumentId <> null then
197+
cancellableTask {
198+
let document = args.NewSolution.GetDocument(args.DocumentId)
199+
200+
let! _, _, _, options = document.GetFSharpCompilationOptionsAsync(nameof (workspace.WorkspaceChanged))
201+
202+
do! checker.NotifyFileChanged(document.FilePath, options)
203+
}
204+
|> CancellableTask.startAsTask CancellationToken.None
205+
|> ignore)
231206

232-
member _.FSharpProjectOptionsManager = optionsManager.Value
207+
let optionsManager = FSharpProjectOptionsManager(checker, workspace)
208+
209+
{ new IFSharpWorkspaceService with
210+
member _.Checker = checker
211+
member _.FSharpProjectOptionsManager = optionsManager
233212
member _.MetadataAsSource = metadataAsSourceService
234213
}
235-
:> _
236214

237215
[<Sealed>]
238216
type private FSharpSolutionEvents(projectManager: FSharpProjectOptionsManager, metadataAsSource: FSharpMetadataAsSourceService) =

0 commit comments

Comments
 (0)