提交 ab18011b 编写于 作者: D Dustin Campbell

Fix issue when pressing ENTER in XML doc comments with a selection

In order to insert XML doc comment exterior trivia (e.g. /// or '''), we grab the caret position prior to the new line being inserted into the editor and then perform a bit of analysis afterward using that position. However, if there's a selection in the editor and the caret is at the end of that selection, the position will be in an unexpected place in the syntax tree, causing that bit of analysis to fail. So, in this case (and all cases), we use the start of the selection as the position to perform analysis on since that position will be consistent after the new line is inserted.
上级 23196248
......@@ -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 =
@"/// <summary>
/// Hello [|World|]$$!
/// </summary>
class C
{
}";
var expected =
@"/// <summary>
/// Hello
/// $$!
/// </summary>
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 =
@"/// <summary>
/// Hello $$[|World|]!
/// </summary>
class C
{
}";
var expected =
@"/// <summary>
/// Hello
/// $$!
/// </summary>
class C
{
}";
VerifyPressingEnter(code, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.DocumentationComments)]
public void Command_Class()
{
......
......@@ -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.
......
......@@ -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));
}
}
}
......
......@@ -736,6 +736,48 @@ End Class
VerifyPressingEnter(code, expected, useTabs:=True)
End Sub
<WorkItem(5486, "https://github.com/dotnet/roslyn/issues/5486")>
<Fact, Trait(Traits.Feature, Traits.Features.DocumentationComments)>
Public Sub PressingEnter_Selection1()
Const code = "
''' <summary>
''' Hello [|World|]$$!
''' </summary>
Class C
End Class
"
Const expected = "
''' <summary>
''' Hello
''' $$!
''' </summary>
Class C
End Class
"
VerifyPressingEnter(code, expected)
End Sub
<WorkItem(5486, "https://github.com/dotnet/roslyn/issues/5486")>
<Fact, Trait(Traits.Feature, Traits.Features.DocumentationComments)>
Public Sub PressingEnter_Selection2()
Const code = "
''' <summary>
''' Hello $$[|World|]!
''' </summary>
Class C
End Class
"
Const expected = "
''' <summary>
''' Hello
''' $$!
''' </summary>
Class C
End Class
"
VerifyPressingEnter(code, expected)
End Sub
<Fact, Trait(Traits.Feature, Traits.Features.DocumentationComments)>
Public Sub Command_Class()
Const code = "
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册