Skip to content

Commit

Permalink
Merge pull request #72508 from sdelarosbil/no-equals-quotes-completion
Browse files Browse the repository at this point in the history
Do not put an equals and quotes when completing an xml attribute if present
  • Loading branch information
CyrusNajmabadi authored Mar 21, 2024
2 parents d2b48fe + b5b2653 commit 460975c
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,35 @@ static void Goo()
""", "cref", "langword", "href");
}

[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72259")]
public async Task SeeAttributeNames2()
{
var text = """
class C
{
/// <summary>
/// <see l$$=""/>
/// </summary>
static void Goo()
{
}
}
""";
var expected = """
class C
{
/// <summary>
/// <see langword=""/>
/// </summary>
static void Goo()
{
}
}
""";

await VerifyProviderCommitAsync(text, "langword", expected, null);
}

[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37504")]
public async Task SeeAlsoAttributeNames()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,76 @@ class c
End Using
End Function

<WpfTheory, CombinatorialData>
Public Async Function InvokeWithOpenAngleSeeCommitSeeWithEqualsQuotes(showCompletionInArgumentLists As Boolean) As Task
Using state = TestStateFactory.CreateCSharpTestState(
<Document><![CDATA[
class c
{
/// <summary>
/// <see $$=""
/// </summary>
void goo() { }
}
]]></Document>, showCompletionInArgumentLists:=showCompletionInArgumentLists)

state.SendInvokeCompletionList()
state.AssertItemsInOrder({"!--", "![CDATA[", "inheritdoc", "see", "seealso"})
state.SendTypeChars("see")
Await state.AssertSelectedCompletionItem(displayText:="see")
state.SendReturn()

' /// <see <see cref=""/$$>=""
Await state.AssertLineTextAroundCaret(" /// <see <see cref=""""/", ">=""""")
End Using
End Function

<WpfTheory, CombinatorialData>
Public Async Function InvokeWithOpenAngleSeeCommitLangwordWithEqualsQuotes(showCompletionInArgumentLists As Boolean) As Task
Using state = TestStateFactory.CreateCSharpTestState(
<Document><![CDATA[
class c
{
/// <summary>
/// <see $$=""
/// </summary>
void goo() { }
}
]]></Document>, showCompletionInArgumentLists:=showCompletionInArgumentLists)

state.SendTypeChars("l")
state.SendInvokeCompletionList()
Await state.AssertSelectedCompletionItem(displayText:="langword")
state.SendReturn()

' /// <see langword="$$"
Await state.AssertLineTextAroundCaret(" /// <see langword=""", """")
End Using
End Function

<WpfTheory, CombinatorialData>
Public Async Function InvokeWithOpenAngleSeeCommitLangwordWithSpaceEqualsQuotes(showCompletionInArgumentLists As Boolean) As Task
Using state = TestStateFactory.CreateCSharpTestState(
<Document><![CDATA[
class c
{
/// <summary>
/// <see $$ =""
/// </summary>
void goo() { }
}
]]></Document>, showCompletionInArgumentLists:=showCompletionInArgumentLists)

state.SendTypeChars("l")
state.SendInvokeCompletionList()
Await state.AssertSelectedCompletionItem(displayText:="langword")
state.SendReturn()

' /// <see langword="$$" =""
Await state.AssertLineTextAroundCaret(" /// <see langword=""", """ =""""")
End Using
End Function

<WpfTheory, CombinatorialData>
Public Function InvokeWithNullKeywordCommitSeeLangword(showCompletionInArgumentLists As Boolean) As Task
Return InvokeWithKeywordCommitSeeLangword("null", showCompletionInArgumentLists)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,29 @@ End Class
End Using
End Function

