Example #1
0
        protected override SyntaxNode AddGlobalSuppressMessageAttribute(
            SyntaxNode newRoot,
            ISymbol targetSymbol,
            Diagnostic diagnostic,
            Workspace workspace,
            Compilation compilation,
            IAddImportsService addImportsService,
            CancellationToken cancellationToken)
        {
            var compilationRoot = (CompilationUnitSyntax)newRoot;
            var isFirst         = !compilationRoot.AttributeLists.Any();

            var fullAttributeName = (QualifiedNameSyntax)SyntaxFactory.ParseName(SuppressMessageAttributeName);
            var usingDirective    = SyntaxFactory.UsingDirective(fullAttributeName.Left);

            var hasUsingDirective = addImportsService.HasExistingImport(compilation, compilationRoot, contextLocation: null, usingDirective);

            if (!hasUsingDirective && isFirst)
            {
                compilationRoot   = Format(compilationRoot.AddUsings(usingDirective));
                hasUsingDirective = true;
            }

            compilationRoot = compilationRoot.AddAttributeLists(
                Format(CreateAttributeList(
                           targetSymbol,
                           diagnostic,
                           isAssemblyAttribute: true,
                           leadingTrivia: default,
Example #2
0
        private (ImmutableArray <SyntaxNode> imports, IEnumerable <INamespaceSymbol> namespaceSymbols, SyntaxNode?context) GetImportDirectivesFromAnnotatedNodes(
            IEnumerable <SyntaxNode> syntaxNodes,
            SyntaxNode root,
            SemanticModel model,
            IAddImportsService addImportsService,
            SyntaxGenerator generator,
            CancellationToken cancellationToken)
        {
            (SyntaxNode first, SyntaxNode last)? nodes = null;
            var importsToAdd = ArrayBuilder <SyntaxNode> .GetInstance();

            var annotatedNodes = syntaxNodes.Where(x => x.HasAnnotations(SymbolAnnotation.Kind));
            var addedSymbols   = new HashSet <INamespaceSymbol>();

            foreach (var annotatedNode in annotatedNodes)
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (annotatedNode.GetAnnotations(DoNotAddImportsAnnotation.Kind).Any())
                {
                    continue;
                }

                var annotations = annotatedNode.GetAnnotations(SymbolAnnotation.Kind);
                foreach (var annotation in annotations)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    foreach (var namedType in SymbolAnnotation.GetSymbols(annotation, model.Compilation).OfType <INamedTypeSymbol>())
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        if (namedType.OriginalDefinition.IsSpecialType() || namedType.IsNullable() || namedType.IsTupleType)
                        {
                            continue;
                        }

                        var namespaceSymbol = namedType.ContainingNamespace;
                        if (namespaceSymbol is null || namespaceSymbol.IsGlobalNamespace)
                        {
                            continue;
                        }

                        nodes = (first : nodes?.first ?? annotatedNode, last : annotatedNode);

                        if (addedSymbols.Contains(namespaceSymbol))
                        {
                            continue;
                        }

                        var namespaceSyntax = GenerateNamespaceImportDeclaration(namespaceSymbol, generator);

                        if (addImportsService.HasExistingImport(model.Compilation, root, annotatedNode, namespaceSyntax, generator))
                        {
                            continue;
                        }

                        if (IsInsideNamespace(annotatedNode, namespaceSymbol, model, cancellationToken))
                        {
                            continue;
                        }

                        addedSymbols.Add(namespaceSymbol);
                        importsToAdd.Add(namespaceSyntax);
                    }
                }
            }

            // we don't add simplifier annotations here,
            // since whatever added the symbol annotation probably also added simplifier annotations,
            // and if not they probably didn't for a reason

            return(importsToAdd.ToImmutableAndFree(), addedSymbols, nodes is var(first, last) ? first.GetCommonRoot(last) : null);
        }
Example #3
0
        private (ImmutableArray <SyntaxNode> imports, IEnumerable <INamespaceSymbol> namespaceSymbols, SyntaxNode?context) GetImportDirectivesFromSyntaxes(
            IEnumerable <SyntaxNode> syntaxNodes,
            ref SyntaxNode root,
            SemanticModel model,
            IAddImportsService addImportsService,
            SyntaxGenerator generator,
            CancellationToken cancellationToken
            )
        {
            var importsToAdd = ArrayBuilder <SyntaxNode> .GetInstance();

            var nodesWithExplicitNamespaces = syntaxNodes
                                              .Select(n => (syntaxnode: n, namespaceSymbol: GetExplicitNamespaceSymbol(n, model)))
                                              .Where(x => x.namespaceSymbol != null);

            using var _ = ArrayBuilder <SyntaxNode> .GetInstance(out var nodesToSimplify);

            var addedSymbols = new HashSet <INamespaceSymbol>();

            foreach (var(node, namespaceSymbol) in nodesWithExplicitNamespaces)
            {
                cancellationToken.ThrowIfCancellationRequested();

                nodesToSimplify.Add(node);

                if (addedSymbols.Contains(namespaceSymbol))
                {
                    continue;
                }

                var namespaceSyntax = GenerateNamespaceImportDeclaration(namespaceSymbol, generator);

                if (addImportsService.HasExistingImport(model.Compilation, root, node, namespaceSyntax, generator))
                {
                    continue;
                }

                if (IsInsideNamespace(node, namespaceSymbol, model, cancellationToken))
                {
                    continue;
                }

                addedSymbols.Add(namespaceSymbol);
                importsToAdd.Add(namespaceSyntax);
            }

            if (nodesToSimplify.Count == 0)
            {
                return(importsToAdd.ToImmutableAndFree(), addedSymbols, null);
            }

            var annotation = new SyntaxAnnotation();

            root = root.ReplaceNodes(
                nodesToSimplify,
                (o, r) => r.WithAdditionalAnnotations(Simplifier.Annotation, annotation));

            var first = root.DescendantNodesAndSelf().First(x => x.HasAnnotation(annotation));
            var last  = root.DescendantNodesAndSelf().Last(x => x.HasAnnotation(annotation));

            return(importsToAdd.ToImmutableAndFree(), addedSymbols, first.GetCommonRoot(last));
        }
Example #4
0
        private async Task <Document> AddImportDirectivesFromSymbolAnnotationsAsync(
            Document document,
            IEnumerable <SyntaxNode> syntaxNodes,
            IAddImportsService addImportsService,
            SyntaxGenerator generator,
            bool placeSystemNamespaceFirst,
            bool allowInHiddenRegions,
            CancellationToken cancellationToken)
        {
            using var _ = PooledDictionary <INamespaceSymbol, SyntaxNode> .GetInstance(out var importToSyntax);

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

            var model = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            SyntaxNode?first = null, last = null;
            var        annotatedNodes = syntaxNodes.Where(x => x.HasAnnotations(SymbolAnnotation.Kind));

            foreach (var annotatedNode in annotatedNodes)
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (annotatedNode.GetAnnotations(DoNotAddImportsAnnotation.Kind).Any())
                {
                    continue;
                }

                var annotations = annotatedNode.GetAnnotations(SymbolAnnotation.Kind);
                foreach (var annotation in annotations)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    foreach (var namedType in SymbolAnnotation.GetSymbols(annotation, model.Compilation).OfType <INamedTypeSymbol>())
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        if (namedType.OriginalDefinition.IsSpecialType() || namedType.IsNullable() || namedType.IsTupleType)
                        {
                            continue;
                        }

                        var namespaceSymbol = namedType.ContainingNamespace;
                        if (namespaceSymbol is null || namespaceSymbol.IsGlobalNamespace)
                        {
                            continue;
                        }

                        first ??= annotatedNode;
                        last = annotatedNode;

                        if (importToSyntax.ContainsKey(namespaceSymbol))
                        {
                            continue;
                        }

                        var namespaceSyntax = GenerateNamespaceImportDeclaration(namespaceSymbol, generator);
                        if (addImportsService.HasExistingImport(model.Compilation, root, annotatedNode, namespaceSyntax, generator))
                        {
                            continue;
                        }

                        if (IsInsideNamespace(annotatedNode, namespaceSymbol, model, cancellationToken))
                        {
                            continue;
                        }

                        importToSyntax[namespaceSymbol] = namespaceSyntax;
                    }
                }
            }

            if (first == null || last == null || importToSyntax.Count == 0)
            {
                return(document);
            }

            var context = first.GetCommonRoot(last);

            // Find the namespace/compilation-unit we'll be adding all these imports to.
            var importContainer = addImportsService.GetImportContainer(root, context, importToSyntax.First().Value);

            // Now remove any imports we think can cause conflicts in that container.
            var safeImportsToAdd = GetSafeToAddImports(importToSyntax.Keys.ToImmutableArray(), importContainer, model, cancellationToken);

            var importsToAdd = importToSyntax.Where(kvp => safeImportsToAdd.Contains(kvp.Key)).Select(kvp => kvp.Value).ToImmutableArray();

            if (importsToAdd.Length == 0)
            {
                return(document);
            }

            root = addImportsService.AddImports(
                model.Compilation, root, context, importsToAdd, generator,
                placeSystemNamespaceFirst, allowInHiddenRegions, cancellationToken);
            return(document.WithSyntaxRoot(root));
        }
