private void AnalyzeNode(SyntaxNodeAnalysisContext context)
        {
            var objectCreationExpression = (TObjectCreationExpressionSyntax)context.Node;
            var language = objectCreationExpression.Language;
            var option   = context.GetAnalyzerOptions().PreferObjectInitializer;

            if (!option.Value)
            {
                // not point in analyzing if the option is off.
                return;
            }

            var syntaxFacts = GetSyntaxFacts();
            var matches     = UseNamedMemberInitializerAnalyzer <TExpressionSyntax, TStatementSyntax, TObjectCreationExpressionSyntax, TMemberAccessExpressionSyntax, TAssignmentStatementSyntax, TVariableDeclaratorSyntax> .Analyze(
                context.SemanticModel, syntaxFacts, objectCreationExpression, context.CancellationToken);

            if (matches == null || matches.Value.Length == 0)
            {
                return;
            }

            var containingStatement = objectCreationExpression.FirstAncestorOrSelf <TStatementSyntax>();

            if (containingStatement == null)
            {
                return;
            }

            if (!IsValidContainingStatement(containingStatement))
            {
                return;
            }

            var nodes = ImmutableArray.Create <SyntaxNode>(containingStatement).AddRange(matches.Value.Select(m => m.Statement));

            if (syntaxFacts.ContainsInterleavedDirective(nodes, context.CancellationToken))
            {
                return;
            }

            var locations = ImmutableArray.Create(objectCreationExpression.GetLocation());

            context.ReportDiagnostic(DiagnosticHelper.Create(
                                         Descriptor,
                                         objectCreationExpression.GetFirstToken().GetLocation(),
                                         option.Notification.Severity,
                                         locations,
                                         properties: null));

            FadeOutCode(context, matches.Value, locations);
        }
Пример #2
0
        protected override async Task FixAllAsync(
            Document document, ImmutableArray <Diagnostic> diagnostics,
            SyntaxEditor editor, CodeActionOptionsProvider options, CancellationToken cancellationToken)
        {
            // Fix-All for this feature is somewhat complicated.  As Object-Initializers
            // could be arbitrarily nested, we have to make sure that any edits we make
            // to one Object-Initializer are seen by any higher ones.  In order to do this
            // we actually process each object-creation-node, one at a time, rewriting
            // the tree for each node.  In order to do this effectively, we use the '.TrackNodes'
            // feature to keep track of all the object creation nodes as we make edits to
            // the tree.  If we didn't do this, then we wouldn't be able to find the
            // second object-creation-node after we make the edit for the first one.
            var services    = document.Project.Solution.Workspace.Services;
            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

            var originalRoot = editor.OriginalRoot;
            var originalObjectCreationNodes = new Stack <TObjectCreationExpressionSyntax>();

            foreach (var diagnostic in diagnostics)
            {
                var objectCreation = (TObjectCreationExpressionSyntax)originalRoot.FindNode(
                    diagnostic.AdditionalLocations[0].SourceSpan, getInnermostNodeForTie: true);
                originalObjectCreationNodes.Push(objectCreation);
            }

            // We're going to be continually editing this tree.  Track all the nodes we
            // care about so we can find them across each edit.
            document = document.WithSyntaxRoot(originalRoot.TrackNodes(originalObjectCreationNodes));

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

            var currentRoot = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            while (originalObjectCreationNodes.Count > 0)
            {
                var originalObjectCreation = originalObjectCreationNodes.Pop();
                var objectCreation         = currentRoot.GetCurrentNodes(originalObjectCreation).Single();

                var matches = UseNamedMemberInitializerAnalyzer <TExpressionSyntax, TStatementSyntax, TObjectCreationExpressionSyntax, TMemberAccessExpressionSyntax, TAssignmentStatementSyntax, TVariableDeclaratorSyntax> .Analyze(
                    semanticModel, syntaxFacts, objectCreation, cancellationToken);

                if (matches == null || matches.Value.Length == 0)
                {
                    continue;
                }

                var statement = objectCreation.FirstAncestorOrSelf <TStatementSyntax>();
                Contract.ThrowIfNull(statement);

                var newStatement = GetNewStatement(statement, objectCreation, matches.Value)
                                   .WithAdditionalAnnotations(Formatter.Annotation);

                var subEditor = new SyntaxEditor(currentRoot, services);

                subEditor.ReplaceNode(statement, newStatement);
                foreach (var match in matches)
                {
                    subEditor.RemoveNode(match.Statement, SyntaxRemoveOptions.KeepUnbalancedDirectives);
                }

                document      = document.WithSyntaxRoot(subEditor.GetChangedRoot());
                semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                currentRoot = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
            }

            editor.ReplaceNode(editor.OriginalRoot, currentRoot);
        }