Ejemplo n.º 1
0
        private bool TryUncommentSingleLineComments(ICommentUncommentService service, SnapshotSpan span, List <TextChange> textChanges, List <ITrackingSpan> 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 firstAndLastLine = DetermineFirstAndLastLine(span);

            for (int lineNumber = firstAndLastLine.Item1.LineNumber; lineNumber <= firstAndLastLine.Item2.LineNumber; ++lineNumber)
            {
                var line     = span.Snapshot.GetLineFromLineNumber(lineNumber);
                var lineText = line.GetText();
                if (lineText.Trim().StartsWith(service.SingleLineCommentString, StringComparison.Ordinal))
                {
                    DeleteText(textChanges, new TextSpan(line.Start.Position + lineText.IndexOf(service.SingleLineCommentString, StringComparison.Ordinal), service.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.Any())
            {
                return(false);
            }

            spansToSelect.Add(span.Snapshot.CreateTrackingSpan(Span.FromBounds(firstAndLastLine.Item1.Start.Position,
                                                                               firstAndLastLine.Item2.End.Position),
                                                               SpanTrackingMode.EdgeExclusive));
            return(true);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Add the necessary edits to uncomment out a single span.
        /// </summary>
        private void UncommentSpan(ICommentUncommentService service, SnapshotSpan span, List <TextChange> textChanges, List <ITrackingSpan> spansToSelect)
        {
            if (TryUncommentSingleLineComments(service, span, textChanges, spansToSelect))
            {
                return;
            }

            TryUncommentContainingBlockComment(service, span, textChanges, spansToSelect);
        }
Ejemplo n.º 3
0
        private bool TryUncommentContainingBlockComment(ICommentUncommentService service, SnapshotSpan span, List <TextChange> textChanges, List <ITrackingSpan> spansToSelect)
        {
            // We didn't make any single line changes.  If the language supports block comments, see
            // if we're inside a containing block comment and uncomment that.

            if (!service.SupportsBlockComment)
            {
                return(false);
            }

            var positionOfStart = -1;
            var positionOfEnd   = -1;
            var spanText        = span.GetText();
            var trimmedSpanText = spanText.Trim();

            // See if the selection includes just a block comment (plus whitespace)
            if (trimmedSpanText.StartsWith(service.BlockCommentStartString, StringComparison.Ordinal) && trimmedSpanText.EndsWith(service.BlockCommentEndString, StringComparison.Ordinal))
            {
                positionOfStart = span.Start + spanText.IndexOf(service.BlockCommentStartString, StringComparison.Ordinal);
                positionOfEnd   = span.Start + spanText.LastIndexOf(service.BlockCommentEndString, StringComparison.Ordinal);
            }
            else
            {
                // 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 text = span.Snapshot.AsText();
                positionOfStart = text.LastIndexOf(service.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(service.BlockCommentEndString, span.Start, caseSensitive: true);
                    if (lastEnd < positionOfStart)
                    {
                        positionOfEnd = text.IndexOf(service.BlockCommentEndString, span.End, caseSensitive: true);
                    }
                    else if (lastEnd + service.BlockCommentEndString.Length > span.End)
                    {
                        // The end of the span is *inside* the end marker, so searching backwards found it.
                        positionOfEnd = lastEnd;
                    }
                }
            }

            if (positionOfStart < 0 || positionOfEnd < 0)
            {
                return(false);
            }

            spansToSelect.Add(span.Snapshot.CreateTrackingSpan(Span.FromBounds(positionOfStart, positionOfEnd + service.BlockCommentEndString.Length), SpanTrackingMode.EdgeExclusive));
            DeleteText(textChanges, new TextSpan(positionOfStart, service.BlockCommentStartString.Length));
            DeleteText(textChanges, new TextSpan(positionOfEnd, service.BlockCommentEndString.Length));
            return(true);
        }
Ejemplo n.º 4
0
 /// <summary>
 /// Adds edits to comment out each non-blank line, at the given indent.
 /// </summary>
 private void ApplyCommentToNonBlankLines(ICommentUncommentService service, List <TextChange> textChanges, Tuple <ITextSnapshotLine, ITextSnapshotLine> firstAndLastLine, int indentToCommentAt)
 {
     for (int lineNumber = firstAndLastLine.Item1.LineNumber; lineNumber <= firstAndLastLine.Item2.LineNumber; ++lineNumber)
     {
         var line = firstAndLastLine.Item1.Snapshot.GetLineFromLineNumber(lineNumber);
         if (!line.IsEmptyOrWhitespace())
         {
             InsertText(textChanges, line.Start + indentToCommentAt, service.SingleLineCommentString);
         }
     }
 }
Ejemplo n.º 5
0
 /// <summary>
 /// Add the necessary edits to the given spans. Also collect tracking spans over each span.
 ///
 /// Internal so that it can be called by unit tests.
 /// </summary>
 internal void CollectEdits(ICommentUncommentService service, NormalizedSnapshotSpanCollection selectedSpans, List <TextChange> textChanges, List <ITrackingSpan> trackingSpans, Operation operation)
 {
     foreach (var span in selectedSpans)
     {
         if (operation == Operation.Comment)
         {
             CommentSpan(service, span, textChanges, trackingSpans);
         }
         else
         {
             UncommentSpan(service, span, textChanges, trackingSpans);
         }
     }
 }
Ejemplo n.º 6
0
        private void Format(ICommentUncommentService service, ITextSnapshot snapshot, IEnumerable <ITrackingSpan> changes, CancellationToken cancellationToken)
        {
            var document = snapshot.GetOpenDocumentInCurrentContextWithChanges();

            if (document == null)
            {
                return;
            }

            var textSpans   = changes.Select(s => s.GetSpan(snapshot)).Select(s => s.Span.ToTextSpan()).ToList();
            var newDocument = service.Format(document, textSpans, cancellationToken);

            newDocument.Project.Solution.Workspace.ApplyDocumentChanges(newDocument, cancellationToken);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Add the necessary edits to comment out a single span.
        /// </summary>
        private void CommentSpan(ICommentUncommentService service, SnapshotSpan span, List <TextChange> textChanges, List <ITrackingSpan> trackingSpans)
        {
            var firstAndLastLine = DetermineFirstAndLastLine(span);

            if (span.IsEmpty && firstAndLastLine.Item1.IsEmptyOrWhitespace())
            {
                return;
            }

            if (!span.IsEmpty && string.IsNullOrWhiteSpace(span.GetText()))
            {
                return;
            }

            if (span.IsEmpty || string.IsNullOrWhiteSpace(span.GetText()))
            {
                var firstNonWhitespaceOnLine = firstAndLastLine.Item1.GetFirstNonWhitespacePosition();
                var insertPosition           = firstNonWhitespaceOnLine.HasValue
                    ? firstNonWhitespaceOnLine.Value
                    : firstAndLastLine.Item1.Start;

                // If there isn't a selection, we select the whole line
                trackingSpans.Add(span.Snapshot.CreateTrackingSpan(Span.FromBounds(firstAndLastLine.Item1.Start, firstAndLastLine.Item1.End), SpanTrackingMode.EdgeInclusive));
                InsertText(textChanges, insertPosition, service.SingleLineCommentString);
            }
            else
            {
                if (service.SupportsBlockComment &&
                    !SpanIncludesAllTextOnIncludedLines(span) &&
                    firstAndLastLine.Item1.LineNumber == firstAndLastLine.Item2.LineNumber)
                {
                    trackingSpans.Add(span.Snapshot.CreateTrackingSpan(span, SpanTrackingMode.EdgeInclusive));
                    InsertText(textChanges, span.Start, service.BlockCommentStartString);
                    InsertText(textChanges, span.End, service.BlockCommentEndString);
                }
                else
                {
                    // Select the entirety of the lines, so that another comment operation will add more comments, not insert block comments.
                    trackingSpans.Add(span.Snapshot.CreateTrackingSpan(Span.FromBounds(firstAndLastLine.Item1.Start.Position, firstAndLastLine.Item2.End.Position), SpanTrackingMode.EdgeInclusive));
                    var indentToCommentAt = DetermineSmallestIndent(span, firstAndLastLine);
                    ApplyCommentToNonBlankLines(service, textChanges, firstAndLastLine, indentToCommentAt);
                }
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Add the necessary edits to uncomment out a single span.
        /// </summary>
        private void UncommentSpan(ICommentUncommentService service, SnapshotSpan span, List <TextChange> textChanges, List <ITrackingSpan> spansToSelect)
        {
            if (service.SupportsBlockComment)
            {
                var positionOfStart = -1;
                var positionOfEnd   = -1;
                var spanText        = span.GetText();
                var trimmedSpanText = spanText.Trim();

                // See if the selection includes just a block comment (plus whitespace)
                if (trimmedSpanText.StartsWith(service.BlockCommentStartString, StringComparison.Ordinal) && trimmedSpanText.EndsWith(service.BlockCommentEndString, StringComparison.Ordinal))
                {
                    positionOfStart = span.Start + spanText.IndexOf(service.BlockCommentStartString, StringComparison.Ordinal);
                    positionOfEnd   = span.Start + spanText.LastIndexOf(service.BlockCommentEndString, StringComparison.Ordinal);
                }
                else
                {
                    // 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 text = span.Snapshot.AsText();
                    positionOfStart = text.LastIndexOf(service.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(service.BlockCommentEndString, span.Start, caseSensitive: true);
                        if (lastEnd < positionOfStart)
                        {
                            positionOfEnd = text.IndexOf(service.BlockCommentEndString, span.End, caseSensitive: true);
                        }
                        else if (lastEnd + service.BlockCommentEndString.Length > span.End)
                        {
                            // The end of the span is *inside* the end marker, so searching backwards found it.
                            positionOfEnd = lastEnd;
                        }
                    }
                }

                if (positionOfStart >= 0 && positionOfEnd >= 0)
                {
                    spansToSelect.Add(span.Snapshot.CreateTrackingSpan(Span.FromBounds(positionOfStart, positionOfEnd + service.BlockCommentEndString.Length), SpanTrackingMode.EdgeExclusive));
                    DeleteText(textChanges, new TextSpan(positionOfStart, service.BlockCommentStartString.Length));
                    DeleteText(textChanges, new TextSpan(positionOfEnd, service.BlockCommentEndString.Length));
                    return;
                }
            }

            var firstAndLastLine = DetermineFirstAndLastLine(span);

            for (int lineNumber = firstAndLastLine.Item1.LineNumber; lineNumber <= firstAndLastLine.Item2.LineNumber; ++lineNumber)
            {
                var line     = span.Snapshot.GetLineFromLineNumber(lineNumber);
                var lineText = line.GetText();
                if (lineText.Trim().StartsWith(service.SingleLineCommentString, StringComparison.Ordinal))
                {
                    DeleteText(textChanges, new TextSpan(line.Start.Position + lineText.IndexOf(service.SingleLineCommentString, StringComparison.Ordinal), service.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.Any())
            {
                spansToSelect.Add(span.Snapshot.CreateTrackingSpan(Span.FromBounds(firstAndLastLine.Item1.Start.Position,
                                                                                   firstAndLastLine.Item2.End.Position),
                                                                   SpanTrackingMode.EdgeExclusive));
            }
        }
Ejemplo n.º 9
0
 public CommentSelectionServiceProxy(ICommentUncommentService commentUncommentService)
 {
     _commentUncommentService = commentUncommentService;
 }