public static async Task <CompletionDescription> GetDescriptionAsync(
            CompletionItem item, Document document, CancellationToken cancellationToken)
        {
            var workspace = document.Project.Solution.Workspace;

            var position = GetDescriptionPosition(item);

            if (position == -1)
            {
                position = item.Span.Start;
            }

            var supportedPlatforms = GetSupportedPlatforms(item, workspace);

            var contextDocument = FindAppropriateDocumentForDescriptionContext(document, supportedPlatforms);

            var semanticModel = await contextDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var symbols = await GetSymbolsAsync(item, document, cancellationToken).ConfigureAwait(false);

            if (symbols.Length > 0)
            {
                return(await CommonCompletionUtilities.CreateDescriptionAsync(workspace, semanticModel, position, symbols, supportedPlatforms, cancellationToken).ConfigureAwait(false));
            }
            else
            {
                return(CompletionDescription.Empty);
            }
        }
Beispiel #2
0
 internal static TextSpan GetCompletionItemSpan(SourceText text, int position) =>
 CommonCompletionUtilities.GetWordSpan(
     text,
     position,
     IsCompletionItemStartCharacter,
     IsWordCharacter
     );
Beispiel #3
0
        public static async Task <CompletionDescription> GetDescriptionAsync(
            CompletionItem item,
            IReadOnlyList <ISymbol> symbols,
            Document document,
            SemanticModel semanticModel,
            CancellationToken cancellationToken
            )
        {
            var workspace = document.Project.Solution.Workspace;

            var position           = GetDescriptionPosition(item);
            var supportedPlatforms = GetSupportedPlatforms(item, workspace);

            if (symbols.Count != 0)
            {
                return(await CommonCompletionUtilities
                       .CreateDescriptionAsync(
                           workspace,
                           semanticModel,
                           position,
                           symbols,
                           supportedPlatforms,
                           cancellationToken
                           )
                       .ConfigureAwait(false));
            }
            else
            {
                return(CompletionDescription.Empty);
            }
        }
Beispiel #4
0
        public static async Task <CompletionDescription> GetCompletionDescriptionAsync(Document document, CompletionItem item, CancellationToken cancellationToken)
        {
            var metadataName = GetMetadataName(item);

            if (!string.IsNullOrEmpty(metadataName))
            {
                var compilation = await document.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

                var symbol = compilation.GetTypeByMetadataName(metadataName);
                if (symbol != null)
                {
                    var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                    // We choose not to display the number of "type overloads" for simplicity.
                    // Otherwise, we need additonal logic to track internal and public visible
                    // types separately, and cache both completion items.
                    return(await CommonCompletionUtilities.CreateDescriptionAsync(
                               document.Project.Solution.Workspace,
                               semanticModel,
                               position : 0,
                               symbol,
                               overloadCount : 0,
                               supportedPlatforms : null,
                               cancellationToken).ConfigureAwait(false));
                }
            }

            return(null);
        }
        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));
        }
Beispiel #6
0
 private static TextSpan GetCompletionItemSpan(SourceText text, int position)
 {
     return(CommonCompletionUtilities.GetWordSpan(
                text,
                position,
                ch => CompletionUtilities.IsCompletionItemStartCharacter(ch) || ch == '{',
                ch => CompletionUtilities.IsWordCharacter(ch) || ch == '{' || ch == '}'));
 }
 private TextSpan GetTextChangeSpan(SourceText text, int position)
 {
     return(CommonCompletionUtilities.GetTextChangeSpan(
                text,
                position,
                (ch) => CompletionUtilities.IsTextChangeSpanStartCharacter(ch) || ch == '{',
                (ch) => CompletionUtilities.IsWordCharacter(ch) || ch == '{' || ch == '}'));
 }
Beispiel #8
0
        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()));
            }
        }
Beispiel #9
0
 public static bool IsStartingNewWord(SourceText text, int characterPosition)
 {
     return(CommonCompletionUtilities.IsStartingNewWord(
                text,
                characterPosition,
                IsWordStartCharacter,
                IsWordCharacter
                ));
 }
Beispiel #10
0
        internal static bool IsTriggerCharacter(SourceText text, int characterPosition)
        {
            // Bring up completion when the user types a quote (i.e.: #r "), or if they type a slash
            // path separator character, or if they type a comma (#r "foo,version...").
            //
            // Also, if they're starting a word.  i.e. #r "c:\W
            var ch = text[characterPosition];

            return(ch == '"' || ch == '\\' || ch == ',' ||
                   CommonCompletionUtilities.IsStartingNewWord(text, characterPosition, char.IsLetter, char.IsLetterOrDigit));
        }
