protected async override Task AddCompletionItemsAsync( CompletionContext completionContext, SyntaxContext syntaxContext, HashSet <string> namespaceInScope, bool isExpandedCompletion, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.Completion_ExtensionMethodImportCompletionProvider_GetCompletionItemsAsync, cancellationToken)) { var syntaxFacts = completionContext.Document.GetRequiredLanguageService <ISyntaxFactsService>(); if (TryGetReceiverTypeSymbol(syntaxContext, syntaxFacts, cancellationToken, out var receiverTypeSymbol)) { var items = await ExtensionMethodImportCompletionHelper.GetUnimportedExtensionMethodsAsync( completionContext.Document, completionContext.Position, receiverTypeSymbol, namespaceInScope, forceIndexCreation : isExpandedCompletion, cancellationToken).ConfigureAwait(false); completionContext.AddItems(items.Select(i => Convert(i))); } else { // If we can't get a valid receiver type, then we don't show expander as available. // We need to set this explicitly here because we didn't do the (more expensive) symbol check inside // `ShouldProvideCompletion` method above, which is intended for quick syntax based check. completionContext.ExpandItemsAvailable = false; } } }
protected override async Task AddCompletionItemsAsync( CompletionContext completionContext, SyntaxContext syntaxContext, HashSet <string> namespaceInScope, bool isExpandedCompletion, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.Completion_ExtensionMethodImportCompletionProvider_GetCompletionItemsAsync, cancellationToken)) { var syntaxFacts = completionContext.Document.GetRequiredLanguageService <ISyntaxFactsService>(); if (TryGetReceiverTypeSymbol(syntaxContext, syntaxFacts, cancellationToken, out var receiverTypeSymbol)) { using var nestedTokenSource = new CancellationTokenSource(); using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(nestedTokenSource.Token, cancellationToken); var inferredTypes = completionContext.CompletionOptions.TargetTypedCompletionFilter ? syntaxContext.InferredTypes : ImmutableArray <ITypeSymbol> .Empty; var getItemsTask = Task.Run(() => ExtensionMethodImportCompletionHelper.GetUnimportedExtensionMethodsAsync( completionContext.Document, completionContext.Position, receiverTypeSymbol, namespaceInScope, inferredTypes, forceIndexCreation: isExpandedCompletion, hideAdvancedMembers: completionContext.CompletionOptions.HideAdvancedMembers, linkedTokenSource.Token)); var timeoutInMilliseconds = completionContext.CompletionOptions.TimeoutInMillisecondsForExtensionMethodImportCompletion; // Timebox is enabled if timeout value is >= 0 and we are not triggered via expander if (timeoutInMilliseconds >= 0 && !isExpandedCompletion) { // timeout == 0 means immediate timeout (for testing purpose) if (timeoutInMilliseconds == 0 || await Task.WhenAny(getItemsTask, Task.Delay(timeoutInMilliseconds, linkedTokenSource.Token)).ConfigureAwait(false) != getItemsTask) { nestedTokenSource.Cancel(); CompletionProvidersLogger.LogExtensionMethodCompletionTimeoutCount(); return; } } // Either the timebox is not enabled, so we need to wait until the operation for complete, // or there's no timeout, and we now have all completion items ready. var items = await getItemsTask.ConfigureAwait(false); var receiverTypeKey = SymbolKey.CreateString(receiverTypeSymbol, cancellationToken); completionContext.AddItems(items.Select(i => Convert(i, receiverTypeKey))); } else { // If we can't get a valid receiver type, then we don't show expander as available. // We need to set this explicitly here because we didn't do the (more expensive) symbol check inside // `ShouldProvideCompletion` method above, which is intended for quick syntax based check. completionContext.ExpandItemsAvailable = false; } } }
protected override async Task AddCompletionItemsAsync( CompletionContext completionContext, SyntaxContext syntaxContext, HashSet <string> namespaceInScope, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.Completion_ExtensionMethodImportCompletionProvider_GetCompletionItemsAsync, cancellationToken)) { var syntaxFacts = completionContext.Document.GetRequiredLanguageService <ISyntaxFactsService>(); if (TryGetReceiverTypeSymbol(syntaxContext, syntaxFacts, cancellationToken, out var receiverTypeSymbol)) { var totalTime = SharedStopwatch.StartNew(); var inferredTypes = completionContext.CompletionOptions.TargetTypedCompletionFilter ? syntaxContext.InferredTypes : ImmutableArray <ITypeSymbol> .Empty; var result = await ExtensionMethodImportCompletionHelper.GetUnimportedExtensionMethodsAsync( completionContext.Document, completionContext.Position, receiverTypeSymbol, namespaceInScope, inferredTypes, forceCacheCreation : completionContext.CompletionOptions.ForceExpandedCompletionIndexCreation, hideAdvancedMembers : completionContext.CompletionOptions.HideAdvancedMembers, cancellationToken).ConfigureAwait(false); if (result is null) { return; } var receiverTypeKey = SymbolKey.CreateString(receiverTypeSymbol, cancellationToken); completionContext.AddItems(result.CompletionItems.Select(i => Convert(i, receiverTypeKey))); // report telemetry: CompletionProvidersLogger.LogExtensionMethodCompletionTicksDataPoint( totalTime.Elapsed, result.GetSymbolsTime, result.CreateItemsTime, result.IsRemote); if (result.IsPartialResult) { CompletionProvidersLogger.LogExtensionMethodCompletionPartialResultCount(); } } } }
protected override void WarmUpCacheInBackground(Document document) { _ = ExtensionMethodImportCompletionHelper.WarmUpCacheAsync(document.Project, CancellationToken.None); }