diff --git a/src/EditorFeatures/CSharpTest/DocumentationComments/DocumentationCommentTests.cs b/src/EditorFeatures/CSharpTest/DocumentationComments/DocumentationCommentTests.cs index 3965936842a567a2f05bebf38c856e99eba6c7d7..e8f9c49d2824e8ded85e9504337f150b0664ec4a 100644 --- a/src/EditorFeatures/CSharpTest/DocumentationComments/DocumentationCommentTests.cs +++ b/src/EditorFeatures/CSharpTest/DocumentationComments/DocumentationCommentTests.cs @@ -1264,6 +1264,52 @@ void M() VerifyPressingEnter(code, expected, useTabs: true); } + [WorkItem(5486, "https://github.com/dotnet/roslyn/issues/5486")] + [Fact, Trait(Traits.Feature, Traits.Features.DocumentationComments)] + public void PressingEnter_Selection1() + { + var code = +@"/// +/// Hello [|World|]$$! +/// +class C +{ +}"; + var expected = +@"/// +/// Hello +/// $$! +/// +class C +{ +}"; + + VerifyPressingEnter(code, expected); + } + + [WorkItem(5486, "https://github.com/dotnet/roslyn/issues/5486")] + [Fact, Trait(Traits.Feature, Traits.Features.DocumentationComments)] + public void PressingEnter_Selection2() + { + var code = +@"/// +/// Hello $$[|World|]! +/// +class C +{ +}"; + var expected = +@"/// +/// Hello +/// $$! +/// +class C +{ +}"; + + VerifyPressingEnter(code, expected); + } + [Fact, Trait(Traits.Feature, Traits.Features.DocumentationComments)] public void Command_Class() { diff --git a/src/EditorFeatures/Core/Implementation/DocumentationComments/AbstractDocumentationCommentCommandHandler.cs b/src/EditorFeatures/Core/Implementation/DocumentationComments/AbstractDocumentationCommentCommandHandler.cs index 58aed62a599acabf46a63092fe32e5a2fd85702c..af33ce70d5b61215edf1ca027f0f2c53b9e61cc9 100644 --- a/src/EditorFeatures/Core/Implementation/DocumentationComments/AbstractDocumentationCommentCommandHandler.cs +++ b/src/EditorFeatures/Core/Implementation/DocumentationComments/AbstractDocumentationCommentCommandHandler.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.Editor.Commands; using Microsoft.CodeAnalysis.Editor.Host; @@ -480,14 +481,34 @@ public void ExecuteCommand(ReturnKeyCommandArgs args, Action nextHandler) // Check to see if the current line starts with exterior trivia. If so, we'll take over. // If not, let the nextHandler run. - var caretPosition = args.TextView.GetCaretPoint(args.SubjectBuffer) ?? -1; - if (caretPosition < 0) + int originalPosition; + + // The original position should be a position that is consistent with the syntax tree, even + // after Enter is pressed. Thus, we use the start of the first selection if there is one. + // Otherwise, getting the tokens to the right or the left might return unexpected results. + + if (args.TextView.Selection.SelectedSpans.Count > 0) + { + var selectedSpan = args.TextView.Selection + .GetSnapshotSpansOnBuffer(args.SubjectBuffer) + .FirstOrNullable(); + + originalPosition = selectedSpan != null + ? args.TextView.BufferGraph.MapUpOrDownToBuffer(selectedSpan.Value.Start, args.SubjectBuffer) ?? -1 + : (args.TextView.GetCaretPoint(args.SubjectBuffer) ?? -1); + } + else + { + originalPosition = args.TextView.GetCaretPoint(args.SubjectBuffer) ?? -1; + } + + if (originalPosition < 0) { nextHandler(); return; } - if (!CurrentLineStartsWithExteriorTrivia(args.SubjectBuffer, caretPosition)) + if (!CurrentLineStartsWithExteriorTrivia(args.SubjectBuffer, originalPosition)) { nextHandler(); return; @@ -509,7 +530,7 @@ public void ExecuteCommand(ReturnKeyCommandArgs args, Action nextHandler) var editorOperations = _editorOperationsFactoryService.GetEditorOperations(args.TextView); editorOperations.InsertNewLine(); - CompleteComment(args.SubjectBuffer, args.TextView, caretPosition, InsertOnEnterTyped, CancellationToken.None); + CompleteComment(args.SubjectBuffer, args.TextView, originalPosition, InsertOnEnterTyped, CancellationToken.None); // Since we're wrapping the ENTER key undo transaction, we always complete // the transaction -- even if we didn't generate anything. diff --git a/src/EditorFeatures/Test/DocumentationComments/AbstractDocumentationCommentTests.cs b/src/EditorFeatures/Test/DocumentationComments/AbstractDocumentationCommentTests.cs index 7700c5b23b4d29697c7a552b5d66004485c07a72..298484d30b0e32b479cbb9248bf5a13b2823ef64 100644 --- a/src/EditorFeatures/Test/DocumentationComments/AbstractDocumentationCommentTests.cs +++ b/src/EditorFeatures/Test/DocumentationComments/AbstractDocumentationCommentTests.cs @@ -118,7 +118,23 @@ private void Verify(string initialMarkup, string expectedMarkup, bool useTabs, A using (var workspace = CreateTestWorkspace(initialMarkup)) { var testDocument = workspace.Documents.Single(); + + Assert.True(testDocument.CursorPosition.HasValue, "No caret position set!"); + var startCaretPosition = testDocument.CursorPosition.Value; + var view = testDocument.GetTextView(); + + if (testDocument.SelectedSpans.Any()) + { + var selectedSpan = testDocument.SelectedSpans[0]; + + var isReversed = selectedSpan.Start == startCaretPosition + ? true + : false; + + view.Selection.Select(new SnapshotSpan(view.TextSnapshot, selectedSpan.Start, selectedSpan.Length), isReversed); + } + view.Caret.MoveTo(new SnapshotPoint(view.TextSnapshot, testDocument.CursorPosition.Value)); if (useTabs) @@ -139,9 +155,9 @@ private void Verify(string initialMarkup, string expectedMarkup, bool useTabs, A Assert.Equal(expectedCode, view.TextSnapshot.GetText()); - var caretPosition = view.Caret.Position.BufferPosition.Position; - Assert.True(expectedPosition == caretPosition, - string.Format("Caret positioned incorrectly. Should have been {0}, but was {1}.", expectedPosition, caretPosition)); + var endCaretPosition = view.Caret.Position.BufferPosition.Position; + Assert.True(expectedPosition == endCaretPosition, + string.Format("Caret positioned incorrectly. Should have been {0}, but was {1}.", expectedPosition, endCaretPosition)); } } } diff --git a/src/EditorFeatures/VisualBasicTest/DocumentationComments/DocumentationCommentTests.vb b/src/EditorFeatures/VisualBasicTest/DocumentationComments/DocumentationCommentTests.vb index 8d131cccfa3855e809caa92ca93b4e3bdf16960a..31c555e8532d1198e23d583805509ab68181e814 100644 --- a/src/EditorFeatures/VisualBasicTest/DocumentationComments/DocumentationCommentTests.vb +++ b/src/EditorFeatures/VisualBasicTest/DocumentationComments/DocumentationCommentTests.vb @@ -736,6 +736,48 @@ End Class VerifyPressingEnter(code, expected, useTabs:=True) End Sub + + + Public Sub PressingEnter_Selection1() + Const code = " +''' +''' Hello [|World|]$$! +''' +Class C +End Class +" + Const expected = " +''' +''' Hello +''' $$! +''' +Class C +End Class +" + VerifyPressingEnter(code, expected) + End Sub + + + + Public Sub PressingEnter_Selection2() + Const code = " +''' +''' Hello $$[|World|]! +''' +Class C +End Class +" + Const expected = " +''' +''' Hello +''' $$! +''' +Class C +End Class +" + VerifyPressingEnter(code, expected) + End Sub + Public Sub Command_Class() Const code = "