Beispiel #11
0
        public CompletionHandler(
            IGlobalOptionService globalOptions,
            [ImportMany] IEnumerable <Lazy <CompletionProvider, CompletionProviderMetadata> > completionProviders)
        {
            _globalOptions = globalOptions;

            _csharpTriggerCharacters = completionProviders.Where(lz => lz.Metadata.Language == LanguageNames.CSharp).SelectMany(
                lz => CommonCompletionUtilities.GetTriggerCharacters(lz.Value)).ToImmutableHashSet();
            _vbTriggerCharacters = completionProviders.Where(lz => lz.Metadata.Language == LanguageNames.VisualBasic).SelectMany(
                lz => CommonCompletionUtilities.GetTriggerCharacters(lz.Value)).ToImmutableHashSet();
        }
Beispiel #12
0
        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));
        }
Beispiel #13
0
        public static string GetInsertionText(ISymbol symbol, SyntaxContext context)
        {
            if (CommonCompletionUtilities.TryRemoveAttributeSuffix(symbol, context, out var name))
            {
                // Cannot escape Attribute name with the suffix removed. Only use the name with
                // the suffix removed if it does not need to be escaped.
                if (name.Equals(name.EscapeIdentifier()))
                {
                    return(name);
                }
            }

            return(symbol.Name.EscapeIdentifier(isQueryContext: context.IsInQuery));
        }
Beispiel #14
0
        public static string GetInsertionText(ISymbol symbol, AbstractSyntaxContext context)
        {
            string name;

            if (CommonCompletionUtilities.TryRemoveAttributeSuffix(symbol, context.IsAttributeNameContext, context.GetLanguageService <ISyntaxFactsService>(), out name))
            {
                // Cannot escape Attribute name with the suffix removed. Only use the name with
                // the suffix removed if it does not need to be escaped.
                if (name.Equals(name.EscapeIdentifier()))
                {
                    return(name);
                }
            }

            return(symbol.Name.EscapeIdentifier(isQueryContext: context.IsInQuery));
        }
        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));
        }
Beispiel #16
0
        public static async Task <CompletionDescription> GetDescriptionAsync(CompletionItem item, ImmutableArray <ISymbol> symbols, Document document, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            var workspace = document.Project.Solution.Workspace;

            var position           = SymbolCompletionItem.GetDescriptionPosition(item);
            var supportedPlatforms = SymbolCompletionItem.GetSupportedPlatforms(item, workspace);

            var contextDocument = FindAppropriateDocumentForDescriptionContext(document, supportedPlatforms);

            if (symbols.Length != 0)
            {
                return(await CommonCompletionUtilities.CreateDescriptionAsync(workspace, semanticModel, position, symbols, supportedPlatforms, cancellationToken).ConfigureAwait(false));
            }
            else
            {
                return(CompletionDescription.Empty);
            }
        }
Beispiel #17
0
            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));
        }
Beispiel #20
0
        public static string GetInsertionText(ISymbol symbol, SyntaxContext context)
        {
            if (CommonCompletionUtilities.TryRemoveAttributeSuffix(symbol, context, out var name))
            {
                // Cannot escape Attribute name with the suffix removed. Only use the name with
                // the suffix removed if it does not need to be escaped.
                if (name.Equals(name.EscapeIdentifier()))
                {
                    return(name);
                }
            }

            if (symbol.Kind == SymbolKind.Label &&
                symbol.DeclaringSyntaxReferences[0].GetSyntax().Kind() == SyntaxKind.DefaultSwitchLabel)
            {
                return(symbol.Name);
            }

            return(symbol.Name.EscapeIdentifier(isQueryContext: context.IsInQuery));
        }
Beispiel #21
0
        private static async Task <TextSpan> GetTextChangeSpanAsync(Document document, TextSpan startSpan, CancellationToken cancellationToken)
        {
            var result      = startSpan;
            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();
            var root        = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var token = root.FindToken(result.Start);

            if (syntaxFacts.IsStringLiteral(token) || syntaxFacts.IsVerbatimStringLiteral(token))
            {
                var text = root.GetText();

                // Expand selection in both directions until a double quote or any line break character is reached
                bool IsWordCharacter(char ch) => !(ch == '"' || TextUtilities.IsAnyLineBreakCharacter(ch));

                result = CommonCompletionUtilities.GetWordSpan(
                    text, startSpan.Start, IsWordCharacter, IsWordCharacter, alwaysExtendEndSpan: true);
            }

            return(result);
        }
