示例#1
0
        public async Task <Document> AddImportsAsync(Document document, IEnumerable <TextSpan> spans, OptionSet options, CancellationToken cancellationToken)
        {
            options = options ?? await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

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

            var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);

            // Create a simple interval tree for simplification spans.
            var spansTree = new SimpleIntervalTree <TextSpan>(TextSpanIntervalIntrospector.Instance, spans);

            Func <SyntaxNodeOrToken, bool> isInSpan = (nodeOrToken) =>
                                                      spansTree.GetOverlappingIntervals(nodeOrToken.FullSpan.Start, nodeOrToken.FullSpan.Length).Any();

            var nodesWithExplicitNamespaces = root.DescendantNodesAndSelf().Where(n => isInSpan(n) && GetExplicitNamespaceSymbol(n, model) != null).ToList();

            var namespacesToAdd = new HashSet <INamespaceSymbol>();

            namespacesToAdd.AddRange(nodesWithExplicitNamespaces.Select(n => GetExplicitNamespaceSymbol(n, model)));

            // annotate these nodes so they get simplified later
            var newRoot  = root.ReplaceNodes(nodesWithExplicitNamespaces, (o, r) => r.WithAdditionalAnnotations(Simplifier.Annotation));
            var newDoc   = document.WithSyntaxRoot(newRoot);
            var newModel = await newDoc.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            newRoot = await this.AddNamespaceImportsAsync(newDoc, newModel, options, namespacesToAdd, cancellationToken).ConfigureAwait(false);

            return(document.WithSyntaxRoot(newRoot));
        }
        public async Task<Document> AddImportsAsync(Document document, IEnumerable<TextSpan> spans, OptionSet options, CancellationToken cancellationToken)
        {
            options = options ?? document.Project.Solution.Workspace.Options;

            var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
            var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);

            // Create a simple interval tree for simplification spans.
            var spansTree = new SimpleIntervalTree<TextSpan>(TextSpanIntervalIntrospector.Instance, spans);

            Func<SyntaxNodeOrToken, bool> isInSpan = (nodeOrToken) =>
                spansTree.GetOverlappingIntervals(nodeOrToken.FullSpan.Start, nodeOrToken.FullSpan.Length).Any();

            var nodesWithExplicitNamespaces = root.DescendantNodesAndSelf().Where(n => isInSpan(n) && GetExplicitNamespaceSymbol(n, model) != null).ToList();

            var namespacesToAdd = new HashSet<INamespaceSymbol>();
            namespacesToAdd.AddRange(nodesWithExplicitNamespaces.Select(n => GetExplicitNamespaceSymbol(n, model)));

            // annotate these nodes so they get simplified later
            var newRoot = root.ReplaceNodes(nodesWithExplicitNamespaces, (o, r) => r.WithAdditionalAnnotations(Simplifier.Annotation));
            var newDoc = document.WithSyntaxRoot(newRoot);
            var newModel = await newDoc.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            newRoot = await this.AddNamespaceImportsAsync(newDoc, newModel, options, namespacesToAdd, cancellationToken).ConfigureAwait(false);
            return document.WithSyntaxRoot(newRoot);
        }
