Ejemplo n.º 1
0
 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));
 }
Ejemplo n.º 3
0
        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,
Ejemplo n.º 5
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,
Ejemplo n.º 6
0
 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);
Ejemplo n.º 8
0
 protected abstract SyntaxNode AddGlobalSuppressMessageAttribute(
     SyntaxNode newRoot,
     ISymbol targetSymbol,
     INamedTypeSymbol suppressMessageAttribute,
     Diagnostic diagnostic,
     HostWorkspaceServices services,
     SyntaxFormattingOptions options,
     IAddImportsService addImportsService,
     CancellationToken cancellationToken);
Ejemplo n.º 9
0
 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);
            }
Ejemplo n.º 11
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);
        }
Ejemplo n.º 12
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));
        }
Ejemplo n.º 13
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));
        }
Ejemplo n.º 14
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));
        }
    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);
            }