Beispiel #22
0
        public static async Task <CompletionDescription> GetDescriptionAsync(CompletionItem item, Document document, CancellationToken cancellationToken)
        {
            var workspace = document.Project.Solution.Workspace;

            var position = GetDescriptionPosition(item);

            if (position == -1)
            {
                position = item.Span.Start;
            }

            var supportedPlatforms = GetSupportedPlatforms(item, workspace);

            // find appropriate document for descripton context
            var contextDocument = document;

            if (supportedPlatforms != null && supportedPlatforms.InvalidProjects.Contains(document.Id.ProjectId))
            {
                var contextId = document.GetLinkedDocumentIds().FirstOrDefault(id => !supportedPlatforms.InvalidProjects.Contains(id.ProjectId));
                if (contextId != null)
                {
                    contextDocument = document.Project.Solution.GetDocument(contextId);
                }
            }

            var semanticModel = await contextDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var symbols = await GetSymbolsAsync(item, document, cancellationToken).ConfigureAwait(false);

            if (symbols.Length > 0)
            {
                return(await CommonCompletionUtilities.CreateDescriptionAsync(workspace, semanticModel, position, symbols, supportedPlatforms, cancellationToken).ConfigureAwait(false));
            }
            else
            {
                return(CompletionDescription.Empty);
            }
        }
Beispiel #23
0
        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));
        }
        public static async Task <CompletionDescription> GetDescriptionForSymbolsAsync(
            CompletionItem item, Document document, ImmutableArray <ISymbol> symbols, SymbolDescriptionOptions options, CancellationToken cancellationToken)
        {
            if (symbols.Length == 0)
            {
                return(CompletionDescription.Empty);
            }

            var position = GetDescriptionPosition(item);

            if (position == -1)
            {
                position = item.Span.Start;
            }

            var supportedPlatforms = GetSupportedPlatforms(item, document.Project.Solution);
            var contextDocument    = FindAppropriateDocumentForDescriptionContext(document, supportedPlatforms);
            var semanticModel      = await contextDocument.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var services = document.Project.Solution.Services;

            return(await CommonCompletionUtilities.CreateDescriptionAsync(services, semanticModel, position, symbols, options, supportedPlatforms, cancellationToken).ConfigureAwait(false));
        }
