AbstractPartialMethodCompletionProvider.cs 5.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;

M
Matt Warren 已提交
12
namespace Microsoft.CodeAnalysis.Completion.Providers
13
{
14
    internal abstract partial class AbstractPartialMethodCompletionProvider : AbstractMemberInsertingCompletionProvider
15 16 17 18 19 20 21 22 23 24 25 26 27 28
    {
        protected static readonly SymbolDisplayFormat SignatureDisplayFormat =
                new SymbolDisplayFormat(
                    genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
                    memberOptions:
                        SymbolDisplayMemberOptions.IncludeParameters,
                    parameterOptions:
                        SymbolDisplayParameterOptions.IncludeName |
                        SymbolDisplayParameterOptions.IncludeType |
                        SymbolDisplayParameterOptions.IncludeParamsRefOut,
                    miscellaneousOptions:
                        SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers |
                        SymbolDisplayMiscellaneousOptions.UseSpecialTypes);

29
        protected AbstractPartialMethodCompletionProvider()
30 31 32
        {
        }

33
        protected abstract bool IsPartialMethodCompletionContext(SyntaxTree tree, int position, CancellationToken cancellationToken, out DeclarationModifiers modifiers, out SyntaxToken token);
34
        protected abstract string GetDisplayText(IMethodSymbol method, SemanticModel semanticModel, int position);
35
        protected abstract bool IsPartial(IMethodSymbol method);
36

M
Matt Warren 已提交
37
        public override async Task ProvideCompletionsAsync(CompletionContext context)
38
        {
39 40 41 42
            var document = context.Document;
            var position = context.Position;
            var cancellationToken = context.CancellationToken;

43 44 45 46
            var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            DeclarationModifiers modifiers;
            SyntaxToken token;
47
            if (!IsPartialMethodCompletionContext(tree, position, cancellationToken, out modifiers, out token))
48
            {
49
                return;
50 51
            }

52 53
            var items = await CreatePartialItemsAsync(
                document, position, context.CompletionListSpan, modifiers, token, cancellationToken).ConfigureAwait(false);
54 55 56

            if (items?.Any() == true)
            {
M
Matt Warren 已提交
57
                context.IsExclusive = true;
58 59
                context.AddItems(items);
            }
60 61
        }

M
Matt Warren 已提交
62
        protected override async Task<ISymbol> GenerateMemberAsync(ISymbol member, INamedTypeSymbol containingType, Document document, CompletionItem item, CancellationToken cancellationToken)
63 64
        {
            var syntaxFactory = document.GetLanguageService<SyntaxGenerator>();
C
CyrusNajmabadi 已提交
65
            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
66 67 68

            return CodeGenerationSymbolFactory.CreateMethodSymbol(attributes: new List<AttributeData>(),
                accessibility: Accessibility.NotApplicable,
M
Matt Warren 已提交
69
                modifiers: MemberInsertionCompletionItem.GetModifiers(item),
70 71 72 73 74 75 76 77
                returnType: semanticModel.Compilation.GetSpecialType(SpecialType.System_Void),
                explicitInterfaceSymbol: null,
                name: member.Name,
                typeParameters: ((IMethodSymbol)member).TypeParameters,
                parameters: member.GetParameters().Select(p => CodeGenerationSymbolFactory.CreateParameterSymbol(p.GetAttributes(), p.RefKind, p.IsParams, p.Type, p.Name)).ToList(),
                statements: syntaxFactory.CreateThrowNotImplementedStatementBlock(semanticModel.Compilation));
        }

78 79
        protected async Task<IEnumerable<CompletionItem>> CreatePartialItemsAsync(
            Document document, int position, TextSpan span, DeclarationModifiers modifiers, SyntaxToken token, CancellationToken cancellationToken)
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
        {
            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
            var enclosingSymbol = semanticModel.GetEnclosingSymbol(position, cancellationToken) as INamedTypeSymbol;

            // Only inside classes and structs
            if (enclosingSymbol == null || !(enclosingSymbol.TypeKind == TypeKind.Struct || enclosingSymbol.TypeKind == TypeKind.Class))
            {
                return null;
            }

            var symbols = semanticModel.LookupSymbols(position, container: enclosingSymbol)
                                        .OfType<IMethodSymbol>()
                                        .Where(m => IsPartial(m) && m.PartialImplementationPart == null);

            var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
            var line = text.Lines.IndexOf(position);
            var lineSpan = text.Lines.GetLineFromPosition(position).Span;
            return symbols.Select(s => CreateItem(s, line, lineSpan, span, semanticModel, modifiers, document, token));
        }

        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);

M
Matt Warren 已提交
105
            return MemberInsertionCompletionItem.Create(
106 107 108 109
                displayText,
                Glyph.MethodPrivate,
                modifiers,
                line,
M
Matt Warren 已提交
110 111 112 113
                method,
                token,
                span.Start,
                rules: this.GetRules());
114 115 116
        }
    }
}