diff --git a/src/EditorFeatures/Core/EditorFeaturesResources.Designer.cs b/src/EditorFeatures/Core/EditorFeaturesResources.Designer.cs index 7fb5ff64856b00f19398809d9ca43676ede68d78..b9888f619bb7547fd7bbe359fcb23a0442dbdef3 100644 --- a/src/EditorFeatures/Core/EditorFeaturesResources.Designer.cs +++ b/src/EditorFeatures/Core/EditorFeaturesResources.Designer.cs @@ -1907,7 +1907,29 @@ internal class EditorFeaturesResources { return ResourceManager.GetString("Toggling_block_comment", resourceCulture); } } - + + /// + /// Looks up a localized string similar to Toggle Line Comment. + /// + internal static string Toggle_Line_Comment + { + get + { + return ResourceManager.GetString("Toggle_Line_Comment", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Toggling line comment.... + /// + internal static string Toggling_line_comment + { + get + { + return ResourceManager.GetString("Toggling_line_comment", resourceCulture); + } + } + /// /// Looks up a localized string similar to Type Parts. /// diff --git a/src/EditorFeatures/Core/EditorFeaturesResources.resx b/src/EditorFeatures/Core/EditorFeaturesResources.resx index 2eca216a14bccd006f65f9e6723a3a9291f63ef4..b191ad9139a69adb62f60283ec47e71ea909c84c 100644 --- a/src/EditorFeatures/Core/EditorFeaturesResources.resx +++ b/src/EditorFeatures/Core/EditorFeaturesResources.resx @@ -895,4 +895,10 @@ Do you want to proceed? Toggling block comment... + + Toggle Line Comment + + + Toggling line comment... + \ No newline at end of file diff --git a/src/EditorFeatures/Core/Extensibility/Commands/PredefinedCommandHandlerNames.cs b/src/EditorFeatures/Core/Extensibility/Commands/PredefinedCommandHandlerNames.cs index a6d007450f955932c14568532842e14fc525461e..9a9575c475709c771b28b8c7b17ac1badbe8c117 100644 --- a/src/EditorFeatures/Core/Extensibility/Commands/PredefinedCommandHandlerNames.cs +++ b/src/EditorFeatures/Core/Extensibility/Commands/PredefinedCommandHandlerNames.cs @@ -147,6 +147,12 @@ internal static class PredefinedCommandHandlerNames /// public const string ToggleBlockComment = "Toggle Block Comment Command Handler"; + /// + /// Command handler name for Toggle Line Comments. + /// + /// + public const string ToggleLineComment = "Toggle Line Comment Command Handler"; + /// /// Command handler name for Paste Content in Interactive Format. /// diff --git a/src/EditorFeatures/Core/Implementation/CommentSelection/AbstractCommentSelectionBase.cs b/src/EditorFeatures/Core/Implementation/CommentSelection/AbstractCommentSelectionBase.cs index 80058b677e608b1a33af3a4cd60c2092ce39c107..0356f80eab6c407a4e00d38b5bb56014bf78b02a 100644 --- a/src/EditorFeatures/Core/Implementation/CommentSelection/AbstractCommentSelectionBase.cs +++ b/src/EditorFeatures/Core/Implementation/CommentSelection/AbstractCommentSelectionBase.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; @@ -11,6 +12,7 @@ using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; +using Microsoft.CodeAnalysis.Text.Shared.Extensions; using Microsoft.VisualStudio.Commanding; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; @@ -200,5 +202,26 @@ private static Document Format(ICommentSelectionService service, ITextSnapshot s var textSpans = changes.SelectAsArray(change => change.Span.ToTextSpan()); return service.FormatAsync(document, textSpans, cancellationToken).WaitAndGetResult(cancellationToken); } + + /// + /// Given a set of lines, find the minimum indent of all of the non-blank, non-whitespace lines. + /// + protected static int DetermineSmallestIndent( + SnapshotSpan span, ITextSnapshotLine firstLine, ITextSnapshotLine lastLine) + { + // TODO: This breaks if you have mixed tabs/spaces, and/or tabsize != indentsize. + var indentToCommentAt = int.MaxValue; + for (var lineNumber = firstLine.LineNumber; lineNumber <= lastLine.LineNumber; ++lineNumber) + { + var line = span.Snapshot.GetLineFromLineNumber(lineNumber); + var firstNonWhitespacePosition = line.GetFirstNonWhitespacePosition(); + var firstNonWhitespaceOnLine = firstNonWhitespacePosition.HasValue + ? firstNonWhitespacePosition.Value - line.Start + : int.MaxValue; + indentToCommentAt = Math.Min(indentToCommentAt, firstNonWhitespaceOnLine); + } + + return indentToCommentAt; + } } } diff --git a/src/EditorFeatures/Core/Implementation/CommentSelection/CommentUncommentSelectionCommandHandler.cs b/src/EditorFeatures/Core/Implementation/CommentSelection/CommentUncommentSelectionCommandHandler.cs index ede5e165dc21e7978b13cad14919034aed26f706..b128eebe318752368226b73d1a46664b4cc5ba6d 100644 --- a/src/EditorFeatures/Core/Implementation/CommentSelection/CommentUncommentSelectionCommandHandler.cs +++ b/src/EditorFeatures/Core/Implementation/CommentSelection/CommentUncommentSelectionCommandHandler.cs @@ -321,25 +321,6 @@ private void AddBlockComment(SnapshotSpan span, ArrayBuilder textCha } } - /// Given a set of lines, find the minimum indent of all of the non-blank, non-whitespace lines. - private static int DetermineSmallestIndent( - SnapshotSpan span, ITextSnapshotLine firstLine, ITextSnapshotLine lastLine) - { - // TODO: This breaks if you have mixed tabs/spaces, and/or tabsize != indentsize. - var indentToCommentAt = int.MaxValue; - for (var lineNumber = firstLine.LineNumber; lineNumber <= lastLine.LineNumber; ++lineNumber) - { - var line = span.Snapshot.GetLineFromLineNumber(lineNumber); - var firstNonWhitespacePosition = line.GetFirstNonWhitespacePosition(); - var firstNonWhitespaceOnLine = firstNonWhitespacePosition.HasValue - ? firstNonWhitespacePosition.Value - line.Start - : int.MaxValue; - indentToCommentAt = Math.Min(indentToCommentAt, firstNonWhitespaceOnLine); - } - - return indentToCommentAt; - } - /// /// Given a span, find the first and last line that are part of the span. NOTE: If the /// span ends in column zero, we back up to the previous line, to handle the case where diff --git a/src/EditorFeatures/Core/Implementation/CommentSelection/ToggleLineCommentCommandHandler.cs b/src/EditorFeatures/Core/Implementation/CommentSelection/ToggleLineCommentCommandHandler.cs new file mode 100644 index 0000000000000000000000000000000000000000..43c273ab496989b48b37c790b7c3707a0239429a --- /dev/null +++ b/src/EditorFeatures/Core/Implementation/CommentSelection/ToggleLineCommentCommandHandler.cs @@ -0,0 +1,191 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.ComponentModel.Composition; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CommentSelection; +using Microsoft.CodeAnalysis.Editor.Shared.Extensions; +using Microsoft.CodeAnalysis.Experiments; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Text; +using Microsoft.CodeAnalysis.Text.Shared.Extensions; +using Microsoft.VisualStudio.Commanding; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor.Commanding.Commands; +using Microsoft.VisualStudio.Text.Operations; +using Microsoft.VisualStudio.Utilities; +using Roslyn.Utilities; +using VSCommanding = Microsoft.VisualStudio.Commanding; + +namespace Microsoft.CodeAnalysis.Editor.Implementation.CommentSelection +{ + [Export(typeof(VSCommanding.ICommandHandler))] + [ContentType(ContentTypeNames.RoslynContentType)] + [Name(PredefinedCommandHandlerNames.ToggleLineComment)] + internal class ToggleLineCommentCommandHandler : + // Value tuple to represent that there is no distinct command to be passed in. + AbstractCommentSelectionBase, + VSCommanding.ICommandHandler + { + private static readonly CommentSelectionResult s_emptyCommentSelectionResult = + new CommentSelectionResult(new List(), new List(), Operation.Uncomment); + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + internal ToggleLineCommentCommandHandler( + ITextUndoHistoryRegistry undoHistoryRegistry, + IEditorOperationsFactoryService editorOperationsFactoryService) + : base(undoHistoryRegistry, editorOperationsFactoryService) + { + } + + public VSCommanding.CommandState GetCommandState(ToggleLineCommentCommandArgs args) + { + if (Workspace.TryGetWorkspace(args.SubjectBuffer.AsTextContainer(), out var workspace)) + { + var experimentationService = workspace.Services.GetRequiredService(); + if (!experimentationService.IsExperimentEnabled(WellKnownExperimentNames.RoslynToggleLineComment)) + { + return VSCommanding.CommandState.Unspecified; + } + } + return GetCommandState(args.SubjectBuffer); + } + + public bool ExecuteCommand(ToggleLineCommentCommandArgs args, CommandExecutionContext context) + => ExecuteCommand(args.TextView, args.SubjectBuffer, ValueTuple.Create(), context); + + public override string DisplayName => EditorFeaturesResources.Toggle_Line_Comment; + + protected override string GetTitle(ValueTuple command) => EditorFeaturesResources.Toggle_Line_Comment; + + protected override string GetMessage(ValueTuple command) => EditorFeaturesResources.Toggling_line_comment; + + internal async override Task CollectEditsAsync(Document document, ICommentSelectionService service, + ITextBuffer subjectBuffer, NormalizedSnapshotSpanCollection selectedSpans, ValueTuple command, CancellationToken cancellationToken) + { + var experimentationService = document.Project.Solution.Workspace.Services.GetRequiredService(); + if (!experimentationService.IsExperimentEnabled(WellKnownExperimentNames.RoslynToggleLineComment)) + { + return s_emptyCommentSelectionResult; + } + + var commentInfo = await service.GetInfoAsync(document, selectedSpans.First().Span.ToTextSpan(), cancellationToken).ConfigureAwait(false); + if (commentInfo.SupportsSingleLineComment) + { + return ToggleLineComment(commentInfo, selectedSpans); + } + + return s_emptyCommentSelectionResult; + } + + private CommentSelectionResult ToggleLineComment(CommentSelectionInfo commentInfo, + NormalizedSnapshotSpanCollection selectedSpans) + { + var textChanges = ArrayBuilder.GetInstance(); + var trackingSpans = ArrayBuilder.GetInstance(); + + var linesInSelections = selectedSpans.ToDictionary( + span => span, + span => GetLinesFromSelectedSpan(span).ToImmutableArray()); + + Operation operation; + // If all the selections are fully commented, uncomment. + if (!linesInSelections.Values.Where(lines => SelectionHasUncommentedLines(lines, commentInfo)).Any()) + { + foreach (var selection in linesInSelections) + { + UncommentLines(selection.Value, textChanges, trackingSpans, commentInfo); + } + + operation = Operation.Uncomment; + } + else + { + foreach (var selection in linesInSelections) + { + CommentLines(selection.Key, selection.Value, textChanges, trackingSpans, commentInfo); + } + + operation = Operation.Comment; + } + + return new CommentSelectionResult(textChanges, trackingSpans, operation); + } + + private static void UncommentLines(ImmutableArray commentedLines, ArrayBuilder textChanges, + ArrayBuilder trackingSpans, CommentSelectionInfo commentInfo) + { + foreach (var line in commentedLines) + { + if (!line.IsEmptyOrWhitespace()) + { + var text = line.GetText(); + var commentIndex = text.IndexOf(commentInfo.SingleLineCommentString) + line.Start; + var spanToRemove = TextSpan.FromBounds(commentIndex, commentIndex + commentInfo.SingleLineCommentString.Length); + DeleteText(textChanges, spanToRemove); + } + } + + trackingSpans.Add(new CommentTrackingSpan(TextSpan.FromBounds(commentedLines.First().Start, commentedLines.Last().End))); + } + + private static void CommentLines(SnapshotSpan selectedSpan, ImmutableArray linesInSelection, + ArrayBuilder textChanges, ArrayBuilder trackingSpans, CommentSelectionInfo commentInfo) + { + var indentation = DetermineSmallestIndent(selectedSpan, linesInSelection.First(), linesInSelection.Last()); + foreach (var line in linesInSelection) + { + if (!line.IsEmptyOrWhitespace()) + { + InsertText(textChanges, line.Start + indentation, commentInfo.SingleLineCommentString); + } + } + + trackingSpans.Add(new CommentTrackingSpan( + TextSpan.FromBounds(linesInSelection.First().Start, linesInSelection.Last().End))); + } + + private List GetLinesFromSelectedSpan(SnapshotSpan span) + { + var lines = new List(); + var startLine = span.Snapshot.GetLineFromPosition(span.Start); + var endLine = span.Snapshot.GetLineFromPosition(span.End); + // Don't include the last line if the span is just the start of the line. + if (endLine.Start == span.End.Position && !span.IsEmpty) + { + endLine = endLine.GetPreviousMatchingLine(_ => true); + } + + if (startLine.LineNumber <= endLine.LineNumber) + { + for (var i = startLine.LineNumber; i <= endLine.LineNumber; i++) + { + lines.Add(span.Snapshot.GetLineFromLineNumber(i)); + } + } + + return lines; + } + + private bool SelectionHasUncommentedLines(ImmutableArray linesInSelection, CommentSelectionInfo commentInfo) + => linesInSelection.Where(l => !IsLineCommented(l, commentInfo)).Any(); + + private static bool IsLineCommented(ITextSnapshotLine line, CommentSelectionInfo info) + { + var lineText = line.GetText(); + if (lineText.Trim().StartsWith(info.SingleLineCommentString, StringComparison.Ordinal) || line.IsEmptyOrWhitespace()) + { + return true; + } + + return false; + } + } +} diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.cs.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.cs.xlf index 2fe3ae6419de19eb5b534392248695941fdbb746..eadafff847c5fc8d51196d27f98d4a2ae979eaf3 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.cs.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.cs.xlf @@ -1294,6 +1294,16 @@ Chcete pokračovat? Toggle Block Comment + + Toggling line comment... + Toggling line comment... + + + + Toggle Line Comment + Toggle Line Comment + + \ No newline at end of file diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.de.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.de.xlf index 4b30385ab3bf8665076ef0071e6cc65dc65f0c62..5a301e394d61069bb4e7c5748b24de6808d92846 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.de.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.de.xlf @@ -1294,6 +1294,16 @@ Möchten Sie fortfahren? Toggle Block Comment + + Toggling line comment... + Toggling line comment... + + + + Toggle Line Comment + Toggle Line Comment + + \ No newline at end of file diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.es.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.es.xlf index 1c0854447c04fbe86ebd0bdc4e77a3eb76ab2dbe..8c7f119c90bfb838e557c25cdec421ae049411d9 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.es.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.es.xlf @@ -1294,6 +1294,16 @@ Do you want to proceed? Toggle Block Comment + + Toggling line comment... + Toggling line comment... + + + + Toggle Line Comment + Toggle Line Comment + + \ No newline at end of file diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.fr.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.fr.xlf index 0107e9e9481d31438924ca5fe0f037cf3874c417..6fdd7f2f24a4f95149e42a612a18b11a50ad0778 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.fr.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.fr.xlf @@ -1294,6 +1294,16 @@ Voulez-vous continuer ? Toggle Block Comment + + Toggling line comment... + Toggling line comment... + + + + Toggle Line Comment + Toggle Line Comment + + \ No newline at end of file diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.it.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.it.xlf index 0345ab6c7f6175d531ba7bf6ecd563ee079d91fe..839088aabc10f83d3037a6705975246c9bd4abba 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.it.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.it.xlf @@ -1294,6 +1294,16 @@ Continuare? Toggle Block Comment + + Toggling line comment... + Toggling line comment... + + + + Toggle Line Comment + Toggle Line Comment + + \ No newline at end of file diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ja.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ja.xlf index 4e42e271d1ee2d7775cf8c4aa4c68f83e0347673..cb1dece728909fe57afedb04e65428a084ef2110 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ja.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ja.xlf @@ -1294,6 +1294,16 @@ Do you want to proceed? Toggle Block Comment + + Toggling line comment... + Toggling line comment... + + + + Toggle Line Comment + Toggle Line Comment + + \ No newline at end of file diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ko.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ko.xlf index 18c9a2aecccc2cc319245abd916f508bb43e39ab..0612d71557b4c9ac634fda9de172b82e810d0967 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ko.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ko.xlf @@ -97,6 +97,16 @@ 기호 - 정적 + + Toggle Line Comment + Toggle Line Comment + + + + Toggling line comment... + Toggling line comment... + + User Members - Constants 사용자 멤버 - 상수 diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pl.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pl.xlf index a1e0c7b719f02f34dca2e62bfdf5d1dcbb7151ce..e0c03a63a5b38eb53dbabdb0a546b5ea6b1645fb 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pl.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pl.xlf @@ -97,6 +97,16 @@ Symbol — statyczny + + Toggle Line Comment + Toggle Line Comment + + + + Toggling line comment... + Toggling line comment... + + User Members - Constants Składowe użytkowników — stałe diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pt-BR.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pt-BR.xlf index 493bf7ca4dc3abec5589ff6c027cee952fbd1631..45eb83314598d53b671988aafe10c68a43044873 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pt-BR.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pt-BR.xlf @@ -97,6 +97,16 @@ Símbolo – Estático + + Toggle Line Comment + Toggle Line Comment + + + + Toggling line comment... + Toggling line comment... + + User Members - Constants Membros de Usuário – Constantes diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ru.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ru.xlf index a37e23195793ee4c16cd8d63f0f308b08591f6a6..e98c177633c42ecfd0f5da1bb109e6273cb9ae28 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ru.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ru.xlf @@ -97,6 +97,16 @@ Символ — статический + + Toggle Line Comment + Toggle Line Comment + + + + Toggling line comment... + Toggling line comment... + + User Members - Constants Участники-пользователи — константы diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.tr.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.tr.xlf index 9fd2ad2a6a48222b856b84b791ac2e8d888f4522..ba11e0e261e99474f895b953e3d3c5aae905ae67 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.tr.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.tr.xlf @@ -97,6 +97,16 @@ Sembol - statik + + Toggle Line Comment + Toggle Line Comment + + + + Toggling line comment... + Toggling line comment... + + User Members - Constants Kullanıcı Üyeler - Sabitler diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hans.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hans.xlf index 72d8e58cca820469421103c757acff0d221ad219..3b061cf889c0f077f0a48dc38c7dad7c1ef24a6b 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hans.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hans.xlf @@ -97,6 +97,16 @@ 符号-静态 + + Toggle Line Comment + Toggle Line Comment + + + + Toggling line comment... + Toggling line comment... + + User Members - Constants 用户成员-常量 diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hant.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hant.xlf index a997cd3de20e5ecf76929c1cd8ec3b07d7a5b39d..d8f1bd0da401d0a9a0cfe6060dbc2b766e9ceb02 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hant.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hant.xlf @@ -97,6 +97,16 @@ 符號 - 靜態 + + Toggle Line Comment + Toggle Line Comment + + + + Toggling line comment... + Toggling line comment... + + User Members - Constants 使用者成員 - 常數 diff --git a/src/EditorFeatures/Test/CommentSelection/AbstractToggleBlockCommentTestBase.cs b/src/EditorFeatures/Test/CommentSelection/AbstractToggleCommentTestBase.cs similarity index 77% rename from src/EditorFeatures/Test/CommentSelection/AbstractToggleBlockCommentTestBase.cs rename to src/EditorFeatures/Test/CommentSelection/AbstractToggleCommentTestBase.cs index 42867173c5d536069b4eddfbe130fa4d3cb37e5a..bcff87c6713d064bf58cc6f83cf1ea25111dcdb5 100644 --- a/src/EditorFeatures/Test/CommentSelection/AbstractToggleBlockCommentTestBase.cs +++ b/src/EditorFeatures/Test/CommentSelection/AbstractToggleCommentTestBase.cs @@ -21,28 +21,30 @@ namespace Microsoft.CodeAnalysis.Editor.UnitTests.CommentSelection { - public abstract class AbstractToggleBlockCommentTestBase + public abstract class AbstractToggleCommentTestBase { - abstract internal ToggleBlockCommentCommandHandler GetToggleBlockCommentCommandHandler(TestWorkspace workspace); + abstract internal AbstractCommentSelectionBase GetToggleCommentCommandHandler(TestWorkspace workspace); - protected void ToggleBlockComment(string markup, string expected) + protected void ToggleComment(string markup, string expected, bool vbWorkspace = false) { - ToggleBlockCommentMultiple(markup, new string[] { expected }); + ToggleCommentMultiple(markup, new string[] { expected }, vbWorkspace); } - protected void ToggleBlockCommentMultiple(string markup, string[] expectedText) + protected void ToggleCommentMultiple(string markup, string[] expectedText, bool vbWorkspace = false) { var exportProvider = ExportProviderCache - .GetOrCreateExportProviderFactory(TestExportProvider.EntireAssemblyCatalogWithCSharpAndVisualBasic.WithPart(typeof(MockToggleBlockCommentExperimentationService))) + .GetOrCreateExportProviderFactory(TestExportProvider.EntireAssemblyCatalogWithCSharpAndVisualBasic.WithPart(typeof(MockToggleCommentExperimentationService))) .CreateExportProvider(); - using (var workspace = TestWorkspace.CreateCSharp(markup, exportProvider: exportProvider)) + using (var workspace = vbWorkspace + ? TestWorkspace.CreateVisualBasic(markup, exportProvider: exportProvider) + : TestWorkspace.CreateCSharp(markup, exportProvider: exportProvider)) { var doc = workspace.Documents.First(); SetupSelection(doc.GetTextView(), doc.SelectedSpans.Select(s => Span.FromBounds(s.Start, s.End))); - var commandHandler = GetToggleBlockCommentCommandHandler(workspace); + var commandHandler = GetToggleCommentCommandHandler(workspace); var textView = doc.GetTextView(); var textBuffer = doc.GetTextBuffer(); @@ -84,11 +86,12 @@ private static void SetupSelection(IWpfTextView textView, IEnumerable span } [ExportWorkspaceService(typeof(IExperimentationService), WorkspaceKind.Test), Shared] - private class MockToggleBlockCommentExperimentationService : IExperimentationService + private class MockToggleCommentExperimentationService : IExperimentationService { public bool IsExperimentEnabled(string experimentName) { - return WellKnownExperimentNames.RoslynToggleBlockComment.Equals(experimentName); + return WellKnownExperimentNames.RoslynToggleBlockComment.Equals(experimentName) + || WellKnownExperimentNames.RoslynToggleLineComment.Equals(experimentName); } } } diff --git a/src/EditorFeatures/Test/CommentSelection/CSharpToggleBlockCommentCommandHandlerTests.cs b/src/EditorFeatures/Test/CommentSelection/CSharpToggleBlockCommentCommandHandlerTests.cs index cc4fbc916d16cbddca004953d41072d47149f0cf..76fb4fcba9fe69982fad54759ed90cf85fdb1b07 100644 --- a/src/EditorFeatures/Test/CommentSelection/CSharpToggleBlockCommentCommandHandlerTests.cs +++ b/src/EditorFeatures/Test/CommentSelection/CSharpToggleBlockCommentCommandHandlerTests.cs @@ -8,11 +8,12 @@ using VSCommanding = Microsoft.VisualStudio.Commanding; using Xunit; using System.Linq; +using System; namespace Microsoft.CodeAnalysis.Editor.UnitTests.CommentSelection { [UseExportProvider] - public class CSharpToggleBlockCommentCommandHandlerTests : AbstractToggleBlockCommentTestBase + public class CSharpToggleBlockCommentCommandHandlerTests : AbstractToggleCommentTestBase { [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] public void AddComment_CommentMarkerStringBeforeSelection() @@ -40,7 +41,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -73,7 +74,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -102,7 +103,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -131,7 +132,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -160,7 +161,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -191,7 +192,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -216,12 +217,12 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } - internal override ToggleBlockCommentCommandHandler GetToggleBlockCommentCommandHandler(TestWorkspace workspace) + internal override AbstractCommentSelectionBase GetToggleCommentCommandHandler(TestWorkspace workspace) { - return (ToggleBlockCommentCommandHandler)workspace.ExportProvider.GetExportedValues() + return (AbstractCommentSelectionBase)workspace.ExportProvider.GetExportedValues() .First(export => typeof(CSharpToggleBlockCommentCommandHandler).Equals(export.GetType())); } } diff --git a/src/EditorFeatures/Test/CommentSelection/ToggleBlockCommentCommandHandlerTests.cs b/src/EditorFeatures/Test/CommentSelection/ToggleBlockCommentCommandHandlerTests.cs index 992157aea94f3167354fc55895bf828b9b4b67e2..8f5e4dedf261f2b84ae372721391fe36cfff1f13 100644 --- a/src/EditorFeatures/Test/CommentSelection/ToggleBlockCommentCommandHandlerTests.cs +++ b/src/EditorFeatures/Test/CommentSelection/ToggleBlockCommentCommandHandlerTests.cs @@ -7,11 +7,12 @@ using Roslyn.Test.Utilities; using VSCommanding = Microsoft.VisualStudio.Commanding; using Xunit; +using System; namespace Microsoft.CodeAnalysis.Editor.UnitTests.CommentSelection { [UseExportProvider] - public class ToggleBlockCommentCommandHandlerTests : AbstractToggleBlockCommentTestBase + public class ToggleBlockCommentCommandHandlerTests : AbstractToggleCommentTestBase { [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] public void AddComment_EmptyCaret() @@ -19,7 +20,7 @@ public void AddComment_EmptyCaret() var markup = @"$$"; var expected = @"[|/**/|]"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -28,7 +29,7 @@ public void AddComment_EmptySelection() var markup = @"[| |]"; var expected = @"[|/* */|]"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -53,7 +54,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -78,7 +79,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -103,7 +104,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -128,7 +129,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -153,7 +154,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -177,7 +178,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -202,7 +203,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -231,7 +232,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -264,7 +265,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -291,7 +292,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -322,7 +323,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -355,7 +356,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -392,7 +393,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -425,7 +426,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -454,7 +455,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -485,7 +486,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -514,7 +515,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -543,7 +544,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -572,7 +573,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -603,7 +604,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -632,7 +633,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -661,7 +662,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -690,7 +691,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -715,7 +716,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -740,7 +741,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -767,7 +768,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -792,7 +793,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -821,7 +822,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -850,7 +851,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -883,7 +884,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -892,7 +893,7 @@ public void RemoveComment_AtBeginningOfFile() var markup = @"[|/**/|]"; var expected = @""; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -921,7 +922,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -950,7 +951,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -979,7 +980,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -1008,7 +1009,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -1035,7 +1036,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -1062,7 +1063,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -1091,7 +1092,7 @@ void M() } }|]"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -1120,7 +1121,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -1151,7 +1152,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -1180,7 +1181,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -1209,7 +1210,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -1242,7 +1243,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -1271,7 +1272,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -1300,7 +1301,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -1329,7 +1330,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -1358,7 +1359,7 @@ void M() } }"; - ToggleBlockComment(markup, expected); + ToggleComment(markup, expected); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -1399,7 +1400,7 @@ void M() }" }; - ToggleBlockCommentMultiple(markup, expectedText); + ToggleCommentMultiple(markup, expectedText); } [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleBlockComment)] @@ -1441,12 +1442,12 @@ void M() }" }; - ToggleBlockCommentMultiple(markup, expectedText); + ToggleCommentMultiple(markup, expectedText); } - internal override ToggleBlockCommentCommandHandler GetToggleBlockCommentCommandHandler(TestWorkspace workspace) + internal override AbstractCommentSelectionBase GetToggleCommentCommandHandler(TestWorkspace workspace) { - return (ToggleBlockCommentCommandHandler)workspace.ExportProvider.GetExportedValues() + return (AbstractCommentSelectionBase)workspace.ExportProvider.GetExportedValues() .First(export => typeof(ToggleBlockCommentCommandHandler).Equals(export.GetType())); } } diff --git a/src/EditorFeatures/Test/CommentSelection/ToggleLineCommentCommandHandlerTests.cs b/src/EditorFeatures/Test/CommentSelection/ToggleLineCommentCommandHandlerTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..f8b625417c02562eee7835d5d3010c2731195aa1 --- /dev/null +++ b/src/EditorFeatures/Test/CommentSelection/ToggleLineCommentCommandHandlerTests.cs @@ -0,0 +1,1084 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Linq; +using Microsoft.CodeAnalysis.Editor.Implementation.CommentSelection; +using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using VSCommanding = Microsoft.VisualStudio.Commanding; +using Xunit; +using System; + +namespace Microsoft.CodeAnalysis.Editor.UnitTests.CommentSelection +{ + [UseExportProvider] + public class ToggleLineCommentCommandHandlerTests : AbstractToggleCommentTestBase + { + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_EmptyCaret() + { + var markup = @"$$"; + var expected = @"[||]"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_EmptySelection() + { + var markup = @"[| |]"; + var expected = @"[||]"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_CaretInUncommentedLine() + { + var markup = +@" +class C +{ + void M() + { + var$$ i = 1; + } +}"; + var expected = +@" +class C +{ + void M() + { +[| //var i = 1;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_CaretBeforeUncommentedLine() + { + var markup = +@" +class C +{ + void M() + { +$$ var i = 1; + } +}"; + var expected = +@" +class C +{ + void M() + { +[| //var i = 1;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_SingleLineSelected() + { + var markup = +@" +class C +{ + void M() + { + [|var i = 1;|] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| //var i = 1;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_PartialSingleLineSelected() + { + var markup = +@" +class C +{ + void M() + { + var [|i = 1;|] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| //var i = 1;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_SingleLineWithWhitespaceSelected() + { + var markup = +@" +class C +{ + void M() + { +[| + var i = 1; + |] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| + //var i = 1; + |] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_SelectionInsideCommentAtEndOfLine() + { + var markup = +@" +class C +{ + void M() + { + var i = 1; // A [|comment|]. + } +}"; + var expected = +@" +class C +{ + void M() + { +[| //var i = 1; // A comment.|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_SelectionAroundCommentAtEndOfLine() + { + var markup = +@" +class C +{ + void M() + { + var i = 1; [|// A comment.|] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| //var i = 1; // A comment.|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_SelectionOutsideCommentAtEndOfLine() + { + var markup = +@" +class C +{ + void M() + { + [|var i = 1; // A comment.|] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| //var i = 1; // A comment.|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_CaretOutsideCommentAtEndOfLine() + { + var markup = +@" +class C +{ + void M() + { + var $$i = 1; // A comment. + } +}"; + var expected = +@" +class C +{ + void M() + { +[| //var i = 1; // A comment.|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_CaretInsideCommentAtEndOfLine() + { + var markup = +@" +class C +{ + void M() + { + var i = 1; // A $$comment. + } +}"; + var expected = +@" +class C +{ + void M() + { +[| //var i = 1; // A comment.|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_CommentMarkerInString() + { + var markup = +@" +class C +{ + void M() + { + [|string s = '\\';|] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| //string s = '\\';|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_MultipleLinesSelected() + { + var markup = +@" +class C +{ + void M() + { + [|var i = 1; + var j = 2;|] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| //var i = 1; + //var j = 2;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_MultipleLinesWithWhitespaceSelected() + { + var markup = +@" +class C +{ + void M() + { +[| + var i = 1; + + var j = 2; + |] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| + //var i = 1; + + //var j = 2; + |] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_MultipleLinesPartiallyCommentedSelected() + { + var markup = +@" +class C +{ + void M() + { + [|//var i = 1; + var j = 2;|] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| ////var i = 1; + //var j = 2;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_MultipleLinesWithCommentsInLineSelected() + { + var markup = +@" +class C +{ + void M() + { + [|var i = 1; // A comment. + var j = 2;|] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| //var i = 1; // A comment. + //var j = 2;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_MultipleLinesWithDifferentIndentationsSelected() + { + var markup = +@" +class C +{ +[| void M() + { + var i = 1; + + var j = 2; + }|] +}"; + var expected = +@" +class C +{ +[| //void M() + //{ + // var i = 1; + + // var j = 2; + //}|] +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_MultiCaret() + { + var markup = +@" +class C +{ + void M() + { + var [||]i = 1; + var [||]j = 2; + } +}"; + var expected = +@" +class C +{ + void M() + { +[| //var i = 1;|] +[| //var j = 2;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_MultiSeletion() + { + var markup = +@" +class C +{ + void M() + { + [|var i = 1;|] + [|var j = 2;|] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| //var i = 1;|] +[| //var j = 2;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_MultiSeletionPartiallyCommented() + { + var markup = +@" +class C +{ + void M() + { + [|//var i = 1;|] + [|var j = 2;|] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| ////var i = 1;|] +[| //var j = 2;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void AddComment_VisualBasicStyleComment() + { + var markup = +@" +Class A + [|Function M() + Dim a = 1 + + End Function|] +End Class"; + var expected = +@" +Class A +[| 'Function M() + ' Dim a = 1 + + 'End Function|] +End Class"; + + ToggleComment(markup, expected, true); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void RemoveComment_CaretInCommentedLine() + { + var markup = +@" +class C +{ + void M() + { + //var$$ i = 1; + } +}"; + var expected = +@" +class C +{ + void M() + { +[| var i = 1;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void RemoveComment_CaretBeforeCommentedLine() + { + var markup = +@" +class C +{ + void M() + { + $$ //var i = 1; + } +}"; + var expected = +@" +class C +{ + void M() + { +[| var i = 1;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void RemoveComment_CaretInCommentedLineWithEndComment() + { + var markup = +@" +class C +{ + void M() + { + //var i = 1; // A $$comment. + } +}"; + var expected = +@" +class C +{ + void M() + { +[| var i = 1; // A comment.|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void RemoveComment_CaretInDoubleCommentedLine() + { + var markup = +@" +class C +{ + void M() + { + ////var$$ i = 1; + } +}"; + var expected = +@" +class C +{ + void M() + { +[| //var i = 1;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void RemoveComment_CommentedLineSelected() + { + var markup = +@" +class C +{ + void M() + { + [|//var i = 1;|] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| var i = 1;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void RemoveComment_InsideCommentSelected() + { + var markup = +@" +class C +{ + void M() + { + //var [|i = 1;|] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| var i = 1;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void RemoveComment_CommentedLineWithWhitespaceSelected() + { + var markup = +@" +class C +{ + void M() + { +[| + //var i = 1; + |] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| + var i = 1; +|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void RemoveComment_CommentMarkerInString() + { + var markup = +@" +class C +{ + void M() + { + [|//string s = '\\';|] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| string s = '\\';|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void RemoveComment_MultipleCommentedLinesSelected() + { + var markup = +@" +class C +{ + void M() + { + [|//var i = 1; + //var j = 2;|] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| var i = 1; + var j = 2;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void RemoveComment_MultipleCommentedLinesAndWhitespaceSelected() + { + var markup = +@" +class C +{ + void M() + { +[| + //var i = 1; + + //var j = 2; + |] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| + var i = 1; + + var j = 2; +|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void RemoveComment_MultipleCommentedLinesWithEndCommentSelected() + { + var markup = +@" +class C +{ + void M() + { + [|//var i = 1; // A comment. + //var j = 2;|] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| var i = 1; // A comment. + var j = 2;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void RemoveComment_MultipleLinesWithDifferentIndentationsSelected() + { + var markup = +@" +class C +{ +[| //void M() + //{ + // var i = 1; + + // var j = 2; + //}|] +}"; + var expected = +@" +class C +{ +[| void M() + { + var i = 1; + + var j = 2; + }|] +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void RemoveComment_MultiCaret() + { + var markup = +@" +class C +{ + void M() + { + //var [||]i = 1; + [||] + //var [||]j = 2; + } +}"; + var expected = +@" +class C +{ + void M() + { +[| var i = 1;|] +[||] +[| var j = 2;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void RemoveComment_MultiSeletion() + { + var markup = +@" +class C +{ + void M() + { + [|//var i = 1;|] + [| |] + [|//var j = 2;|] + } +}"; + var expected = +@" +class C +{ + void M() + { +[| var i = 1;|] +[||] +[| var j = 2;|] + } +}"; + + ToggleComment(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void RemoveComment_VisualBasicStyleComment() + { + var markup = +@" +Class A + [|'Function M() + ' Dim a = 1 + + 'End Function|] +End Class"; + var expected = +@" +Class A +[| Function M() + Dim a = 1 + + End Function|] +End Class"; + + ToggleComment(markup, expected, true); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void ToggleComment_MultipleLinesSelected() + { + var markup = +@" +class C +{ + void M() + { + [|//var i = 1; + + var j = 2;|] + } +}"; + var expected = new string[] + { +@" +class C +{ + void M() + { +[| ////var i = 1; + + //var j = 2;|] + } +}", +@" +class C +{ + void M() + { +[| //var i = 1; + + var j = 2;|] + } +}" + }; + + + ToggleCommentMultiple(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void ToggleComment_MultipleSelection() + { + var markup = +@" +class C +{ + void M() + { + [|//var i = 1;|] +[||] + [|var j = 2;|] + } +}"; + var expected = new string[] + { +@" +class C +{ + void M() + { +[| ////var i = 1;|] +[||] +[| //var j = 2;|] + } +}", +@" +class C +{ + void M() + { +[| //var i = 1;|] +[||] +[| var j = 2;|] + } +}" + }; + + + ToggleCommentMultiple(markup, expected); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ToggleLineComment)] + public void ToggleComment_VisualBasicStyleComment() + { + var markup = +@" +Class A + [|Function M() + Dim a = 1 + + End Function|] +End Class"; + var expected = new string[] + { +@" +Class A +[| 'Function M() + ' Dim a = 1 + + 'End Function|] +End Class", +@" +Class A +[| Function M() + Dim a = 1 + + End Function|] +End Class" + }; + + ToggleCommentMultiple(markup, expected, true); + } + + internal override AbstractCommentSelectionBase GetToggleCommentCommandHandler(TestWorkspace workspace) + { + return (AbstractCommentSelectionBase)workspace.ExportProvider.GetExportedValues() + .First(export => typeof(ToggleLineCommentCommandHandler).Equals(export.GetType())); + } + } +} diff --git a/src/Test/Utilities/Portable/Traits/Traits.cs b/src/Test/Utilities/Portable/Traits/Traits.cs index 69a2323dc4e2c6aa761bf1e33d96f43d3cce9bde..99368954dbebf92e2f60e80d0581c638288fd97e 100644 --- a/src/Test/Utilities/Portable/Traits/Traits.cs +++ b/src/Test/Utilities/Portable/Traits/Traits.cs @@ -250,6 +250,7 @@ public static class Features public const string TextStructureNavigator = nameof(TextStructureNavigator); public const string TodoComments = nameof(TodoComments); public const string ToggleBlockComment = nameof(ToggleBlockComment); + public const string ToggleLineComment = nameof(ToggleLineComment); public const string TypeInferenceService = nameof(TypeInferenceService); public const string Venus = nameof(Venus); public const string ValidateFormatString = nameof(ValidateFormatString); diff --git a/src/Workspaces/Core/Portable/Experiments/IExperimentationService.cs b/src/Workspaces/Core/Portable/Experiments/IExperimentationService.cs index 5ca2295808d39fb185bdc0e9071e3893a8a8234f..dcad0a80b89a1284384b35be0594c456733cd6f8 100644 --- a/src/Workspaces/Core/Portable/Experiments/IExperimentationService.cs +++ b/src/Workspaces/Core/Portable/Experiments/IExperimentationService.cs @@ -23,5 +23,6 @@ internal static class WellKnownExperimentNames public const string CompletionAPI = nameof(CompletionAPI); public const string PartialLoadMode = "Roslyn.PartialLoadMode"; public const string RoslynToggleBlockComment = "Roslyn.ToggleBlockComment"; + public const string RoslynToggleLineComment = "Roslyn.ToggleLineComment"; } }