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);
        }
示例#2
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
        }
        public AbstractAggregatedFormattingResult(
            SyntaxNode node,
            IList<AbstractFormattingResult> formattingResults,
            SimpleIntervalTree<TextSpan> formattingSpans)
        {
            Contract.ThrowIfNull(node);
            Contract.ThrowIfNull(formattingResults);

            this.Node = node;
            _formattingResults = formattingResults;
            _formattingSpans = formattingSpans;

            _lazyTextChanges = new CancellableLazy<IList<TextChange>>(CreateTextChanges);
            _lazyNode = new CancellableLazy<SyntaxNode>(CreateFormattedRoot);
        }
示例#4
0
        public TriviaRewriter(
            SyntaxNode node,
            SimpleIntervalTree<TextSpan> spanToFormat,
            Dictionary<ValueTuple<SyntaxToken, SyntaxToken>, TriviaData> map,
            CancellationToken cancellationToken)
        {
            Contract.ThrowIfNull(node);
            Contract.ThrowIfNull(map);

            _node = node;
            _spans = spanToFormat;
            _cancellationToken = cancellationToken;

            _trailingTriviaMap = new Dictionary<SyntaxToken, SyntaxTriviaList>();
            _leadingTriviaMap = new Dictionary<SyntaxToken, SyntaxTriviaList>();

            PreprocessTriviaListMap(map, cancellationToken);
        }
示例#5
0
        public async Task <Document> AddImportsAsync(
            Document document, IEnumerable <TextSpan> spans,
            OptionSet options, CancellationToken cancellationToken)
        {
            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);

            bool isInSpan(SyntaxNodeOrToken nodeOrToken) =>
            spansTree.HasIntervalThatOverlapsWith(nodeOrToken.FullSpan.Start, nodeOrToken.FullSpan.Length);

            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
        private static bool AllChangesCanBeApplied(
            SimpleIntervalTree <TextChange, IntervalIntrospector> cumulativeChanges,
            ImmutableArray <TextChange> currentChanges,
            ref TemporaryArray <TextChange> overlappingSpans,
            ref TemporaryArray <TextChange> intersectingSpans
            )
        {
            foreach (var change in currentChanges)
            {
                overlappingSpans.Clear();
                intersectingSpans.Clear();

                cumulativeChanges.FillWithIntervalsThatOverlapWith(
                    change.Span.Start,
                    change.Span.Length,
                    ref overlappingSpans
                    );

                cumulativeChanges.FillWithIntervalsThatIntersectWith(
                    change.Span.Start,
                    change.Span.Length,
                    ref intersectingSpans
                    );

                var value = ChangeCanBeApplied(
                    change,
                    overlappingSpans: in overlappingSpans,
                    intersectingSpans: in intersectingSpans
                    );
                if (!value)
                {
                    return(false);
                }
            }

            // All the changes would merge in fine.  We can absorb this.
            return(true);
        }
示例#7
0
        /// <summary>
        /// Returns true if the passed in node contains an interleaved pp directive.
        ///
        /// i.e. The following returns false:
        ///
        ///   void Foo() {
        /// #if true
        /// #endif
        ///   }
        ///
        /// #if true
        ///   void Foo() {
        ///   }
        /// #endif
        ///
        /// but these return true:
        ///
        /// #if true
        ///   void Foo() {
        /// #endif
        ///   }
        ///
        ///   void Foo() {
        /// #if true
        ///   }
        /// #endif
        ///
        /// #if true
        ///   void Foo() {
        /// #else
        ///   }
        /// #endif
        ///
        /// i.e. the method returns true if it contains a PP directive that belongs to a grouping
        /// constructs (like #if/#endif or #region/#endregion), but the grouping construct isn't
        /// entirely contained within the span of the node.
        /// </summary>
        public static bool ContainsInterleavedDirective(
            this SyntaxNode syntaxNode,
            CancellationToken cancellationToken)
        {
            // Check if this node contains a start or end pp construct whose matching construct is
            // not contained within this node.  If so, this node must be pinned and cannot move.
            //
            // Also, keep track of those spans so that if we see #else/#elif we can tell if they
            // belong to a pp span that is entirely within the node.
            var ifEndIfSpans = SimpleIntervalTree.Create(TextSpanIntervalIntrospector.Instance);

            var span = syntaxNode.Span;

            foreach (var token in syntaxNode.DescendantTokens())
            {
                if (ContainsInterleavedDirective(span, token, ref ifEndIfSpans, cancellationToken))
                {
                    return(true);
                }
            }

            return(false);
        }
