Exemple #1
0
        public override async Task ProvideCompletionsAsync(CompletionContext completionContext)
        {
            try
            {
                var document          = completionContext.Document;
                var cancellationToken = completionContext.CancellationToken;

                var context = await completionContext.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false) as CSharpSyntaxContext;

                Contract.ThrowIfNull(context);

                var semanticModel = context.SemanticModel;

                var index = GetElementIndex(context);
                if (index == null)
                {
                    return;
                }

                var typeInferrer  = document.GetRequiredLanguageService <ITypeInferenceService>();
                var inferredTypes = typeInferrer.InferTypes(semanticModel, context.TargetToken.Parent !.SpanStart, cancellationToken)
                                    .Where(t => t.IsTupleType)
                                    .Cast <INamedTypeSymbol>()
                                    .ToImmutableArray();

                AddItems(inferredTypes, index.Value, completionContext, context.TargetToken.Parent.SpanStart);
            }
            catch (Exception e) when(FatalError.ReportAndCatchUnlessCanceled(e, ErrorSeverity.General))
            {
                // 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(static k => k.SymbolKind == SymbolKind.Parameter))
        public override async Task ProvideCompletionsAsync(CompletionContext context)
        {
            try
            {
                var document          = context.Document;
                var position          = context.Position;
                var cancellationToken = context.CancellationToken;

                var tree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

                if (tree.IsInNonUserCode(position, cancellationToken))
                {
                    return;
                }

                var syntaxContext = await context.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false);

                var semanticModel = syntaxContext.SemanticModel;

                if (syntaxContext.IsInTaskLikeTypeContext)
                {
                    return;
                }

                var token = syntaxContext.TargetToken;
                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 types = typeInferenceService.InferTypes(semanticModel, position, cancellationToken);

                if (types.Length == 0)
                {
                    types = ImmutableArray.Create <ITypeSymbol>(semanticModel.Compilation.ObjectType);
                }

                foreach (var type in types)
                {
                    await HandleSingleTypeAsync(context, semanticModel, token, type, cancellationToken).ConfigureAwait(false);
                }
            }
            catch (Exception e) when(FatalError.ReportAndPropagateUnlessCanceled(e, ErrorSeverity.General))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
Exemple #4
0
        private static async Task <bool> ShouldShowSpeculativeTCompletionItemAsync(Document document, CompletionContext completionContext, CancellationToken cancellationToken)
        {
            var position   = completionContext.Position;
            var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            if (syntaxTree.IsInNonUserCode(position, cancellationToken) ||
                syntaxTree.IsPreProcessorDirectiveContext(position, cancellationToken))
            {
                return(false);
            }

            // We could be in the middle of a ref/generic/tuple type, instead of a simple T case.
            // If we managed to walk out and get a different SpanStart, we treat it as a simple $$T case.

            var context = await completionContext.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false);

            if (context.IsTaskLikeTypeContext)
            {
                return(false);
            }

            var spanStart = position;

            while (true)
            {
                var oldSpanStart = spanStart;

                spanStart = WalkOutOfGenericType(syntaxTree, spanStart, context.SemanticModel, cancellationToken);
                spanStart = WalkOutOfTupleType(syntaxTree, spanStart, cancellationToken);
                spanStart = WalkOutOfRefType(syntaxTree, spanStart, cancellationToken);

                if (spanStart == oldSpanStart)
                {
                    break;
                }
            }

            return(IsStartOfSpeculativeTContext(syntaxTree, spanStart, cancellationToken));
        }
Exemple #5
0
        public sealed override async Task ProvideCompletionsAsync(CompletionContext context)
        {
            var cancellationToken   = context.CancellationToken;
            var originatingDocument = context.Document;
            var position            = context.Position;
            var solution            = originatingDocument.Project.Solution;
            var syntaxContext       = await context.GetSyntaxContextWithExistingSpeculativeModelAsync(originatingDocument, cancellationToken).ConfigureAwait(false);

            if (!syntaxContext.IsPreProcessorExpressionContext)
            {
                return;
            }

            // Walk all the projects this document is linked in so that we get the full set of preprocessor symbols
            // defined across all of them.
            var syntaxFacts       = originatingDocument.GetRequiredLanguageService <ISyntaxFactsService>();
            var preprocessorNames = new HashSet <string>(syntaxFacts.StringComparer);

            foreach (var documentId in solution.GetRelatedDocumentIds(originatingDocument.Id))
            {
                var document          = solution.GetRequiredDocument(documentId);
                var currentSyntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

                preprocessorNames.AddRange(currentSyntaxTree.Options.PreprocessorSymbolNames);
            }

            // Keep all the preprocessor symbol names together.  We don't want to intermingle them with any keywords we
            // include (like `true/false`)
            foreach (var name in preprocessorNames.OrderBy(a => a))
            {
                context.AddItem(CommonCompletionItem.Create(
                                    name,
                                    displayTextSuffix: "",
                                    CompletionItemRules.Default,
                                    glyph: Glyph.Keyword,
                                    sortText: "_0_" + name));
            }
        }