Example #5
0
        private async Task <Document> AddImportDirectivesFromSyntaxesAsync(
            Document document,
            IEnumerable <SyntaxNode> syntaxNodes,
            IAddImportsService addImportsService,
            SyntaxGenerator generator,
            bool placeSystemNamespaceFirst,
            bool allowInHiddenRegions,
            CancellationToken cancellationToken)
        {
            using var _1 = ArrayBuilder <SyntaxNode> .GetInstance(out var importsToAdd);

            using var _2 = ArrayBuilder <SyntaxNode> .GetInstance(out var nodesToSimplify);

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

            var model = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var nodesWithExplicitNamespaces = syntaxNodes
                                              .Select(n => (syntaxnode: n, namespaceSymbol: GetExplicitNamespaceSymbol(n, model)))
                                              .Where(x => x.namespaceSymbol != null);

            var addedSymbols = new HashSet <INamespaceSymbol>();

            foreach (var(node, namespaceSymbol) in nodesWithExplicitNamespaces)
            {
                cancellationToken.ThrowIfCancellationRequested();

                nodesToSimplify.Add(node);

                if (addedSymbols.Contains(namespaceSymbol))
                {
                    continue;
                }

                var namespaceSyntax = GenerateNamespaceImportDeclaration(namespaceSymbol, generator);
                if (addImportsService.HasExistingImport(model.Compilation, root, node, namespaceSyntax, generator))
                {
                    continue;
                }

                if (IsInsideNamespace(node, namespaceSymbol, model, cancellationToken))
                {
                    continue;
                }

                addedSymbols.Add(namespaceSymbol);
                importsToAdd.Add(namespaceSyntax);
            }

            if (nodesToSimplify.Count == 0)
            {
                return(document);
            }

            var annotation = new SyntaxAnnotation();

            root = root.ReplaceNodes(
                nodesToSimplify,
                (o, r) => r.WithAdditionalAnnotations(Simplifier.Annotation, annotation));

            var first = root.DescendantNodesAndSelf().First(x => x.HasAnnotation(annotation));
            var last  = root.DescendantNodesAndSelf().Last(x => x.HasAnnotation(annotation));

            var context = first.GetCommonRoot(last);

            root = addImportsService.AddImports(
                model.Compilation, root, context, importsToAdd, generator,
                placeSystemNamespaceFirst, allowInHiddenRegions, cancellationToken);

            return(document.WithSyntaxRoot(root));
        }