示例#8
0
        protected override ImmutableArray <Diagnostic> AnalyzeSemanticModel(
            SemanticModelAnalysisContext context,
            SimpleIntervalTree <TextSpan, TextSpanIntervalIntrospector>?codeBlockIntervalTree
            )
        {
            var semanticModel     = context.SemanticModel;
            var cancellationToken = context.CancellationToken;

            var syntaxTree = semanticModel.SyntaxTree;
            var optionSet  = context.Options.GetAnalyzerOptionSet(syntaxTree, cancellationToken);
            var root       = syntaxTree.GetRoot(cancellationToken);

            var simplifier = new TypeSyntaxSimplifierWalker(
                this,
                semanticModel,
                optionSet,
                ignoredSpans: codeBlockIntervalTree,
                cancellationToken
                );

            simplifier.Visit(root);
            return(simplifier.Diagnostics);
        }
示例#9
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);
        }
 protected override IFormattingResult CreateAggregatedFormattingResult(SyntaxNode node, IList<AbstractFormattingResult> results, SimpleIntervalTree<TextSpan> formattingSpans = null)
 {
     return new AggregatedFormattingResult(node, results, formattingSpans);
 }
示例#11
0
        protected override void AnalyzeSemanticModel(SemanticModelAnalysisContext context, SimpleIntervalTree <TextSpan, TextSpanIntervalIntrospector>?codeBlockIntervalTree)
        {
            var semanticModel     = context.SemanticModel;
            var cancellationToken = context.CancellationToken;

            var syntaxTree = semanticModel.SyntaxTree;
            var optionSet  = context.Options.GetAnalyzerOptionSet(syntaxTree, cancellationToken);
            var root       = syntaxTree.GetRoot(cancellationToken);

            var simplifier = new TypeSyntaxSimplifierWalker(this, semanticModel, optionSet, ignoredSpans: codeBlockIntervalTree, cancellationToken);

            simplifier.Visit(root);
            if (!simplifier.HasDiagnostics)
            {
                return;
            }

            foreach (var diagnostic in simplifier.Diagnostics)
            {
                context.ReportDiagnostic(diagnostic);
            }
        }
        private async Task <Document> ReduceAsyncInternal(
            Document document,
            ImmutableArray <TextSpan> spans,
            OptionSet optionSet,
            ImmutableArray <AbstractReducer> reducers,
            CancellationToken cancellationToken)
        {
            // Create a simple interval tree for simplification spans.
            var spansTree = new SimpleIntervalTree <TextSpan>(TextSpanIntervalIntrospector.Instance, spans);

            bool isNodeOrTokenOutsideSimplifySpans(SyntaxNodeOrToken nodeOrToken) =>
            !spansTree.HasIntervalThatOverlapsWith(nodeOrToken.FullSpan.Start, nodeOrToken.FullSpan.Length);

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

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

            // 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 = await semanticModel.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);
            }

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

            if (nodesAndTokensToReduce.Any())
            {
                if (reducers.IsDefault)
                {
                    reducers = _reducers;
                }

                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);
        }
示例#13
0
 public AggregatedFormattingResult(SyntaxNode node, IList <AbstractFormattingResult> results, SimpleIntervalTree <TextSpan> formattingSpans) :
     base(node, results, formattingSpans)
 {
 }