示例#3
0
        private void Validate(TextSpan textSpan)
        {
#if DEBUG
            if (nonOverlappingSpans == null)
            {
                nonOverlappingSpans = SimpleIntervalTree.Create(TextSpanIntervalIntrospector.Instance);
            }

            // new span should not overlap with any span that we already have.
            Contract.Requires(!nonOverlappingSpans.GetOverlappingIntervals(textSpan.Start, textSpan.Length).Any());

            nonOverlappingSpans = nonOverlappingSpans.AddInterval(textSpan);
#endif
        }
        private async Task <SyntaxNode> ReduceAsync(
            Document document,
            SyntaxNode root,
            SemanticModel semanticModel,
            IEnumerable <TextSpan> spans,
            OptionSet optionSet,
            IEnumerable <AbstractReducer> reducers,
            CancellationToken cancellationToken)
        {
            // Create a simple interval tree for simplification spans.
            var spansTree = new SimpleIntervalTree <TextSpan>(TextSpanIntervalIntrospector.Instance, spans);

            Func <SyntaxNodeOrToken, bool> isNodeOrTokenOutsideSimplifySpans = (nodeOrToken) =>
                                                                               !spansTree.GetOverlappingIntervals(nodeOrToken.FullSpan.Start, nodeOrToken.FullSpan.Length).Any();

            // Get the list of syntax nodes and tokens that need to be reduced.
            ImmutableArray <NodeOrTokenToReduce> nodesAndTokensToReduce = this.GetNodesAndTokensToReduce(root, isNodeOrTokenOutsideSimplifySpans);

            if (nodesAndTokensToReduce.Any())
            {
                if (reducers == null)
                {
                    reducers = this.GetReducers();
                }

                var reducedNodesMap  = new ConcurrentDictionary <SyntaxNode, SyntaxNode>();
                var reducedTokensMap = new ConcurrentDictionary <SyntaxToken, SyntaxToken>();

                // Reduce all the nodesAndTokensToReduce using the given reducers/rewriters and
                // store the reduced nodes and/or tokens in the reduced nodes/tokens maps.
                // Note that this method doesn't update the original syntax tree.
                await this.ReduceAsync(document, root, nodesAndTokensToReduce, reducers, optionSet, semanticModel, reducedNodesMap, reducedTokensMap, cancellationToken).ConfigureAwait(false);

                if (reducedNodesMap.Any() || reducedTokensMap.Any())
                {
                    // Update the syntax tree with reduced nodes/tokens.
                    root = root.ReplaceSyntax(
                        nodes: reducedNodesMap.Keys,
                        computeReplacementNode: (o, n) => TransformReducedNode(reducedNodesMap[o], n),
                        tokens: reducedTokensMap.Keys,
                        computeReplacementToken: (o, n) => reducedTokensMap[o],
                        trivia: SpecializedCollections.EmptyEnumerable <SyntaxTrivia>(),
                        computeReplacementTrivia: null);
                }
            }

            return(root);
        }
示例#5
0
        public async Task <Document> AddImportsAsync(
            Document document, IEnumerable <TextSpan> spans,
            OptionSet options, CancellationToken cancellationToken)
        {
            options = options ?? await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

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

            var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);

            // Create a simple interval tree for simplification spans.
            var spansTree = new SimpleIntervalTree <TextSpan>(TextSpanIntervalIntrospector.Instance, spans);

            Func <SyntaxNodeOrToken, bool> isInSpan = nodeOrToken =>
                                                      spansTree.GetOverlappingIntervals(nodeOrToken.FullSpan.Start, nodeOrToken.FullSpan.Length).Any();

            var nodesWithExplicitNamespaces = root.DescendantNodesAndSelf().Where(n => isInSpan(n) && GetExplicitNamespaceSymbol(n, model) != null).ToList();

            var namespacesToAdd = new HashSet <INamespaceSymbol>();

            namespacesToAdd.AddRange(nodesWithExplicitNamespaces.Select(
                                         n => GetExplicitNamespaceSymbol(n, model)));

            var generator = SyntaxGenerator.GetGenerator(document);
            var imports   = namespacesToAdd.Select(ns => generator.NamespaceImportDeclaration(ns.ToDisplayString()).WithAdditionalAnnotations(Simplifier.Annotation))
                            .ToArray();

            // annotate these nodes so they get simplified later
            var newRoot = root.ReplaceNodes(
                nodesWithExplicitNamespaces,
                (o, r) => r.WithAdditionalAnnotations(Simplifier.Annotation));

            var placeSystemNamespaceFirst = options.GetOption(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language);
            var addImportsService         = document.GetLanguageService <IAddImportsService>();
            var finalRoot = addImportsService.AddImports(
                model.Compilation, newRoot, newRoot, imports, placeSystemNamespaceFirst);

            return(document.WithSyntaxRoot(finalRoot));
        }
