private async Task <CommentSelectionResult> ToggleBlockCommentsAsync(Document document, CommentSelectionInfo commentInfo,
                                                                             ITextStructureNavigator navigator, NormalizedSnapshotSpanCollection selectedSpans, CancellationToken cancellationToken)
        {
            var firstLineAroundSelection = selectedSpans.First().Start.GetContainingLine().Start;
            var lastLineAroundSelection  = selectedSpans.Last().End.GetContainingLine().End;
            var linesContainingSelection = TextSpan.FromBounds(firstLineAroundSelection, lastLineAroundSelection);
            var blockCommentedSpans      = await GetBlockCommentsInDocumentAsync(
                document, selectedSpans.First().Snapshot, linesContainingSelection, commentInfo, cancellationToken).ConfigureAwait(false);

            var blockCommentSelections = selectedSpans.SelectAsArray(span => new BlockCommentSelectionHelper(blockCommentedSpans, span));

            var returnOperation = Operation.Uncomment;

            var textChanges = ArrayBuilder <TextChange> .GetInstance();

            var trackingSpans = ArrayBuilder <CommentTrackingSpan> .GetInstance();

            // Try to uncomment until an already uncommented span is found.
            foreach (var blockCommentSelection in blockCommentSelections)
            {
                // If any selection does not have comments to remove, then the operation should be comment.
                if (!TryUncommentBlockComment(blockCommentedSpans, blockCommentSelection, textChanges, trackingSpans, commentInfo))
                {
                    returnOperation = Operation.Comment;
                    break;
                }
            }

            if (returnOperation == Operation.Comment)
            {
                textChanges.Clear();
                trackingSpans.Clear();
                foreach (var blockCommentSelection in blockCommentSelections)
                {
                    BlockCommentSpan(blockCommentSelection, navigator, textChanges, trackingSpans, commentInfo);
                }
            }

            return(new CommentSelectionResult(textChanges.ToArrayAndFree(), trackingSpans.ToArrayAndFree(), returnOperation));
        }