From ab741991bc466204c2433ab5d32c25b8c0614552 Mon Sep 17 00:00:00 2001 From: Gen Lu Date: Tue, 10 May 2022 12:36:32 -0700 Subject: [PATCH 1/4] More SyntaxContext sharing for completion --- .../DeclarationNameCompletionProvider.cs | 7 ++++--- .../EnumAndCompletionListTagCompletionProvider.cs | 4 ++-- .../SnippetCompletionProvider.cs | 10 ++++++---- .../SpeculativeTCompletionProvider.cs | 13 ++++++------- .../TupleNameCompletionProvider.cs | 7 ++++--- .../Providers/AbstractAwaitCompletionProvider.cs | 3 +-- .../Providers/AbstractKeywordCompletionProvider.cs | 10 +++++----- .../AbstractPreprocessorCompletionProvider.cs | 5 +---- .../SharedSyntaxContextsWithSpeculativeModel.cs | 8 ++++---- .../Impl/Snippets/SnippetCompletionProvider.vb | 3 +-- 10 files changed, 34 insertions(+), 36 deletions(-) diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs index d18b025f07732..7395f923599a7 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs @@ -53,14 +53,15 @@ public override async Task ProvideCompletionsAsync(CompletionContext completionC var position = completionContext.Position; var document = completionContext.Document; var cancellationToken = completionContext.CancellationToken; - var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); if (!completionContext.CompletionOptions.ShowNameSuggestions) { return; } - var context = CSharpSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken); + var context = await completionContext.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false) as CSharpSyntaxContext; + Contract.ThrowIfNull(context); + if (context.IsInNonUserCode) { return; @@ -77,7 +78,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext completionC AddNamesFromExistingOverloads(context, partialSemanticModel, result, cancellationToken); } - var baseNames = GetBaseNames(semanticModel, nameInfo); + var baseNames = GetBaseNames(context.SemanticModel, nameInfo); if (baseNames != default) { await GetRecommendedNamesAsync(baseNames, nameInfo, context, document, result, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs index 35cd8755be451..e40458a90feeb 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs @@ -69,8 +69,8 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) if (tree.IsInNonUserCode(position, cancellationToken)) return; - var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); - var syntaxContext = CSharpSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken); + var syntaxContext = await context.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false); + var semanticModel = syntaxContext.SemanticModel; if (syntaxContext.IsInTaskLikeTypeContext) return; diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/SnippetCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/SnippetCompletionProvider.cs index c7f4aa577c010..2487f578a9f89 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/SnippetCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/SnippetCompletionProvider.cs @@ -65,7 +65,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) context.AddItems(await document.GetUnionItemsFromDocumentAndLinkedDocumentsAsync( UnionCompletionItemComparer.Instance, - d => GetSnippetsForDocumentAsync(d, position, cancellationToken)).ConfigureAwait(false)); + d => GetSnippetsForDocumentAsync(d, context, cancellationToken)).ConfigureAwait(false)); } } catch (Exception e) when (FatalError.ReportAndCatchUnlessCanceled(e, ErrorSeverity.General)) @@ -75,8 +75,9 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) } private static async Task> GetSnippetsForDocumentAsync( - Document document, int position, CancellationToken cancellationToken) + Document document, CompletionContext completionContext, CancellationToken cancellationToken) { + var position = completionContext.Position; var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var syntaxFacts = document.GetRequiredLanguageService(); var semanticFacts = document.GetRequiredLanguageService(); @@ -93,8 +94,9 @@ private static async Task> GetSnippetsForDocument return ImmutableArray.Empty; } - var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); - var context = CSharpSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken); + var context = await completionContext.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false); + var semanticModel = context.SemanticModel; + if (context.IsInTaskLikeTypeContext) return ImmutableArray.Empty; diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/SpeculativeTCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/SpeculativeTCompletionProvider.cs index 6683678142149..3a4c0bccc7421 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/SpeculativeTCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/SpeculativeTCompletionProvider.cs @@ -17,6 +17,7 @@ using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Completion.Providers { @@ -43,11 +44,10 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) try { var document = context.Document; - var position = context.Position; var cancellationToken = context.CancellationToken; var showSpeculativeT = await document.IsValidContextForDocumentOrLinkedDocumentsAsync( - (doc, ct) => ShouldShowSpeculativeTCompletionItemAsync(doc, position, ct), + (doc, ct) => ShouldShowSpeculativeTCompletionItemAsync(doc, context, ct), cancellationToken).ConfigureAwait(false); if (showSpeculativeT) @@ -63,8 +63,9 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) } } - private static async Task ShouldShowSpeculativeTCompletionItemAsync(Document document, int position, CancellationToken cancellationToken) + private static async Task ShouldShowSpeculativeTCompletionItemAsync(Document document, CompletionContext completionContext, CancellationToken cancellationToken) { + var position = completionContext.Position; var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (syntaxTree.IsInNonUserCode(position, cancellationToken) || syntaxTree.IsPreProcessorDirectiveContext(position, cancellationToken)) @@ -75,10 +76,8 @@ private static async Task ShouldShowSpeculativeTCompletionItemAsync(Docume // We could be in the middle of a ref/generic/tuple type, instead of a simple T case. // If we managed to walk out and get a different SpanStart, we treat it as a simple $$T case. - var token = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken); - var semanticModel = await document.ReuseExistingSpeculativeModelAsync(token.Parent, cancellationToken).ConfigureAwait(false); + var context = await completionContext.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false); - var context = CSharpSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken); if (context.IsInTaskLikeTypeContext) return false; @@ -87,7 +86,7 @@ private static async Task ShouldShowSpeculativeTCompletionItemAsync(Docume { var oldSpanStart = spanStart; - spanStart = WalkOutOfGenericType(syntaxTree, spanStart, semanticModel, cancellationToken); + spanStart = WalkOutOfGenericType(syntaxTree, spanStart, context.SemanticModel, cancellationToken); spanStart = WalkOutOfTupleType(syntaxTree, spanStart, cancellationToken); spanStart = WalkOutOfRefType(syntaxTree, spanStart, cancellationToken); diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/TupleNameCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/TupleNameCompletionProvider.cs index 74049eb26f8b2..ddf523d620b1a 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/TupleNameCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/TupleNameCompletionProvider.cs @@ -18,6 +18,7 @@ using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Completion.Providers { @@ -41,12 +42,12 @@ public override async Task ProvideCompletionsAsync(CompletionContext completionC try { var document = completionContext.Document; - var position = completionContext.Position; var cancellationToken = completionContext.CancellationToken; - var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); + var context = await completionContext.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false) as CSharpSyntaxContext; + Contract.ThrowIfNull(context); - var context = CSharpSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken); + var semanticModel = context.SemanticModel; var index = GetElementIndex(context); if (index == null) diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractAwaitCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractAwaitCompletionProvider.cs index b80cd734385f5..e72f3b6b18ee5 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractAwaitCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractAwaitCompletionProvider.cs @@ -88,8 +88,7 @@ public sealed override async Task ProvideCompletionsAsync(CompletionContext cont if (syntaxFacts.IsInNonUserCode(syntaxTree, position, cancellationToken)) return; - var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); - var syntaxContext = document.GetRequiredLanguageService().CreateContext(document, semanticModel, position, cancellationToken); + var syntaxContext = await context.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false); var isAwaitKeywordContext = IsAwaitKeywordContext(syntaxContext); var dotAwaitContext = GetDotAwaitKeywordContext(syntaxContext, cancellationToken); diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs index df0f01226be69..3bc5daf253762 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs @@ -36,15 +36,15 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) { context.AddItems(await context.Document.GetUnionItemsFromDocumentAndLinkedDocumentsAsync( s_comparer, - d => RecommendCompletionItemsAsync(d, context.Position, cancellationToken)).ConfigureAwait(false)); + d => RecommendCompletionItemsAsync(d, context, cancellationToken)).ConfigureAwait(false)); } } - private async Task> RecommendCompletionItemsAsync(Document document, int position, CancellationToken cancellationToken) + private async Task> RecommendCompletionItemsAsync(Document document, CompletionContext context, CancellationToken cancellationToken) { - var syntaxContextService = document.GetRequiredLanguageService(); - var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); - var syntaxContext = (TContext)syntaxContextService.CreateContext(document, semanticModel, position, cancellationToken); + var position = context.Position; + var syntaxContext = await context.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false) as TContext; + Contract.ThrowIfNull(syntaxContext); var keywords = await RecommendKeywordsAsync(document, position, syntaxContext, cancellationToken).ConfigureAwait(false); return keywords.SelectAsArray(k => CreateItem(k, syntaxContext, cancellationToken)); } diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractPreprocessorCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractPreprocessorCompletionProvider.cs index c1e64e5635016..f039c9496605a 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractPreprocessorCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractPreprocessorCompletionProvider.cs @@ -20,11 +20,8 @@ public sealed override async Task ProvideCompletionsAsync(CompletionContext cont var cancellationToken = context.CancellationToken; var originatingDocument = context.Document; var position = context.Position; - - var semanticModel = await originatingDocument.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); - var service = originatingDocument.GetRequiredLanguageService(); var solution = originatingDocument.Project.Solution; - var syntaxContext = service.CreateContext(originatingDocument, semanticModel, position, cancellationToken); + var syntaxContext = await context.GetSyntaxContextWithExistingSpeculativeModelAsync(originatingDocument, cancellationToken).ConfigureAwait(false); if (!syntaxContext.IsPreProcessorExpressionContext) return; diff --git a/src/Features/Core/Portable/Completion/SharedSyntaxContextsWithSpeculativeModel.cs b/src/Features/Core/Portable/Completion/SharedSyntaxContextsWithSpeculativeModel.cs index 888efbd984271..011b60958d0ed 100644 --- a/src/Features/Core/Portable/Completion/SharedSyntaxContextsWithSpeculativeModel.cs +++ b/src/Features/Core/Portable/Completion/SharedSyntaxContextsWithSpeculativeModel.cs @@ -35,16 +35,16 @@ public Task GetSyntaxContextAsync(Document document, Cancellation if (_document.Id != document.Id && !_lazyRelatedDocumentIds.Value.Contains(document.Id)) throw new ArgumentException("Don't support getting SyntaxContext for document unrelated to the original document"); - lazyContext = GetLazySyntaxContextWithSpeculativeModel(document); + lazyContext = GetLazySyntaxContextWithSpeculativeModel(document, this); } return lazyContext.GetValueAsync(cancellationToken); // Extract a local function to avoid creating a closure for code path of cache hit. - AsyncLazy GetLazySyntaxContextWithSpeculativeModel(Document document) + static AsyncLazy GetLazySyntaxContextWithSpeculativeModel(Document document, SharedSyntaxContextsWithSpeculativeModel self) { - return _cache.GetOrAdd(document, d => AsyncLazy.Create(cancellationToken - => CompletionHelper.CreateSyntaxContextWithExistingSpeculativeModelAsync(d, _position, cancellationToken), cacheResult: true)); + return self._cache.GetOrAdd(document, d => AsyncLazy.Create(cancellationToken + => CompletionHelper.CreateSyntaxContextWithExistingSpeculativeModelAsync(d, self._position, cancellationToken), cacheResult: true)); } } } diff --git a/src/VisualStudio/VisualBasic/Impl/Snippets/SnippetCompletionProvider.vb b/src/VisualStudio/VisualBasic/Impl/Snippets/SnippetCompletionProvider.vb index 685882e3d63db..53916c54a9c40 100644 --- a/src/VisualStudio/VisualBasic/Impl/Snippets/SnippetCompletionProvider.vb +++ b/src/VisualStudio/VisualBasic/Impl/Snippets/SnippetCompletionProvider.vb @@ -89,8 +89,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Snippets Return End If - Dim semanticModel = Await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(False) - Dim syntaxContext = VisualBasicSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken) + Dim syntaxContext = Await context.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(False) If syntaxContext.IsInTaskLikeTypeContext Then Return End If From 79abb57568933445ab63be4be1710c12dfa469dc Mon Sep 17 00:00:00 2001 From: Gen Lu Date: Tue, 10 May 2022 12:59:04 -0700 Subject: [PATCH 2/4] Share SyntaxContext for recommender based completion providers --- .../UnnamedSymbolCompletionProvider.cs | 6 +++--- ...ractRecommendationServiceBasedCompletionProvider.cs | 2 +- .../Recommendations/AbstractRecommendationService.cs | 10 ++++++++-- .../Portable/Recommendations/IRecommendationService.cs | 6 ++++++ 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/OperatorsAndIndexer/UnnamedSymbolCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/OperatorsAndIndexer/UnnamedSymbolCompletionProvider.cs index 31206cffa7622..fe3c85da6775d 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/OperatorsAndIndexer/UnnamedSymbolCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/OperatorsAndIndexer/UnnamedSymbolCompletionProvider.cs @@ -111,11 +111,11 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) return; var recommender = document.GetRequiredLanguageService(); - - var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); + var syntaxContext = await context.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false); + var semanticModel = syntaxContext.SemanticModel; var options = context.CompletionOptions.ToRecommendationServiceOptions(); - var recommendedSymbols = recommender.GetRecommendedSymbolsAtPosition(document, semanticModel, position, options, cancellationToken); + var recommendedSymbols = recommender.GetRecommendedSymbolsInContext(syntaxContext, options, cancellationToken); AddUnnamedSymbols(context, position, semanticModel, recommendedSymbols.UnnamedSymbols, cancellationToken); } diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractRecommendationServiceBasedCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractRecommendationServiceBasedCompletionProvider.cs index f70eaaae6409d..a030f435b8f13 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractRecommendationServiceBasedCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractRecommendationServiceBasedCompletionProvider.cs @@ -34,7 +34,7 @@ internal abstract class AbstractRecommendationServiceBasedCompletionProvider(); - var recommendedSymbols = recommender.GetRecommendedSymbolsAtPosition(context.Document, context.SemanticModel, position, recommendationOptions, cancellationToken); + var recommendedSymbols = recommender.GetRecommendedSymbolsInContext(context, recommendationOptions, cancellationToken); if (context.IsInTaskLikeTypeContext) { diff --git a/src/Workspaces/Core/Portable/Recommendations/AbstractRecommendationService.cs b/src/Workspaces/Core/Portable/Recommendations/AbstractRecommendationService.cs index 8dea60dbbf689..c76c2a62ad3ea 100644 --- a/src/Workspaces/Core/Portable/Recommendations/AbstractRecommendationService.cs +++ b/src/Workspaces/Core/Portable/Recommendations/AbstractRecommendationService.cs @@ -26,7 +26,13 @@ protected abstract AbstractRecommendationServiceRunner CreateRunner( public RecommendedSymbols GetRecommendedSymbolsAtPosition(Document document, SemanticModel semanticModel, int position, RecommendationServiceOptions options, CancellationToken cancellationToken) { var context = CreateContext(document, semanticModel, position, cancellationToken); - var result = CreateRunner(context, options.FilterOutOfScopeLocals, cancellationToken).GetRecommendedSymbols(); + return GetRecommendedSymbolsInContext(context, options, cancellationToken); + } + + public RecommendedSymbols GetRecommendedSymbolsInContext(SyntaxContext syntaxContext, RecommendationServiceOptions options, CancellationToken cancellationToken) + { + var semanticModel = syntaxContext.SemanticModel; + var result = CreateRunner((TSyntaxContext)syntaxContext, options.FilterOutOfScopeLocals, cancellationToken).GetRecommendedSymbols(); var namedSymbols = result.NamedSymbols; var unnamedSymbols = result.UnnamedSymbols; @@ -34,7 +40,7 @@ public RecommendedSymbols GetRecommendedSymbolsAtPosition(Document document, Sem namedSymbols = namedSymbols.FilterToVisibleAndBrowsableSymbols(options.HideAdvancedMembers, semanticModel.Compilation); unnamedSymbols = unnamedSymbols.FilterToVisibleAndBrowsableSymbols(options.HideAdvancedMembers, semanticModel.Compilation); - var shouldIncludeSymbolContext = new ShouldIncludeSymbolContext(context, cancellationToken); + var shouldIncludeSymbolContext = new ShouldIncludeSymbolContext(syntaxContext, cancellationToken); namedSymbols = namedSymbols.WhereAsArray(shouldIncludeSymbolContext.ShouldIncludeSymbol); unnamedSymbols = unnamedSymbols.WhereAsArray(shouldIncludeSymbolContext.ShouldIncludeSymbol); diff --git a/src/Workspaces/Core/Portable/Recommendations/IRecommendationService.cs b/src/Workspaces/Core/Portable/Recommendations/IRecommendationService.cs index 3f98c0059c492..b9a26a066cff8 100644 --- a/src/Workspaces/Core/Portable/Recommendations/IRecommendationService.cs +++ b/src/Workspaces/Core/Portable/Recommendations/IRecommendationService.cs @@ -5,6 +5,7 @@ using System.Collections.Immutable; using System.Threading; using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery; namespace Microsoft.CodeAnalysis.Recommendations { @@ -16,6 +17,11 @@ RecommendedSymbols GetRecommendedSymbolsAtPosition( int position, RecommendationServiceOptions options, CancellationToken cancellationToken); + + RecommendedSymbols GetRecommendedSymbolsInContext( + SyntaxContext syntaxContext, + RecommendationServiceOptions options, + CancellationToken cancellationToken); } internal readonly struct RecommendedSymbols From 8fd7a375c2ae6fe2d51f41af350ef66a9c6f2024 Mon Sep 17 00:00:00 2001 From: Gen Lu Date: Tue, 10 May 2022 16:34:25 -0700 Subject: [PATCH 3/4] API consolidation --- .../DeclarationNameCompletionProvider.cs | 4 +--- .../ChangeSignature/AbstractChangeSignatureService.cs | 5 ++++- .../Providers/AbstractKeywordCompletionProvider.cs | 3 +-- .../Recommendations/CSharpRecommendationService.cs | 3 --- .../Recommendations/AbstractRecommendationService.cs | 9 --------- .../Portable/Recommendations/IRecommendationService.cs | 7 ------- .../Core/Portable/Recommendations/Recommender.cs | 8 ++++++-- .../Recommendations/VisualBasicRecommendationService.vb | 4 ---- 8 files changed, 12 insertions(+), 31 deletions(-) diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs index 7395f923599a7..f925da91abc72 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs @@ -59,9 +59,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext completionC return; } - var context = await completionContext.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false) as CSharpSyntaxContext; - Contract.ThrowIfNull(context); - + var context = (CSharpSyntaxContext)await completionContext.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false); if (context.IsInNonUserCode) { return; diff --git a/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs b/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs index 238c8ca820e82..899e5425f85a0 100644 --- a/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs +++ b/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs @@ -24,6 +24,7 @@ using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Recommendations; using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery; using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; @@ -916,7 +917,9 @@ private async Task GenerateInferredCallsiteExpressionAsync( var recommender = document.GetRequiredLanguageService(); var options = RecommendationServiceOptions.From(document.Project); - var recommendations = recommender.GetRecommendedSymbolsAtPosition(document, semanticModel, position, options, cancellationToken).NamedSymbols; + + var context = document.GetRequiredLanguageService().CreateContext(document, semanticModel, position, cancellationToken); + var recommendations = recommender.GetRecommendedSymbolsInContext(context, options, cancellationToken).NamedSymbols; var sourceSymbols = recommendations.Where(r => r.IsNonImplicitAndFromSource()); diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs index 3bc5daf253762..7caf809dfa7c3 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs @@ -43,8 +43,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) private async Task> RecommendCompletionItemsAsync(Document document, CompletionContext context, CancellationToken cancellationToken) { var position = context.Position; - var syntaxContext = await context.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false) as TContext; - Contract.ThrowIfNull(syntaxContext); + var syntaxContext = (TContext)await context.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false); var keywords = await RecommendKeywordsAsync(document, position, syntaxContext, cancellationToken).ConfigureAwait(false); return keywords.SelectAsArray(k => CreateItem(k, syntaxContext, cancellationToken)); } diff --git a/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationService.cs b/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationService.cs index 031295d9d0434..7c493ae409783 100644 --- a/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationService.cs +++ b/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationService.cs @@ -20,9 +20,6 @@ public CSharpRecommendationService() { } - protected override CSharpSyntaxContext CreateContext(Document document, SemanticModel semanticModel, int position, CancellationToken cancellationToken) - => CSharpSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken); - protected override AbstractRecommendationServiceRunner CreateRunner(CSharpSyntaxContext context, bool filterOutOfScopeLocals, CancellationToken cancellationToken) => new CSharpRecommendationServiceRunner(context, filterOutOfScopeLocals, cancellationToken); } diff --git a/src/Workspaces/Core/Portable/Recommendations/AbstractRecommendationService.cs b/src/Workspaces/Core/Portable/Recommendations/AbstractRecommendationService.cs index c76c2a62ad3ea..29afdff7ab0f8 100644 --- a/src/Workspaces/Core/Portable/Recommendations/AbstractRecommendationService.cs +++ b/src/Workspaces/Core/Portable/Recommendations/AbstractRecommendationService.cs @@ -17,18 +17,9 @@ namespace Microsoft.CodeAnalysis.Recommendations internal abstract partial class AbstractRecommendationService : IRecommendationService where TSyntaxContext : SyntaxContext { - protected abstract TSyntaxContext CreateContext( - Document document, SemanticModel semanticModel, int position, CancellationToken cancellationToken); - protected abstract AbstractRecommendationServiceRunner CreateRunner( TSyntaxContext context, bool filterOutOfScopeLocals, CancellationToken cancellationToken); - public RecommendedSymbols GetRecommendedSymbolsAtPosition(Document document, SemanticModel semanticModel, int position, RecommendationServiceOptions options, CancellationToken cancellationToken) - { - var context = CreateContext(document, semanticModel, position, cancellationToken); - return GetRecommendedSymbolsInContext(context, options, cancellationToken); - } - public RecommendedSymbols GetRecommendedSymbolsInContext(SyntaxContext syntaxContext, RecommendationServiceOptions options, CancellationToken cancellationToken) { var semanticModel = syntaxContext.SemanticModel; diff --git a/src/Workspaces/Core/Portable/Recommendations/IRecommendationService.cs b/src/Workspaces/Core/Portable/Recommendations/IRecommendationService.cs index b9a26a066cff8..9227fe209690c 100644 --- a/src/Workspaces/Core/Portable/Recommendations/IRecommendationService.cs +++ b/src/Workspaces/Core/Portable/Recommendations/IRecommendationService.cs @@ -11,13 +11,6 @@ namespace Microsoft.CodeAnalysis.Recommendations { internal interface IRecommendationService : ILanguageService { - RecommendedSymbols GetRecommendedSymbolsAtPosition( - Document document, - SemanticModel semanticModel, - int position, - RecommendationServiceOptions options, - CancellationToken cancellationToken); - RecommendedSymbols GetRecommendedSymbolsInContext( SyntaxContext syntaxContext, RecommendationServiceOptions options, diff --git a/src/Workspaces/Core/Portable/Recommendations/Recommender.cs b/src/Workspaces/Core/Portable/Recommendations/Recommender.cs index 63c8a351e2c27..153534b40fec3 100644 --- a/src/Workspaces/Core/Portable/Recommendations/Recommender.cs +++ b/src/Workspaces/Core/Portable/Recommendations/Recommender.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery; namespace Microsoft.CodeAnalysis.Recommendations { @@ -25,8 +26,10 @@ public static IEnumerable GetRecommendedSymbolsAtPosition( var solution = workspace.CurrentSolution; options ??= solution.Options; var document = solution.GetRequiredDocument(semanticModel.SyntaxTree); + var context = document.GetRequiredLanguageService().CreateContext(document, semanticModel, position, cancellationToken); + var languageRecommender = document.GetRequiredLanguageService(); - return languageRecommender.GetRecommendedSymbolsAtPosition(document, semanticModel, position, RecommendationServiceOptions.From(options, document.Project.Language), cancellationToken).NamedSymbols; + return languageRecommender.GetRecommendedSymbolsInContext(context, RecommendationServiceOptions.From(options, document.Project.Language), cancellationToken).NamedSymbols; } [Obsolete("Use GetRecommendedSymbolsAtPositionAsync(Document, ...)")] @@ -49,8 +52,9 @@ public static async Task> GetRecommendedSymbolsAtPositio var solution = document.Project.Solution; var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); options ??= solution.Options; + var context = document.GetRequiredLanguageService().CreateContext(document, semanticModel, position, cancellationToken); var languageRecommender = document.GetRequiredLanguageService(); - return languageRecommender.GetRecommendedSymbolsAtPosition(document, semanticModel, position, RecommendationServiceOptions.From(options, document.Project.Language), cancellationToken).NamedSymbols; + return languageRecommender.GetRecommendedSymbolsInContext(context, RecommendationServiceOptions.From(options, document.Project.Language), cancellationToken).NamedSymbols; } } } diff --git a/src/Workspaces/VisualBasic/Portable/Recommendations/VisualBasicRecommendationService.vb b/src/Workspaces/VisualBasic/Portable/Recommendations/VisualBasicRecommendationService.vb index 4e8f0c5ebc35b..e1caff2aef8c8 100644 --- a/src/Workspaces/VisualBasic/Portable/Recommendations/VisualBasicRecommendationService.vb +++ b/src/Workspaces/VisualBasic/Portable/Recommendations/VisualBasicRecommendationService.vb @@ -18,10 +18,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Recommendations Public Sub New() End Sub - Protected Overrides Function CreateContext(document As Document, semanticModel As SemanticModel, position As Integer, cancellationToken As CancellationToken) As VisualBasicSyntaxContext - Return VisualBasicSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken) - End Function - Protected Overrides Function CreateRunner(context As VisualBasicSyntaxContext, filterOutOfScopeLocals As Boolean, cancellationToken As CancellationToken) As AbstractRecommendationServiceRunner Return New VisualBasicRecommendationServiceRunner(context, filterOutOfScopeLocals, cancellationToken) End Function From 9ebd02c183aa9498623682de3d626d908fc00bec Mon Sep 17 00:00:00 2001 From: "gel@microsoft.com" Date: Wed, 11 May 2022 16:34:40 -0700 Subject: [PATCH 4/4] Fix merge --- .../CompletionProviders/DeclarationNameCompletionProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs index 6946b3f6c5b4a..b4275f66224d0 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs @@ -68,7 +68,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext completionC // Do not show name suggestions for unbound "async" identifier. // Most likely user is writing an async method, so name suggestion will just interfere him if (context.TargetToken.IsKindOrHasMatchingText(SyntaxKind.AsyncKeyword) && - semanticModel.GetSymbolInfo(context.TargetToken).GetAnySymbol() is null) + context.SemanticModel.GetSymbolInfo(context.TargetToken).GetAnySymbol() is null) { return; }