示例#14
0
        private ImmutableArray <Diagnostic> AnalyzeSemanticModel(SemanticModelAnalysisContext context, int positionOfFirstReducingNullableDirective, SimpleIntervalTree <TextSpan, TextSpanIntervalIntrospector>?codeBlockIntervalTree, SimpleIntervalTree <TextSpan, TextSpanIntervalIntrospector>?possibleNullableImpactIntervalTree)
        {
            var root = context.SemanticModel.SyntaxTree.GetCompilationUnitRoot(context.CancellationToken);

            using (var simplifier = new NullableImpactingSpanWalker(context.SemanticModel, positionOfFirstReducingNullableDirective, ignoredSpans: codeBlockIntervalTree, context.CancellationToken))
            {
                simplifier.Visit(root);
                possibleNullableImpactIntervalTree ??= new SimpleIntervalTree <TextSpan, TextSpanIntervalIntrospector>(new TextSpanIntervalIntrospector(), values: null);
                foreach (var interval in simplifier.Spans)
                {
                    possibleNullableImpactIntervalTree.AddIntervalInPlace(interval);
                }
            }

            using var diagnostics = TemporaryArray <Diagnostic> .Empty;

            var compilationOptions = ((CSharpCompilationOptions)context.SemanticModel.Compilation.Options).NullableContextOptions;

            DirectiveTriviaSyntax? previousRetainedDirective = null;
            NullableContextOptions?retainedOptions           = compilationOptions;

            DirectiveTriviaSyntax?currentOptionsDirective = null;
            var currentOptions = retainedOptions;

            for (var directive = root.GetFirstDirective(); directive is not null; directive = directive.GetNextDirective())
            {
                context.CancellationToken.ThrowIfCancellationRequested();

                if (directive.IsKind(SyntaxKind.NullableDirectiveTrivia, out NullableDirectiveTriviaSyntax? nullableDirectiveTrivia))
                {
                    // Once we reach a new directive, check to see if we can remove the previous directive
                    var removedCurrent = false;
                    if (IsReducing(retainedOptions, currentOptions))
                    {
                        // We can't have found a reducing directive and not know which directive it was
                        Contract.ThrowIfNull(currentOptionsDirective);

                        if (possibleNullableImpactIntervalTree is null ||
                            !possibleNullableImpactIntervalTree.HasIntervalThatOverlapsWith(currentOptionsDirective.Span.End, nullableDirectiveTrivia.SpanStart - currentOptionsDirective.Span.End))
                        {
                            diagnostics.Add(Diagnostic.Create(Descriptor, currentOptionsDirective.GetLocation()));
                        }
                    }

                    if (!removedCurrent)
                    {
                        previousRetainedDirective = currentOptionsDirective;
                        retainedOptions           = currentOptions;
                    }

                    currentOptionsDirective = nullableDirectiveTrivia;
                    currentOptions          = CSharpRemoveRedundantNullableDirectiveDiagnosticAnalyzer.GetNullableContextOptions(compilationOptions, currentOptions, nullableDirectiveTrivia);
                }
                else if (directive.IsKind(SyntaxKind.IfDirectiveTrivia, SyntaxKind.ElifDirectiveTrivia, SyntaxKind.ElseDirectiveTrivia))
                {
                    possibleNullableImpactIntervalTree ??= new SimpleIntervalTree <TextSpan, TextSpanIntervalIntrospector>(new TextSpanIntervalIntrospector(), values: null);
                    possibleNullableImpactIntervalTree.AddIntervalInPlace(directive.Span);
                }
            }

            // Once we reach the end of the file, check to see if we can remove the last directive
            if (IsReducing(retainedOptions, currentOptions))
            {
                // We can't have found a reducing directive and not know which directive it was
                Contract.ThrowIfNull(currentOptionsDirective);

                if (possibleNullableImpactIntervalTree is null ||
                    !possibleNullableImpactIntervalTree.HasIntervalThatOverlapsWith(currentOptionsDirective.Span.End, root.Span.End - currentOptionsDirective.Span.End))
                {
                    diagnostics.Add(Diagnostic.Create(Descriptor, currentOptionsDirective.GetLocation()));
                }
            }

            return(diagnostics.ToImmutableAndClear());
        }
