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)); }
private SyntaxToken FindCorrectBaseTokenOfRelativeIndentBlockOperation(IndentBlockOperation operation, TokenStream tokenStream) { if (operation.Option.IsOn(IndentBlockOption.RelativeToFirstTokenOnBaseTokenLine)) { return(tokenStream.FirstTokenOfBaseTokenLine(operation.BaseToken)); } return(operation.BaseToken); }
public RelativeIndentationData( int inseparableRegionSpanStart, TextSpan textSpan, IndentBlockOperation operation, Lazy <int> indentationGetter ) : base(textSpan, indentationGetter) { this.Operation = operation; this.InseparableRegionSpan = TextSpan.FromBounds( inseparableRegionSpanStart, textSpan.End ); }
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); }
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); }