Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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));
        }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        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);
        }
Esempio n. 7
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);
        }