private List <IndentBlockOperation> GetInitialIndentBlockOperations(SyntaxToken startToken, SyntaxToken endToken)
            {
                var span     = TextSpan.FromBounds(startToken.SpanStart, endToken.Span.End);
                var node     = startToken.GetCommonRoot(endToken).GetParentWithBiggerSpan();
                var previous = default(SyntaxNode);

                // starting from the common node, move up to the parent
                var operations = new List <IndentBlockOperation>();
                var list       = new List <IndentBlockOperation>();

                while (node != null)
                {
                    // get all operations for the nodes that contains the formatting span, but not ones contained by the span
                    node.DescendantNodesAndSelf(n => n != previous && n.Span.IntersectsWith(span) && !span.Contains(n.Span))
                    .Do(n =>
                    {
                        _formattingRules.AddIndentBlockOperations(list, n);
                        foreach (var element in list)
                        {
                            if (element != null)
                            {
                                operations.Add(element);
                            }
                        }

                        list.Clear();
                    });

                    // found some. use these as initial indentation
                    if (operations.Any(o => o.TextSpan.Contains(span)))
                    {
                        break;
                    }

                    previous = node;
                    node     = node.Parent;
                }

                // make sure operations we have has effects over the formatting span
                operations.RemoveAll(o => o == null || !o.TextSpan.IntersectsWith(span));

                // we couldn't find anything
                // return initial location so that we can get base indentation correctly
                if (operations.Count == 0)
                {
                    operations.Add(new IndentBlockOperation(
                                       startToken: _rootNode.GetFirstToken(includeZeroWidth: true),
                                       endToken: _rootNode.GetLastToken(includeZeroWidth: true),
                                       textSpan: _rootNode.FullSpan,
                                       indentationDelta: 0,
                                       option: IndentBlockOption.AbsolutePosition));

                    return(operations);
                }

                operations.Sort(CommonFormattingHelpers.IndentBlockOperationComparer);
                return(operations);
            }
Beispiel #2
0
        private List <IndentBlockOperation> GetParentIndentBlockOperations(SyntaxToken token)
        {
            var allNodes = GetParentNodes(token);

            // gather all indent operations
            var list = new List <IndentBlockOperation>();

            allNodes.Do(n => _formattingRules.AddIndentBlockOperations(list, n));

            // sort them in right order
            list.RemoveAll(CommonFormattingHelpers.IsNull);
            list.Sort(CommonFormattingHelpers.IndentBlockOperationComparer);

            return(list);
        }
Beispiel #3
0
        protected virtual NodeOperations CreateNodeOperations(CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // iterating tree is very expensive. do it once and cache it to list
            List <SyntaxNode> nodeIterator;

            using (Logger.LogBlock(FunctionId.Formatting_IterateNodes, cancellationToken))
            {
                const int magicLengthToNodesRatio = 5;
                var       result = new List <SyntaxNode>(Math.Max(this.SpanToFormat.Length / magicLengthToNodesRatio, 4));

                foreach (var node in _commonRoot.DescendantNodesAndSelf(this.SpanToFormat))
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    result.Add(node);
                }

                nodeIterator = result;
            }

            // iterate through each operation using index to not create any unnecessary object
            cancellationToken.ThrowIfCancellationRequested();
            List <IndentBlockOperation> indentBlockOperation;

            using (Logger.LogBlock(FunctionId.Formatting_CollectIndentBlock, cancellationToken))
            {
                indentBlockOperation = AddOperations <IndentBlockOperation>(nodeIterator, (l, n) => _formattingRules.AddIndentBlockOperations(l, n), cancellationToken);
            }

            cancellationToken.ThrowIfCancellationRequested();
            List <SuppressOperation> suppressOperation;

            using (Logger.LogBlock(FunctionId.Formatting_CollectSuppressOperation, cancellationToken))
            {
                suppressOperation = AddOperations <SuppressOperation>(nodeIterator, (l, n) => _formattingRules.AddSuppressOperations(l, n), cancellationToken);
            }

            cancellationToken.ThrowIfCancellationRequested();
            List <AlignTokensOperation> alignmentOperation;

            using (Logger.LogBlock(FunctionId.Formatting_CollectAlignOperation, cancellationToken))
            {
                var operations = AddOperations <AlignTokensOperation>(nodeIterator, (l, n) => _formattingRules.AddAlignTokensOperations(l, n), cancellationToken);

                // make sure we order align operation from left to right
                operations.Sort((o1, o2) => o1.BaseToken.Span.CompareTo(o2.BaseToken.Span));

                alignmentOperation = operations;
            }

            cancellationToken.ThrowIfCancellationRequested();
            List <AnchorIndentationOperation> anchorIndentationOperations;

            using (Logger.LogBlock(FunctionId.Formatting_CollectAnchorOperation, cancellationToken))
            {
                anchorIndentationOperations = AddOperations <AnchorIndentationOperation>(nodeIterator, (l, n) => _formattingRules.AddAnchorIndentationOperations(l, n), cancellationToken);
            }

            return(new NodeOperations(indentBlockOperation, suppressOperation, anchorIndentationOperations, alignmentOperation));
        }