private async Task <CompletionItem> CreateItemAsync( Workspace workspace, SemanticModel semanticModel, int textChangeSpanPosition, ISymbol symbol, SyntaxToken token, CancellationToken cancellationToken) { int tokenPosition = token.SpanStart; string symbolText = string.Empty; if (symbol is INamespaceOrTypeSymbol && token.IsKind(SyntaxKind.DotToken)) { symbolText = symbol.Name.EscapeIdentifier(); if (symbol.GetArity() > 0) { symbolText += "{"; symbolText += string.Join(", ", ((INamedTypeSymbol)symbol).TypeParameters); symbolText += "}"; } } else { symbolText = symbol.ToMinimalDisplayString(semanticModel, tokenPosition, CrefFormat); var parameters = symbol.GetParameters().Select(p => { var displayName = p.Type.ToMinimalDisplayString(semanticModel, tokenPosition); if (p.RefKind == RefKind.Out) { return("out " + displayName); } if (p.RefKind == RefKind.Ref) { return("ref " + displayName); } return(displayName); }); var parameterList = !symbol.IsIndexer() ? string.Format("({0})", string.Join(", ", parameters)) : string.Format("[{0}]", string.Join(", ", parameters)); symbolText += parameterList; } var insertionText = symbolText .Replace('<', '{') .Replace('>', '}') .Replace("()", ""); var text = await semanticModel.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); return(new CrefCompletionItem( workspace, completionProvider: this, displayText: insertionText, insertionText: insertionText, textSpan: GetTextChangeSpan(text, textChangeSpanPosition), descriptionFactory: CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, tokenPosition, symbol), glyph: symbol.GetGlyph(), sortText: symbolText)); }
public override async Task ProduceCompletionListAsync(CompletionListContext 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.MakeExclusive(true); } var enclosing = semanticModel.GetEnclosingNamedTypeOrAssembly(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, initializedType) && 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); var filterSpan = GetTextChangeSpan(text, position); foreach (var uninitializedMember in uninitializedMembers) { context.AddItem(CreateItem( workspace, uninitializedMember.Name, filterSpan, CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, initializerLocation.SourceSpan.Start, uninitializedMember), uninitializedMember.GetGlyph())); } }
public override async Task <ImmutableArray <SymbolDisplayPart> > GetDescriptionAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (this.LazyDescription == null) { Interlocked.CompareExchange( ref this.LazyDescription, new AsyncLazy <ImmutableArray <SymbolDisplayPart> >( CommonCompletionUtilities.CreateDescriptionFactory(this.Context.Workspace, this.Context.SemanticModel, this.Position, this.Symbols, this.supportedPlatorms), cacheResult: true), null); } return(await base.GetDescriptionAsync(cancellationToken).ConfigureAwait(false)); }
private CompletionItem CreateItem(IMethodSymbol method, int line, TextSpan lineSpan, TextSpan span, SemanticModel semanticModel, DeclarationModifiers modifiers, Document document, SyntaxToken token) { modifiers = new DeclarationModifiers(method.IsStatic, isUnsafe: method.IsUnsafe(), isPartial: true, isAsync: modifiers.IsAsync); var displayText = GetDisplayText(method, semanticModel, span.Start); return(new MemberInsertionCompletionItem( this, displayText, span, CommonCompletionUtilities.CreateDescriptionFactory(document.Project.Solution.Workspace, semanticModel, span.Start, method), Glyph.MethodPrivate, modifiers, line, method.GetSymbolKey(), token)); }
private MemberInsertionCompletionItem CreateItem( ISymbol symbol, TextSpan textChangeSpan, ISymbolDisplayService symbolDisplayService, SemanticModel semanticModel, SyntaxToken startToken, DeclarationModifiers modifiers) { var position = startToken.SpanStart; var displayString = symbolDisplayService.ToMinimalDisplayString(semanticModel, position, symbol, _overrideNameFormat); return(new MemberInsertionCompletionItem(_provider, displayString, textChangeSpan, CommonCompletionUtilities.CreateDescriptionFactory(_document.Project.Solution.Workspace, semanticModel, position, symbol), symbol.GetGlyph(), modifiers, _startLineNumber, symbol.GetSymbolKey(), startToken)); }
protected override async Task <IEnumerable <CompletionItem> > GetItemsWorkerAsync(Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken) { var workspace = document.Project.Solution.Workspace; var semanticModel = await document.GetSemanticModelForSpanAsync(new TextSpan(position, 0), cancellationToken).ConfigureAwait(false); var typeAndLocation = GetInitializedType(document, semanticModel, position, cancellationToken); if (typeAndLocation == null) { return(null); } var initializedType = typeAndLocation.Item1 as INamedTypeSymbol; var initializerLocation = typeAndLocation.Item2; if (initializedType == null) { return(null); } // 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, initializedType) && 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)); var text = await semanticModel.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); var changes = GetTextChangeSpan(text, position); // Return the members return(uninitializedMembers.Select( m => CreateItem(workspace, m.Name, changes, CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, initializerLocation.SourceSpan.Start, m), m.GetGlyph()))); }
private async Task <IEnumerable <CompletionItem> > GetNameEqualsItemsAsync(Workspace workspace, SemanticModel semanticModel, int position, SyntaxToken token, AttributeSyntax attributeSyntax, ISet <string> existingNamedParameters, CancellationToken cancellationToken) { var attributeNamedParameters = GetAttributeNamedParameters(semanticModel, position, attributeSyntax, cancellationToken); var unspecifiedNamedParameters = attributeNamedParameters.Where(p => !existingNamedParameters.Contains(p.Name)); var text = await semanticModel.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); return(from p in attributeNamedParameters where !existingNamedParameters.Contains(p.Name) select new CompletionItem( this, p.Name.ToIdentifierToken().ToString() + SpaceEqualsString, CompletionUtilities.GetTextChangeSpan(text, position), CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, token.SpanStart, p), p.GetGlyph(), sortText: p.Name, rules: ItemRules.Instance)); }
private async Task <IEnumerable <CompletionItem> > GetNameColonItemsAsync( Workspace workspace, SemanticModel semanticModel, int position, SyntaxToken token, AttributeSyntax attributeSyntax, ISet <string> existingNamedParameters, CancellationToken cancellationToken) { var parameterLists = GetParameterLists(semanticModel, position, attributeSyntax, cancellationToken); parameterLists = parameterLists.Where(pl => IsValid(pl, existingNamedParameters)); var text = await semanticModel.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); return (from pl in parameterLists from p in pl where !existingNamedParameters.Contains(p.Name) select new CSharpCompletionItem( workspace, this, p.Name.ToIdentifierToken().ToString() + ColonString, CompletionUtilities.GetTextChangeSpan(text, position), CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, token.SpanStart, p), p.GetGlyph(), sortText: p.Name)); }
protected override async Task <IEnumerable <CompletionItem> > GetItemsWorkerAsync( Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken) { var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (tree.IsInNonUserCode(position, cancellationToken)) { return(null); } var token = tree.FindTokenOnLeftOfPosition(position, cancellationToken); if (token.IsMandatoryNamedParameterPosition()) { return(null); } var typeInferenceService = document.GetLanguageService <ITypeInferenceService>(); 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(null); } } if (type.TypeKind != TypeKind.Enum) { type = GetCompletionListType(type, semanticModel.GetEnclosingNamedType(position, cancellationToken), semanticModel.Compilation); if (type == null) { return(null); } } if (!type.IsEditorBrowsable(document.ShouldHideAdvancedMembers(), semanticModel.Compilation)) { return(null); } // 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 textChangeSpan = CompletionUtilities.GetTextChangeSpan(text, position); var item = new CSharpCompletionItem( workspace, this, displayText: displayText, filterSpan: textChangeSpan, descriptionFactory: CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, position, alias ?? type), glyph: (alias ?? type).GetGlyph(), preselect: true); return(SpecializedCollections.SingletonEnumerable(item)); }
protected override async Task <IEnumerable <CompletionItem> > GetItemsWorkerAsync( Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken) { var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (syntaxTree.IsInNonUserCode(position, cancellationToken)) { return(null); } var token = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken); token = token.GetPreviousTokenIfTouchingWord(position); if (token.Kind() != SyntaxKind.OpenParenToken && token.Kind() != SyntaxKind.OpenBracketToken && token.Kind() != SyntaxKind.CommaToken) { return(null); } var argumentList = token.Parent as BaseArgumentListSyntax; if (argumentList == null) { return(null); } var semanticModel = await document.GetSemanticModelForNodeAsync(argumentList, cancellationToken).ConfigureAwait(false); var parameterLists = GetParameterLists(semanticModel, position, argumentList.Parent, cancellationToken); if (parameterLists == null) { return(null); } 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); var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); return(unspecifiedParameters.Select( p => { // 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 workspace = document.Project.Solution.Workspace; var escaped = p.Name.ToIdentifierToken().ToString(); return new CompletionItem( this, escaped + ColonString, CompletionUtilities.GetTextChangeSpan(text, position), CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, token.SpanStart, p), p.GetGlyph(), sortText: p.Name, filterText: escaped, rules: ItemRules.Instance); })); }
public override async Task ProduceCompletionListAsync(CompletionListContext 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>(); 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 textChangeSpan = CompletionUtilities.GetTextChangeSpan(text, position); var item = new CompletionItem( this, displayText: displayText, filterSpan: textChangeSpan, descriptionFactory: CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, position, alias ?? type), glyph: (alias ?? type).GetGlyph(), preselect: true, rules: ItemRules.Instance); context.AddItem(item); } catch (Exception e) when(FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
public override async Task ProduceCompletionListAsync(CompletionListContext 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.MakeExclusive(true); } var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var filterSpan = CompletionUtilities.GetTextChangeSpan(text, position); 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(new CompletionItem( this, escapedName + ColonString, filterSpan, CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, token.SpanStart, parameter), parameter.GetGlyph(), sortText: parameter.Name, filterText: escapedName, rules: ItemRules.Instance)); } }
private CompletionItem CreateItem( Workspace workspace, SemanticModel semanticModel, ISymbol symbol, SyntaxToken token, TextSpan filterSpan, 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(new Item( completionProvider: this, displayText: insertionText, insertionText: insertionText, textSpan: filterSpan, descriptionFactory: CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, position, symbol), glyph: symbol.GetGlyph(), sortText: symbolText)); }