private async Task <IEnumerable <CompletionItem> > GetNameEqualsItemsAsync(CompletionContext context, SemanticModel semanticModel, SyntaxToken token, AttributeSyntax attributeSyntax, ISet <string> existingNamedParameters) { var attributeNamedParameters = GetAttributeNamedParameters(semanticModel, context.Position, attributeSyntax, context.CancellationToken); var unspecifiedNamedParameters = attributeNamedParameters.Where(p => !existingNamedParameters.Contains(p.Name)); var text = await semanticModel.SyntaxTree.GetTextAsync(context.CancellationToken).ConfigureAwait(false); return(from p in attributeNamedParameters where !existingNamedParameters.Contains(p.Name) select SymbolCompletionItem.Create( displayText : p.Name.ToIdentifierToken().ToString() + SpaceEqualsString, insertionText : null, symbol : p, contextPosition : token.SpanStart, sortText : p.Name, rules : CompletionItemRules.Default)); }
private async Task <IEnumerable <CompletionItem> > GetNameColonItemsAsync( CompletionContext context, SemanticModel semanticModel, SyntaxToken token, AttributeSyntax attributeSyntax, ISet <string> existingNamedParameters) { var parameterLists = GetParameterLists(semanticModel, context.Position, attributeSyntax, context.CancellationToken); parameterLists = parameterLists.Where(pl => IsValid(pl, existingNamedParameters)); var text = await semanticModel.SyntaxTree.GetTextAsync(context.CancellationToken).ConfigureAwait(false); return(from pl in parameterLists from p in pl where !existingNamedParameters.Contains(p.Name) select SymbolCompletionItem.Create( displayText : p.Name.ToIdentifierToken().ToString() + ColonString, insertionText : null, span : context.DefaultItemSpan, symbol : p, descriptionPosition : token.SpanStart, sortText : p.Name, rules : CompletionItemRules.Default)); }
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) { 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; } }
private CompletionItem CreateItem( Workspace workspace, SemanticModel semanticModel, ISymbol symbol, SyntaxToken token, TextSpan span, StringBuilder builder) { int position = token.SpanStart; if (symbol is INamespaceOrTypeSymbol && token.IsKind(SyntaxKind.DotToken)) { // Handle qualified namespace and type names. builder.Append(symbol.ToDisplayString(QualifiedCrefFormat)); } else { // Handle unqualified namespace and type names, or member names. builder.Append(symbol.ToMinimalDisplayString(semanticModel, position, CrefFormat)); var parameters = symbol.GetParameters(); if (!parameters.IsDefaultOrEmpty) { // Note: we intentionally don't add the "params" modifier for any parameters. builder.Append(symbol.IsIndexer() ? '[' : '('); for (int i = 0; i < parameters.Length; i++) { if (i > 0) { builder.Append(", "); } var parameter = parameters[i]; if (parameter.RefKind == RefKind.Out) { builder.Append("out "); } else if (parameter.RefKind == RefKind.Ref) { builder.Append("ref "); } builder.Append(parameter.Type.ToMinimalDisplayString(semanticModel, position)); } builder.Append(symbol.IsIndexer() ? ']' : ')'); } } var symbolText = builder.ToString(); var insertionText = builder .Replace('<', '{') .Replace('>', '}') .ToString(); return(SymbolCompletionItem.Create( displayText: insertionText, insertionText: insertionText, span: span, symbol: symbol, descriptionPosition: position, sortText: symbolText, rules: GetRules(insertionText))); }
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)); } }