Exemple #6
0
        private static async Task <ImmutableArray <CompletionItem> > GetSnippetsForDocumentAsync(
            Document document, CompletionContext completionContext, CancellationToken cancellationToken)
        {
            var position   = completionContext.Position;
            var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var syntaxFacts   = document.GetRequiredLanguageService <ISyntaxFactsService>();
            var semanticFacts = document.GetRequiredLanguageService <ISemanticFactsService>();

            var root        = syntaxTree.GetRoot(cancellationToken);
            var leftToken   = root.FindTokenOnLeftOfPosition(position, includeDirectives: true);
            var targetToken = leftToken.GetPreviousTokenIfTouchingWord(position);

            if (syntaxFacts.IsInNonUserCode(syntaxTree, position, cancellationToken) ||
                syntaxTree.IsRightOfDotOrArrowOrColonColon(position, targetToken, cancellationToken) ||
                syntaxFacts.GetContainingTypeDeclaration(root, position) is EnumDeclarationSyntax ||
                syntaxTree.IsPossibleTupleContext(leftToken, position))
            {
                return(ImmutableArray <CompletionItem> .Empty);
            }

            var context = await completionContext.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false);

            var semanticModel = context.SemanticModel;

            if (context.IsInTaskLikeTypeContext)
            {
                return(ImmutableArray <CompletionItem> .Empty);
            }

            if (syntaxFacts.IsPreProcessorDirectiveContext(syntaxTree, position, cancellationToken))
            {
                var directive = leftToken.GetAncestor <DirectiveTriviaSyntax>();
                Contract.ThrowIfNull(directive);

                if (!directive.DirectiveNameToken.IsKind(
                        SyntaxKind.IfKeyword,
                        SyntaxKind.RegionKeyword,
                        SyntaxKind.ElseKeyword,
                        SyntaxKind.ElifKeyword,
                        SyntaxKind.ErrorKeyword,
                        SyntaxKind.LineKeyword,
                        SyntaxKind.PragmaKeyword,
                        SyntaxKind.EndIfKeyword,
                        SyntaxKind.UndefKeyword,
                        SyntaxKind.EndRegionKeyword,
                        SyntaxKind.WarningKeyword))
                {
                    return(GetSnippetCompletionItems(
                               document.Project.Solution.Workspace, semanticModel, isPreProcessorContext: true));
                }
            }
            else
            {
                if (semanticFacts.IsGlobalStatementContext(semanticModel, position, cancellationToken) ||
                    semanticFacts.IsExpressionContext(semanticModel, position, cancellationToken) ||
                    semanticFacts.IsStatementContext(semanticModel, position, cancellationToken) ||
                    semanticFacts.IsTypeContext(semanticModel, position, cancellationToken) ||
                    semanticFacts.IsTypeDeclarationContext(semanticModel, position, cancellationToken) ||
                    semanticFacts.IsNamespaceContext(semanticModel, position, cancellationToken) ||
                    semanticFacts.IsNamespaceDeclarationNameContext(semanticModel, position, cancellationToken) ||
                    semanticFacts.IsMemberDeclarationContext(semanticModel, position, cancellationToken) ||
                    semanticFacts.IsLabelContext(semanticModel, position, cancellationToken))
                {
                    return(GetSnippetCompletionItems(
                               document.Project.Solution.Workspace, semanticModel, isPreProcessorContext: false));
                }
            }

            return(ImmutableArray <CompletionItem> .Empty);
        }
Exemple #7
0
        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
            }
        }
Exemple #8
0
        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;