public override async Task ProvideCompletionsAsync(CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var workspace = document.Project.Solution.Workspace; var semanticModel = await document.GetSemanticModelForSpanAsync(new TextSpan(position, length: 0), cancellationToken).ConfigureAwait(false); var typeAndLocation = GetInitializedType(document, semanticModel, position, cancellationToken); if (typeAndLocation == null) { return; } var initializedType = typeAndLocation.Item1 as INamedTypeSymbol; var initializerLocation = typeAndLocation.Item2; if (initializedType == null) { return; } if (await IsExclusiveAsync(document, position, cancellationToken).ConfigureAwait(false)) { context.IsExclusive = true; } var enclosing = semanticModel.GetEnclosingNamedType(position, cancellationToken); // Find the members that can be initialized. If we have a NamedTypeSymbol, also get the overridden members. IEnumerable<ISymbol> members = semanticModel.LookupSymbols(position, initializedType); members = members.Where(m => IsInitializable(m, enclosing) && m.CanBeReferencedByName && IsLegalFieldOrProperty(m, enclosing) && !m.IsImplicitlyDeclared); // Filter out those members that have already been typed var alreadyTypedMembers = GetInitializedMembers(semanticModel.SyntaxTree, position, cancellationToken); var uninitializedMembers = members.Where(m => !alreadyTypedMembers.Contains(m.Name)); uninitializedMembers = uninitializedMembers.Where(m => m.IsEditorBrowsable(document.ShouldHideAdvancedMembers(), semanticModel.Compilation)); var text = await semanticModel.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); foreach (var uninitializedMember in uninitializedMembers) { context.AddItem(SymbolCompletionItem.Create( displayText: uninitializedMember.Name, insertionText: null, span: context.DefaultItemSpan, symbol: uninitializedMember, descriptionPosition: initializerLocation.SourceSpan.Start, rules: s_rules )); } }
private static void AddItems(ImmutableArray <INamedTypeSymbol> inferredTypes, int index, CompletionContext context, int spanStart) { foreach (var type in inferredTypes) { if (index >= type.TupleElements.Length) { return; } // Note: the filter text does not include the ':'. We want to ensure that if // the user types the name exactly (up to the colon) that it is selected as an // exact match. var field = type.TupleElements[index]; context.AddItem(SymbolCompletionItem.CreateWithSymbolId( displayText: field.Name, displayTextSuffix: ColonString, symbols: ImmutableArray.Create(field), rules: CompletionItemRules.Default, contextPosition: spanStart, filterText: field.Name)); } }
public override async Task ProvideCompletionsAsync(CompletionContext completionContext) { var position = completionContext.Position; var document = completionContext.Document; var cancellationToken = completionContext.CancellationToken; var semanticModel = await document.GetSemanticModelForSpanAsync(new Text.TextSpan(position, 0), cancellationToken).ConfigureAwait(false); var context = CSharpSyntaxContext.CreateContext(document.Project.Solution.Workspace, semanticModel, position, cancellationToken); if (context.IsInNonUserCode) { return; } var nameInfo = await NameDeclarationInfo.GetDeclarationInfo(document, position, cancellationToken).ConfigureAwait(false); var baseNames = GetBaseNames(semanticModel, nameInfo); if (baseNames == default) { return; } var recommendedNames = await GetRecommendedNamesAsync(baseNames, nameInfo, context, document, cancellationToken).ConfigureAwait(false); int sortValue = 0; foreach (var(name, kind) in recommendedNames) { // We've produced items in the desired order, add a sort text to each item to prevent alphabetization completionContext.AddItem(CreateCompletionItem(name, GetGlyph(kind, nameInfo.DeclaredAccessibility), sortValue.ToString("D8"))); sortValue++; } completionContext.SuggestionModeItem = CommonCompletionItem.Create(CSharpFeaturesResources.Name, CompletionItemRules.Default); }
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), cancellationToken).ConfigureAwait(false); if (showSpeculativeT) { const string T = nameof(T); context.AddItem(CommonCompletionItem.Create( T, displayTextSuffix: "", CompletionItemRules.Default, glyph: Glyph.TypeParameter)); } } catch (Exception e) when(FatalError.ReportAndCatchUnlessCanceled(e)) { // nop } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { // wrap it in try catch, because exception for some reason sometimes crash entire VisualStudio try { if (!context.Document.SupportsSemanticModel) { return; } var syntaxRoot = await context.Document.GetSyntaxRootAsync(); var semanticModel = await context.Document.GetSemanticModelAsync(); var tokenAtCursor = Helpers.GetCurrentArgumentListSyntaxToken(syntaxRoot, context.Position); if (tokenAtCursor.Kind() == SyntaxKind.None) { return; } var mockedMethodArgumentList = tokenAtCursor.Parent as ArgumentListSyntax; var mockedMethodInvocation = mockedMethodArgumentList?.Parent as InvocationExpressionSyntax; var setupMethodLambda = mockedMethodInvocation?.Parent as LambdaExpressionSyntax; var setupMethodArgument = setupMethodLambda?.Parent as ArgumentSyntax; var setupMethodArgumentList = setupMethodArgument?.Parent as ArgumentListSyntax; var setupMethodInvocation = setupMethodArgumentList?.Parent as InvocationExpressionSyntax; if (Helpers.IsMoqSetupMethod(semanticModel, setupMethodInvocation)) { var matchingMockedMethods = Helpers.GetAllMatchingMockedMethodSymbolsFromSetupMethodInvocation(semanticModel, setupMethodInvocation); // TODO Narrow the list of matching signatures if some arguments are already provided foreach (IMethodSymbol matchingMockedMethodSymbol in matchingMockedMethods.Where(m => m.Parameters.Any())) { // We are at first argument if (tokenAtCursor.IsKind(SyntaxKind.OpenParenToken)) { // Generate It.IsAny<>() for the whole signature if we are within first argument var fullMethodHelper = string.Join(", ", matchingMockedMethodSymbol.Parameters.Select(p => "It.IsAny<" + p.Type.ToMinimalDisplayString(semanticModel, mockedMethodArgumentList.SpanStart) + ">()")); context.AddItem(CompletionItem.Create(fullMethodHelper, rules: _preselectCompletionRules)); // There are more than one argument so suggest completion for first argument only too if (matchingMockedMethodSymbol.Parameters.Length > 1) { var oneArgumentHelper = "It.IsAny<" + matchingMockedMethodSymbol.Parameters[0].Type.ToMinimalDisplayString(semanticModel, mockedMethodArgumentList.SpanStart) + ">()"; context.AddItem(CompletionItem.Create(oneArgumentHelper, rules: _standardCompletionRules)); } } // We are at second+ argument else { // Generate It.IsAny<>() for single argument var allCommaTokens = mockedMethodArgumentList.ChildTokens().Where(t => t.IsKind(SyntaxKind.CommaToken)).ToList(); int paramIdx = allCommaTokens.IndexOf(tokenAtCursor) + 1; if (matchingMockedMethodSymbol.Parameters.Length > paramIdx) { var oneArgumentHelper = "It.IsAny<" + matchingMockedMethodSymbol.Parameters[paramIdx].Type.ToMinimalDisplayString(semanticModel, mockedMethodArgumentList.SpanStart) + ">()"; context.AddItem(CompletionItem.Create(oneArgumentHelper, rules: _standardCompletionRules)); } } } } } catch (Exception) { // ignore } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { // wrap it in try catch, because exception for some reason sometimes crash entire VisualStudio try { if (!context.Document.SupportsSemanticModel) { return; } var syntaxRoot = await context.Document.GetSyntaxRootAsync(); var semanticModel = await context.Document.GetSemanticModelAsync(); var tokenAtCursor = Helpers.GetCurrentArgumentListSyntaxToken(syntaxRoot, context.Position); if (!tokenAtCursor.IsKind(SyntaxKind.OpenParenToken) && !tokenAtCursor.IsKind(SyntaxKind.CommaToken)) { return; } var argumentList = tokenAtCursor.Parent as ArgumentListSyntax; var allCommaTokens = argumentList.ChildTokens().Where(t => t.IsKind(SyntaxKind.CommaToken)).ToList(); int argumentIdx = tokenAtCursor.IsKind(SyntaxKind.CommaToken) ? allCommaTokens.IndexOf(tokenAtCursor) + 1 : 0; var constructorCall = argumentList.Parent as ObjectCreationExpressionSyntax; var matchingConstructorSymbols = Helpers.GetAllMatchingSymbols <IMethodSymbol>(semanticModel, constructorCall); if (matchingConstructorSymbols == null) { return; } var matchingSymbols = new HashSet <ISymbol>(); var symbols = semanticModel.LookupSymbols(context.Position); foreach (var symbol in symbols) { INamedTypeSymbol symbolType; if (symbol is IFieldSymbol) { var fieldSymbol = symbol as IFieldSymbol; symbolType = fieldSymbol?.Type as INamedTypeSymbol; } else if (symbol is ILocalSymbol) { var localSymbol = symbol as ILocalSymbol; symbolType = localSymbol.Type as INamedTypeSymbol; } else { continue; } if (symbolType == null || symbolType.ConstructedFrom == null) { continue; } if (symbolType.ConstructedFrom.ToString() != "Moq.Mock<T>" || symbolType.TypeArguments.Length != 1) { continue; } var typeArgument = symbolType.TypeArguments[0]; foreach (var methodSymbol in matchingConstructorSymbols.Where(m => m.Parameters.Length > argumentIdx)) { if (methodSymbol.Parameters[argumentIdx].Type.ToString() == typeArgument.ToString()) { matchingSymbols.Add(symbol); } } } foreach (var symbol in matchingSymbols) { context.AddItem(CompletionItem.Create(symbol.Name + ".Object", rules: _preselectCompletionRules)); } } catch (Exception) { // ignore } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (syntaxTree.IsInNonUserCode(position, cancellationToken)) { return; } var token = syntaxTree .FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position); if (!token.IsKind(SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, SyntaxKind.CommaToken)) { return; } var argumentList = token.Parent as BaseArgumentListSyntax; if (argumentList == null) { return; } var semanticModel = await document.GetSemanticModelForNodeAsync(argumentList, cancellationToken).ConfigureAwait(false); var parameterLists = GetParameterLists(semanticModel, position, argumentList.Parent, cancellationToken); if (parameterLists == null) { return; } var existingNamedParameters = GetExistingNamedParameters(argumentList, position); parameterLists = parameterLists.Where(pl => IsValid(pl, existingNamedParameters)); var unspecifiedParameters = parameterLists.SelectMany(pl => pl) .Where(p => !existingNamedParameters.Contains(p.Name)) .Distinct(this); if (!unspecifiedParameters.Any()) { return; } if (token.IsMandatoryNamedParameterPosition()) { context.IsExclusive = true; } var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var workspace = document.Project.Solution.Workspace; foreach (var parameter in unspecifiedParameters) { // Note: the filter text does not include the ':'. We want to ensure that if // the user types the name exactly (up to the colon) that it is selected as an // exact match. var escapedName = parameter.Name.ToIdentifierToken().ToString(); context.AddItem(SymbolCompletionItem.Create( displayText: escapedName + ColonString, insertionText: null, span: context.DefaultItemSpan, symbol: parameter, descriptionPosition: token.SpanStart, filterText: escapedName, rules: CompletionItemRules.Default)); } }
public override async Task ProvideCompletionsAsync(CompletionContext completionContext) { try { 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); if (context.IsInNonUserCode) { return; } var nameInfo = await NameDeclarationInfo.GetDeclarationInfoAsync(document, position, cancellationToken).ConfigureAwait(false); using var _ = ArrayBuilder <(string name, SymbolKind kind)> .GetInstance(out var result); // Suggest names from existing overloads. if (nameInfo.PossibleSymbolKinds.Any(k => k.SymbolKind == SymbolKind.Parameter)) { var(_, partialSemanticModel) = await document.GetPartialSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (partialSemanticModel is not null) { AddNamesFromExistingOverloads(context, partialSemanticModel, result, cancellationToken); } } var baseNames = GetBaseNames(semanticModel, nameInfo); if (baseNames != default) { await GetRecommendedNamesAsync(baseNames, nameInfo, context, document, result, cancellationToken).ConfigureAwait(false); } var recommendedNames = result.ToImmutable(); if (recommendedNames.IsEmpty) { return; } var sortValue = 0; foreach (var(name, kind) in recommendedNames) { // We've produced items in the desired order, add a sort text to each item to prevent alphabetization completionContext.AddItem(CreateCompletionItem(name, GetGlyph(kind, nameInfo.DeclaredAccessibility), sortValue.ToString("D8"))); sortValue++; } completionContext.SuggestionModeItem = CommonCompletionItem.Create( CSharpFeaturesResources.Name, displayTextSuffix: "", CompletionItemRules.Default); } catch (Exception e) when(FatalError.ReportAndCatchUnlessCanceled(e, ErrorSeverity.General)) { // nop } }
void AddDelegateHandlers(CompletionContext context, SyntaxNode parent, SemanticModel semanticModel, ITypeSymbol delegateType, int position, string optDelegateName, CancellationToken cancellationToken) { var delegateMethod = delegateType.GetDelegateInvokeMethod(); string thisLineIndent; string oneIndent; var editor = IdeApp.Workbench?.ActiveDocument?.Editor; if (editor != null) { thisLineIndent = editor.IndentationTracker.GetIndentationString(editor.OffsetToLineNumber(position)); oneIndent = editor.Options.TabsToSpaces ? new string (' ', editor.Options.TabSize) : "\t"; } else { thisLineIndent = oneIndent = "\t"; } string EolMarker = "\n"; bool addSemicolon = true; bool addDefault = true; string delegateEndString = EolMarker + thisLineIndent + "}" + (addSemicolon ? ";" : ""); CompletionItem item; if (addDefault) { item = CreateCompletionItem( "delegate", "Creates anonymous delegate.", "delegate {" + EolMarker + thisLineIndent + oneIndent, delegateEndString ); if (!context.Items.Any(i => i.DisplayText == item.DisplayText)) { context.AddItem(item); } //if (LanguageVersion.Major >= 5) item = CreateCompletionItem( "async delegate", "Creates anonymous async delegate.", "async delegate {" + EolMarker + thisLineIndent + oneIndent, delegateEndString ); if (!context.Items.Any(i => i.DisplayText == item.DisplayText)) { context.AddItem(item); } } var sb = new StringBuilder("("); var sbWithoutTypes = new StringBuilder("("); for (int k = 0; k < delegateMethod.Parameters.Length; k++) { if (k > 0) { sb.Append(", "); sbWithoutTypes.Append(", "); } sb.Append(CSharpAmbience.SafeMinimalDisplayString(delegateMethod.Parameters [k], semanticModel, position, overrideNameFormat)); sbWithoutTypes.Append(delegateMethod.Parameters [k].Name); } sb.Append(")"); sbWithoutTypes.Append(")"); var signature = sb.ToString() .Replace(", params ", ", ") .Replace("(params ", "("); if (context.Items.All(data => data.DisplayText != signature)) { item = CreateCompletionItem( signature + " =>", "Creates typed lambda expression.", signature + " => ", (addSemicolon ? ";" : "") ); //item.CompletionCategory = category; if (!context.Items.Any(i => i.DisplayText == item.DisplayText)) { context.AddItem(item); } // if (LanguageVersion.Major >= 5) { item = CreateCompletionItem( "async " + signature + " =>", "Creates typed async lambda expression.", "async " + signature + " => ", (addSemicolon ? ";" : "") ); //item.CompletionCategory = category; if (!context.Items.Any(i => i.DisplayText == item.DisplayText)) { context.AddItem(item); } var signatureWithoutTypes = sbWithoutTypes.ToString(); if (!delegateMethod.Parameters.Any(p => p.RefKind != RefKind.None) && context.Items.All(data => data.DisplayText != signatureWithoutTypes)) { item = CreateCompletionItem( signatureWithoutTypes + " =>", "Creates typed lambda expression.", signatureWithoutTypes + " => ", (addSemicolon ? ";" : "") ); //item.CompletionCategory = category; if (!context.Items.Any(i => i.DisplayText == item.DisplayText)) { context.AddItem(item); context.SuggestionModeItem = item; } //if (LanguageVersion.Major >= 5) { item = CreateCompletionItem( "async " + signatureWithoutTypes + " =>", "Creates typed async lambda expression.", "async " + signatureWithoutTypes + " => ", (addSemicolon ? ";" : "") ); //item.CompletionCategory = category; if (!context.Items.Any(i => i.DisplayText == item.DisplayText)) { context.AddItem(item); } //} } } item = CreateNewMethodCreationItem(parent, semanticModel, delegateType, position, optDelegateName, delegateMethod, cancellationToken); // item.CompletionCategory = category; if (!context.Items.Any(i => i.DisplayText == item.DisplayText)) { context.AddItem(item); context.SuggestionModeItem = item; } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (syntaxTree.IsInNonUserCode(position, cancellationToken)) { return; } var token = syntaxTree .FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position); if (!token.IsKind(SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, SyntaxKind.CommaToken)) { return; } var argumentList = token.Parent as BaseArgumentListSyntax; if (argumentList == null) { return; } var semanticModel = await document.GetSemanticModelForNodeAsync(argumentList, cancellationToken).ConfigureAwait(false); var parameterLists = GetParameterLists(semanticModel, position, argumentList.Parent, cancellationToken); if (parameterLists == null) { return; } var existingNamedParameters = GetExistingNamedParameters(argumentList, position); parameterLists = parameterLists.Where(pl => IsValid(pl, existingNamedParameters)); var unspecifiedParameters = parameterLists.SelectMany(pl => pl) .Where(p => !existingNamedParameters.Contains(p.Name)) .Distinct(this); if (!unspecifiedParameters.Any()) { return; } // Consider refining this logic to mandate completion with an argument name, if preceded by an out-of-position name // See https://github.com/dotnet/roslyn/issues/20657 var languageVersion = ((CSharpParseOptions)document.Project.ParseOptions).LanguageVersion; if (languageVersion < LanguageVersion.CSharp7_2 && token.IsMandatoryNamedParameterPosition()) { context.IsExclusive = true; } var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var workspace = document.Project.Solution.Workspace; foreach (var parameter in unspecifiedParameters) { // Note: the filter text does not include the ':'. We want to ensure that if // the user types the name exactly (up to the colon) that it is selected as an // exact match. var escapedName = parameter.Name.ToIdentifierToken().ToString(); context.AddItem(SymbolCompletionItem.CreateWithSymbolId( displayText: escapedName + ColonString, symbols: ImmutableArray.Create(parameter), rules: s_rules.WithMatchPriority(SymbolMatchPriority.PreferNamedArgument), contextPosition: token.SpanStart, filterText: escapedName)); } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { if (!context.Options.GetOption(RegularExpressionsOptions.ProvideRegexCompletions, context.Document.Project.Language)) { return; } if (context.Trigger.Kind != CompletionTriggerKind.Invoke && context.Trigger.Kind != CompletionTriggerKind.InvokeAndCommitIfUnique && context.Trigger.Kind != CompletionTriggerKind.Insertion) { return; } var position = context.Position; var(tree, stringToken) = await _language.TryGetTreeAndTokenAtPositionAsync( context.Document, position, context.CancellationToken).ConfigureAwait(false); if (tree == null || position <= stringToken.SpanStart || position >= stringToken.Span.End) { return; } var embeddedContext = new EmbeddedCompletionContext(_language, context, tree, stringToken); ProvideCompletions(embeddedContext); if (embeddedContext.Items.Count == 0) { return; } foreach (var embeddedItem in embeddedContext.Items) { var change = embeddedItem.Change; var textChange = change.TextChange; var properties = ImmutableDictionary.CreateBuilder <string, string>(); properties.Add(StartKey, textChange.Span.Start.ToString()); properties.Add(LengthKey, textChange.Span.Length.ToString()); properties.Add(NewTextKey, textChange.NewText); properties.Add(DescriptionKey, embeddedItem.FullDescription); properties.Add(EmbeddedLanguageCompletionProvider.EmbeddedProviderName, Name); if (change.NewPosition != null) { properties.Add(NewPositionKey, change.NewPosition.ToString()); } // Keep everything sorted in the order we just produced the items in. var sortText = context.Items.Count.ToString("0000"); context.AddItem(CompletionItem.Create( displayText: embeddedItem.DisplayText, inlineDescription: embeddedItem.InlineDescription, sortText: sortText, properties: properties.ToImmutable(), rules: s_rules)); } context.IsExclusive = true; }
public override async Task ProvideCompletionsAsync(CompletionContext context) { try { var document = context.Document; var position = context.Position; var options = context.Options; var cancellationToken = context.CancellationToken; var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (tree.IsInNonUserCode(position, cancellationToken)) { return; } var token = tree.FindTokenOnLeftOfPosition(position, cancellationToken); if (token.IsMandatoryNamedParameterPosition()) { return; } var typeInferenceService = document.GetLanguageService <ITypeInferenceService>(); Contract.ThrowIfNull(typeInferenceService, nameof(typeInferenceService)); var span = new TextSpan(position, 0); var semanticModel = await document.GetSemanticModelForSpanAsync(span, cancellationToken).ConfigureAwait(false); var type = typeInferenceService.InferType(semanticModel, position, objectAsDefault: true, cancellationToken: cancellationToken); // If we have a Nullable<T>, unwrap it. if (type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) { type = type.GetTypeArguments().FirstOrDefault(); if (type == null) { return; } } if (type.TypeKind != TypeKind.Enum) { type = GetCompletionListType(type, semanticModel.GetEnclosingNamedType(position, cancellationToken), semanticModel.Compilation); if (type == null) { return; } } if (!type.IsEditorBrowsable(options.GetOption(CompletionOptions.HideAdvancedMembers, semanticModel.Language), semanticModel.Compilation)) { return; } // Does type have any aliases? ISymbol alias = await type.FindApplicableAlias(position, semanticModel, cancellationToken).ConfigureAwait(false); var displayService = document.GetLanguageService <ISymbolDisplayService>(); var displayText = alias != null ? alias.Name : displayService.ToMinimalDisplayString(semanticModel, position, type); var workspace = document.Project.Solution.Workspace; var text = await semanticModel.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); var item = SymbolCompletionItem.Create( displayText: displayText, insertionText: null, span: context.DefaultItemSpan, symbol: alias ?? type, descriptionPosition: position, preselect: true, rules: s_rules); context.AddItem(item); } catch (Exception e) when(FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
public sealed override async Task ProvideCompletionsAsync(CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var syntaxFacts = document.GetRequiredLanguageService <ISyntaxFactsService>(); var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (syntaxFacts.IsInNonUserCode(syntaxTree, position, cancellationToken)) { return; } var syntaxContext = await context.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false); var isAwaitKeywordContext = IsAwaitKeywordContext(syntaxContext); var dotAwaitContext = GetDotAwaitKeywordContext(syntaxContext, cancellationToken); if (!isAwaitKeywordContext && dotAwaitContext == DotAwaitContext.None) { return; } var token = syntaxContext.TargetToken; var declaration = GetAsyncSupportingDeclaration(token); var properties = ImmutableDictionary <string, string> .Empty .Add(AwaitCompletionTargetTokenPosition, token.SpanStart.ToString()); var makeContainerAsync = declaration is not null && !SyntaxGenerator.GetGenerator(document).GetModifiers(declaration).IsAsync; if (makeContainerAsync) { properties = properties.Add(MakeContainerAsync, string.Empty); } if (isAwaitKeywordContext) { properties = properties.Add(AddAwaitAtCurrentPosition, string.Empty); context.AddItem(CreateCompletionItem( properties, _awaitKeyword, _awaitKeyword, FeaturesResources.Asynchronously_waits_for_the_task_to_finish, isComplexTextEdit: makeContainerAsync)); } else { Contract.ThrowIfTrue(dotAwaitContext == DotAwaitContext.None); // add the `await` option that will remove the dot and add `await` to the start of the expression. context.AddItem(CreateCompletionItem( properties, _awaitKeyword, _awaitKeyword, FeaturesResources.Await_the_preceding_expression, isComplexTextEdit: true)); if (dotAwaitContext == DotAwaitContext.AwaitAndConfigureAwait) { // add the `awaitf` option to do the same, but also add .ConfigureAwait(false); properties = properties.Add(AppendConfigureAwait, string.Empty); context.AddItem(CreateCompletionItem( properties, _awaitfDisplayText, _awaitfFilterText, string.Format(FeaturesResources.Await_the_preceding_expression_and_add_ConfigureAwait_0, _falseKeyword), isComplexTextEdit: true)); } } return;
public override async Task ProvideCompletionsAsync(CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var semanticModel = await document .ReuseExistingSpeculativeModelAsync(position, cancellationToken) .ConfigureAwait(false); if ( !( GetInitializedType(document, semanticModel, position, cancellationToken) is var(type, initializerLocation) ) ) { return; } if (type is ITypeParameterSymbol typeParameterSymbol) { type = typeParameterSymbol.GetNamedTypeSymbolConstraint(); } if (!(type is INamedTypeSymbol initializedType)) { return; } if (await IsExclusiveAsync(document, position, cancellationToken).ConfigureAwait(false)) { context.IsExclusive = true; } var enclosing = semanticModel.GetEnclosingNamedType(position, cancellationToken); // Find the members that can be initialized. If we have a NamedTypeSymbol, also get the overridden members. IEnumerable <ISymbol> members = semanticModel.LookupSymbols(position, initializedType); members = members.Where( m => IsInitializable(m, enclosing) && m.CanBeReferencedByName && IsLegalFieldOrProperty(m) && !m.IsImplicitlyDeclared ); // Filter out those members that have already been typed var alreadyTypedMembers = GetInitializedMembers( semanticModel.SyntaxTree, position, cancellationToken ); var uninitializedMembers = members.Where(m => !alreadyTypedMembers.Contains(m.Name)); uninitializedMembers = uninitializedMembers.Where( m => m.IsEditorBrowsable( document.ShouldHideAdvancedMembers(), semanticModel.Compilation ) ); foreach (var uninitializedMember in uninitializedMembers) { context.AddItem( SymbolCompletionItem.CreateWithSymbolId( displayText: EscapeIdentifier(uninitializedMember), displayTextSuffix: "", insertionText: null, symbols: ImmutableArray.Create(uninitializedMember), contextPosition: initializerLocation.SourceSpan.Start, rules: s_rules ) ); } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { // wrap it in try catch, because exception for some reason sometimes crash entire VisualStudio try { if (!context.Document.SupportsSemanticModel) { return; } var syntaxRoot = await context.Document.GetSyntaxRootAsync(); var semanticModel = await context.Document.GetSemanticModelAsync(); var tokenAtCursor = Helpers.GetCurrentTypeArgumentList(syntaxRoot, context.Position); if (!tokenAtCursor.IsKind(SyntaxKind.GreaterThanToken)) { return; } var typeArgumentList = tokenAtCursor.Parent as TypeArgumentListSyntax; // We are aiming Mock<T>, so can do shortcut exit here for mismatches if (typeArgumentList.Arguments.Count != 1) { return; } var genericName = typeArgumentList?.Parent as GenericNameSyntax; // TODO: Yuk! Sometimes additional parent appears. var memberSyntax = genericName?.Parent as IncompleteMemberSyntax ?? genericName?.Parent?.Parent as IncompleteMemberSyntax; var classDeclaration = memberSyntax?.Parent as ClassDeclarationSyntax; // Ignore if not a field/method declaration if (classDeclaration == null) { return; } var typeInfo = semanticModel.GetTypeInfo(genericName); var type = typeInfo.Type as INamedTypeSymbol; if (type == null || type.ConstructedFrom == null) { return; } if (type.ConstructedFrom.ToString() != "Moq.Mock<T>") { return; } var mockedType = typeArgumentList.Arguments[0]; var mockedTypeInfo = semanticModel.GetTypeInfo(mockedType); if (mockedTypeInfo.Type == null) { return; } var mockedTypeName = mockedTypeInfo.Type.Name; if (mockedTypeName.Length > 1 && mockedTypeName[0] == 'I' && Char.IsUpper(mockedTypeName[1])) // ISomething { mockedTypeName = mockedTypeName.Substring(1); } context.AddItem(CompletionItem.Create(mockedTypeName.Substring(0, 1).ToLower() + mockedTypeName.Substring(1) + "Mock", rules: _preselectCompletionRules)); } catch (Exception) { // ignore } }
private static async Task HandleSingleTypeAsync(CompletionContext context, SemanticModel semanticModel, SyntaxToken token, ITypeSymbol type, CancellationToken cancellationToken) { // If we have a Nullable<T>, unwrap it. if (type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) { var typeArg = type.GetTypeArguments().FirstOrDefault(); if (typeArg == null) return; type = typeArg; } var position = context.Position; if (type.TypeKind != TypeKind.Enum) { var enumType = TryGetEnumTypeInEnumInitializer(semanticModel, token, type, cancellationToken) ?? TryGetCompletionListType(type, semanticModel.GetEnclosingNamedType(position, cancellationToken), semanticModel.Compilation); if (enumType == null) return; type = enumType; } var options = context.Options; var hideAdvancedMembers = options.GetOption(CompletionOptions.HideAdvancedMembers, semanticModel.Language); if (!type.IsEditorBrowsable(hideAdvancedMembers, semanticModel.Compilation)) return; // Does type have any aliases? var alias = await type.FindApplicableAliasAsync(position, semanticModel, cancellationToken).ConfigureAwait(false); var displayText = alias != null ? alias.Name : type.ToMinimalDisplayString(semanticModel, position); // Add the enum itself. var symbol = alias ?? type; var sortText = symbol.Name; context.AddItem(SymbolCompletionItem.CreateWithSymbolId( displayText, displayTextSuffix: "", symbols: ImmutableArray.Create(symbol), rules: s_enumTypeRules, contextPosition: position, sortText: sortText)); // And now all the accessible members of the enum. if (type.TypeKind == TypeKind.Enum) { // We'll want to build a list of the actual enum members and all accessible instances of that enum, too var index = 0; var fields = type.GetMembers().OfType<IFieldSymbol>().Where(f => f.IsConst).Where(f => f.HasConstantValue); foreach (var field in fields.OrderBy(f => IntegerUtilities.ToInt64(f.ConstantValue))) { index++; if (!field.IsEditorBrowsable(hideAdvancedMembers, semanticModel.Compilation)) continue; var memberDisplayName = $"{displayText}.{field.Name}"; context.AddItem(SymbolCompletionItem.CreateWithSymbolId( displayText: memberDisplayName, displayTextSuffix: "", symbols: ImmutableArray.Create<ISymbol>(field), rules: CompletionItemRules.Default, contextPosition: position, sortText: $"{sortText}_{index:0000}", filterText: memberDisplayName)); } } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var cancellationToken = context.CancellationToken; var syntaxRoot = await context.Document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var node = syntaxRoot.FindNode(context.CompletionListSpan); var semanticModel = await context.Document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); // Check that we're inside a string literal which is a method argument if (!(node is ArgumentSyntax argNode) || !(argNode.Expression is LiteralExpressionSyntax literalNode) || !(argNode.Parent.Parent is InvocationExpressionSyntax invNode)) { return; } // Check that is is a method call if (!(semanticModel.GetSymbolInfo(invNode, cancellationToken).Symbol is IMethodSymbol methodSymbol)) { return; } // Check that it is a Dapper extension method call var sqlMapperSymbol = semanticModel.Compilation.GetTypeByMetadataName("Dapper.SqlMapper"); if (sqlMapperSymbol == null || !methodSymbol.ContainingType.Equals(sqlMapperSymbol) || methodSymbol.Name != "Query" || !methodSymbol.IsGenericMethod) { return; } // We don't want to show any other IntelliSense items except ours context.IsExclusive = true; // Get the string literal's value, considering the current position string text = literalNode.Token.ValueText; text = text.Substring(0, context.Position - literalNode.Token.SpanStart - 1); if (String.IsNullOrEmpty(text)) { context.AddItem(CompletionItem.Create("SELECT", tags: ImmutableArray.Create(WellKnownTags.Keyword))); } else { var parseResult = Parser.Parse(text); if (parseResult.Script.Batches.Count == 0 || parseResult.Script.Batches[0].Statements.Count == 0) { return; } var statement = parseResult.Script.Batches[0].Statements[0]; if (!(statement is SqlSelectStatement selectStatement)) { return; } if (!(selectStatement.SelectSpecification?.QueryExpression is SqlQuerySpecification query)) { return; } if (query.SelectClause.SelectExpressions.All(e => String.IsNullOrWhiteSpace(e.Sql))) { context.AddItem(CompletionItem.Create("TOP", tags: ImmutableArray.Create(WellKnownTags.Keyword))); context.AddItem(CompletionItem.Create("*", tags: ImmutableArray.Create(WellKnownTags.Keyword))); bool singleTable = methodSymbol.TypeArguments.Length == 1; foreach (var typePar in methodSymbol.TypeArguments) { foreach (var property in typePar.GetMembers() .OfType <IPropertySymbol>() .Where(p => p.DeclaredAccessibility.HasFlag(Accessibility.Public) && p.GetMethod != null)) { string propText = singleTable ? property.Name : $"{typePar.Name}.{property.Name}"; context.AddItem(CompletionItem.Create(propText, tags: ImmutableArray.Create(WellKnownTags.Property))); } } } } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { try { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var syntaxFacts = document.GetRequiredLanguageService <ISyntaxFactsService>(); var semanticFacts = document.GetRequiredLanguageService <ISemanticFactsService>(); if (syntaxFacts.IsInNonUserCode(syntaxTree, position, cancellationToken) || syntaxFacts.IsPreProcessorDirectiveContext(syntaxTree, position, cancellationToken)) { return; } var targetToken = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position); if (!syntaxTree.IsRightOfDotOrArrowOrColonColon(position, targetToken, cancellationToken)) { return; } var node = targetToken.Parent; if (!node.IsKind(SyntaxKind.ExplicitInterfaceSpecifier, out ExplicitInterfaceSpecifierSyntax? specifierNode)) { return; } // Bind the interface name which is to the left of the dot var name = specifierNode.Name; var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); var symbol = semanticModel.GetSymbolInfo(name, cancellationToken).Symbol as ITypeSymbol; if (symbol?.TypeKind != TypeKind.Interface) { return; } // We're going to create a entry for each one, including the signature var namePosition = name.SpanStart; foreach (var member in symbol.GetMembers()) { if (!member.IsAbstract && !member.IsVirtual) { continue; } if (member.IsAccessor() || member.Kind == SymbolKind.NamedType || !semanticModel.IsAccessible(node.SpanStart, member)) { continue; } var memberString = member.ToMinimalDisplayString(semanticModel, namePosition, s_signatureDisplayFormat); // Split the member string into two parts (generally the name, and the signature portion). We want // the split so that other features (like spell-checking), only look at the name portion. var(displayText, displayTextSuffix) = SplitMemberName(memberString); context.AddItem(SymbolCompletionItem.CreateWithSymbolId( displayText, displayTextSuffix, insertionText: memberString, symbols: ImmutableArray.Create <ISymbol>(member), contextPosition: position, rules: CompletionItemRules.Default)); } } catch (Exception e) when(FatalError.ReportWithoutCrashUnlessCanceled(e)) { // nop } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var document = context.Document; var position = context.Position; var options = context.Options; var cancellationToken = context.CancellationToken; var span = new TextSpan(position, length: 0); var semanticModel = await document.GetSemanticModelForSpanAsync(span, cancellationToken).ConfigureAwait(false); var syntaxTree = semanticModel.SyntaxTree; var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>(); var semanticFacts = document.GetLanguageService <ISemanticFactsService>(); if (syntaxFacts.IsInNonUserCode(syntaxTree, position, cancellationToken) || semanticFacts.IsPreProcessorDirectiveContext(semanticModel, position, cancellationToken)) { return; } if (!syntaxTree.IsRightOfDotOrArrowOrColonColon(position, cancellationToken)) { return; } var node = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position) .Parent; if (node.Kind() != SyntaxKind.ExplicitInterfaceSpecifier) { return; } // Bind the interface name which is to the left of the dot var name = ((ExplicitInterfaceSpecifierSyntax)node).Name; var symbol = semanticModel.GetSymbolInfo(name, cancellationToken).Symbol as ITypeSymbol; if (symbol?.TypeKind != TypeKind.Interface) { return; } var members = semanticModel.LookupSymbols( position: name.SpanStart, container: symbol) .Where(s => !s.IsStatic) .FilterToVisibleAndBrowsableSymbols(options.GetOption(CompletionOptions.HideAdvancedMembers, semanticModel.Language), semanticModel.Compilation); // We're going to create a entry for each one, including the signature var namePosition = name.SpanStart; var text = await syntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); foreach (var member in members) { var displayText = member.ToMinimalDisplayString(semanticModel, namePosition, s_signatureDisplayFormat); var insertionText = displayText; context.AddItem(SymbolCompletionItem.Create( displayText, insertionText: insertionText, span: context.DefaultItemSpan, symbol: member, contextPosition: position, descriptionPosition: position, rules: CompletionItemRules.Default)); } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var token = TryGetOpenBraceOrCommaInPropertyPatternClause( tree, position, cancellationToken ); if (token == default || !(token.Parent.Parent is PatternSyntax)) { return; } var semanticModel = await document .ReuseExistingSpeculativeModelAsync(position, cancellationToken) .ConfigureAwait(false); var pattern = (PatternSyntax)token.Parent.Parent; var type = semanticModel.GetTypeInfo(pattern, cancellationToken).ConvertedType; if (type == null) { return; } // Find the members that can be tested. IEnumerable <ISymbol> members = semanticModel.LookupSymbols(position, type); members = members.Where( m => m.CanBeReferencedByName && IsFieldOrReadableProperty(m) && !m.IsImplicitlyDeclared && !m.IsStatic ); // Filter out those members that have already been typed var propertyPatternClause = (PropertyPatternClauseSyntax)token.Parent; // List the members that are already tested in this property sub-pattern var alreadyTestedMembers = new HashSet <string>( propertyPatternClause.Subpatterns .Select(p => p.NameColon?.Name.Identifier.ValueText) .Where(s => !string.IsNullOrEmpty(s)) ); var untestedMembers = members.Where( m => !alreadyTestedMembers.Contains(m.Name) && m.IsEditorBrowsable( document.ShouldHideAdvancedMembers(), semanticModel.Compilation ) ); foreach (var untestedMember in untestedMembers) { const string ColonString = ":"; context.AddItem( SymbolCompletionItem.CreateWithSymbolId( displayText: untestedMember.Name.EscapeIdentifier(), displayTextSuffix: ColonString, insertionText: null, symbols: ImmutableArray.Create(untestedMember), contextPosition: token.GetLocation().SourceSpan.Start, rules: s_rules ) ); } }
public override async Task ProvideCompletionsAsync(CompletionContext completionContext) { if (!completionContext.Document.SupportsSemanticModel) { return; } var position = completionContext.Position; var document = completionContext.Document; var cancellationToken = completionContext.CancellationToken; var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var span = completionContext.CompletionListSpan; var token = root.FindToken(span.Start); var node = token.Parent?.AncestorsAndSelf().FirstOrDefault(a => a.FullSpan.Contains(span)); if (node is LiteralExpressionSyntax literal && node?.Parent is AttributeArgumentSyntax argument && // TODO: we support only property syntax for completion in attributes, // since that's what XA has right now anyway, and we need to lookup the // [Category] attribute on the property. argument.NameEquals != null && node?.Parent?.Parent?.Parent is AttributeSyntax attribute) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken); var projectPath = string.IsNullOrEmpty(document.Project.FilePath) ? null : Path.GetDirectoryName(document.Project.FilePath); // From the attribute syntax, we'll get the constructor for the attribute var symbol = (semanticModel.GetSymbolInfo(attribute, cancellationToken).Symbol as IMethodSymbol)?.ContainingType; if (symbol?.ContainingNamespace.ToDisplayString() == "Android.App") { var name = argument.NameEquals.Name.ToString(); // First try explicit completion hint via Category var propertyInfo = symbol.GetMembers(name).FirstOrDefault() as IPropertySymbol; if (propertyInfo == null) { return; } string[] categories; var categoryAttr = propertyInfo.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.ToDisplayString() == typeof(CategoryAttribute).FullName); if (categoryAttr == null) { // Apply default heuristics based on member name // Label/Description: @string // Icon/RoundIcon: @drawable; @mipmap // Theme: @style if (name == "Label" || name == "Description") { categories = new[] { "string" } } ; else if (name == "Icon" || name == "RoundIcon") { categories = new[] { "drawable", "mipmap" } } ; else if (name == "Theme") { categories = new[] { "style" } } ; else { return; } } else if (!categoryAttr.ConstructorArguments.IsDefaultOrEmpty) { categories = ((string)categoryAttr.ConstructorArguments[0].Value) .Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) .Select(s => s.Trim().TrimStart('@')) .ToArray(); } else { return; } var compilation = await document.Project.GetCompilationAsync(completionContext.CancellationToken); var resourceDesignerAttribute = compilation.Assembly.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) == "global::Android.Runtime.ResourceDesignerAttribute"); if (resourceDesignerAttribute != null && resourceDesignerAttribute.ConstructorArguments.Any()) { var resourceDesigner = compilation.GetTypeByMetadataName((string)resourceDesignerAttribute.ConstructorArguments.First().Value); if (resourceDesigner != null) { foreach (var category in categories) { var resourceSymbol = resourceDesigner.GetTypeMembers().FirstOrDefault(x => x.Name.Equals(category, StringComparison.OrdinalIgnoreCase)); if (resourceSymbol != null) { foreach (var member in resourceSymbol.GetMembers().Where(x => x.Kind == SymbolKind.Field)) { completionContext.AddItem(CompletionItem.Create( displayText: member.Name, displayTextPrefix: $"@{category}/", sortText: $"@{category}/{member.Name}", properties: ImmutableDictionary.Create <string, string>() .Add("Summary", member.GetDocumentationCommentXml()) // Add the starting quote char to start position .Add("Start", (node.Span.Start + 1).ToString()) // Remove the two quote characters .Add("Length", (node.Span.Length - 2).ToString()), tags: ImmutableArray.Create(WellKnownTags.Constant, "Xamarin"), rules: CompletionItemRules.Default)); } } } } } } } await Task.CompletedTask; }
public override async Task ProvideCompletionsAsync(CompletionContext context) { try { var document = context.Document; var position = context.Position; var options = context.Options; var cancellationToken = context.CancellationToken; var span = new TextSpan(position, length: 0); var semanticModel = await document.GetSemanticModelForSpanAsync(span, cancellationToken).ConfigureAwait(false); var syntaxTree = semanticModel.SyntaxTree; var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>(); var semanticFacts = document.GetLanguageService <ISemanticFactsService>(); if (syntaxFacts.IsInNonUserCode(syntaxTree, position, cancellationToken) || semanticFacts.IsPreProcessorDirectiveContext(semanticModel, position, cancellationToken)) { return; } var targetToken = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position); if (!syntaxTree.IsRightOfDotOrArrowOrColonColon(position, targetToken, cancellationToken)) { return; } var node = targetToken.Parent; if (node.Kind() != SyntaxKind.ExplicitInterfaceSpecifier) { return; } // Bind the interface name which is to the left of the dot var name = ((ExplicitInterfaceSpecifierSyntax)node).Name; var symbol = semanticModel.GetSymbolInfo(name, cancellationToken).Symbol as ITypeSymbol; if (symbol?.TypeKind != TypeKind.Interface) { return; } var members = symbol.GetMembers(); // We're going to create a entry for each one, including the signature var namePosition = name.SpanStart; var text = await syntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); foreach (var member in members) { if (member.IsAccessor() || member.Kind == SymbolKind.NamedType || !(member.IsAbstract || member.IsVirtual) || !semanticModel.IsAccessible(node.SpanStart, member)) { continue; } var displayText = member.ToMinimalDisplayString( semanticModel, namePosition, s_signatureDisplayFormat); var insertionText = displayText; var item = SymbolCompletionItem.CreateWithSymbolId( displayText, displayTextSuffix: "", insertionText: insertionText, symbols: ImmutableArray.Create(member), contextPosition: position, rules: CompletionItemRules.Default); item = item.AddProperty(InsertionTextOnOpenParen, member.Name); context.AddItem(item); } } catch (Exception e) when(FatalError.ReportWithoutCrashUnlessCanceled(e)) { // nop } }
public override async Task ProvideCompletionsAsync(CompletionContext completionContext) { try { var position = completionContext.Position; var document = completionContext.Document; var cancellationToken = completionContext.CancellationToken; if (!completionContext.CompletionOptions.ShowNameSuggestions) { return; } var context = (CSharpSyntaxContext)await completionContext.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false); if (context.IsInNonUserCode) { return; } // 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) && context.SemanticModel.GetSymbolInfo(context.TargetToken).GetAnySymbol() is null) { return; } var nameInfo = await NameDeclarationInfo.GetDeclarationInfoAsync(document, position, cancellationToken).ConfigureAwait(false); using var _ = ArrayBuilder <(string name, SymbolKind kind)> .GetInstance(out var result); // Suggest names from existing overloads. if (nameInfo.PossibleSymbolKinds.Any(k => k.SymbolKind == SymbolKind.Parameter)) { var(_, partialSemanticModel) = await document.GetPartialSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (partialSemanticModel is not null) { AddNamesFromExistingOverloads(context, partialSemanticModel, result, cancellationToken); } } var baseNames = GetBaseNames(context.SemanticModel, nameInfo); if (baseNames != default) { var namingStyleOptions = await document.GetNamingStylePreferencesAsync(completionContext.CompletionOptions.NamingStyleFallbackOptions, cancellationToken).ConfigureAwait(false); GetRecommendedNames(baseNames, nameInfo, context, result, namingStyleOptions, cancellationToken); } var recommendedNames = result.ToImmutable(); if (recommendedNames.IsEmpty) { return; } var sortValue = 0; foreach (var(name, kind) in recommendedNames) { // We've produced items in the desired order, add a sort text to each item to prevent alphabetization completionContext.AddItem(CreateCompletionItem(name, GetGlyph(kind, nameInfo.DeclaredAccessibility), sortValue.ToString("D8"))); sortValue++; } completionContext.SuggestionModeItem = CommonCompletionItem.Create( CSharpFeaturesResources.Name, displayTextSuffix: "", CompletionItemRules.Default); } catch (Exception e) when(FatalError.ReportAndCatchUnlessCanceled(e, ErrorSeverity.General)) { // nop } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken); if (syntaxRoot == null) { return; } var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken); var node = syntaxRoot.FindNode(context.CompletionListSpan); var argumentSyntaxNode = node.AncestorsAndSelf().OfType <ArgumentSyntax>().FirstOrDefault(); if (argumentSyntaxNode == null) { return; } var lambdaExpression = argumentSyntaxNode.Ancestors().OfType <LambdaExpressionSyntax>().FirstOrDefault(); if (lambdaExpression == null) { return; } var mockMethod = lambdaExpression.Ancestors().FirstOrDefault(x => semanticModel.GetSymbolInfo(x, context.CancellationToken).CandidateSymbols.Any(s => s.ContainingType.Name == "Mock" && s.ContainingAssembly.Name == "Moq")); if (mockMethod == null) { return; } var typingMethod = argumentSyntaxNode.Ancestors().OfType <InvocationExpressionSyntax>().First(); var calingMethod = semanticModel.GetSymbolInfo(typingMethod, context.CancellationToken); if (!(calingMethod.CandidateSymbols[0] is IMethodSymbol callingMethodSymbol)) { return; } var index = argumentSyntaxNode.Parent.ChildNodes().ToList().FindIndex(x => x.Equals(argumentSyntaxNode)); if (index < callingMethodSymbol.Parameters.Length) { context.AddItem(CompletionItem.Create(GetCompletionDisplayText(callingMethodSymbol.Parameters[index].Type), null, null, ImmutableDictionary.Create <string, string>(), ImmutableArray.Create(WellKnownTags.Method), CompletionItemRules.Create(formatOnCommit: true, matchPriority: MatchPriority.Preselect))); } if (index == 0) { context.AddItem(CompletionItem.Create(String.Join(", ", callingMethodSymbol.Parameters.Select(x => GetCompletionDisplayText(x.Type))), null, null, ImmutableDictionary.Create <string, string>(), ImmutableArray.Create(WellKnownTags.Method), CompletionItemRules.Create(formatOnCommit: true))); } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var cancellationToken = context.CancellationToken; // Получаем семантическую модель (она понадобится для работы с типами и методами) var semanticModel = await context.Document .GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); // Находим синтаксическую ноду, внутри который был вызван IntelliSense var syntaxRoot = await context.Document .GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var node = syntaxRoot.FindNode(context.CompletionListSpan); // Проверяем, что мы внутри строкового литерала, который к тому же является аргументом вызова метода if (!(node is ArgumentSyntax argNode) || !(argNode.Expression is LiteralExpressionSyntax literalNode) || !(argNode.Parent.Parent is InvocationExpressionSyntax invNode)) { return; } // Получаем семантическую информацию о вызываемом методе var symbolInfo = semanticModel.GetSymbolInfo(invNode, cancellationToken); var methodSymbol = (symbolInfo.Symbol ?? symbolInfo.CandidateSymbols.FirstOrDefault()) as IMethodSymbol; if (methodSymbol == null) { return; } // Проверяем, что это действительно метод Dapper var sqlMapperSymbol = semanticModel.Compilation.GetTypeByMetadataName("Dapper.SqlMapper"); if (sqlMapperSymbol == null || !methodSymbol.ContainingType.Equals(sqlMapperSymbol) || methodSymbol.Name != "Query" || !methodSymbol.IsGenericMethod) { return; } // Даём системе понять, что мы хотим показывать только наши completion items, и никакие другие // (не использовать другие completion provider'ы, кроме текущего) context.IsExclusive = true; // Получаем строку от начала строкового литерала до курсора ввода string text = literalNode.Token.ValueText; int selectedLength = context.Position - literalNode.Token.SpanStart - 1; if (selectedLength < text.Length) { text = text.Substring(0, selectedLength); } // Собираем информацию о всех свойствах DTO-классов, используемых в запросе var properties = methodSymbol.TypeArguments.SelectMany(t => t .GetMembers() .OfType <IPropertySymbol>() .Where(p => p.DeclaredAccessibility.HasFlag(Accessibility.Public) && p.GetMethod != null)).ToArray(); // Определяем, в какой части SQL-запроса мы сейчас находимся, и что же нужно показывать пользователю if (String.IsNullOrEmpty(text)) { // Добавляем новый пункт в IntelliSense... context.AddItem(CompletionItem.Create("SELECT") // ...показывая его, как ключевое слово языка (соответствующая иконка) .AddTag(WellKnownTags.Keyword)); } else { if (text.StartsWith("SELECT ", StringComparison.OrdinalIgnoreCase) && !text.EndsWith(" FROM ", StringComparison.OrdinalIgnoreCase)) { if (text.Equals("SELECT ", StringComparison.OrdinalIgnoreCase)) { context.AddItem(CompletionItem.Create("DISTINCT", sortText: "K DISTINCT") .AddTag(WellKnownTags.Keyword)); context.AddItem(CompletionItem.Create("TOP", sortText: "K TOP") .AddTag(WellKnownTags.Keyword)); } if (!text.EndsWith(" TOP ", StringComparison.OrdinalIgnoreCase)) { context.AddItem(CompletionItem.Create("*", sortText: "K *") .AddTag(WellKnownTags.Keyword)); bool singleTable = methodSymbol.TypeArguments.Length == 1; foreach (var property in properties) { string propText = singleTable ? property.Name : $"{property.ContainingType.Name}.{property.Name}"; context.AddItem(CompletionItem.Create(propText, sortText: $"P {propText}") .AddTag(WellKnownTags.Property) // Добавляем XML-комментарий от свойства DTO-класса как метаинформацию .AddProperty("comment", property.GetDocumentationCommentXml())); } } if (text.EndsWith(" * ", StringComparison.OrdinalIgnoreCase) || properties.Any(p => text.EndsWith(p.Name + " "))) { context.AddItem(CompletionItem.Create("FROM", sortText: "K FROM") .AddTag(WellKnownTags.Keyword)); } } else if (text.EndsWith(" FROM ", StringComparison.OrdinalIgnoreCase)) { foreach (var typePar in methodSymbol.TypeArguments) { context.AddItem(CompletionItem.Create(typePar.Name) .AddTag(WellKnownTags.Class) // Добавляем XML-комментарий от DTO-класса как метаинформацию .AddProperty("comment", typePar.GetDocumentationCommentXml())); } } } }
void AddDelegateHandlers(CompletionContext context, SyntaxNode parent, SemanticModel semanticModel, ITypeSymbol delegateType, int position, string optDelegateName, CancellationToken cancellationToken) { var delegateMethod = delegateType.GetDelegateInvokeMethod(); string EolMarker = "\n"; bool addSemicolon = true; bool addDefault = true; string delegateEndString = EolMarker + thisLineIndentMarker + "}" + (addSemicolon ? ";" : ""); CompletionItem item; if (addDefault) { item = CreateCompletionItem( "delegate", "Creates anonymous delegate.", "delegate {" + EolMarker + thisLineIndentMarker + eolMarker, delegateEndString, position ); if (!context.Items.Any(i => i.DisplayText == item.DisplayText)) { context.AddItem(item); } //if (LanguageVersion.Major >= 5) item = CreateCompletionItem( "async delegate", "Creates anonymous async delegate.", "async delegate {" + EolMarker + thisLineIndentMarker + eolMarker, delegateEndString, position ); if (!context.Items.Any(i => i.DisplayText == item.DisplayText)) { context.AddItem(item); } } var sb = StringBuilderCache.Allocate("("); var sbWithoutTypes = StringBuilderCache.Allocate("("); for (int k = 0; k < delegateMethod.Parameters.Length; k++) { if (k > 0) { sb.Append(", "); sbWithoutTypes.Append(", "); } sb.Append(CSharpAmbience.SafeMinimalDisplayString(delegateMethod.Parameters [k], semanticModel, position, overrideNameFormat)); sbWithoutTypes.Append(delegateMethod.Parameters [k].Name); } sb.Append(")"); sbWithoutTypes.Append(")"); var signature = StringBuilderCache.ReturnAndFree(sb) .Replace(", params ", ", ") .Replace("(params ", "("); if (context.Items.All(data => data.DisplayText != signature)) { item = CreateCompletionItem( signature + " =>", "Creates typed lambda expression.", signature + " => ", (addSemicolon ? ";" : ""), position ); //item.CompletionCategory = category; if (!context.Items.Any(i => i.DisplayText == item.DisplayText)) { context.AddItem(item); } // if (LanguageVersion.Major >= 5) { item = CreateCompletionItem( "async " + signature + " =>", "Creates typed async lambda expression.", "async " + signature + " => ", (addSemicolon ? ";" : ""), position ); //item.CompletionCategory = category; if (!context.Items.Any(i => i.DisplayText == item.DisplayText)) { context.AddItem(item); } var signatureWithoutTypes = sbWithoutTypes.ToString(); if (!delegateMethod.Parameters.Any(p => p.RefKind != RefKind.None) && context.Items.All(data => data.DisplayText != signatureWithoutTypes)) { item = CreateCompletionItem( signatureWithoutTypes + " =>", "Creates typed lambda expression.", signatureWithoutTypes + " => ", (addSemicolon ? ";" : ""), position ); //item.CompletionCategory = category; if (!context.Items.Any(i => i.DisplayText == item.DisplayText)) { context.AddItem(item.WithRules(item.Rules.WithMatchPriority(int.MaxValue))); } //if (LanguageVersion.Major >= 5) { item = CreateCompletionItem( "async " + signatureWithoutTypes + " =>", "Creates typed async lambda expression.", "async " + signatureWithoutTypes + " => ", (addSemicolon ? ";" : ""), position ); //item.CompletionCategory = category; if (!context.Items.Any(i => i.DisplayText == item.DisplayText)) { context.AddItem(item); } //} } } StringBuilderCache.Free(sbWithoutTypes); item = CreateNewMethodCreationItem(parent, semanticModel, delegateType, position, optDelegateName, delegateMethod, cancellationToken); // item.CompletionCategory = category; if (!context.Items.Any(i => i.DisplayText == item.DisplayText)) { context.AddItem(item.WithRules(item.Rules.WithMatchPriority(int.MaxValue))); } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); if (GetInitializedType(document, semanticModel, position, cancellationToken) is not var(type, initializerLocation)) { return; } if (type is ITypeParameterSymbol typeParameterSymbol) { type = typeParameterSymbol.GetNamedTypeSymbolConstraint(); } if (type is not INamedTypeSymbol initializedType) { return; } if (await IsExclusiveAsync(document, position, cancellationToken).ConfigureAwait(false)) { context.IsExclusive = true; } var enclosing = semanticModel.GetEnclosingNamedType(position, cancellationToken); Contract.ThrowIfNull(enclosing); // Find the members that can be initialized. If we have a NamedTypeSymbol, also get the overridden members. IEnumerable <ISymbol> members = semanticModel.LookupSymbols(position, initializedType); members = members.Where(m => IsInitializable(m, enclosing) && m.CanBeReferencedByName && IsLegalFieldOrProperty(m) && !m.IsImplicitlyDeclared); // Filter out those members that have already been typed var alreadyTypedMembers = GetInitializedMembers(semanticModel.SyntaxTree, position, cancellationToken); var uninitializedMembers = members.Where(m => !alreadyTypedMembers.Contains(m.Name)); // Sort the members by name so if we preselect one, it'll be stable uninitializedMembers = uninitializedMembers.Where(m => m.IsEditorBrowsable(context.CompletionOptions.HideAdvancedMembers, semanticModel.Compilation)) .OrderBy(m => m.Name); var firstUnitializedRequiredMember = true; foreach (var uninitializedMember in uninitializedMembers) { var rules = s_rules; // We'll hard select the first required member to make it a bit easier to type out an object initializer // with a bunch of members. if (firstUnitializedRequiredMember && uninitializedMember.IsRequired()) { rules = rules.WithSelectionBehavior(CompletionItemSelectionBehavior.HardSelection).WithMatchPriority(MatchPriority.Preselect); firstUnitializedRequiredMember = false; } context.AddItem(SymbolCompletionItem.CreateWithSymbolId( displayText: EscapeIdentifier(uninitializedMember), displayTextSuffix: "", insertionText: null, symbols: ImmutableArray.Create(uninitializedMember), contextPosition: initializerLocation.SourceSpan.Start, inlineDescription: uninitializedMember.IsRequired() ? FeaturesResources.Required : null, rules: rules)); } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { try { var document = context.Document; var position = context.Position; var options = context.Options; var cancellationToken = context.CancellationToken; var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (tree.IsInNonUserCode(position, cancellationToken)) { return; } var token = tree.FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position); if (token.IsMandatoryNamedParameterPosition()) { return; } // Don't show up within member access // This previously worked because the type inferrer didn't work // in member access expressions. // The regular SymbolCompletionProvider will handle completion after . if (token.IsKind(SyntaxKind.DotToken)) { return; } var typeInferenceService = document.GetLanguageService <ITypeInferenceService>(); Contract.ThrowIfNull(typeInferenceService, nameof(typeInferenceService)); var span = new TextSpan(position, 0); var semanticModel = await document.GetSemanticModelForSpanAsync(span, cancellationToken).ConfigureAwait(false); var type = typeInferenceService.InferType(semanticModel, position, objectAsDefault: true, cancellationToken: cancellationToken); // If we have a Nullable<T>, unwrap it. if (type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) { type = type.GetTypeArguments().FirstOrDefault(); if (type == null) { return; } } if (type.TypeKind != TypeKind.Enum) { type = TryGetEnumTypeInEnumInitializer(semanticModel, token, type, cancellationToken) ?? TryGetCompletionListType(type, semanticModel.GetEnclosingNamedType(position, cancellationToken), semanticModel.Compilation); if (type == null) { return; } } if (!type.IsEditorBrowsable(options.GetOption(CompletionOptions.HideAdvancedMembers, semanticModel.Language), semanticModel.Compilation)) { return; } // Does type have any aliases? var alias = await type.FindApplicableAlias(position, semanticModel, cancellationToken).ConfigureAwait(false); var displayService = document.GetLanguageService <ISymbolDisplayService>(); var displayText = alias != null ? alias.Name : displayService.ToMinimalDisplayString(semanticModel, position, type); var workspace = document.Project.Solution.Workspace; var text = await semanticModel.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); var item = SymbolCompletionItem.CreateWithSymbolId( displayText: displayText, symbols: ImmutableArray.Create(alias ?? type), rules: s_rules.WithMatchPriority(MatchPriority.Preselect), contextPosition: position); context.AddItem(item); } catch (Exception e) when(FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { // This provider is exported for all workspaces - so limit it to just our workspace & the debugger's intellisense workspace if (context.Document.Project.Solution.Workspace.Kind != WorkspaceKind.AnyCodeRoslynWorkspace && context.Document.Project.Solution.Workspace.Kind != StringConstants.DebuggerIntellisenseWorkspaceKind) { return; } var lspClient = _roslynLspClientServiceFactory.ActiveLanguageServerClient; if (lspClient == null) { return; } var text = await context.Document.GetTextAsync(context.CancellationToken).ConfigureAwait(false); var completionParams = new LSP.CompletionParams { TextDocument = ProtocolConversions.DocumentToTextDocumentIdentifier(context.Document), Position = ProtocolConversions.LinePositionToPosition(text.Lines.GetLinePosition(context.Position)), Context = new LSP.CompletionContext { TriggerCharacter = context.Trigger.Character.ToString(), TriggerKind = GetTriggerKind(context.Trigger) } }; var completionObject = await lspClient.RequestAsync(LSP.Methods.TextDocumentCompletion.ToLSRequest(), completionParams, context.CancellationToken).ConfigureAwait(false); if (completionObject == null) { return; } var completionList = ((JToken)completionObject).ToObject <RoslynCompletionItem[]>(); foreach (var item in completionList) { ImmutableArray <string> tags; if (item.Tags != null) { tags = item.Tags.AsImmutable(); } else { var glyph = ProtocolConversions.CompletionItemKindToGlyph(item.Kind); tags = GlyphTags.GetTags(glyph); } var properties = ImmutableDictionary.CreateBuilder <string, string>(); if (!string.IsNullOrEmpty(item.Detail)) { // The display text is encoded as TaggedText | value properties.Add("Description", $"Text|{item.Detail}"); } properties.Add("InsertionText", item.InsertText); properties.Add("ResolveData", JToken.FromObject(item).ToString()); var completionItem = CompletionItem.Create(item.Label, item.FilterText, item.SortText, properties: properties.ToImmutable(), tags: tags); context.AddItem(completionItem); } }
private static async Task HandleSingleTypeAsync( CompletionContext context, SemanticModel semanticModel, SyntaxToken token, ITypeSymbol type, CancellationToken cancellationToken ) { // If we have a Nullable<T>, unwrap it. if (type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) { var typeArg = type.GetTypeArguments().FirstOrDefault(); if (typeArg == null) { return; } type = typeArg; } // When true, this completion provider shows both the type (e.g. DayOfWeek) and its qualified members (e.g. // DayOfWeek.Friday). We set this to false for enum-like cases (static members of structs and classes) so we // only show the qualified members in these cases. var showType = true; var position = context.Position; var enclosingNamedType = semanticModel.GetEnclosingNamedType( position, cancellationToken ); if (type.TypeKind != TypeKind.Enum) { var enumType = TryGetEnumTypeInEnumInitializer(semanticModel, token, type, cancellationToken) ?? TryGetCompletionListType( type, enclosingNamedType, semanticModel.Compilation ); if (enumType == null) { if ( context.Trigger.Kind == CompletionTriggerKind.Insertion && s_triggerCharacters.Contains(context.Trigger.Character) ) { // This completion provider understands static members of matching types, but doesn't // proactively trigger completion for them to avoid interfering with common typing patterns. return; } // If this isn't an enum or marked with completionlist, also check if it contains static members of // a matching type. These 'enum-like' types have similar characteristics to enum completion, but do // not show the containing type as a separate item in completion. showType = false; enumType = TryGetTypeWithStaticMembers(type); if (enumType == null) { return; } } type = enumType; } var options = context.Options; var hideAdvancedMembers = options.GetOption( CompletionOptions.HideAdvancedMembers, semanticModel.Language ); if (!type.IsEditorBrowsable(hideAdvancedMembers, semanticModel.Compilation)) { return; } // Does type have any aliases? var alias = await type.FindApplicableAliasAsync( position, semanticModel, cancellationToken ) .ConfigureAwait(false); var displayText = alias != null ? alias.Name : type.ToMinimalDisplayString(semanticModel, position); // Add the enum itself. var symbol = alias ?? type; var sortText = symbol.Name; if (showType) { context.AddItem( SymbolCompletionItem.CreateWithSymbolId( displayText, displayTextSuffix: "", symbols: ImmutableArray.Create(symbol), rules: s_enumTypeRules, contextPosition: position, sortText: sortText ) ); } // And now all the accessible members of the enum. if (type.TypeKind == TypeKind.Enum) { // We'll want to build a list of the actual enum members and all accessible instances of that enum, too var index = 0; var fields = type.GetMembers() .OfType <IFieldSymbol>() .Where(f => f.IsConst) .Where(f => f.HasConstantValue); foreach ( var field in fields.OrderBy(f => IntegerUtilities.ToInt64(f.ConstantValue)) ) { index++; if (!field.IsEditorBrowsable(hideAdvancedMembers, semanticModel.Compilation)) { continue; } var memberDisplayName = $"{displayText}.{field.Name}"; context.AddItem( SymbolCompletionItem.CreateWithSymbolId( displayText: memberDisplayName, displayTextSuffix: "", symbols: ImmutableArray.Create <ISymbol>(field), rules: CompletionItemRules.Default, contextPosition: position, sortText: $"{sortText}_{index:0000}", filterText: memberDisplayName ) ); } } else if (enclosingNamedType is not null) { // Build a list of the members with the same type as the target foreach (var member in type.GetMembers()) { ISymbol staticSymbol; ITypeSymbol symbolType; if (member is IFieldSymbol { IsStatic: true } field) { staticSymbol = field; symbolType = field.Type; } else if ( member is IPropertySymbol { IsStatic: true, IsIndexer: false } property ) { staticSymbol = property; symbolType = property.Type; }
public override async Task ProvideCompletionsAsync(CompletionContext context) { try { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var tree = await document .GetSyntaxTreeAsync(cancellationToken) .ConfigureAwait(false); if (tree.IsInNonUserCode(position, cancellationToken)) { return; } var targetToken = tree.FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position); if ( !targetToken.IsKind(SyntaxKind.AliasKeyword) && !( targetToken.IsKind(SyntaxKind.IdentifierToken) && targetToken.HasMatchingText(SyntaxKind.AliasKeyword) ) ) { return; } if ( targetToken.Parent.IsKind(SyntaxKind.ExternAliasDirective) || ( targetToken.Parent.IsKind(SyntaxKind.IdentifierName) && targetToken.Parent.IsParentKind(SyntaxKind.IncompleteMember) ) ) { var compilation = await document.Project .GetCompilationAsync(cancellationToken) .ConfigureAwait(false); var aliases = compilation.ExternalReferences .SelectMany(r => r.Properties.Aliases) .ToSet(); if (aliases.Any()) { var root = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false); var usedAliases = root.ChildNodes() .OfType <ExternAliasDirectiveSyntax>() .Where(e => !e.Identifier.IsMissing) .Select(e => e.Identifier.ValueText); aliases.RemoveRange(usedAliases); aliases.Remove(MetadataReferenceProperties.GlobalAlias); var text = await document .GetTextAsync(cancellationToken) .ConfigureAwait(false); foreach (var alias in aliases) { context.AddItem( CommonCompletionItem.Create( alias, displayTextSuffix: "", CompletionItemRules.Default, glyph: Glyph.Namespace ) ); } } } } catch (Exception e) when(FatalError.ReportAndCatchUnlessCanceled(e)) { // nop } }