예제 #1
0
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var document          = context.Document;
            var textSpan          = context.Span;
            var cancellationToken = context.CancellationToken;

            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();
            var sourceText  = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            // We offer the refactoring when the user is either on the header of a class/struct,
            // or if they're between any members of a class/struct and are on a blank line.
            if (!syntaxFacts.IsOnTypeHeader(root, textSpan.Start) &&
                !syntaxFacts.IsBetweenTypeMembers(sourceText, root, textSpan.Start))
            {
                return;
            }

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

            // Only supported on classes/structs.
            var containingType = AbstractGenerateFromMembersCodeRefactoringProvider.GetEnclosingNamedType(
                semanticModel, root, textSpan.Start, cancellationToken);

            var overridableMembers = containingType.GetOverridableMembers(cancellationToken);

            if (overridableMembers.Length == 0)
            {
                return;
            }

            context.RegisterRefactoring(new GenerateOverridesWithDialogCodeAction(
                                            this, document, textSpan, containingType, overridableMembers));
        }
예제 #2
0
        protected override bool TryInitializeState(
            SemanticDocument document, TextSpan textSpan, CancellationToken cancellationToken,
            out INamedTypeSymbol classType)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // Offer the feature if we're on the header for the class/struct, or if we're on the
            // first base-type of a class.

            var syntaxFacts = document.Document.GetLanguageService <ISyntaxFactsService>();

            if (syntaxFacts.IsOnTypeHeader(document.Root, textSpan.Start))
            {
                classType = AbstractGenerateFromMembersCodeRefactoringProvider.GetEnclosingNamedType(
                    document.SemanticModel, document.Root, textSpan.Start, cancellationToken);
                return(classType?.TypeKind == TypeKind.Class);
            }

            var syntaxTree = document.SyntaxTree;
            var node       = document.Root.FindToken(textSpan.Start).GetAncestor <TypeSyntax>();

            if (node != null)
            {
                if (node.Parent is BaseTypeSyntax && node.Parent.IsParentKind(SyntaxKind.BaseList))
                {
                    var baseList = (BaseListSyntax)node.Parent.Parent;
                    if (baseList.Types.Count > 0 &&
                        baseList.Types[0].Type == node &&
                        baseList.IsParentKind(SyntaxKind.ClassDeclaration))
                    {
                        var semanticModel = document.SemanticModel;
                        classType = semanticModel.GetDeclaredSymbol(baseList.Parent, cancellationToken) as INamedTypeSymbol;
                        return(classType != null);
                    }
                }
            }

            classType = null;
            return(false);
        }