Beispiel #25
0
        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));
        }
        public ServerCapabilities GetCapabilities(ClientCapabilities clientCapabilities)
        {
            var capabilities = new ServerCapabilities();

            if (clientCapabilities is VSInternalClientCapabilities vsClientCapabilities && vsClientCapabilities.SupportsVisualStudioExtensions)
            {
                capabilities = GetVSServerCapabilities();
            }

            var commitCharacters  = CompletionRules.Default.DefaultCommitCharacters.Select(c => c.ToString()).ToArray();
            var triggerCharacters = _completionProviders.SelectMany(
                lz => CommonCompletionUtilities.GetTriggerCharacters(lz.Value)).Distinct().Select(c => c.ToString()).ToArray();

            capabilities.DefinitionProvider     = true;
            capabilities.RenameProvider         = true;
            capabilities.ImplementationProvider = true;
            capabilities.CodeActionProvider     = new CodeActionOptions {
                CodeActionKinds = new[] { CodeActionKind.QuickFix, CodeActionKind.Refactor }, ResolveProvider = true
            };
            capabilities.CompletionProvider = new VisualStudio.LanguageServer.Protocol.CompletionOptions
            {
                ResolveProvider     = true,
                AllCommitCharacters = commitCharacters,
                TriggerCharacters   = triggerCharacters,
            };

            capabilities.SignatureHelpProvider = new SignatureHelpOptions {
                TriggerCharacters = new[] { "(", "," }
            };
            capabilities.DocumentSymbolProvider           = true;
            capabilities.WorkspaceSymbolProvider          = true;
            capabilities.DocumentFormattingProvider       = true;
            capabilities.DocumentRangeFormattingProvider  = true;
            capabilities.DocumentOnTypeFormattingProvider = new DocumentOnTypeFormattingOptions {
                FirstTriggerCharacter = "}", MoreTriggerCharacter = new[] { ";", "\n" }
            };
            capabilities.ReferencesProvider     = true;
            capabilities.FoldingRangeProvider   = true;
            capabilities.ExecuteCommandProvider = new ExecuteCommandOptions();
            capabilities.TextDocumentSync       = new TextDocumentSyncOptions
            {
                Change    = TextDocumentSyncKind.Incremental,
                OpenClose = true
            };

            capabilities.HoverProvider = true;

            capabilities.SemanticTokensOptions = new SemanticTokensOptions
            {
                Full = new SemanticTokensFullOptions {
                    Delta = true
                },
                Range  = true,
                Legend = new SemanticTokensLegend
                {
                    TokenTypes     = SemanticTokenTypes.AllTypes.Concat(SemanticTokensHelpers.RoslynCustomTokenTypes).ToArray(),
                    TokenModifiers = new string[] { SemanticTokenModifiers.Static }
                }
            };

            return(capabilities);
        }
        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 ServerCapabilities GetCapabilities(ClientCapabilities clientCapabilities)
        {
            var capabilities = new ServerCapabilities();

            if (clientCapabilities is VSInternalClientCapabilities vsClientCapabilities && vsClientCapabilities.SupportsVisualStudioExtensions)
            {
                capabilities = GetVSServerCapabilities();
            }

            var commitCharacters  = CompletionRules.Default.DefaultCommitCharacters.Select(c => c.ToString()).ToArray();
            var triggerCharacters = _completionProviders.SelectMany(
                lz => CommonCompletionUtilities.GetTriggerCharacters(lz.Value)).Distinct().Select(c => c.ToString()).ToArray();

            capabilities.DefinitionProvider     = true;
            capabilities.RenameProvider         = true;
            capabilities.ImplementationProvider = true;
            capabilities.CodeActionProvider     = new CodeActionOptions {
                CodeActionKinds = new[] { CodeActionKind.QuickFix, CodeActionKind.Refactor }, ResolveProvider = true
            };
            capabilities.CompletionProvider = new VisualStudio.LanguageServer.Protocol.CompletionOptions
            {
                ResolveProvider     = true,
                AllCommitCharacters = commitCharacters,
                TriggerCharacters   = triggerCharacters,
            };

            capabilities.SignatureHelpProvider = new SignatureHelpOptions {
                TriggerCharacters = new[] { "(", "," }
            };
            capabilities.DocumentSymbolProvider           = true;
            capabilities.WorkspaceSymbolProvider          = true;
            capabilities.DocumentFormattingProvider       = true;
            capabilities.DocumentRangeFormattingProvider  = true;
            capabilities.DocumentOnTypeFormattingProvider = new DocumentOnTypeFormattingOptions {
                FirstTriggerCharacter = "}", MoreTriggerCharacter = new[] { ";", "\n" }
            };
            capabilities.ReferencesProvider     = true;
            capabilities.FoldingRangeProvider   = true;
            capabilities.ExecuteCommandProvider = new ExecuteCommandOptions();
            capabilities.TextDocumentSync       = new TextDocumentSyncOptions
            {
                Change    = TextDocumentSyncKind.Incremental,
                OpenClose = true
            };

            capabilities.HoverProvider = true;

            // Using only range handling has shown to be more performant than using a combination of full/edits/range handling,
            // especially for larger files. With range handling, we only need to compute tokens for whatever is in view, while
            // with full/edits handling we need to compute tokens for the entire file and then potentially run a diff between
            // the old and new tokens.
            capabilities.SemanticTokensOptions = new SemanticTokensOptions
            {
                Full   = false,
                Range  = true,
                Legend = new SemanticTokensLegend
                {
                    TokenTypes     = SemanticTokenTypes.AllTypes.Concat(SemanticTokensHelpers.RoslynCustomTokenTypes).ToArray(),
                    TokenModifiers = new string[] { SemanticTokenModifiers.Static }
                }
            };

            return(capabilities);
        }
Beispiel #29
0
        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);
            }));
        }
Beispiel #30
0
 internal static TextSpan GetTextChangeSpan(SourceText text, int position)
 {
     return(CommonCompletionUtilities.GetTextChangeSpan(text, position, IsTextChangeSpanStartCharacter, IsWordCharacter));
 }