private bool TryComputeRefactoring(
            CodeRefactoringContext context, SyntaxNode root, SyntaxNode declaration,
            OptionSet optionSet, UseExpressionBodyHelper helper)
        {
            var document = context.Document;

            var succeeded = false;

            if (helper.CanOfferUseExpressionBody(optionSet, declaration, forAnalyzer: false))
            {
                context.RegisterRefactoring(new MyCodeAction(
                                                helper.UseExpressionBodyTitle.ToString(),
                                                c => UpdateDocumentAsync(
                                                    document, root, declaration, helper,
                                                    useExpressionBody: true, cancellationToken: c)),
                                            declaration.Span);
                succeeded = true;
            }

            var(canOffer, _) = helper.CanOfferUseBlockBody(optionSet, declaration, forAnalyzer: false);
            if (canOffer)
            {
                context.RegisterRefactoring(
                    new MyCodeAction(
                        helper.UseBlockBodyTitle.ToString(),
                        c => UpdateDocumentAsync(
                            document, root, declaration, helper,
                            useExpressionBody: false, cancellationToken: c)),
                    declaration.Span);
                succeeded = true;
            }

            return(succeeded);
        }
Пример #2
0
        private static SyntaxNode?TryGetDeclaration(
            UseExpressionBodyHelper helper,
            SourceText text,
            SyntaxNode node,
            int position
            )
        {
            var declaration = GetDeclaration(node, helper);

            if (declaration == null)
            {
                return(null);
            }

            if (position < declaration.SpanStart)
            {
                // The user is allowed to be before the starting point of this node, as long as
                // they're only between the start of the node and the start of the same line the
                // node starts on.  This prevents unnecessarily showing this feature in areas like
                // the comment of a method.
                if (!text.AreOnSameLine(position, declaration.SpanStart))
                {
                    return(null);
                }
            }

            return(declaration);
        }
Пример #3
0
        private static async Task <Document> UpdateDocumentAsync(
            Document document,
            SyntaxNode root,
            SyntaxNode declaration,
            UseExpressionBodyHelper helper,
            bool useExpressionBody,
            CancellationToken cancellationToken
            )
        {
            var semanticModel = await document
                                .GetSemanticModelAsync(cancellationToken)
                                .ConfigureAwait(false);

            var updatedDeclaration = helper.Update(semanticModel, declaration, useExpressionBody);

            var parent =
                declaration is AccessorDeclarationSyntax ? declaration.Parent : declaration;

            RoslynDebug.Assert(parent is object);
            var updatedParent = parent
                                .ReplaceNode(declaration, updatedDeclaration)
                                .WithAdditionalAnnotations(Formatter.Annotation);

            var newRoot = root.ReplaceNode(parent, updatedParent);

            return(document.WithSyntaxRoot(newRoot));
        }
        private Task <Document> UpdateDocumentAsync(
            Document document, SyntaxNode root, SyntaxNode declaration,
            OptionSet options, UseExpressionBodyHelper helper, bool useExpressionBody,
            CancellationToken cancellationToken)
        {
            var updatedDeclaration = helper.Update(declaration, options, useExpressionBody)
                                     .WithAdditionalAnnotations(Formatter.Annotation);
            var newRoot = root.ReplaceNode(declaration, updatedDeclaration);

            return(Task.FromResult(document.WithSyntaxRoot(newRoot)));
        }
        private SyntaxNode GetDeclaration(SyntaxNode node, UseExpressionBodyHelper helper)
        {
            for (var current = node; current != null; current = current.Parent)
            {
                if (helper.SyntaxKinds.Contains(current.Kind()))
                {
                    return(current);
                }
            }

            return(null);
        }
