Exemple #1
0
        public int GetIndentationOfCurrentPosition(
            SyntaxNode root,
            IndentBlockOperation startingOperation,
            Func <SyntaxToken, int> tokenColumnGetter,
            CancellationToken cancellationToken)
        {
            var token = startingOperation.StartToken;

            // gather all indent operations
            var list = GetParentIndentBlockOperations(token);

            // remove one that is smaller than current one
            for (int i = list.Count - 1; i >= 0; i--)
            {
                if (CommonFormattingHelpers.IndentBlockOperationComparer(startingOperation, list[i]) < 0)
                {
                    list.RemoveAt(i);
                }
                else
                {
                    break;
                }
            }

            return(GetIndentationOfCurrentPosition(root, token, list, token.SpanStart, /* extraSpaces */ 0, tokenColumnGetter, cancellationToken));
        }
Exemple #2
0
        private SyntaxToken FindCorrectBaseTokenOfRelativeIndentBlockOperation(IndentBlockOperation operation, TokenStream tokenStream)
        {
            if (operation.Option.IsOn(IndentBlockOption.RelativeToFirstTokenOnBaseTokenLine))
            {
                return(tokenStream.FirstTokenOfBaseTokenLine(operation.BaseToken));
            }

            return(operation.BaseToken);
        }
Exemple #3
0
 public RelativeIndentationData(
     int inseparableRegionSpanStart,
     TextSpan textSpan,
     IndentBlockOperation operation,
     Lazy <int> indentationGetter
     ) : base(textSpan, indentationGetter)
 {
     this.Operation             = operation;
     this.InseparableRegionSpan = TextSpan.FromBounds(
         inseparableRegionSpanStart,
         textSpan.End
         );
 }
Exemple #4
0
        internal static int GetAdjustedIndentationDelta(
            this IndentBlockOperation operation,
            ISyntaxFacts syntaxFacts,
            SyntaxNode root,
            SyntaxToken indentationAnchor
            )
        {
            if (operation.Option.IsOn(IndentBlockOption.AbsolutePosition))
            {
                // Absolute positioning is absolute
                return(operation.IndentationDeltaOrPosition);
            }

            if (!operation.Option.IsOn(IndentBlockOption.IndentIfConditionOfAnchorToken))
            {
                // No adjustment operations are being applied
                return(operation.IndentationDeltaOrPosition);
            }

            // Consider syntax forms similar to the following:
            //
            //   if (conditionLine1
            //     conditionLine2)
            //
            // Adjustments may be requested for conditionLine2 in cases where the anchor for relative indentation is the
            // first token of the containing statement (in this case, the 'if' token).
            if (
                syntaxFacts.IsOnIfStatementHeader(
                    root,
                    operation.BaseToken.SpanStart,
                    out var conditionStatement
                    ) ||
                syntaxFacts.IsOnWhileStatementHeader(
                    root,
                    operation.BaseToken.SpanStart,
                    out conditionStatement
                    )
                )
            {
                if (conditionStatement.GetFirstToken() == indentationAnchor)
                {
                    // The node is located within the condition of a conditional block statement (or
                    // syntactically-similar), uses a relative anchor to the block statement, and has requested an
                    // additional indentation adjustment for this case.
                    return(operation.IndentationDeltaOrPosition + 1);
                }
            }

            // No adjustments were necessary/applicable
            return(operation.IndentationDeltaOrPosition);
        }