<WpfFact>
Public Async Function InvokeWithOpenAngleSeeCommitSeeWithEqualsQuotes() As Task
Using state = TestStateFactory.CreateVisualBasicTestState(
<Document><![CDATA[
Class C
''' <summary>
''' <see $$=""
''' </summary>
Sub Goo()
End Sub
End Class
]]></Document>)

state.SendTypeChars("l")
Await state.AssertCompletionSession()
Await state.AssertSelectedCompletionItem(displayText:="langword")
state.SendReturn()

' ''' <see langword="$$"
Await state.AssertLineTextAroundCaret(" ''' <see langword=""", """")
End Using
End Function

<WpfFact>
Public Async Function InvokeWithOpenAngleCommitSeeOnCloseAngle() As Task

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ public override bool IsInsertionTrigger(SourceText text, int characterPosition,

if (IsAttributeNameContext(token, position, out var elementName, out var existingAttributes))
{
return GetAttributeItems(elementName, existingAttributes);
var nextToken = token.GetNextToken();
return GetAttributeItems(elementName, existingAttributes,
addEqualsAndQuotes: !nextToken.IsKind(SyntaxKind.EqualsToken) || nextToken.HasLeadingTrivia);
}

var wasTriggeredAfterSpace = trigger.Kind == CompletionTriggerKind.Insertion && trigger.Character == ' ';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,14 @@ private CompletionItem GetItem(string name)
return CreateCompletionItem(name);
}

protected IEnumerable<CompletionItem> GetAttributeItems(string tagName, ISet<string> existingAttributes)
protected IEnumerable<CompletionItem> GetAttributeItems(string tagName, ISet<string> existingAttributes, bool addEqualsAndQuotes)
{
return s_attributeMap.Where(x => x.elementName == tagName && !existingAttributes.Contains(x.attributeName))
.Select(x => CreateCompletionItem(x.attributeName, beforeCaretText: x.text, afterCaretText: "\""));
return s_attributeMap
.Where(x => x.elementName == tagName && !existingAttributes.Contains(x.attributeName))
.Select(x => CreateCompletionItem(
x.attributeName,
beforeCaretText: addEqualsAndQuotes ? x.text : x.text[..^2],
afterCaretText: addEqualsAndQuotes ? "\"" : ""));
}

protected IEnumerable<CompletionItem> GetAlwaysVisibleItems()
Expand Down Expand Up @@ -279,6 +283,13 @@ public override async Task<CompletionChange> GetChangeAsync(Document document, C
var replacementText = beforeCaretText;
var newPosition = replacementSpan.Start + beforeCaretText.Length;

if (text.Length > replacementSpan.End + 1
&& text[replacementSpan.End] == '='
&& text[replacementSpan.End + 1] == '"')
{
newPosition += 2;
}

if (commitChar.HasValue && !char.IsWhiteSpace(commitChar.Value) && commitChar.Value != replacementText[^1])
{
// include the commit character
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,20 +237,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers

If targetToken.IsChildToken(Function(n As XmlNameSyntax) n.LocalName) AndAlso targetToken.Parent Is tagNameSyntax Then
' <exception |
items.AddRange(GetAttributes(tagName, tagAttributes))
items.AddRange(GetAttributes(token, tagName, tagAttributes))
End If

'<exception a|
If targetToken.IsChildToken(Function(n As XmlNameSyntax) n.LocalName) AndAlso targetToken.Parent.IsParentKind(SyntaxKind.XmlAttribute) Then
' <exception |
items.AddRange(GetAttributes(tagName, tagAttributes))
items.AddRange(GetAttributes(token, tagName, tagAttributes))
End If

'<exception a=""|
If (targetToken.IsChildToken(Function(s As XmlStringSyntax) s.EndQuoteToken) AndAlso targetToken.Parent.IsParentKind(SyntaxKind.XmlAttribute)) OrElse
targetToken.IsChildToken(Function(a As XmlNameAttributeSyntax) a.EndQuoteToken) OrElse
targetToken.IsChildToken(Function(a As XmlCrefAttributeSyntax) a.EndQuoteToken) Then
items.AddRange(GetAttributes(tagName, tagAttributes))
items.AddRange(GetAttributes(token, tagName, tagAttributes))
End If

' <param name="|"
Expand Down Expand Up @@ -330,9 +330,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
Return TryCast(attribute, XmlNameAttributeSyntax)?.Reference?.Identifier.ValueText
End Function

Private Function GetAttributes(tagName As String, attributes As SyntaxList(Of XmlNodeSyntax)) As IEnumerable(Of CompletionItem)
Private Function GetAttributes(token As SyntaxToken, tagName As String, attributes As SyntaxList(Of XmlNodeSyntax)) As IEnumerable(Of CompletionItem)
Dim existingAttributeNames = attributes.Select(AddressOf GetAttributeName).WhereNotNull().ToSet()
Return GetAttributeItems(tagName, existingAttributeNames)
Dim nextToken = token.GetNextToken()
Return GetAttributeItems(tagName, existingAttributeNames,
addEqualsAndQuotes:=Not nextToken.IsKind(SyntaxKind.EqualsToken) Or nextToken.HasLeadingTrivia)
End Function

Private Shared Function GetAttributeName(node As XmlNodeSyntax) As String
Expand Down

0 comments on commit 460975c

Please sign in to comment.