Пример #6
0
        private Task <Document> UpdateDocumentAsync(
            Document document, SyntaxNode root, SyntaxNode declaration,
            OptionSet options, UseExpressionBodyHelper helper, bool useExpressionBody,
            CancellationToken cancellationToken)
        {
            var parseOptions       = root.SyntaxTree.Options;
            var updatedDeclaration = helper.Update(declaration, options, parseOptions, useExpressionBody);

            var parent = declaration is AccessorDeclarationSyntax
                ? declaration.Parent
                : declaration;
            var updatedParent = parent.ReplaceNode(declaration, updatedDeclaration)
                                .WithAdditionalAnnotations(Formatter.Annotation);

            var newRoot = root.ReplaceNode(parent, updatedParent);

            return(Task.FromResult(document.WithSyntaxRoot(newRoot)));
        }
        private Diagnostic AnalyzeSyntax(
            OptionSet optionSet, SyntaxNode declaration, UseExpressionBodyHelper helper)
        {
            var preferExpressionBodiedOption = optionSet.GetOption(helper.Option);
            var severity = preferExpressionBodiedOption.Notification.Value;

            if (helper.CanOfferUseExpressionBody(optionSet, declaration, forAnalyzer: true))
            {
                var location = severity == DiagnosticSeverity.Hidden
                    ? declaration.GetLocation()
                    : helper.GetDiagnosticLocation(declaration);

                var additionalLocations = ImmutableArray.Create(declaration.GetLocation());
                var properties          = ImmutableDictionary <string, string> .Empty.Add(nameof(UseExpressionBody), "");

                return(Diagnostic.Create(
                           CreateDescriptorWithId(helper.DiagnosticId, helper.UseExpressionBodyTitle, helper.UseExpressionBodyTitle, severity, GetCustomTags(severity)),
                           location, additionalLocations: additionalLocations, properties: properties));
            }

            var(canOffer, fixesError) = helper.CanOfferUseBlockBody(optionSet, declaration, forAnalyzer: true);
            if (canOffer)
            {
                // They have an expression body.  Create a diagnostic to convert it to a block
                // if they don't want expression bodies for this member.
                var location = severity == DiagnosticSeverity.Hidden
                    ? declaration.GetLocation()
                    : helper.GetExpressionBody(declaration).GetLocation();

                var properties = ImmutableDictionary <string, string> .Empty;
                if (fixesError)
                {
                    properties = properties.Add(FixesError, "");
                }

                var additionalLocations = ImmutableArray.Create(declaration.GetLocation());
                return(Diagnostic.Create(
                           CreateDescriptorWithId(helper.DiagnosticId, helper.UseBlockBodyTitle, helper.UseBlockBodyTitle, severity, GetCustomTags(severity)),
                           location, additionalLocations: additionalLocations, properties: properties));
            }

            return(null);
        }
Пример #8
0
        private static Diagnostic?AnalyzeSyntax(
            OptionSet optionSet, SyntaxNode declaration, UseExpressionBodyHelper helper)
        {
            var preferExpressionBodiedOption = optionSet.GetOption(helper.Option);
            var severity = preferExpressionBodiedOption.Notification.Severity;

            if (helper.CanOfferUseExpressionBody(optionSet, declaration, forAnalyzer: true))
            {
                var location = severity.WithDefaultSeverity(DiagnosticSeverity.Hidden) == ReportDiagnostic.Hidden
                    ? declaration.GetLocation()
                    : helper.GetDiagnosticLocation(declaration);

                var additionalLocations = ImmutableArray.Create(declaration.GetLocation());
                var properties          = ImmutableDictionary <string, string?> .Empty.Add(nameof(UseExpressionBody), "");

                return(DiagnosticHelper.Create(
                           CreateDescriptorWithId(helper.DiagnosticId, helper.EnforceOnBuild, helper.UseExpressionBodyTitle, helper.UseExpressionBodyTitle),
                           location, severity, additionalLocations: additionalLocations, properties: properties));
            }

            if (helper.CanOfferUseBlockBody(optionSet, declaration, forAnalyzer: true, out var fixesError, out var expressionBody))
            {
                // They have an expression body.  Create a diagnostic to convert it to a block
                // if they don't want expression bodies for this member.
                var location = severity.WithDefaultSeverity(DiagnosticSeverity.Hidden) == ReportDiagnostic.Hidden
                    ? declaration.GetLocation()
                    : expressionBody.GetLocation();

                var properties = ImmutableDictionary <string, string?> .Empty;
                if (fixesError)
                {
                    properties = properties.Add(FixesError, "");
                }

                var additionalLocations = ImmutableArray.Create(declaration.GetLocation());
                return(DiagnosticHelper.Create(
                           CreateDescriptorWithId(helper.DiagnosticId, helper.EnforceOnBuild, helper.UseBlockBodyTitle, helper.UseBlockBodyTitle),
                           location, severity, additionalLocations: additionalLocations, properties: properties));
            }

            return(null);
        }