示例#6
0
        public async Task<Document> AddImportsAsync(
            Document document, IEnumerable<TextSpan> spans,
            OptionSet options, CancellationToken cancellationToken)
        {
            options = options ?? await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

            var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
            var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);

            // Create a simple interval tree for simplification spans.
            var spansTree = new SimpleIntervalTree<TextSpan>(TextSpanIntervalIntrospector.Instance, spans);

            Func<SyntaxNodeOrToken, bool> isInSpan = nodeOrToken =>
                spansTree.GetOverlappingIntervals(nodeOrToken.FullSpan.Start, nodeOrToken.FullSpan.Length).Any();

            var nodesWithExplicitNamespaces = root.DescendantNodesAndSelf().Where(n => isInSpan(n) && GetExplicitNamespaceSymbol(n, model) != null).ToList();

            var namespacesToAdd = new HashSet<INamespaceSymbol>();
            namespacesToAdd.AddRange(nodesWithExplicitNamespaces.Select(
                n => GetExplicitNamespaceSymbol(n, model)));

            var generator = SyntaxGenerator.GetGenerator(document);
            var imports = namespacesToAdd.Select(ns => generator.NamespaceImportDeclaration(ns.ToDisplayString()).WithAdditionalAnnotations(Simplifier.Annotation))
                                         .ToArray();

            // annotate these nodes so they get simplified later
            var newRoot = root.ReplaceNodes(
                nodesWithExplicitNamespaces,
                (o, r) => r.WithAdditionalAnnotations(Simplifier.Annotation));

            var placeSystemNamespaceFirst = options.GetOption(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language);
            var addImportsService = document.GetLanguageService<IAddImportsService>();
            var finalRoot = addImportsService.AddImports(
                model.Compilation, newRoot, newRoot, imports, placeSystemNamespaceFirst);

            return document.WithSyntaxRoot(finalRoot);
        }
        private async Task <Document> ReduceAsyncInternal(
            Document document,
            List <TextSpan> spans,
            OptionSet optionSet,
            IEnumerable <AbstractReducer> reducers,
            CancellationToken cancellationToken)
        {
            // Create a simple interval tree for simplification spans.
            var spansTree = new SimpleIntervalTree <TextSpan>(TextSpanIntervalIntrospector.Instance, spans);

            Func <SyntaxNodeOrToken, bool> isNodeOrTokenOutsideSimplifySpans = (nodeOrToken) =>
                                                                               !spansTree.GetOverlappingIntervals(nodeOrToken.FullSpan.Start, nodeOrToken.FullSpan.Length).Any();

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var root = semanticModel.SyntaxTree.GetRoot(cancellationToken);

            // prep namespace imports marked for simplification
            var removeIfUnusedAnnotation = new SyntaxAnnotation();
            var originalRoot             = root;

            root = this.PrepareNamespaceImportsForRemovalIfUnused(document, root, removeIfUnusedAnnotation, isNodeOrTokenOutsideSimplifySpans);
            var hasImportsToSimplify = root != originalRoot;

            if (hasImportsToSimplify)
            {
                document      = document.WithSyntaxRoot(root);
                semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                root = semanticModel.SyntaxTree.GetRoot(cancellationToken);
            }

            // Get the list of syntax nodes and tokens that need to be reduced.
            var nodesAndTokensToReduce = this.GetNodesAndTokensToReduce(root, isNodeOrTokenOutsideSimplifySpans);

            if (nodesAndTokensToReduce.Any())
            {
                if (reducers == null)
                {
                    reducers = this.GetReducers();
                }

                var reducedNodesMap  = new ConcurrentDictionary <SyntaxNode, SyntaxNode>();
                var reducedTokensMap = new ConcurrentDictionary <SyntaxToken, SyntaxToken>();

                // Reduce all the nodesAndTokensToReduce using the given reducers/rewriters and
                // store the reduced nodes and/or tokens in the reduced nodes/tokens maps.
                // Note that this method doesn't update the original syntax tree.
                await this.ReduceAsync(document, root, nodesAndTokensToReduce, reducers, optionSet, semanticModel, reducedNodesMap, reducedTokensMap, cancellationToken).ConfigureAwait(false);

                if (reducedNodesMap.Any() || reducedTokensMap.Any())
                {
                    // Update the syntax tree with reduced nodes/tokens.
                    root = root.ReplaceSyntax(
                        nodes: reducedNodesMap.Keys,
                        computeReplacementNode: (o, n) => TransformReducedNode(reducedNodesMap[o], n),
                        tokens: reducedTokensMap.Keys,
                        computeReplacementToken: (o, n) => reducedTokensMap[o],
                        trivia: SpecializedCollections.EmptyEnumerable <SyntaxTrivia>(),
                        computeReplacementTrivia: null);

                    document = document.WithSyntaxRoot(root);
                }
            }

            if (hasImportsToSimplify)
            {
                // remove any unused namespace imports that were marked for simplification
                document = await this.RemoveUnusedNamespaceImportsAsync(document, removeIfUnusedAnnotation, cancellationToken).ConfigureAwait(false);
            }

            return(document);
        }