public void AddAnchorIndentationOperation(AnchorIndentationOperation operation) { // don't add stuff if it is empty if (operation.TextSpan.IsEmpty || _anchorMap.Contains(operation.TextSpan) || _anchorBaseTokenMap.ContainsKey(operation.AnchorToken)) { return; } // If the indentation changes on a line which other code is anchored to, adjust those other lines to reflect // the same change in indentation. Note that we anchor to the first token on a line to account for common // cases like the following code, where the `{` token is anchored to the `(` token of `()`: // // ↓ this space can be removed, which moves `(` one character to the left // var x = Method( () => // { // ↑ this `{` anchors to `var` instead of `(`, which prevents it from moving when `(` is moved // }); // // The calculation of true anchor token (which is always the first token on a line) is delayed to account // for cases where the original anchor token is moved to a new line during a formatting operation. var anchorToken = _tokenStream.FirstTokenOfBaseTokenLine(operation.AnchorToken); var originalSpace = _tokenStream.GetOriginalColumn(anchorToken); var data = new AnchorData(operation, anchorToken, originalSpace); _anchorTree.AddIntervalInPlace(data); _anchorBaseTokenMap.Add(operation.AnchorToken, data); _anchorMap.Add(operation.TextSpan); }
private void AddWrappingSuppressOperation(SuppressOperation operation, bool twoTokensOnSameLine) { // don't add stuff if it is empty if (operation == null || operation.TextSpan.IsEmpty) { return; } var option = operation.Option; if (!option.IsMaskOn(SuppressOption.NoWrapping) || _suppressWrappingMap.Contains(operation.TextSpan)) { return; } if (!(option.IsOn(SuppressOption.NoWrappingIfOnSingleLine) && twoTokensOnSameLine) && !(option.IsOn(SuppressOption.NoWrappingIfOnMultipleLine) && !twoTokensOnSameLine)) { return; } var ignoreElastic = option.IsMaskOn(SuppressOption.IgnoreElasticWrapping) || !operation.ContainsElasticTrivia(_tokenStream); var data = new SuppressWrappingData(operation.TextSpan, ignoreElastic: ignoreElastic); _suppressWrappingMap.Add(operation.TextSpan); _suppressWrappingTree.AddIntervalInPlace(data); }
private void AddSpacingSuppressOperation(SuppressOperation operation, bool twoTokensOnSameLine) { // don't add stuff if it is empty if (operation == null || operation.TextSpan.IsEmpty) { return; } // we might need to merge bits with enclosing suppress flag var option = operation.Option; if (!option.IsMaskOn(SuppressOption.NoSpacing) || _suppressSpacingMap.Contains(operation.TextSpan)) { return; } if (!(option.IsOn(SuppressOption.NoSpacingIfOnSingleLine) && twoTokensOnSameLine) && !(option.IsOn(SuppressOption.NoSpacingIfOnMultipleLine) && !twoTokensOnSameLine)) { return; } var data = new SuppressSpacingData(operation.TextSpan); _suppressSpacingMap.Add(operation.TextSpan); _suppressSpacingTree.AddIntervalInPlace(data); }
public void Initialize( ChainedFormattingRules formattingRules, SyntaxToken startToken, SyntaxToken endToken, CancellationToken cancellationToken ) { var rootNode = this.TreeData.Root; if (_tokenStream.IsFormattingWholeDocument) { // if we are trying to format whole document, there is no reason to get initial context. just set // initial indentation. var data = new RootIndentationData(rootNode); _indentationTree.AddIntervalInPlace(data); _indentationMap.Add(data.TextSpan); return; } var initialContextFinder = new InitialContextFinder( _tokenStream, formattingRules, rootNode ); var(indentOperations, suppressOperations) = initialContextFinder.Do( startToken, endToken ); if (indentOperations != null) { var indentationOperations = indentOperations; var initialOperation = indentationOperations[0]; var baseIndentationFinder = new BottomUpBaseIndentationFinder( formattingRules, this.Options.GetOption(FormattingOptions2.TabSize), this.Options.GetOption(FormattingOptions2.IndentationSize), _tokenStream, _engine.SyntaxFacts ); var initialIndentation = baseIndentationFinder.GetIndentationOfCurrentPosition( rootNode, initialOperation, t => _tokenStream.GetCurrentColumn(t), cancellationToken ); var data = new SimpleIndentationData(initialOperation.TextSpan, initialIndentation); _indentationTree.AddIntervalInPlace(data); _indentationMap.Add(data.TextSpan); // hold onto initial operations _initialIndentBlockOperations = indentationOperations; } suppressOperations?.Do(o => this.AddInitialSuppressOperation(o)); }
public void AddAnchorIndentationOperation(AnchorIndentationOperation operation) { // don't add stuff if it is empty if (operation.TextSpan.IsEmpty || _anchorMap.Contains(operation.TextSpan) || _anchorBaseTokenMap.ContainsKey(operation.AnchorToken)) { return; } var originalSpace = _tokenStream.GetOriginalColumn(operation.StartToken); var data = new AnchorData(operation, originalSpace); _anchorTree.AddIntervalInPlace(data); _anchorBaseTokenMap.Add(operation.AnchorToken, data); _anchorMap.Add(operation.TextSpan); }
private void AddFormattingSuppressOperation(SuppressOperation operation) { // don't add stuff if it is empty if (operation == null || operation.TextSpan.IsEmpty) { return; } // we might need to merge bits with enclosing suppress flag var option = operation.Option; if (!option.IsOn(SuppressOption.DisableFormatting) || _suppressFormattingMap.Contains(operation.TextSpan)) { return; } var data = new SuppressSpacingData(operation.TextSpan); _suppressFormattingMap.Add(operation.TextSpan); _suppressFormattingTree.AddIntervalInPlace(data); }
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); }