private static bool TryUncommentSingleLineComments(CommentSelectionInfo info, SnapshotSpan span, ArrayBuilder <TextChange> textChanges, ArrayBuilder <CommentTrackingSpan> spansToSelect) { // First see if we're selecting any lines that have the single-line comment prefix. // If so, then we'll just remove the single-line comment prefix from those lines. var(firstLine, lastLine) = DetermineFirstAndLastLine(span); for (var lineNumber = firstLine.LineNumber; lineNumber <= lastLine.LineNumber; ++lineNumber) { var line = span.Snapshot.GetLineFromLineNumber(lineNumber); var lineText = line.GetText(); if (lineText.Trim().StartsWith(info.SingleLineCommentString, StringComparison.Ordinal)) { DeleteText(textChanges, new TextSpan(line.Start.Position + lineText.IndexOf(info.SingleLineCommentString, StringComparison.Ordinal), info.SingleLineCommentString.Length)); } } // If we made any changes, select the entirety of the lines we change, so that subsequent invocations will // affect the same lines. if (textChanges.Count == 0) { return(false); } spansToSelect.Add(new CommentTrackingSpan(TextSpan.FromBounds(firstLine.Start.Position, lastLine.End.Position))); return(true); }
private static void UncommentContainingBlockComment(CommentSelectionInfo info, SnapshotSpan span, ArrayBuilder <TextChange> textChanges, ArrayBuilder <CommentTrackingSpan> spansToSelect) { // See if we are (textually) contained in a block comment. // This could allow a selection that spans multiple block comments to uncomment the beginning of // the first and end of the last. Oh well. var positionOfEnd = -1; var text = span.Snapshot.AsText(); var positionOfStart = text.LastIndexOf(info.BlockCommentStartString, span.Start, caseSensitive: true); // If we found a start comment marker, make sure there isn't an end comment marker after it but before our span. if (positionOfStart >= 0) { var lastEnd = text.LastIndexOf(info.BlockCommentEndString, span.Start, caseSensitive: true); if (lastEnd < positionOfStart) { positionOfEnd = text.IndexOf(info.BlockCommentEndString, span.End, caseSensitive: true); } else if (lastEnd + info.BlockCommentEndString.Length > span.End) { // The end of the span is *inside* the end marker, so searching backwards found it. positionOfEnd = lastEnd; } } UncommentPosition(info, textChanges, spansToSelect, positionOfStart, positionOfEnd); }
private static void UncommentPosition(CommentSelectionInfo info, ArrayBuilder <TextChange> textChanges, ArrayBuilder <CommentTrackingSpan> spansToSelect, int positionOfStart, int positionOfEnd) { if (positionOfStart < 0 || positionOfEnd < 0) { return; } spansToSelect.Add(new CommentTrackingSpan(TextSpan.FromBounds(positionOfStart, positionOfEnd + info.BlockCommentEndString.Length))); DeleteText(textChanges, new TextSpan(positionOfStart, info.BlockCommentStartString.Length)); DeleteText(textChanges, new TextSpan(positionOfEnd, info.BlockCommentEndString.Length)); }
private static void ApplySingleLineCommentToNonBlankLines( CommentSelectionInfo info, ArrayBuilder <TextChange> textChanges, ITextSnapshotLine firstLine, ITextSnapshotLine lastLine, int indentToCommentAt) { var snapshot = firstLine.Snapshot; for (var lineNumber = firstLine.LineNumber; lineNumber <= lastLine.LineNumber; ++lineNumber) { var line = snapshot.GetLineFromLineNumber(lineNumber); if (!line.IsEmptyOrWhitespace()) { InsertText(textChanges, line.Start + indentToCommentAt, info.SingleLineCommentString); } } }
private static bool TryUncommentExactlyBlockComment(CommentSelectionInfo info, SnapshotSpan span, ArrayBuilder <TextChange> textChanges, ArrayBuilder <CommentTrackingSpan> spansToSelect) { var spanText = span.GetText(); var trimmedSpanText = spanText.Trim(); // See if the selection includes just a block comment (plus whitespace) if (trimmedSpanText.StartsWith(info.BlockCommentStartString, StringComparison.Ordinal) && trimmedSpanText.EndsWith(info.BlockCommentEndString, StringComparison.Ordinal)) { var positionOfStart = span.Start + spanText.IndexOf(info.BlockCommentStartString, StringComparison.Ordinal); var positionOfEnd = span.Start + spanText.LastIndexOf(info.BlockCommentEndString, StringComparison.Ordinal); UncommentPosition(info, textChanges, spansToSelect, positionOfStart, positionOfEnd); return(true); } return(false); }
protected override Task <ImmutableArray <TextSpan> > GetBlockCommentsInDocumentAsync(Document document, ITextSnapshot snapshot, TextSpan linesContainingSelections, CommentSelectionInfo commentInfo, CancellationToken cancellationToken) { var allText = snapshot.AsText(); var commentedSpans = ArrayBuilder <TextSpan> .GetInstance(); var openIdx = 0; while ((openIdx = allText.IndexOf(commentInfo.BlockCommentStartString, openIdx, caseSensitive: true)) >= 0) { // Retrieve the first closing marker located after the open index. var closeIdx = allText.IndexOf(commentInfo.BlockCommentEndString, openIdx + commentInfo.BlockCommentStartString.Length, caseSensitive: true); // If an open marker is found without a close marker, it's an unclosed comment. if (closeIdx < 0) { closeIdx = allText.Length - commentInfo.BlockCommentEndString.Length; } var blockCommentSpan = new TextSpan(openIdx, closeIdx + commentInfo.BlockCommentEndString.Length - openIdx); commentedSpans.Add(blockCommentSpan); openIdx = closeIdx; } return(Task.FromResult(commentedSpans.ToImmutableAndFree())); }
private static void AddBlockComment(SnapshotSpan span, ArrayBuilder <TextChange> textChanges, ArrayBuilder <CommentTrackingSpan> trackingSpans, CommentSelectionInfo commentInfo) { trackingSpans.Add(new CommentTrackingSpan(TextSpan.FromBounds(span.Start, span.End))); InsertText(textChanges, span.Start, commentInfo.BlockCommentStartString); InsertText(textChanges, span.End, commentInfo.BlockCommentEndString); }
private static void AddSingleLineComments(SnapshotSpan span, ArrayBuilder <TextChange> textChanges, ArrayBuilder <CommentTrackingSpan> trackingSpans, ITextSnapshotLine firstLine, ITextSnapshotLine lastLine, CommentSelectionInfo commentInfo) { // Select the entirety of the lines, so that another comment operation will add more // comments, not insert block comments. trackingSpans.Add(new CommentTrackingSpan(TextSpan.FromBounds(firstLine.Start.Position, lastLine.End.Position))); var indentToCommentAt = DetermineSmallestIndent(span, firstLine, lastLine); ApplySingleLineCommentToNonBlankLines(commentInfo, textChanges, firstLine, lastLine, indentToCommentAt); }