示例#15
0
 protected abstract IFormattingResult CreateAggregatedFormattingResult(SyntaxNode node, IList <AbstractFormattingResult> results, SimpleIntervalTree <TextSpan, TextSpanIntervalIntrospector> formattingSpans = null);
示例#16
0
 protected override IFormattingResult CreateAggregatedFormattingResult(SyntaxNode node, IList <AbstractFormattingResult> results, SimpleIntervalTree <TextSpan> formattingSpans = null)
 {
     return(new AggregatedFormattingResult(node, results, formattingSpans));
 }
示例#17
0
        public async Task <Document> AddImportsAsync(
            Document document,
            IEnumerable <TextSpan> spans,
            Strategy strategy,
            OptionSet?options,
            CancellationToken cancellationToken
            )
        {
            options ??= await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

            var root = await document
                       .GetRequiredSyntaxRootAsync(cancellationToken)
                       .ConfigureAwait(false);

            var addImportsService = document.GetRequiredLanguageService <IAddImportsService>();
            var generator         = document.GetRequiredLanguageService <SyntaxGenerator>();

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

            Func <SyntaxNode, bool> overlapsWithSpan = n =>
                                                       spansTree.HasIntervalThatOverlapsWith(n.FullSpan.Start, n.FullSpan.Length);

            // Only dive deeper into nodes that actually overlap with the span we care about.  And also only include
            // those child nodes that themselves overlap with the span.  i.e. if we have:
            //
            //                Parent
            //       /                    \
            //      A  [|   B     C   |]   D
            //
            // We'll dive under the parent because it overlaps with the span.  But we only want to include (and dive
            // into) B and C not A and D.
            var nodes = root.DescendantNodesAndSelf(overlapsWithSpan).Where(overlapsWithSpan);

            var placeSystemNamespaceFirst = options.GetOption(
                GenerationOptions.PlaceSystemNamespaceFirst,
                document.Project.Language
                );
            var allowInHiddenRegions = document.CanAddImportsInHiddenRegions();

            if (strategy == Strategy.AddImportsFromSymbolAnnotations)
            {
                return(await AddImportDirectivesFromSymbolAnnotationsAsync(
                           document,
                           nodes,
                           addImportsService,
                           generator,
                           placeSystemNamespaceFirst,
                           allowInHiddenRegions,
                           cancellationToken
                           )
                       .ConfigureAwait(false));
            }

            if (strategy == Strategy.AddImportsFromSyntaxes)
            {
                return(await AddImportDirectivesFromSyntaxesAsync(
                           document,
                           nodes,
                           addImportsService,
                           generator,
                           placeSystemNamespaceFirst,
                           allowInHiddenRegions,
                           cancellationToken
                           )
                       .ConfigureAwait(false));
            }

            throw ExceptionUtilities.UnexpectedValue(strategy);
        }
 protected override IFormattingResult CreateAggregatedFormattingResult(SyntaxNode node, IList <AbstractFormattingResult> results, SimpleIntervalTree <TextSpan, TextSpanIntervalIntrospector>?formattingSpans = null)
 => new AggregatedFormattingResult(node, results, formattingSpans);
示例#19
0
 protected abstract ImmutableArray <Diagnostic> AnalyzeSemanticModel(SemanticModelAnalysisContext context, SimpleIntervalTree <TextSpan, TextSpanIntervalIntrospector>?codeBlockIntervalTree);
