From 7a9d3a5824edf2b47486239ed730452a1f92ae19 Mon Sep 17 00:00:00 2001 From: majocha Date: Thu, 30 Mar 2023 00:02:57 +0200 Subject: [PATCH 1/3] untangle statusbar situation --- vsintegration/src/FSharp.Editor/Common/Vs.fs | 24 +++++---- .../Completion/CompletionProvider.fs | 12 +---- .../Completion/CompletionService.fs | 19 ++----- .../FSharp.Editor/Completion/SignatureHelp.fs | 7 +-- .../DocComments/XMLDocumentation.fs | 5 +- .../Navigation/FindDefinitionService.fs | 9 +--- .../Navigation/FindUsagesService.fs | 2 - .../Navigation/GoToDefinition.fs | 50 +++++++------------ .../Navigation/GoToDefinitionService.fs | 14 ++---- .../Navigation/NavigableSymbolsService.fs | 21 +++----- .../QuickInfo/QuickInfoProvider.fs | 20 ++------ 11 files changed, 58 insertions(+), 125 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/Common/Vs.fs b/vsintegration/src/FSharp.Editor/Common/Vs.fs index 672aace90eb..5f47b8172c4 100644 --- a/vsintegration/src/FSharp.Editor/Common/Vs.fs +++ b/vsintegration/src/FSharp.Editor/Common/Vs.fs @@ -6,6 +6,7 @@ open System open System.Runtime.InteropServices open Microsoft.VisualStudio open Microsoft.VisualStudio.Editor +open Microsoft.VisualStudio.Shell open Microsoft.VisualStudio.Shell.Interop open Microsoft.VisualStudio.TextManager.Interop @@ -89,16 +90,21 @@ module internal VsRunningDocumentTable = if IntPtr.Zero <> unkData then Marshal.Release(unkData) |> ignore -[] -module internal ServiceProviderExtensions = - type internal System.IServiceProvider with +type internal GlobalProvider = - member sp.GetService<'S, 'T>() = sp.GetService(typeof<'S>) :?> 'T + static member GetServiceAsync<'S, 'T when 'S: not struct and 'T: not struct>() = + task { + do! ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync() + return! ServiceProvider.GetGlobalServiceAsync<'S, 'T>(swallowExceptions = false) + } - member sp.TextManager = sp.GetService() + static member GetService<'S, 'T when 'S: not struct and 'T: not struct>() = + ThreadHelper.JoinableTaskFactory.Run(GlobalProvider.GetServiceAsync<'S, 'T>) - member sp.RunningDocumentTable = - sp.GetService() + static member TextManager = GlobalProvider.GetService() - member sp.XMLMemberIndexService = - sp.GetService() + static member RunningDocumentTable = + GlobalProvider.GetService() + + static member XMLMemberIndexService = + GlobalProvider.GetService() diff --git a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs index 935a18b3bb8..f9538158591 100644 --- a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs +++ b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs @@ -13,8 +13,6 @@ open Microsoft.CodeAnalysis.Completion open Microsoft.CodeAnalysis.Text open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Completion -open Microsoft.VisualStudio.Shell - open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.EditorServices open FSharp.Compiler.Syntax @@ -23,12 +21,7 @@ open FSharp.Compiler.Tokenization module Logger = Microsoft.VisualStudio.FSharp.Editor.Logger -type internal FSharpCompletionProvider - ( - workspace: Workspace, - serviceProvider: SVsServiceProvider, - assemblyContentProvider: AssemblyContentProvider - ) = +type internal FSharpCompletionProvider(workspace: Workspace, assemblyContentProvider: AssemblyContentProvider) = inherit FSharpCompletionProviderBase() @@ -92,8 +85,7 @@ type internal FSharpCompletionProvider let settings: EditorOptions = workspace.Services.GetService() - let documentationBuilder = - XmlDocumentation.CreateDocumentationBuilder(serviceProvider.XMLMemberIndexService) + let documentationBuilder = XmlDocumentation.CreateDocumentationBuilder() static let mruItems = Dictionary< (* Item.FullName *) string (* hints *) , int>() diff --git a/vsintegration/src/FSharp.Editor/Completion/CompletionService.fs b/vsintegration/src/FSharp.Editor/Completion/CompletionService.fs index bcb4e3ea942..72ff7cfae01 100644 --- a/vsintegration/src/FSharp.Editor/Completion/CompletionService.fs +++ b/vsintegration/src/FSharp.Editor/Completion/CompletionService.fs @@ -13,13 +13,7 @@ open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Completion open Microsoft.VisualStudio.Shell -type internal FSharpCompletionService - ( - workspace: Workspace, - serviceProvider: SVsServiceProvider, - assemblyContentProvider: AssemblyContentProvider, - settings: EditorOptions - ) = +type internal FSharpCompletionService(workspace: Workspace, assemblyContentProvider: AssemblyContentProvider, settings: EditorOptions) = inherit FSharpCompletionServiceWithProviders(workspace) let projectInfoManager = @@ -30,7 +24,7 @@ type internal FSharpCompletionService let builtInProviders = ImmutableArray.Create( - FSharpCompletionProvider(workspace, serviceProvider, assemblyContentProvider), + FSharpCompletionProvider(workspace, assemblyContentProvider), FSharpCommonCompletionProvider.Create(HashDirectiveCompletionProvider.Create(workspace, projectInfoManager)) ) @@ -61,16 +55,9 @@ type internal FSharpCompletionService [, FSharpConstants.FSharpLanguageName)>] type internal FSharpCompletionServiceFactory [] ( - serviceProvider: SVsServiceProvider, assemblyContentProvider: AssemblyContentProvider, settings: EditorOptions ) = interface ILanguageServiceFactory with member _.CreateLanguageService(hostLanguageServices: HostLanguageServices) : ILanguageService = - upcast - new FSharpCompletionService( - hostLanguageServices.WorkspaceServices.Workspace, - serviceProvider, - assemblyContentProvider, - settings - ) + upcast new FSharpCompletionService(hostLanguageServices.WorkspaceServices.Workspace, assemblyContentProvider, settings) diff --git a/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs b/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs index f08aaa568f0..df6752005c0 100644 --- a/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs +++ b/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs @@ -9,8 +9,6 @@ open Microsoft.CodeAnalysis open Microsoft.CodeAnalysis.Text open Microsoft.CodeAnalysis.ExternalAccess.FSharp.SignatureHelp -open Microsoft.VisualStudio.Shell - open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.EditorServices open FSharp.Compiler.Symbols @@ -56,10 +54,9 @@ type SignatureHelpData = [] [)>] -type internal FSharpSignatureHelpProvider [] (serviceProvider: SVsServiceProvider) = +type internal FSharpSignatureHelpProvider() = - let documentationBuilder = - XmlDocumentation.CreateDocumentationBuilder(serviceProvider.XMLMemberIndexService) + let documentationBuilder = XmlDocumentation.CreateDocumentationBuilder() static let oneColAfter (lp: LinePosition) = LinePosition(lp.Line, lp.Character + 1) diff --git a/vsintegration/src/FSharp.Editor/DocComments/XMLDocumentation.fs b/vsintegration/src/FSharp.Editor/DocComments/XMLDocumentation.fs index b28e9d20a04..379c68a8971 100644 --- a/vsintegration/src/FSharp.Editor/DocComments/XMLDocumentation.fs +++ b/vsintegration/src/FSharp.Editor/DocComments/XMLDocumentation.fs @@ -3,12 +3,10 @@ namespace Microsoft.VisualStudio.FSharp.Editor open System -open System.Collections.Immutable open System.Runtime.CompilerServices open System.Text.RegularExpressions open Microsoft.VisualStudio.Shell open Microsoft.VisualStudio.Shell.Interop -open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.EditorServices open FSharp.Compiler.Symbols open FSharp.Compiler.Syntax @@ -562,5 +560,6 @@ module internal XmlDocumentation = let documentationBuilderCache = ConditionalWeakTable() - let CreateDocumentationBuilder (xmlIndexService: IVsXMLMemberIndexService) = + let CreateDocumentationBuilder () = + let xmlIndexService = GlobalProvider.XMLMemberIndexService documentationBuilderCache.GetValue(xmlIndexService, (fun _ -> Provider(xmlIndexService) :> IDocumentationBuilder)) diff --git a/vsintegration/src/FSharp.Editor/Navigation/FindDefinitionService.fs b/vsintegration/src/FSharp.Editor/Navigation/FindDefinitionService.fs index cd938c41b83..884ea193da4 100644 --- a/vsintegration/src/FSharp.Editor/Navigation/FindDefinitionService.fs +++ b/vsintegration/src/FSharp.Editor/Navigation/FindDefinitionService.fs @@ -10,22 +10,15 @@ open FSharp.Compiler.Text.Range open Microsoft.CodeAnalysis open Microsoft.CodeAnalysis.ExternalAccess.FSharp.GoToDefinition -open Microsoft.VisualStudio.Shell -open Microsoft.VisualStudio.Shell.Interop open System.Collections.Immutable open System.Threading.Tasks [)>] [)>] type internal FSharpFindDefinitionService [] (metadataAsSource: FSharpMetadataAsSourceService) = - - let statusBar = - StatusBar(ServiceProvider.GlobalProvider.GetService()) - interface IFSharpFindDefinitionService with member _.FindDefinitionsAsync(document: Document, position: int, cancellationToken: CancellationToken) = - let navigation = - FSharpNavigation(statusBar, metadataAsSource, document, rangeStartup) + let navigation = FSharpNavigation(metadataAsSource, document, rangeStartup) let definitions = navigation.FindDefinitions(position, cancellationToken) ImmutableArray.CreateRange(definitions) |> Task.FromResult diff --git a/vsintegration/src/FSharp.Editor/Navigation/FindUsagesService.fs b/vsintegration/src/FSharp.Editor/Navigation/FindUsagesService.fs index 5a4606bacb8..8a72e1ca36f 100644 --- a/vsintegration/src/FSharp.Editor/Navigation/FindUsagesService.fs +++ b/vsintegration/src/FSharp.Editor/Navigation/FindUsagesService.fs @@ -10,8 +10,6 @@ open Microsoft.CodeAnalysis.ExternalAccess.FSharp open Microsoft.CodeAnalysis.ExternalAccess.FSharp.FindUsages open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Editor.FindUsages -open FSharp.Compiler -open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.EditorServices open FSharp.Compiler.Text open Microsoft.CodeAnalysis.Text diff --git a/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs b/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs index 4901de036c4..776a928de00 100644 --- a/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs +++ b/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs @@ -109,7 +109,9 @@ module private ExternalSymbol = | _ -> [] // TODO: Uncomment code when VS has a fix for updating the status bar. -type StatusBar(statusBar: IVsStatusbar) = +type StatusBar() = + let statusBar = GlobalProvider.GetService() + let mutable _searchIcon = int16 Microsoft.VisualStudio.Shell.Interop.Constants.SBAI_Find :> obj @@ -394,7 +396,6 @@ type internal GoToDefinition(metadataAsSource: FSharpMetadataAsSourceService) = ( document: Document, textSpan: Microsoft.CodeAnalysis.Text.TextSpan, - statusBar: StatusBar, cancellationToken: CancellationToken ) = let navigableItem = FSharpGoToDefinitionNavigableItem(document, textSpan) @@ -407,9 +408,10 @@ type internal GoToDefinition(metadataAsSource: FSharpMetadataAsSourceService) = navigationService.TryNavigateToSpan(workspace, navigableItem.Document.Id, navigableItem.SourceSpan, cancellationToken) if not navigationSucceeded then - statusBar.TempMessage(SR.CannotNavigateUnknown()) + StatusBar().TempMessage(SR.CannotNavigateUnknown()) - member _.NavigateToItem(navigableItem: FSharpNavigableItem, statusBar: StatusBar, cancellationToken: CancellationToken) = + member _.NavigateToItem(navigableItem: FSharpNavigableItem, cancellationToken: CancellationToken) = + let statusBar = StatusBar() use __ = statusBar.Animate() statusBar.Message(SR.NavigatingTo()) @@ -434,12 +436,11 @@ type internal GoToDefinition(metadataAsSource: FSharpMetadataAsSourceService) = targetDocument: Document, targetSourceText: SourceText, symbolRange: range, - statusBar: StatusBar, cancellationToken: CancellationToken ) = asyncMaybe { let! item = this.FindDeclarationOfSymbolAtRange(targetDocument, symbolRange, targetSourceText) - return this.NavigateToItem(item, statusBar, cancellationToken) + return this.NavigateToItem(item, cancellationToken) } /// Find the definition location (implementation file/.fs) of the target symbol @@ -448,12 +449,11 @@ type internal GoToDefinition(metadataAsSource: FSharpMetadataAsSourceService) = targetDocument: Document, targetSourceText: SourceText, symbolRange: range, - statusBar: StatusBar, cancellationToken: CancellationToken ) = asyncMaybe { let! item = this.FindDefinitionOfSymbolAtRange(targetDocument, symbolRange, targetSourceText) - return this.NavigateToItem(item, statusBar, cancellationToken) + return this.NavigateToItem(item, cancellationToken) } member this.NavigateToExternalDeclaration @@ -546,7 +546,7 @@ type internal GoToDefinition(metadataAsSource: FSharpMetadataAsSourceService) = | _ -> TextSpan() let navItem = FSharpGoToDefinitionNavigableItem(tmpShownDoc, span) - this.NavigateToItem(navItem, statusBar, cancellationToken) + this.NavigateToItem(navItem, cancellationToken) true | _ -> false | _ -> false @@ -744,13 +744,7 @@ module internal FSharpQuickInfo = return result |> Option.defaultValue (symbolUse.Range, None, Some targetQuickInfo) } -type internal FSharpNavigation - ( - statusBar: StatusBar, - metadataAsSource: FSharpMetadataAsSourceService, - initialDoc: Document, - thisSymbolUseRange: range - ) = +type internal FSharpNavigation(metadataAsSource: FSharpMetadataAsSourceService, initialDoc: Document, thisSymbolUseRange: range) = let workspace = initialDoc.Project.Solution.Workspace let solution = workspace.CurrentSolution @@ -791,15 +785,13 @@ type internal FSharpNavigation match initialDoc.FilePath, targetPath with | Signature, Signature - | Implementation, Implementation -> return gtd.TryNavigateToTextSpan(targetDoc, targetTextSpan, statusBar, cancellationToken) + | Implementation, Implementation -> return gtd.TryNavigateToTextSpan(targetDoc, targetTextSpan, cancellationToken) // Adjust the target from signature to implementation. - | Implementation, Signature -> - return! gtd.NavigateToSymbolDefinitionAsync(targetDoc, targetSource, range, statusBar, cancellationToken) + | Implementation, Signature -> return! gtd.NavigateToSymbolDefinitionAsync(targetDoc, targetSource, range, cancellationToken) // Adjust the target from implmentation to signature. - | Signature, Implementation -> - return! gtd.NavigateToSymbolDeclarationAsync(targetDoc, targetSource, range, statusBar, cancellationToken) + | Signature, Implementation -> return! gtd.NavigateToSymbolDeclarationAsync(targetDoc, targetSource, range, cancellationToken) } |> Async.Ignore |> Async.StartImmediate @@ -818,6 +810,7 @@ type internal FSharpNavigation member _.TryGoToDefinition(position, cancellationToken) = let gtd = GoToDefinition(metadataAsSource) + let statusBar = StatusBar() let gtdTask = gtd.FindDefinitionTask(initialDoc, position, cancellationToken) // Wrap this in a try/with as if the user clicks "Cancel" on the thread dialog, we'll be cancelled. @@ -829,7 +822,7 @@ type internal FSharpNavigation if gtdTask.Status = TaskStatus.RanToCompletion && gtdTask.Result.IsSome then match gtdTask.Result.Value with | FSharpGoToDefinitionResult.NavigableItem (navItem), _ -> - gtd.NavigateToItem(navItem, statusBar, cancellationToken) + gtd.NavigateToItem(navItem, cancellationToken) // 'true' means do it, like Sheev Palpatine would want us to. true | FSharpGoToDefinitionResult.ExternalAssembly (targetSymbolUse, metadataReferences), _ -> @@ -876,7 +869,7 @@ type internal DocCommentId = | Type of EntityPath: string list | None -type FSharpNavigableLocation(statusBar: StatusBar, metadataAsSource: FSharpMetadataAsSourceService, symbolRange: range, project: Project) = +type FSharpNavigableLocation(metadataAsSource: FSharpMetadataAsSourceService, symbolRange: range, project: Project) = interface IFSharpNavigableLocation with member _.NavigateToAsync(_options: FSharpNavigationOptions2, cancellationToken: CancellationToken) : Task = asyncMaybe { @@ -892,10 +885,8 @@ type FSharpNavigableLocation(statusBar: StatusBar, metadataAsSource: FSharpMetad Implementation match targetPath with - | Signature -> - return! gtd.NavigateToSymbolDefinitionAsync(targetDoc, targetSource, symbolRange, statusBar, cancellationToken) - | Implementation -> - return! gtd.NavigateToSymbolDeclarationAsync(targetDoc, targetSource, symbolRange, statusBar, cancellationToken) + | Signature -> return! gtd.NavigateToSymbolDefinitionAsync(targetDoc, targetSource, symbolRange, cancellationToken) + | Implementation -> return! gtd.NavigateToSymbolDeclarationAsync(targetDoc, targetSource, symbolRange, cancellationToken) } |> Async.map (fun a -> a.IsSome) |> RoslynHelpers.StartAsyncAsTask cancellationToken @@ -908,9 +899,6 @@ type FSharpCrossLanguageSymbolNavigationService() = let workspace = componentModel.GetService() - let statusBar = - StatusBar(ServiceProvider.GlobalProvider.GetService()) - let metadataAsSource = componentModel .DefaultExportProvider @@ -1141,7 +1129,7 @@ type FSharpCrossLanguageSymbolNavigationService() = // More results can theoretically be returned in case of method overloads, or when we have both signature and implementation files. if locations.Count() >= 1 then let (location, project) = locations.First() - return FSharpNavigableLocation(statusBar, metadataAsSource, location, project) :> IFSharpNavigableLocation + return FSharpNavigableLocation(metadataAsSource, location, project) :> IFSharpNavigableLocation else return Unchecked.defaultof<_> // returning null here, so Roslyn can fallback to default source-as-metadata implementation. } diff --git a/vsintegration/src/FSharp.Editor/Navigation/GoToDefinitionService.fs b/vsintegration/src/FSharp.Editor/Navigation/GoToDefinitionService.fs index 9588fc3a7bb..a3a800c9ef6 100644 --- a/vsintegration/src/FSharp.Editor/Navigation/GoToDefinitionService.fs +++ b/vsintegration/src/FSharp.Editor/Navigation/GoToDefinitionService.fs @@ -2,7 +2,6 @@ namespace Microsoft.VisualStudio.FSharp.Editor -open System open System.Composition open System.Threading open System.Threading.Tasks @@ -12,31 +11,24 @@ open FSharp.Compiler.Text.Range open Microsoft.CodeAnalysis open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Editor -open Microsoft.VisualStudio.Shell -open Microsoft.VisualStudio.Shell.Interop - [)>] [)>] type internal FSharpGoToDefinitionService [] (metadataAsSource: FSharpMetadataAsSourceService) = - let statusBar = - StatusBar(ServiceProvider.GlobalProvider.GetService()) - interface IFSharpGoToDefinitionService with /// Invoked with Peek Definition. member _.FindDefinitionsAsync(document: Document, position: int, cancellationToken: CancellationToken) = - let navigation = - FSharpNavigation(statusBar, metadataAsSource, document, rangeStartup) + let navigation = FSharpNavigation(metadataAsSource, document, rangeStartup) navigation.FindDefinitions(position, cancellationToken) |> Task.FromResult /// Invoked with Go to Definition. /// Try to navigate to the definiton of the symbol at the symbolRange in the originDocument member _.TryGoToDefinition(document: Document, position: int, cancellationToken: CancellationToken) = + let statusBar = StatusBar() statusBar.Message(SR.LocatingSymbol()) use __ = statusBar.Animate() - let navigation = - FSharpNavigation(statusBar, metadataAsSource, document, rangeStartup) + let navigation = FSharpNavigation(metadataAsSource, document, rangeStartup) navigation.TryGoToDefinition(position, cancellationToken) diff --git a/vsintegration/src/FSharp.Editor/Navigation/NavigableSymbolsService.fs b/vsintegration/src/FSharp.Editor/Navigation/NavigableSymbolsService.fs index 5a87b2fc474..99a07f8fd1d 100644 --- a/vsintegration/src/FSharp.Editor/Navigation/NavigableSymbolsService.fs +++ b/vsintegration/src/FSharp.Editor/Navigation/NavigableSymbolsService.fs @@ -8,31 +8,28 @@ open System.Threading.Tasks open System.ComponentModel.Composition open Microsoft.CodeAnalysis.Text -open Microsoft.CodeAnalysis.Navigation open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Navigation open Microsoft.VisualStudio.Language.Intellisense open Microsoft.VisualStudio.Text open Microsoft.VisualStudio.Text.Editor -open Microsoft.VisualStudio.Shell.Interop open Microsoft.VisualStudio.Utilities -open Microsoft.VisualStudio.Shell [] -type internal FSharpNavigableSymbol(item: FSharpNavigableItem, span: SnapshotSpan, gtd: GoToDefinition, statusBar: StatusBar) = +type internal FSharpNavigableSymbol(item: FSharpNavigableItem, span: SnapshotSpan, gtd: GoToDefinition) = interface INavigableSymbol with member _.Navigate(_: INavigableRelationship) = - gtd.NavigateToItem(item, statusBar, CancellationToken.None) + gtd.NavigateToItem(item, CancellationToken.None) member _.Relationships = seq { yield PredefinedNavigableRelationships.Definition } member _.SymbolSpan = span -type internal FSharpNavigableSymbolSource(metadataAsSource, serviceProvider: IServiceProvider) = +type internal FSharpNavigableSymbolSource(metadataAsSource) = let mutable disposed = false let gtd = GoToDefinition(metadataAsSource) - let statusBar = StatusBar(serviceProvider.GetService()) + let statusBar = StatusBar() interface INavigableSymbolSource with member _.GetNavigableSymbolAsync(triggerSpan: SnapshotSpan, cancellationToken: CancellationToken) = @@ -67,7 +64,7 @@ type internal FSharpNavigableSymbolSource(metadataAsSource, serviceProvider: ISe match result with | FSharpGoToDefinitionResult.NavigableItem (navItem) -> - return FSharpNavigableSymbol(navItem, symbolSpan, gtd, statusBar) :> INavigableSymbol + return FSharpNavigableSymbol(navItem, symbolSpan, gtd) :> INavigableSymbol | FSharpGoToDefinitionResult.ExternalAssembly (targetSymbolUse, metadataReferences) -> let nav = @@ -105,12 +102,8 @@ type internal FSharpNavigableSymbolSource(metadataAsSource, serviceProvider: ISe [] [] [] -type internal FSharpNavigableSymbolService [] - ( - [)>] serviceProvider: IServiceProvider, - metadataAsSource: FSharpMetadataAsSourceService - ) = +type internal FSharpNavigableSymbolService [] (metadataAsSource: FSharpMetadataAsSourceService) = interface INavigableSymbolSourceProvider with member _.TryCreateNavigableSymbolSource(_: ITextView, _: ITextBuffer) = - new FSharpNavigableSymbolSource(metadataAsSource, serviceProvider) :> INavigableSymbolSource + new FSharpNavigableSymbolSource(metadataAsSource) diff --git a/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs b/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs index 45d24fb9d56..12fbeecf9a6 100644 --- a/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs +++ b/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs @@ -24,8 +24,6 @@ open Microsoft.IO type internal FSharpAsyncQuickInfoSource ( - statusBar: StatusBar, - xmlMemberIndexService: IVsXMLMemberIndexService, metadataAsSource: FSharpMetadataAsSourceService, textBuffer: ITextBuffer, editorOptions: EditorOptions @@ -92,8 +90,7 @@ type internal FSharpAsyncQuickInfoSource let getTrackingSpan (span: TextSpan) = textBuffer.CurrentSnapshot.CreateTrackingSpan(span.Start, span.Length, SpanTrackingMode.EdgeInclusive) - let documentationBuilder = - XmlDocumentation.CreateDocumentationBuilder(xmlMemberIndexService) + let documentationBuilder = XmlDocumentation.CreateDocumentationBuilder() match sigQuickInfo, targetQuickInfo with | None, None -> return null @@ -104,8 +101,7 @@ type internal FSharpAsyncQuickInfoSource let imageId = Tokenizer.GetImageIdForSymbol(quickInfo.Symbol, quickInfo.SymbolKind) - let navigation = - FSharpNavigation(statusBar, metadataAsSource, document, symbolUseRange) + let navigation = FSharpNavigation(metadataAsSource, document, symbolUseRange) let content = QuickInfoViewProvider.provideContent ( @@ -173,8 +169,7 @@ type internal FSharpAsyncQuickInfoSource let imageId = Tokenizer.GetImageIdForSymbol(targetQuickInfo.Symbol, targetQuickInfo.SymbolKind) - let navigation = - FSharpNavigation(statusBar, metadataAsSource, document, symbolUseRange) + let navigation = FSharpNavigation(metadataAsSource, document, symbolUseRange) let content = QuickInfoViewProvider.provideContent ( @@ -197,17 +192,10 @@ type internal FSharpAsyncQuickInfoSource [] type internal FSharpAsyncQuickInfoSourceProvider [] ( - [)>] serviceProvider: IServiceProvider, metadataAsSource: FSharpMetadataAsSourceService, editorOptions: EditorOptions ) = interface IAsyncQuickInfoSourceProvider with override _.TryCreateQuickInfoSource(textBuffer: ITextBuffer) : IAsyncQuickInfoSource = - // GetService calls must be made on the UI thread - // It is safe to do it here (see #4713) - let statusBar = StatusBar(serviceProvider.GetService()) - let xmlMemberIndexService = serviceProvider.XMLMemberIndexService - - new FSharpAsyncQuickInfoSource(statusBar, xmlMemberIndexService, metadataAsSource, textBuffer, editorOptions) - :> IAsyncQuickInfoSource + new FSharpAsyncQuickInfoSource(metadataAsSource, textBuffer, editorOptions) :> IAsyncQuickInfoSource From 11c1a096acadcc2c8890251930539dbb319b7a96 Mon Sep 17 00:00:00 2001 From: majocha Date: Thu, 30 Mar 2023 11:37:15 +0200 Subject: [PATCH 2/3] more --- .../Classification/ClassificationDefinitions.fs | 10 ++++------ vsintegration/src/FSharp.Editor/Common/Logging.fs | 15 +++------------ .../src/FSharp.Editor/FSharp.Editor.fsproj | 2 +- 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/Classification/ClassificationDefinitions.fs b/vsintegration/src/FSharp.Editor/Classification/ClassificationDefinitions.fs index 79405d93b48..4483986153a 100644 --- a/vsintegration/src/FSharp.Editor/Classification/ClassificationDefinitions.fs +++ b/vsintegration/src/FSharp.Editor/Classification/ClassificationDefinitions.fs @@ -17,7 +17,6 @@ open Microsoft.VisualStudio.Text.Classification open Microsoft.VisualStudio.Utilities open Microsoft.CodeAnalysis.Classification -open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.EditorServices [] @@ -88,8 +87,7 @@ module internal ClassificationDefinitions = type internal ThemeColors [] ( classificationformatMapService: IClassificationFormatMapService, - classificationTypeRegistry: IClassificationTypeRegistryService, - [)>] serviceProvider: IServiceProvider + classificationTypeRegistry: IClassificationTypeRegistryService ) = let (|LightTheme|DarkTheme|UnknownTheme|) id = @@ -106,7 +104,7 @@ module internal ClassificationDefinitions = let getCurrentThemeId () = let themeService = - serviceProvider.GetService(typeof) :?> IVsColorThemeService + GlobalProvider.GetService() themeService.CurrentTheme.ThemeId @@ -146,10 +144,10 @@ module internal ClassificationDefinitions = let setColors _ = let fontAndColorStorage = - serviceProvider.GetService(typeof) :?> IVsFontAndColorStorage + GlobalProvider.GetService() let fontAndColorCacheManager = - serviceProvider.GetService(typeof) :?> IVsFontAndColorCacheManager + GlobalProvider.GetService() fontAndColorCacheManager.CheckCache(ref DefGuidList.guidTextEditorFontCategory) |> ignore diff --git a/vsintegration/src/FSharp.Editor/Common/Logging.fs b/vsintegration/src/FSharp.Editor/Common/Logging.fs index 4800b012779..41316c990bd 100644 --- a/vsintegration/src/FSharp.Editor/Common/Logging.fs +++ b/vsintegration/src/FSharp.Editor/Common/Logging.fs @@ -3,7 +3,6 @@ open System open System.Diagnostics open System.ComponentModel.Composition -open Microsoft.VisualStudio.Shell open Microsoft.VisualStudio.Shell.Interop open Microsoft.VisualStudio.FSharp.Editor @@ -30,9 +29,9 @@ module Config = open Config [] -type Logger [] ([)>] serviceProvider: IServiceProvider) = +type Logger() = let outputWindow = - serviceProvider.GetService() |> Option.ofObj + GlobalProvider.GetService() |> Option.ofObj let createPane () = outputWindow @@ -49,14 +48,6 @@ type Logger [] ([)>] ser Some pane | _ -> None - static let mutable globalServiceProvider: IServiceProvider option = None - - static member GlobalServiceProvider - with get () = - globalServiceProvider - |> Option.defaultValue (ServiceProvider.GlobalProvider :> IServiceProvider) - and set v = globalServiceProvider <- Some v - member _.FSharpLoggingPane = getPane () |> function @@ -92,7 +83,7 @@ module Logging = let inline debug msg = Printf.kprintf Debug.WriteLine msg - let private logger = lazy Logger(Logger.GlobalServiceProvider) + let private logger = lazy Logger() let private log logType msg = logger.Value.Log(logType, msg) let logMsg msg = log LogType.Message msg diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index e14959f62a6..ce730ca1353 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -36,11 +36,11 @@ + - From 28435cef01436a0bea6105da576c84386017884a Mon Sep 17 00:00:00 2001 From: majocha Date: Wed, 5 Apr 2023 14:07:26 +0200 Subject: [PATCH 3/3] less impact --- .../ClassificationDefinitions.fs | 6 +-- .../src/FSharp.Editor/Common/Logging.fs | 4 +- vsintegration/src/FSharp.Editor/Common/Vs.fs | 48 ++++++++++++++----- .../Completion/CompletionProvider.fs | 12 ++++- .../Completion/CompletionService.fs | 19 ++++++-- .../FSharp.Editor/Completion/SignatureHelp.fs | 7 ++- .../DocComments/XMLDocumentation.fs | 3 +- .../Navigation/GoToDefinition.fs | 3 +- .../QuickInfo/QuickInfoProvider.fs | 6 ++- 9 files changed, 80 insertions(+), 28 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/Classification/ClassificationDefinitions.fs b/vsintegration/src/FSharp.Editor/Classification/ClassificationDefinitions.fs index 4483986153a..3e9ae2abbb9 100644 --- a/vsintegration/src/FSharp.Editor/Classification/ClassificationDefinitions.fs +++ b/vsintegration/src/FSharp.Editor/Classification/ClassificationDefinitions.fs @@ -104,7 +104,7 @@ module internal ClassificationDefinitions = let getCurrentThemeId () = let themeService = - GlobalProvider.GetService() + ServiceProvider.GlobalProvider.GetService() themeService.CurrentTheme.ThemeId @@ -144,10 +144,10 @@ module internal ClassificationDefinitions = let setColors _ = let fontAndColorStorage = - GlobalProvider.GetService() + ServiceProvider.GlobalProvider.GetService() let fontAndColorCacheManager = - GlobalProvider.GetService() + ServiceProvider.GlobalProvider.GetService() fontAndColorCacheManager.CheckCache(ref DefGuidList.guidTextEditorFontCategory) |> ignore diff --git a/vsintegration/src/FSharp.Editor/Common/Logging.fs b/vsintegration/src/FSharp.Editor/Common/Logging.fs index 41316c990bd..0e3ae8081d6 100644 --- a/vsintegration/src/FSharp.Editor/Common/Logging.fs +++ b/vsintegration/src/FSharp.Editor/Common/Logging.fs @@ -3,6 +3,7 @@ open System open System.Diagnostics open System.ComponentModel.Composition +open Microsoft.VisualStudio.Shell open Microsoft.VisualStudio.Shell.Interop open Microsoft.VisualStudio.FSharp.Editor @@ -31,7 +32,8 @@ open Config [] type Logger() = let outputWindow = - GlobalProvider.GetService() |> Option.ofObj + ServiceProvider.GlobalProvider.GetService() + |> Option.ofObj let createPane () = outputWindow diff --git a/vsintegration/src/FSharp.Editor/Common/Vs.fs b/vsintegration/src/FSharp.Editor/Common/Vs.fs index 5f47b8172c4..9bfdfe85a6e 100644 --- a/vsintegration/src/FSharp.Editor/Common/Vs.fs +++ b/vsintegration/src/FSharp.Editor/Common/Vs.fs @@ -90,21 +90,43 @@ module internal VsRunningDocumentTable = if IntPtr.Zero <> unkData then Marshal.Release(unkData) |> ignore -type internal GlobalProvider = +[] +module internal ServiceProviderExtensions = + type internal IAsyncServiceProvider with - static member GetServiceAsync<'S, 'T when 'S: not struct and 'T: not struct>() = - task { - do! ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync() - return! ServiceProvider.GetGlobalServiceAsync<'S, 'T>(swallowExceptions = false) - } + member sp.GetServiceAsync<'TService, 'TInterface>() = + backgroundTask { + match sp with + | :? IAsyncServiceProvider2 as sp2 -> + let! service = sp2.GetServiceAsync(typeof<'TService>, swallowExceptions = false) + return service :?> 'TInterface + | _ -> + let! service = sp.GetServiceAsync(typeof<'TService>) - static member GetService<'S, 'T when 'S: not struct and 'T: not struct>() = - ThreadHelper.JoinableTaskFactory.Run(GlobalProvider.GetServiceAsync<'S, 'T>) + if service = null then + raise (ServiceUnavailableException(typeof<'TService>)) - static member TextManager = GlobalProvider.GetService() + return service :?> 'TInterface + } - static member RunningDocumentTable = - GlobalProvider.GetService() + type internal IServiceProvider with - static member XMLMemberIndexService = - GlobalProvider.GetService() + member sp.GetService<'TService, 'TInterface>() = + ThreadHelper.JoinableTaskFactory.Run(fun () -> + task { + do! ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync() + let service = sp.GetService(typeof<'TService>) + + if service = null then + raise (ServiceUnavailableException(typeof<'TService>)) + + return service :?> 'TInterface + }) + + member sp.TextManager = sp.GetService() + + member sp.RunningDocumentTable = + sp.GetService() + + member sp.XMLMemberIndexService = + sp.GetService() diff --git a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs index f9538158591..935a18b3bb8 100644 --- a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs +++ b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs @@ -13,6 +13,8 @@ open Microsoft.CodeAnalysis.Completion open Microsoft.CodeAnalysis.Text open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Completion +open Microsoft.VisualStudio.Shell + open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.EditorServices open FSharp.Compiler.Syntax @@ -21,7 +23,12 @@ open FSharp.Compiler.Tokenization module Logger = Microsoft.VisualStudio.FSharp.Editor.Logger -type internal FSharpCompletionProvider(workspace: Workspace, assemblyContentProvider: AssemblyContentProvider) = +type internal FSharpCompletionProvider + ( + workspace: Workspace, + serviceProvider: SVsServiceProvider, + assemblyContentProvider: AssemblyContentProvider + ) = inherit FSharpCompletionProviderBase() @@ -85,7 +92,8 @@ type internal FSharpCompletionProvider(workspace: Workspace, assemblyContentProv let settings: EditorOptions = workspace.Services.GetService() - let documentationBuilder = XmlDocumentation.CreateDocumentationBuilder() + let documentationBuilder = + XmlDocumentation.CreateDocumentationBuilder(serviceProvider.XMLMemberIndexService) static let mruItems = Dictionary< (* Item.FullName *) string (* hints *) , int>() diff --git a/vsintegration/src/FSharp.Editor/Completion/CompletionService.fs b/vsintegration/src/FSharp.Editor/Completion/CompletionService.fs index 72ff7cfae01..bcb4e3ea942 100644 --- a/vsintegration/src/FSharp.Editor/Completion/CompletionService.fs +++ b/vsintegration/src/FSharp.Editor/Completion/CompletionService.fs @@ -13,7 +13,13 @@ open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Completion open Microsoft.VisualStudio.Shell -type internal FSharpCompletionService(workspace: Workspace, assemblyContentProvider: AssemblyContentProvider, settings: EditorOptions) = +type internal FSharpCompletionService + ( + workspace: Workspace, + serviceProvider: SVsServiceProvider, + assemblyContentProvider: AssemblyContentProvider, + settings: EditorOptions + ) = inherit FSharpCompletionServiceWithProviders(workspace) let projectInfoManager = @@ -24,7 +30,7 @@ type internal FSharpCompletionService(workspace: Workspace, assemblyContentProvi let builtInProviders = ImmutableArray.Create( - FSharpCompletionProvider(workspace, assemblyContentProvider), + FSharpCompletionProvider(workspace, serviceProvider, assemblyContentProvider), FSharpCommonCompletionProvider.Create(HashDirectiveCompletionProvider.Create(workspace, projectInfoManager)) ) @@ -55,9 +61,16 @@ type internal FSharpCompletionService(workspace: Workspace, assemblyContentProvi [, FSharpConstants.FSharpLanguageName)>] type internal FSharpCompletionServiceFactory [] ( + serviceProvider: SVsServiceProvider, assemblyContentProvider: AssemblyContentProvider, settings: EditorOptions ) = interface ILanguageServiceFactory with member _.CreateLanguageService(hostLanguageServices: HostLanguageServices) : ILanguageService = - upcast new FSharpCompletionService(hostLanguageServices.WorkspaceServices.Workspace, assemblyContentProvider, settings) + upcast + new FSharpCompletionService( + hostLanguageServices.WorkspaceServices.Workspace, + serviceProvider, + assemblyContentProvider, + settings + ) diff --git a/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs b/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs index df6752005c0..f08aaa568f0 100644 --- a/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs +++ b/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs @@ -9,6 +9,8 @@ open Microsoft.CodeAnalysis open Microsoft.CodeAnalysis.Text open Microsoft.CodeAnalysis.ExternalAccess.FSharp.SignatureHelp +open Microsoft.VisualStudio.Shell + open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.EditorServices open FSharp.Compiler.Symbols @@ -54,9 +56,10 @@ type SignatureHelpData = [] [)>] -type internal FSharpSignatureHelpProvider() = +type internal FSharpSignatureHelpProvider [] (serviceProvider: SVsServiceProvider) = - let documentationBuilder = XmlDocumentation.CreateDocumentationBuilder() + let documentationBuilder = + XmlDocumentation.CreateDocumentationBuilder(serviceProvider.XMLMemberIndexService) static let oneColAfter (lp: LinePosition) = LinePosition(lp.Line, lp.Character + 1) diff --git a/vsintegration/src/FSharp.Editor/DocComments/XMLDocumentation.fs b/vsintegration/src/FSharp.Editor/DocComments/XMLDocumentation.fs index 379c68a8971..3ab9a2362d3 100644 --- a/vsintegration/src/FSharp.Editor/DocComments/XMLDocumentation.fs +++ b/vsintegration/src/FSharp.Editor/DocComments/XMLDocumentation.fs @@ -560,6 +560,5 @@ module internal XmlDocumentation = let documentationBuilderCache = ConditionalWeakTable() - let CreateDocumentationBuilder () = - let xmlIndexService = GlobalProvider.XMLMemberIndexService + let CreateDocumentationBuilder (xmlIndexService: IVsXMLMemberIndexService) = documentationBuilderCache.GetValue(xmlIndexService, (fun _ -> Provider(xmlIndexService) :> IDocumentationBuilder)) diff --git a/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs b/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs index 776a928de00..7a18b2ad4b0 100644 --- a/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs +++ b/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs @@ -110,7 +110,8 @@ module private ExternalSymbol = // TODO: Uncomment code when VS has a fix for updating the status bar. type StatusBar() = - let statusBar = GlobalProvider.GetService() + let statusBar = + ServiceProvider.GlobalProvider.GetService() let mutable _searchIcon = int16 Microsoft.VisualStudio.Shell.Interop.Constants.SBAI_Find :> obj diff --git a/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs b/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs index 12fbeecf9a6..5ea98ddacba 100644 --- a/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs +++ b/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs @@ -90,7 +90,11 @@ type internal FSharpAsyncQuickInfoSource let getTrackingSpan (span: TextSpan) = textBuffer.CurrentSnapshot.CreateTrackingSpan(span.Start, span.Length, SpanTrackingMode.EdgeInclusive) - let documentationBuilder = XmlDocumentation.CreateDocumentationBuilder() + let! xmlIndexService = + AsyncServiceProvider.GlobalProvider.GetServiceAsync() + + let documentationBuilder = + XmlDocumentation.CreateDocumentationBuilder(xmlIndexService) match sigQuickInfo, targetQuickInfo with | None, None -> return null