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,
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); }
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)); }
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)); }
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)); }