private IFormattingResult FormatMergedSpan(
            SyntaxNode node,
            AnalyzerConfigOptions options,
            IEnumerable <AbstractFormattingRule> rules,
            IList <TextSpan> spansToFormat,
            CancellationToken cancellationToken
            )
        {
            var spanToFormat = TextSpan.FromBounds(
                spansToFormat[0].Start,
                spansToFormat[spansToFormat.Count - 1].End
                );
            var pair = node.ConvertToTokenPair(spanToFormat);

            if (node.IsInvalidTokenRange(pair.Item1, pair.Item2))
            {
                return(CreateAggregatedFormattingResult(
                           node,
                           SpecializedCollections.EmptyList <AbstractFormattingResult>()
                           ));
            }

            // more expensive case
            var result = Format(node, options, rules, pair.Item1, pair.Item2, cancellationToken);

            return(CreateAggregatedFormattingResult(
                       node,
                       new List <AbstractFormattingResult>(1)
            {
                result
            },
                       SimpleIntervalTree.Create(new TextSpanIntervalIntrospector(), spanToFormat)
                       ));
        }
Пример #2
0
        /// <summary>
        /// Make sure annotations are positioned outside of any spans. If not, merge two adjacent spans to one.
        /// </summary>
        private IEnumerable <TextSpan> GetNonOverlappingSpans(ISyntaxFactsService syntaxFactsService, SyntaxNode root, IEnumerable <TextSpan> spans, CancellationToken cancellationToken)
        {
            // Create interval tree for spans
            var intervalTree = SimpleIntervalTree.Create(TextSpanIntervalIntrospector.Instance, spans);

            // Find tokens that are outside of spans
            var tokenSpans = new List <TextSpan>();

            foreach (var span in spans)
            {
                cancellationToken.ThrowIfCancellationRequested();

                SyntaxToken startToken;
                SyntaxToken endToken;
                TextSpan    spanAlignedToTokens = GetSpanAlignedToTokens(syntaxFactsService, root, span, out startToken, out endToken);

                SyntaxToken previousToken = startToken.GetPreviousToken(includeZeroWidth: true, includeSkipped: true, includeDirectives: true, includeDocumentationComments: true);
                SyntaxToken nextToken     = endToken.GetNextToken(includeZeroWidth: true, includeSkipped: true, includeDirectives: true, includeDocumentationComments: true);

                // Make sure the previous and next tokens we found do not overlap with any existing spans. If they do, merge two spans.
                previousToken = (previousToken.RawKind == 0) ? root.GetFirstToken(includeZeroWidth: true) : previousToken;
                var start = intervalTree.GetOverlappingIntervals(previousToken.SpanStart, previousToken.Span.Length).Any() ?
                            previousToken.SpanStart : startToken.SpanStart;

                nextToken = (nextToken.RawKind == 0) ? root.GetLastToken(includeZeroWidth: true) : nextToken;
                var end = intervalTree.GetOverlappingIntervals(nextToken.SpanStart, nextToken.Span.Length).Any() ?
                          nextToken.Span.End : endToken.Span.End;

                tokenSpans.Add(TextSpan.FromBounds(start, end));
            }

            return(tokenSpans.ToNormalizedSpans());
        }
Пример #3
0
 private SyntaxTreeState(bool completed, int?positionOfFirstReducingNullableDirective)
 {
     Completed = completed;
     PositionOfFirstReducingNullableDirective = positionOfFirstReducingNullableDirective;
     if (!completed)
     {
         IntervalTree = SimpleIntervalTree.Create(new TextSpanIntervalIntrospector(), Array.Empty <TextSpan>());
         PossibleNullableImpactIntervalTree = SimpleIntervalTree.Create(new TextSpanIntervalIntrospector(), Array.Empty <TextSpan>());
     }
 }
Пример #4
0
        private static IEnumerable <SimpleIntervalTree <Tuple <int, int, string> > > CreateTrees(IEnumerable <Tuple <int, int, string> > values)
        {
            yield return(SimpleIntervalTree.Create(new TupleIntrospector <string>(), values));

            var tree1 = SimpleIntervalTree.Create(new TupleIntrospector <string>());

            foreach (var v in values)
            {
                tree1 = tree1.AddInterval(v);
            }

            yield return(tree1);
        }
Пример #5
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
        }
Пример #6
0
        protected override SyntaxNode Rewriter(
            Dictionary <ValueTuple <SyntaxToken, SyntaxToken>, TriviaData> changeMap,
            CancellationToken cancellationToken
            )
        {
            var rewriter = new TriviaRewriter(
                this.TreeInfo.Root,
                SimpleIntervalTree.Create(new TextSpanIntervalIntrospector(), this.FormattedSpan),
                changeMap,
                cancellationToken
                );

            return(rewriter.Transform());
        }
        private async Task <IFormattingResult> FormatMergedSpanAsync(
            SyntaxNode node, OptionSet options, IEnumerable <IFormattingRule> rules, IList <TextSpan> spansToFormat, CancellationToken cancellationToken)
        {
            var spanToFormat = TextSpan.FromBounds(spansToFormat[0].Start, spansToFormat[spansToFormat.Count - 1].End);
            var pair         = node.ConvertToTokenPair(spanToFormat);

            if (node.IsInvalidTokenRange(pair.Item1, pair.Item2))
            {
                return(CreateAggregatedFormattingResult(node, SpecializedCollections.EmptyList <AbstractFormattingResult>()));
            }

            // more expensive case
            var result = await FormatAsync(node, options, rules, pair.Item1, pair.Item2, cancellationToken).ConfigureAwait(false);

            return(CreateAggregatedFormattingResult(node, new List <AbstractFormattingResult>(1)
            {
                result
            }, SimpleIntervalTree.Create(TextSpanIntervalIntrospector.Instance, spanToFormat)));
        }
Пример #8
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);
        }
 protected SimpleIntervalTree <TextSpan, TextSpanIntervalIntrospector> GetFormattingSpans() =>
 _formattingSpans
 ?? SimpleIntervalTree.Create(
     new TextSpanIntervalIntrospector(),
     _formattingResults.Select(r => r.FormattedSpan)
     );
Пример #10
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 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);
            }
Пример #12
0
 protected SimpleIntervalTree <TextSpan> GetFormattingSpans()
 {
     return(_formattingSpans ?? SimpleIntervalTree.Create(TextSpanIntervalIntrospector.Instance, _formattingResults.Select(r => r.FormattedSpan)));
 }