Beispiel #1
0
            public bool ApplyAlignment(
                AlignTokensOperation operation, Dictionary <SyntaxToken, int> previousChangesMap, CancellationToken cancellationToken)
            {
                Contract.ThrowIfNull(previousChangesMap);

                IList <TokenData> tokenData;

                switch (operation.Option)
                {
                case AlignTokensOption.AlignIndentationOfTokensToBaseToken:
                {
                    if (!ApplyAlignment(operation.BaseToken, operation.Tokens, previousChangesMap, out tokenData, cancellationToken))
                    {
                        return(false);
                    }

                    break;
                }

                case AlignTokensOption.AlignPositionOfTokensToIndentation:
                {
                    // token will be align to current indentation. for this operation, we don't care
                    // about base token
                    if (operation.Tokens.IsEmpty())
                    {
                        return(false);
                    }

                    tokenData = GetTokenWithIndices(operation.Tokens);

                    // no valid tokens. do nothing and return
                    if (tokenData.Count == 0)
                    {
                        return(false);
                    }

                    ApplySpacesToAlignWithCurrentIndentation(tokenData, previousChangesMap, cancellationToken);
                    break;
                }

                case AlignTokensOption.AlignToFirstTokenOnBaseTokenLine:
                {
                    if (!ApplyAlignment(tokenStream.FirstTokenOfBaseTokenLine(operation.BaseToken), operation.Tokens, previousChangesMap, out tokenData, cancellationToken))
                    {
                        return(false);
                    }

                    break;
                }

                default:
                {
                    return(Contract.FailWithReturn <bool>("Unknown option"));
                }
                }

                ApplyIndentationChangesToDependentTokens(tokenData, previousChangesMap, cancellationToken);

                return(true);
            }
Beispiel #2
0
        private SyntaxToken FindCorrectBaseTokenOfRelativeIndentBlockOperation(IndentBlockOperation operation, TokenStream tokenStream)
        {
            if (operation.Option.IsOn(IndentBlockOption.RelativeToFirstTokenOnBaseTokenLine))
            {
                return(tokenStream.FirstTokenOfBaseTokenLine(operation.BaseToken));
            }

            return(operation.BaseToken);
        }
Beispiel #3
0
        private int GetIndentationOfCurrentPosition(
            SyntaxNode root,
            SyntaxToken token,
            List <IndentBlockOperation> list,
            int position,
            int extraSpaces,
            Func <SyntaxToken, int> tokenColumnGetter,
            CancellationToken cancellationToken)
        {
            var tuple            = GetIndentationRuleOfCurrentPosition(root, token, list, position);
            var indentationLevel = tuple.Item1;
            var operation        = tuple.Item2;

            if (operation == null)
            {
                return(indentationLevel * _indentationSize + extraSpaces);
            }

            if (operation.IsRelativeIndentation)
            {
                var baseToken = operation.BaseToken;

                // If the SmartIndenter created this IndentationFinder then tokenStream will be a null hence we should do a null check on the tokenStream
                if (operation.Option.IsOn(IndentBlockOption.RelativeToFirstTokenOnBaseTokenLine))
                {
                    if (_tokenStream != null)
                    {
                        baseToken = _tokenStream.FirstTokenOfBaseTokenLine(baseToken);
                    }
                    else
                    {
                        var textLine = baseToken.SyntaxTree.GetText(cancellationToken).Lines.GetLineFromPosition(baseToken.SpanStart);
                        baseToken = baseToken.SyntaxTree.GetRoot(cancellationToken).FindToken(textLine.Start);
                    }
                }

                var baseIndentation = tokenColumnGetter(baseToken);
                return(Math.Max(0, baseIndentation + (indentationLevel + operation.IndentationDeltaOrPosition) * _indentationSize));
            }

            if (operation.Option.IsOn(IndentBlockOption.AbsolutePosition))
            {
                return(Math.Max(0, indentationLevel + extraSpaces));
            }

            throw ExceptionUtilities.Unreachable;
        }
Beispiel #4
0
            public bool ApplyAlignment(
                AlignTokensOperation operation, Dictionary <SyntaxToken, int> previousChangesMap, CancellationToken cancellationToken)
            {
                Contract.ThrowIfNull(previousChangesMap);

                IList <TokenData> tokenData;

                switch (operation.Option)
                {
                case AlignTokensOption.AlignIndentationOfTokensToBaseToken:
                {
                    if (!ApplyAlignment(operation.BaseToken, operation.Tokens, previousChangesMap, out tokenData, cancellationToken))
                    {
                        return(false);
                    }

                    break;
                }

                case AlignTokensOption.AlignIndentationOfTokensToFirstTokenOfBaseTokenLine:
                {
                    if (!ApplyAlignment(_tokenStream.FirstTokenOfBaseTokenLine(operation.BaseToken), operation.Tokens, previousChangesMap, out tokenData, cancellationToken))
                    {
                        return(false);
                    }

                    break;
                }

                default:
                {
                    return(Contract.FailWithReturn <bool>("Unknown option"));
                }
                }

                ApplyIndentationChangesToDependentTokens(tokenData, previousChangesMap, cancellationToken);

                return(true);
            }
Beispiel #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);
        }