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); }
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); }
protected virtual NodeOperations CreateNodeOperations(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); // iterating tree is very expensive. do it once and cache it to list SegmentedList <SyntaxNode> nodeIterator; using (Logger.LogBlock(FunctionId.Formatting_IterateNodes, cancellationToken)) { const int magicLengthToNodesRatio = 5; var result = new SegmentedList <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)); }
protected virtual NodeOperations CreateNodeOperationTasks(CancellationToken cancellationToken) { // iterating tree is very expensive. do it once and cache it to list var nodeIteratorTask = this.TaskExecutor.StartNew(() => { 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); } return(result); } }, cancellationToken); // iterate through each operation using index to not create any unnecessary object var indentBlockOperationTask = this.TaskExecutor.ContinueWith(nodeIteratorTask, task => { using (Logger.LogBlock(FunctionId.Formatting_CollectIndentBlock, cancellationToken)) { return(AddOperations <IndentBlockOperation>(task.Result, (l, n) => _formattingRules.AddIndentBlockOperations(l, n), cancellationToken)); } }, cancellationToken); var suppressOperationTask = this.TaskExecutor.ContinueWith(nodeIteratorTask, task => { using (Logger.LogBlock(FunctionId.Formatting_CollectSuppressOperation, cancellationToken)) { return(AddOperations <SuppressOperation>(task.Result, (l, n) => _formattingRules.AddSuppressOperations(l, n), cancellationToken)); } }, cancellationToken); var alignmentOperationTask = this.TaskExecutor.ContinueWith(nodeIteratorTask, task => { using (Logger.LogBlock(FunctionId.Formatting_CollectAlignOperation, cancellationToken)) { var operations = AddOperations <AlignTokensOperation>(task.Result, (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)); return(operations); } }, cancellationToken); var anchorIndentationOperationsTask = this.TaskExecutor.ContinueWith(nodeIteratorTask, task => { using (Logger.LogBlock(FunctionId.Formatting_CollectAnchorOperation, cancellationToken)) { return(AddOperations <AnchorIndentationOperation>(task.Result, (l, n) => _formattingRules.AddAnchorIndentationOperations(l, n), cancellationToken)); } }, cancellationToken); return(new NodeOperations(indentBlockOperationTask, suppressOperationTask, anchorIndentationOperationsTask, alignmentOperationTask)); }