示例#20
0
        protected override SyntaxNode Rewriter(Dictionary <ValueTuple <SyntaxToken, SyntaxToken>, TriviaData> changeMap, CancellationToken cancellationToken)
        {
            var rewriter = new TriviaRewriter(this.TreeInfo.Root, SimpleIntervalTree.Create(TextSpanIntervalIntrospector.Instance, this.FormattedSpan), changeMap, cancellationToken);

            return(rewriter.Transform());
        }
示例#21
0
 protected SimpleIntervalTree <TextSpan> GetFormattingSpans()
 {
     return(_formattingSpans ?? SimpleIntervalTree.Create(TextSpanIntervalIntrospector.Instance, _formattingResults.Select(r => r.FormattedSpan)));
 }
            public void AnalyzeCodeBlock(CodeBlockAnalysisContext context)
            {
                if (_analyzer.IsIgnoredCodeBlock(context.CodeBlock))
                {
                    return;
                }

                var(completed, intervalTree) = _codeBlockIntervals.GetOrAdd(context.CodeBlock.SyntaxTree, _ => (new StrongBox <bool>(false), SimpleIntervalTree.Create(new TextSpanIntervalIntrospector(), Array.Empty <TextSpan>())));
                if (completed.Value)
                {
                    return;
                }

                RoslynDebug.AssertNotNull(intervalTree);
                lock (completed)
                {
                    if (completed.Value)
                    {
                        return;
                    }

                    if (intervalTree.HasIntervalThatOverlapsWith(context.CodeBlock.FullSpan.Start, context.CodeBlock.FullSpan.End))
                    {
                        return;
                    }

                    intervalTree.AddIntervalInPlace(context.CodeBlock.FullSpan);
                }

                _analyzer.AnalyzeCodeBlock(context);
            }
示例#23
0
 /// <summary>
 /// check whether the given span is intersects with the tree
 /// </summary>
 public static bool IntersectsWith(this SimpleIntervalTree <TextSpan> tree, TextSpan span)
 {
     return(tree.GetIntersectingIntervals(span.Start, span.Length).Any());
 }
 protected abstract IFormattingResult CreateAggregatedFormattingResult(SyntaxNode node, IList<AbstractFormattingResult> results, SimpleIntervalTree<TextSpan> formattingSpans = null);
 protected abstract void AnalyzeSemanticModel(SemanticModelAnalysisContext context, SimpleIntervalTree <TextSpan, TextSpanIntervalIntrospector>?codeBlockIntervalTree);
 public AggregatedFormattingResult(SyntaxNode node, IList<AbstractFormattingResult> results, SimpleIntervalTree<TextSpan> formattingSpans) :
     base(node, results, formattingSpans)
 {
 }
示例#27
0
 private static IEnumerable <SimpleIntervalTree <Tuple <int, int, string>, TupleIntrospector <string> > > CreateTrees(IEnumerable <Tuple <int, int, string> > values)
 {
     yield return(SimpleIntervalTree.Create(new TupleIntrospector <string>(), values));
 }
        public TypeSyntaxSimplifierWalker(CSharpSimplifyTypeNamesDiagnosticAnalyzer analyzer, SemanticModel semanticModel, OptionSet optionSet, SimpleIntervalTree <TextSpan, TextSpanIntervalIntrospector>?ignoredSpans, CancellationToken cancellationToken)
            : base(SyntaxWalkerDepth.StructuredTrivia)
        {
            _analyzer          = analyzer;
            _semanticModel     = semanticModel;
            _optionSet         = optionSet;
            _ignoredSpans      = ignoredSpans;
            _cancellationToken = cancellationToken;

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

            _aliasedNames = GetAliasedNames(root as CompilationUnitSyntax);
        }
 protected SimpleIntervalTree <TextSpan, TextSpanIntervalIntrospector> GetFormattingSpans() =>
 _formattingSpans
 ?? SimpleIntervalTree.Create(
     new TextSpanIntervalIntrospector(),
     _formattingResults.Select(r => r.FormattedSpan)
     );
