private List <SuppressOperation>?GetInitialSuppressOperations(
                SyntaxToken token,
                SuppressOption mask
                )
            {
                var startNode     = token.Parent;
                var startPosition = token.SpanStart;

                // starting from given token, move up to root until the first meaningful
                // operation has found
                var list = new List <SuppressOperation>();

                bool predicate(SuppressOperation o)
                {
                    if (o == null)
                    {
                        return(true);
                    }

                    if (!o.TextSpan.Contains(startPosition))
                    {
                        return(true);
                    }

                    if (
                        o.ContainsElasticTrivia(_tokenStream) &&
                        !o.Option.IsOn(SuppressOption.IgnoreElasticWrapping)
                        )
                    {
                        return(true);
                    }

                    if (!o.Option.IsMaskOn(mask))
                    {
                        return(true);
                    }

                    return(false);
                }

                var currentIndentationNode = startNode;

                while (currentIndentationNode != null)
                {
                    _formattingRules.AddSuppressOperations(list, currentIndentationNode);

                    list.RemoveAll(predicate);
                    if (list.Count > 0)
                    {
                        return(list);
                    }

                    currentIndentationNode = currentIndentationNode.Parent;
                }

                return(null);
            }
        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));
        }