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);
        }
        private 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.UseExpressionBodyTitle, helper.UseExpressionBodyTitle),
                           location, severity, 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.WithDefaultSeverity(DiagnosticSeverity.Hidden) == ReportDiagnostic.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(DiagnosticHelper.Create(
                           CreateDescriptorWithId(helper.DiagnosticId, helper.UseBlockBodyTitle, helper.UseBlockBodyTitle),
                           location, severity, additionalLocations: additionalLocations, properties: properties));
            }

            return(null);
        }
        private async Task <Document> UpdateDocumentAsync(
            Document document, SyntaxNode root, SyntaxNode declaration,
            OptionSet options, UseExpressionBodyHelper helper, bool useExpressionBody,
            CancellationToken cancellationToken)
        {
            var parseOptions  = root.SyntaxTree.Options;
            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var updatedDeclaration = helper.Update(semanticModel, 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(document.WithSyntaxRoot(newRoot));
        }
        private bool TryComputeRefactoring(
            CodeRefactoringContext context,
            SyntaxNode root, SyntaxNode node, OptionSet optionSet,
            UseExpressionBodyHelper helper)
        {
            var declaration = GetDeclaration(node, helper);

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

            var document = context.Document;

            bool succeeded = false;

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

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

            return(succeeded);
        }