未验证 提交 68d8f536 编写于 作者: J Joey Robichaud 提交者: GitHub

Merge pull request #37397 from YairHalberstadt/convert-interpolated-strings-treats-char-as-string

Convert To Interpolated Strings refactoring provider should treat cha…
......@@ -54,6 +54,19 @@ void M()
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)]
public async Task TestMissingOnConcatenatedStrings3()
{
await TestMissingInRegularAndScriptAsync(
@"public class C
{
void M()
{
var v = ""string"" + '.' + [||]""string"";
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)]
public async Task TestWithStringOnLeft()
{
......@@ -270,6 +283,19 @@ void M()
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)]
public async Task TestMissingWithMixedStringTypes3()
{
await TestMissingInRegularAndScriptAsync(
@"public class C
{
void M()
{
var v = 1 + @""string"" + 2 + [||]'\n';
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)]
public async Task TestWithOverloadedOperator()
{
......@@ -728,6 +754,77 @@ void M()
{
var v = $""{1}{(""string"")}"";
}
}");
}
[WorkItem(37324, "https://github.com/dotnet/roslyn/issues/37324")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)]
public async Task TestConcatenationWithChar()
{
await TestInRegularAndScriptAsync(
@"public class C
{
void M()
{
var hello = ""hello"";
var world = ""world"";
var str = hello [||]+ ' ' + world;
}
}",
@"public class C
{
void M()
{
var hello = ""hello"";
var world = ""world"";
var str = $""{hello} {world}"";
}
}");
}
[WorkItem(37324, "https://github.com/dotnet/roslyn/issues/37324")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)]
public async Task TestConcatenationWithCharAfterStringLiteral()
{
await TestInRegularAndScriptAsync(
@"public class C
{
void M()
{
var world = ""world"";
var str = ""hello"" [||]+ ' ' + world;
}
}",
@"public class C
{
void M()
{
var world = ""world"";
var str = $""hello {world}"";
}
}");
}
[WorkItem(37324, "https://github.com/dotnet/roslyn/issues/37324")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)]
public async Task TestConcatenationWithCharBeforeStringLiteral()
{
await TestInRegularAndScriptAsync(
@"public class C
{
void M()
{
var hello = ""hello"";
var str = hello [||]+ ' ' + ""world"";
}
}",
@"public class C
{
void M()
{
var hello = ""hello"";
var str = $""{hello} world"";
}
}");
}
}
......
......@@ -462,6 +462,68 @@ Public Class C
Sub M()
dim v = $""{3}string{1}string""
End Sub
End Class")
End Function
<WorkItem(37324, "https://github.com/dotnet/roslyn/issues/37324")>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)>
Public Async Function TestConcatenationWithChar() As Task
Await TestInRegularAndScriptAsync(
"
Public Class C
Private Sub M()
Dim hello = ""hello""
Dim world = ""world""
Dim str = hello [||]& "" ""c & world
End Sub
End Class",
"
Public Class C
Private Sub M()
Dim hello = ""hello""
Dim world = ""world""
Dim str = $""{hello} {world}""
End Sub
End Class")
End Function
<WorkItem(37324, "https://github.com/dotnet/roslyn/issues/37324")>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)>
Public Async Function TestConcatenationWithCharAfterStringLiteral() As Task
Await TestInRegularAndScriptAsync(
"
Public Class C
Private Sub M()
Dim world = ""world""
Dim str = ""hello"" [||]& "" ""c & world
End Sub
End Class",
"
Public Class C
Private Sub M()
Dim world = ""world""
Dim str = $""hello {world}""
End Sub
End Class")
End Function
<WorkItem(37324, "https://github.com/dotnet/roslyn/issues/37324")>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)>
Public Async Function TestConcatenationWithCharBeforeStringLiteral() As Task
Await TestInRegularAndScriptAsync(
"
Public Class C
Private Sub M()
Dim hello = ""hello""
Dim str = hello [||]& "" ""c & ""world""
End Sub
End Class",
"
Public Class C
Private Sub M()
Dim hello = ""hello""
Dim str = $""{hello} world""
End Sub
End Class")
End Function
End Class
......
......@@ -27,7 +27,7 @@ protected override SyntaxToken CreateInterpolatedStringStartToken(bool isVerbati
protected override SyntaxToken CreateInterpolatedStringEndToken()
=> SyntaxFactory.Token(SyntaxKind.InterpolatedStringEndToken);
protected override string GetTextWithoutQuotes(string text, bool isVerbatim)
protected override string GetTextWithoutQuotes(string text, bool isVerbatim, bool isCharacterLiteral)
=> isVerbatim
? text.Substring("@'".Length, text.Length - "@''".Length)
: text.Substring("'".Length, text.Length - "''".Length);
......
......@@ -60,7 +60,9 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
var pieces = new List<SyntaxNode>();
CollectPiecesDown(syntaxFacts, pieces, top, semanticModel, cancellationToken);
var stringLiterals = pieces.Where(syntaxFacts.IsStringLiteralExpression).ToImmutableArray();
var stringLiterals = pieces
.Where(x => syntaxFacts.IsStringLiteralExpression(x) || syntaxFacts.IsCharacterLiteralExpression(x))
.ToImmutableArray();
// If the entire expression is just concatenated strings, then don't offer to
// make an interpolated string. The user likely manually split this for
......@@ -113,12 +115,13 @@ private Task<Document> UpdateDocumentAsync(Document document, SyntaxNode root, S
var previousContentWasStringLiteralExpression = false;
foreach (var piece in pieces)
{
var currentContentIsStringLiteral = syntaxFacts.IsStringLiteralExpression(piece);
if (currentContentIsStringLiteral)
var isCharacterLiteral = syntaxFacts.IsCharacterLiteralExpression(piece);
var currentContentIsStringOrCharacterLiteral = syntaxFacts.IsStringLiteralExpression(piece) || isCharacterLiteral;
if (currentContentIsStringOrCharacterLiteral)
{
var text = piece.GetFirstToken().Text;
var textWithEscapedBraces = text.Replace("{", "{{").Replace("}", "}}");
var textWithoutQuotes = GetTextWithoutQuotes(textWithEscapedBraces, isVerbatimStringLiteral);
var textWithoutQuotes = GetTextWithoutQuotes(textWithEscapedBraces, isVerbatimStringLiteral, isCharacterLiteral);
if (previousContentWasStringLiteralExpression)
{
// Last part we added to the content list was also an interpolated-string-text-node.
......@@ -145,7 +148,7 @@ private Task<Document> UpdateDocumentAsync(Document document, SyntaxNode root, S
}
// Update this variable to be true every time we encounter a new string literal expression
// so we know to concatinate future string literals together if we encounter them.
previousContentWasStringLiteralExpression = currentContentIsStringLiteral;
previousContentWasStringLiteralExpression = currentContentIsStringOrCharacterLiteral;
}
return generator.InterpolatedStringExpression(startToken, content, endToken);
......@@ -158,7 +161,7 @@ private static SyntaxNode ConcatinateTextToTextNode(SyntaxGenerator generator, S
return generator.InterpolatedStringText(generator.InterpolatedStringTextToken(newText));
}
protected abstract string GetTextWithoutQuotes(string text, bool isVerbatimStringLiteral);
protected abstract string GetTextWithoutQuotes(string text, bool isVerbatimStringLiteral, bool isCharacterLiteral);
protected abstract SyntaxToken CreateInterpolatedStringStartToken(bool isVerbatimStringLiteral);
protected abstract SyntaxToken CreateInterpolatedStringEndToken();
......
......@@ -21,8 +21,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ConvertToInterpolatedString
Return SyntaxFactory.Token(SyntaxKind.DoubleQuoteToken)
End Function
Protected Overrides Function GetTextWithoutQuotes(text As String, isVerbatim As Boolean) As String
Return text.Substring("'".Length, text.Length - "''".Length)
Protected Overrides Function GetTextWithoutQuotes(text As String, isVerbatim As Boolean, isCharacterLiteral As Boolean) As String
If isCharacterLiteral Then
Return text.Substring("'".Length, text.Length - "''C".Length)
Else
Return text.Substring("'".Length, text.Length - "''".Length)
End If
End Function
End Class
End Namespace
......@@ -1311,6 +1311,9 @@ public override bool IsInterpolatedStringTextToken(SyntaxToken token)
public bool IsStringLiteralExpression(SyntaxNode node)
=> node.Kind() == SyntaxKind.StringLiteralExpression;
public bool IsCharacterLiteralExpression(SyntaxNode node)
=> node.Kind() == SyntaxKind.CharacterLiteralExpression;
public bool IsVerbatimStringLiteral(SyntaxToken token)
=> token.IsVerbatimStringLiteral();
......
......@@ -84,6 +84,7 @@ internal interface ISyntaxFactsService : ILanguageService
bool IsVerbatimStringLiteral(SyntaxToken token);
bool IsInterpolatedStringTextToken(SyntaxToken token);
bool IsStringLiteralExpression(SyntaxNode node);
bool IsCharacterLiteralExpression(SyntaxNode node);
bool IsTypeNamedVarInVariableOrFieldDeclaration(SyntaxToken token, SyntaxNode parent);
bool IsTypeNamedDynamic(SyntaxToken token, SyntaxNode parent);
......
......@@ -1362,6 +1362,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return node.Kind() = SyntaxKind.StringLiteralExpression
End Function
Public Function IsCharacterLiteralExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsCharacterLiteralExpression
Return node.Kind() = SyntaxKind.CharacterLiteralExpression
End Function
Public Function IsVerbatimStringLiteral(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsVerbatimStringLiteral
' VB does not have verbatim strings
Return False
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册