Exemple #5
0
        public void AddIndentBlockOperation(IndentBlockOperation operation)
        {
            var intervalTreeSpan = operation.TextSpan;

            // don't add stuff if it is empty
            if (intervalTreeSpan.IsEmpty ||
                _indentationMap.Contains(intervalTreeSpan))
            {
                return;
            }

            // relative indentation case where indentation depends on other token
            if (operation.IsRelativeIndentation)
            {
                var effectiveBaseToken = operation.Option.IsOn(IndentBlockOption.RelativeToFirstTokenOnBaseTokenLine) ? _tokenStream.FirstTokenOfBaseTokenLine(operation.BaseToken) : operation.BaseToken;
                var inseparableRegionStartingPosition = effectiveBaseToken.FullSpan.Start;
                var relativeIndentationGetter         = new Lazy <int>(() =>
                {
                    var baseIndentationDelta = operation.GetAdjustedIndentationDelta(_engine.SyntaxFacts, TreeData.Root, effectiveBaseToken);
                    var indentationDelta     = baseIndentationDelta * this.Options.GetOption(FormattingOptions2.IndentationSize);

                    // baseIndentation is calculated for the adjusted token if option is RelativeToFirstTokenOnBaseTokenLine
                    var baseIndentation = _tokenStream.GetCurrentColumn(operation.Option.IsOn(IndentBlockOption.RelativeToFirstTokenOnBaseTokenLine) ?
                                                                        _tokenStream.FirstTokenOfBaseTokenLine(operation.BaseToken) :
                                                                        operation.BaseToken);

                    return(baseIndentation + indentationDelta);
                }, isThreadSafe: true);

                // set new indentation
                var relativeIndentationData = new RelativeIndentationData(inseparableRegionStartingPosition, intervalTreeSpan, operation, relativeIndentationGetter);

                _indentationTree.AddIntervalInPlace(relativeIndentationData);
                _relativeIndentationTree.AddIntervalInPlace(relativeIndentationData);
                _indentationMap.Add(intervalTreeSpan);

                return;
            }

            // absolute position case
            if (operation.Option.IsOn(IndentBlockOption.AbsolutePosition))
            {
                _indentationTree.AddIntervalInPlace(new SimpleIndentationData(intervalTreeSpan, operation.IndentationDeltaOrPosition));
                _indentationMap.Add(intervalTreeSpan);
                return;
            }

            // regular indentation case where indentation is based on its previous indentation
            var indentationData = _indentationTree.GetSmallestContainingInterval(operation.TextSpan.Start, 0);

            if (indentationData == null)
            {
                // no previous indentation
                var indentation = operation.IndentationDeltaOrPosition * this.Options.GetOption(FormattingOptions2.IndentationSize);
                _indentationTree.AddIntervalInPlace(new SimpleIndentationData(intervalTreeSpan, indentation));
                _indentationMap.Add(intervalTreeSpan);
                return;
            }

            // get indentation based on its previous indentation
            var indentationGetter = new Lazy <int>(() =>
            {
                var indentationDelta = operation.IndentationDeltaOrPosition * this.Options.GetOption(FormattingOptions2.IndentationSize);

                return(indentationData.Indentation + indentationDelta);
            }, isThreadSafe: true);

            // set new indentation
            _indentationTree.AddIntervalInPlace(new LazyIndentationData(intervalTreeSpan, indentationGetter));
            _indentationMap.Add(intervalTreeSpan);
        }
            private RelativeIndentationData(FormattingContext formattingContext, int inseparableRegionSpanStart, TextSpan textSpan, IndentBlockOperation operation, Func <FormattingContext, IndentBlockOperation, SyntaxToken> effectiveBaseTokenGetter, Func <FormattingContext, IndentBlockOperation, SyntaxToken, int> indentationDeltaGetter, Func <FormattingContext, SyntaxToken, int> baseIndentationGetter, int lazyIndentationDelta)
                : base(textSpan)
            {
                _formattingContext        = formattingContext;
                _effectiveBaseTokenGetter = effectiveBaseTokenGetter;
                _indentationDeltaGetter   = indentationDeltaGetter;
                _baseIndentationGetter    = baseIndentationGetter;

                _lazyIndentationDelta = lazyIndentationDelta;

                this.Operation             = operation;
                this.InseparableRegionSpan = TextSpan.FromBounds(inseparableRegionSpanStart, textSpan.End);
            }