public static SyntaxNode AddImport( this IAddImportsService service, SyntaxNode root, SyntaxNode contextLocation, SyntaxNode newImport, bool placeSystemNamespaceFirst) { return service.AddImports(root, contextLocation, SpecializedCollections.SingletonEnumerable(newImport), placeSystemNamespaceFirst); }
public static SyntaxNode AddImport( this IAddImportsService service, Compilation compilation, SyntaxNode root, SyntaxNode contextLocation, SyntaxNode newImport, SyntaxGenerator generator, bool placeSystemNamespaceFirst, CancellationToken cancellationToken) { return(service.AddImports(compilation, root, contextLocation, SpecializedCollections.SingletonEnumerable(newImport), generator, placeSystemNamespaceFirst, cancellationToken)); }
protected override SyntaxNode AddGlobalSuppressMessageAttribute( SyntaxNode newRoot, ISymbol targetSymbol, INamedTypeSymbol suppressMessageAttribute, Diagnostic diagnostic, HostSolutionServices services, SyntaxFormattingOptions options, IAddImportsService addImportsService, CancellationToken cancellationToken) { var compilationRoot = (CompilationUnitSyntax)newRoot; var isFirst = !compilationRoot.AttributeLists.Any(); var attributeName = suppressMessageAttribute.GenerateNameSyntax() .WithAdditionalAnnotations(Simplifier.AddImportsAnnotation); compilationRoot = compilationRoot.AddAttributeLists( CreateAttributeList( targetSymbol, attributeName, diagnostic, isAssemblyAttribute: true, leadingTrivia: default)); if (isFirst && !newRoot.HasLeadingTrivia) { compilationRoot = compilationRoot.WithLeadingTrivia(SyntaxFactory.Comment(GlobalSuppressionsFileHeaderComment)); } return(compilationRoot); }
protected override SyntaxNode AddGlobalSuppressMessageAttribute( SyntaxNode newRoot, ISymbol targetSymbol, INamedTypeSymbol suppressMessageAttribute, Diagnostic diagnostic, Workspace workspace, Compilation compilation, IAddImportsService addImportsService, CancellationToken cancellationToken ) { var compilationRoot = (CompilationUnitSyntax)newRoot; var isFirst = !compilationRoot.AttributeLists.Any(); var attributeName = suppressMessageAttribute .GenerateNameSyntax() .WithAdditionalAnnotations(Simplifier.AddImportsAnnotation); compilationRoot = compilationRoot.AddAttributeLists( CreateAttributeList( targetSymbol, attributeName, diagnostic, isAssemblyAttribute: true, leadingTrivia: default,
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,
public static SyntaxNode AddImport( this IAddImportsService service, Compilation compilation, SyntaxNode root, SyntaxNode contextLocation, SyntaxNode newImport, SyntaxGenerator generator, AddImportPlacementOptions options, CancellationToken cancellationToken) { return(service.AddImports(compilation, root, contextLocation, SpecializedCollections.SingletonEnumerable(newImport), generator, options, cancellationToken)); }
protected abstract SyntaxNode AddGlobalSuppressMessageAttribute( SyntaxNode newRoot, ISymbol targetSymbol, Diagnostic diagnostic, Workspace workspace, Compilation compilation, IAddImportsService addImportsService, CancellationToken cancellationToken);
protected abstract SyntaxNode AddGlobalSuppressMessageAttribute( SyntaxNode newRoot, ISymbol targetSymbol, INamedTypeSymbol suppressMessageAttribute, Diagnostic diagnostic, HostWorkspaceServices services, SyntaxFormattingOptions options, IAddImportsService addImportsService, CancellationToken cancellationToken);
public static SyntaxNode AddImport( this IAddImportsService service, Compilation compilation, SyntaxNode root, SyntaxNode contextLocation, SyntaxNode newImport, SyntaxGenerator generator, CodeGenerationPreferences preferences, bool allowInHiddenRegions, CancellationToken cancellationToken) { return(service.AddImports(compilation, root, contextLocation, SpecializedCollections.SingletonEnumerable(newImport), generator, preferences, allowInHiddenRegions, cancellationToken)); }
/// <summary> /// Add imports for the namespace specified by <paramref name="names"/> /// to the provided <paramref name="containers"/> /// </summary> private async Task <Document> AddImportsInContainersAsync( Document document, IAddImportsService addImportService, ImmutableArray <SyntaxNode> containers, ImmutableArray <string> names, bool placeSystemNamespaceFirst, CancellationToken cancellationToken) { // Sort containers based on their span start, to make the result of // adding imports deterministic. if (containers.Length > 1) { containers = containers.Sort(SyntaxNodeSpanStartComparer.Instance); } var imports = CreateImports(document, names, withFormatterAnnotation: true); foreach (var container in containers) { // If the container is a namespace declaration, the context we pass to // AddImportService must be a child of the declaration, otherwise the // import will be added to root node instead. var contextLocation = container is TNamespaceDeclarationSyntax ? container.DescendantNodes().First() : container; var compilation = await document.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); root = addImportService.AddImports(compilation, root, contextLocation, imports, placeSystemNamespaceFirst); document = document.WithSyntaxRoot(root); } return(document); }
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)); }
internal static async ValueTask <AddImportPlacementOptions> GetAddImportPlacementOptionsAsync(this Document document, IAddImportsService addImportsService, AddImportPlacementOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) { #if CODE_STYLE var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); return(addImportsService.GetAddImportOptions(document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree), allowInHiddenRegions: false, fallbackOptions: null)); #else return(await document.GetAddImportPlacementOptionsAsync(fallbackOptionsProvider, cancellationToken).ConfigureAwait(false)); #endif }
/// <summary> /// Fix each reference and return a collection of proper containers (innermost container /// with imports) that new import should be added to based on reference locations. /// If <paramref name="namespaceParts"/> is specified (not default), the fix would be: /// 1. qualify the reference with new namespace and mark it for simplification, or /// 2. find and mark the qualified reference for simplification. /// Otherwise, there would be no namespace replacement. /// </summary> private async Task <(Document, ImmutableArray <SyntaxNode>)> FixReferencesAsync( Document document, IAddImportsService addImportService, ISyncNamespaceService syncNamespaceService, IEnumerable <ReferenceLocation> refLocations, ImmutableArray <string> namespaceParts, CancellationToken cancellationToken) { var editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); var root = editor.OriginalRoot; var containers = PooledHashSet <SyntaxNode> .GetInstance(); var generator = SyntaxGenerator.GetGenerator(document); var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>(); // We need a dummy import to figure out the container for given reference. var dummyImport = CreateImport(generator, "Dummy", withFormatterAnnotation: false); foreach (var refLoc in refLocations) { Debug.Assert(document.Id == refLoc.Document.Id); // Ignore references via alias. For simple cases where the alias is defined as the type we are interested, // it will be handled properly because it is one of the reference to the type symbol. Otherwise, we don't // attempt to make a potential fix, and user might end up with errors as a result. if (refLoc.Alias != null) { continue; } // Other documents in the solution might have changed after we calculated those ReferenceLocation, // so we can't trust anything to be still up-to-date except their spans. // Get inner most node in case of type used as a base type. e.g. // // public class Foo {} // public class Bar : Foo {} // // For the reference to Foo where it is used as a base class, the BaseTypeSyntax and the TypeSyntax // have exact same span. var refNode = root.FindNode(refLoc.Location.SourceSpan, findInsideTrivia: true, getInnermostNodeForTie: true); if (syncNamespaceService.TryGetReplacementReferenceSyntax( refNode, namespaceParts, syntaxFacts, out var oldNode, out var newNode)) { editor.ReplaceNode(oldNode, newNode.WithAdditionalAnnotations(Simplifier.Annotation)); } // Use a dummy import node to figure out which container the new import will be added to. var container = addImportService.GetImportContainer(root, refNode, dummyImport); containers.Add(container); } foreach (var container in containers) { editor.TrackNode(container); } var fixedDocument = editor.GetChangedDocument(); root = await fixedDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var result = (fixedDocument, containers.SelectAsArray(c => root.GetCurrentNode(c))); containers.Free(); return(result); }