未验证 提交 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
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.
先完成此消息的编辑!
想要评论请 注册