protected async Task <IDictionary <SyntaxNode, ISet <INamedTypeSymbol> > > GetAllReferencedDefinitionsAsync( Compilation compilation, IEnumerable <ISymbol> members, CancellationToken cancellationToken) { var namespaceScopeToReferencedDefinitions = new Dictionary <SyntaxNode, ISet <INamedTypeSymbol> >(); var root = await Document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); Func <SyntaxNode, ISet <INamedTypeSymbol> > createSet = _ => new HashSet <INamedTypeSymbol>(); var annotatedNodes = root.GetAnnotatedNodesAndTokens(SymbolAnnotation.Kind); foreach (var annotatedNode in annotatedNodes) { cancellationToken.ThrowIfCancellationRequested(); if (annotatedNode.GetAnnotations(DoNotAddImportsAnnotation.Kind).Any()) { continue; } SyntaxNode namespaceScope = null; var annotations = annotatedNode.GetAnnotations(SymbolAnnotation.Kind); foreach (var annotation in annotations) { cancellationToken.ThrowIfCancellationRequested(); foreach (var namedType in SymbolAnnotation.GetSymbols(annotation, compilation).OfType <INamedTypeSymbol>()) { cancellationToken.ThrowIfCancellationRequested(); if (!IsBuiltIn(namedType)) { namespaceScope = namespaceScope ?? this.GetInnermostNamespaceScope(annotatedNode); var referencedDefinitions = namespaceScopeToReferencedDefinitions.GetOrAdd( namespaceScope, createSet); referencedDefinitions.Add(namedType); } } } } return(namespaceScopeToReferencedDefinitions); }
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 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)); }