示例#30
0
 /// <summary>
 /// check whether the given span is intersects with the tree
 /// </summary>
 public static bool HasIntervalThatIntersectsWith(
     this SimpleIntervalTree <TextSpan, TextSpanIntervalIntrospector> tree,
     TextSpan span
     ) => tree.HasIntervalThatIntersectsWith(span.Start, span.Length);
示例#31
0
        public async Task <Document> AddImportsAsync(
            Document document,
            IEnumerable <TextSpan> spans,
            Strategy strategy,
            bool safe,
            OptionSet?options,
            CancellationToken cancellationToken)
        {
            options ??= await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

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

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

            var addImportsService = document.GetRequiredLanguageService <IAddImportsService>();
            var generator         = document.GetRequiredLanguageService <SyntaxGenerator>();

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

            var nodes = root.DescendantNodesAndSelf().Where(IsInSpan);

            var(importDirectivesToAdd, namespaceSymbols, context) = strategy switch
            {
                Strategy.AddImportsFromSymbolAnnotations
                => GetImportDirectivesFromAnnotatedNodes(nodes, root, model, addImportsService, generator, cancellationToken),
                Strategy.AddImportsFromSyntaxes
                => GetImportDirectivesFromSyntaxes(nodes, ref root, model, addImportsService, generator, cancellationToken),
                _ => throw new InvalidEnumArgumentException(nameof(strategy), (int)strategy, typeof(Strategy)),
            };

            if (importDirectivesToAdd.Length == 0)
            {
                return(document.WithSyntaxRoot(root)); //keep any added simplifier annotations
            }

            if (safe)
            {
                // Mark the context with an annotation.
                // This will allow us to find it after we have called MakeSafeToAddNamespaces.
                var annotation = new SyntaxAnnotation();
                RoslynDebug.Assert(context is object);
                document = document.WithSyntaxRoot(root.ReplaceNode(context, context.WithAdditionalAnnotations(annotation)));
                root     = (await document.GetSyntaxRootAsync().ConfigureAwait(false)) !;

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

                Contract.ThrowIfNull(model);

                // Make Safe to add namespaces
                document = document.WithSyntaxRoot(
                    MakeSafeToAddNamespaces(root, namespaceSymbols, model, document.Project.Solution.Workspace, cancellationToken));
                root = (await document.GetSyntaxRootAsync().ConfigureAwait(false)) !;

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

                Contract.ThrowIfNull(model);

                // Find the context. It might be null if we have removed the context in the process of complexifying the tree.
                context = root.DescendantNodesAndSelf().FirstOrDefault(x => x.HasAnnotation(annotation)) ?? root;
            }

            var placeSystemNamespaceFirst = options.GetOption(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language);

            root = addImportsService.AddImports(model.Compilation, root, context, importDirectivesToAdd, generator, placeSystemNamespaceFirst, cancellationToken);

            return(document.WithSyntaxRoot(root));

            bool IsInSpan(SyntaxNode node) =>
            spansTree.HasIntervalThatOverlapsWith(node.FullSpan.Start, node.FullSpan.Length);
        }
        public TypeSyntaxSimplifierWalker(CSharpSimplifyTypeNamesDiagnosticAnalyzer analyzer, SemanticModel semanticModel, CSharpSimplifierOptions options, SimpleIntervalTree <TextSpan, TextSpanIntervalIntrospector>?ignoredSpans, CancellationToken cancellationToken)
            : base(SyntaxWalkerDepth.StructuredTrivia)
        {
            _analyzer          = analyzer;
            _semanticModel     = semanticModel;
            _options           = options;
            _ignoredSpans      = ignoredSpans;
            _cancellationToken = cancellationToken;

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

            _aliasedNames = PooledHashSet <string> .GetInstance();

            AddAliasedNames((CompilationUnitSyntax)root);
        }