From 0b3ee6f4b9d363af0fc9237cc82ff6eda66bb791 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Fri, 26 Feb 2021 09:17:14 -0800 Subject: [PATCH 1/7] Update ConvertConcatenationToInterpolatedStringTests to the new test framework --- ...tConcatenationToInterpolatedStringTests.cs | 191 ++++++++++-------- ...tConcatenationToInterpolatedStringTests.vb | 100 ++++----- 2 files changed, 154 insertions(+), 137 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs b/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs index 81c949e9201dd..64b769e352a53 100644 --- a/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs +++ b/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs @@ -11,70 +11,73 @@ using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; +using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeRefactoringVerifier< + Microsoft.CodeAnalysis.CSharp.ConvertToInterpolatedString.CSharpConvertConcatenationToInterpolatedStringRefactoringProvider>; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ConvertToInterpolatedString { - public class ConvertConcatenationToInterpolatedStringTests : AbstractCSharpCodeActionTest + public class ConvertConcatenationToInterpolatedStringTests { - protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspace workspace, TestParameters parameters) - => new CSharpConvertConcatenationToInterpolatedStringRefactoringProvider(); - [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestMissingOnSimpleString() { - await TestMissingInRegularAndScriptAsync( -@"public class C + var code = @"public class C { void M() { var v = [||]""string""; } -}"); +}"; + + await VerifyCS.VerifyRefactoringAsync(code, code); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestMissingOnConcatenatedStrings1() { - await TestMissingInRegularAndScriptAsync( -@"public class C + var code = @"public class C { void M() { var v = [||]""string"" + ""string""; } -}"); +}"; + + await VerifyCS.VerifyRefactoringAsync(code, code); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestMissingOnConcatenatedStrings2() { - await TestMissingInRegularAndScriptAsync( -@"public class C + var code = @"public class C { void M() { var v = ""string"" + [||]""string""; } -}"); +}"; + + await VerifyCS.VerifyRefactoringAsync(code, code); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestMissingOnConcatenatedStrings3() { - await TestMissingInRegularAndScriptAsync( -@"public class C + var code = @"public class C { void M() { var v = ""string"" + '.' + [||]""string""; } -}"); +}"; + + await VerifyCS.VerifyRefactoringAsync(code, code); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithStringOnLeft() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -94,7 +97,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestRightSideOfString() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -114,7 +117,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithStringOnRight() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -134,7 +137,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithComplexExpressionOnLeft() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -154,7 +157,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithTrivia1() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @" public class C { @@ -180,7 +183,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithComplexExpressions() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -200,7 +203,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithEscapes1() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @" public class C { @@ -222,7 +225,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithEscapes2() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @" public class C { @@ -244,7 +247,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithVerbatimString1() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -264,46 +267,49 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestMissingWithMixedStringTypes1() { - await TestMissingInRegularAndScriptAsync( -@"public class C + var code = @"public class C { void M() { var v = 1 + [||]@""string"" + 2 + ""string""; } -}"); +}"; + + await VerifyCS.VerifyRefactoringAsync(code, code); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestMissingWithMixedStringTypes2() { - await TestMissingInRegularAndScriptAsync( -@"public class C + var code = @"public class C { void M() { var v = 1 + @""string"" + 2 + [||]""string""; } -}"); +}"; + + await VerifyCS.VerifyRefactoringAsync(code, code); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestMissingWithMixedStringTypes3() { - await TestMissingInRegularAndScriptAsync( -@"public class C + var code = @"public class C { void M() { var v = 1 + @""string"" + 2 + [||]'\n'; } -}"); +}"; + + await VerifyCS.VerifyRefactoringAsync(code, code); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithOverloadedOperator() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class D { public static bool operator +(D d, string s) => false; @@ -337,8 +343,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithOverloadedOperator2() { - await TestMissingInRegularAndScriptAsync( -@"public class D + var code = @"public class D { public static bool operator +(D d, string s) => false; public static bool operator +(string s, D d) => false; @@ -351,14 +356,16 @@ void M() D d = null; var v = d + [||]""string"" + 1; } -}"); +}"; + + await VerifyCS.VerifyRefactoringAsync(code, code); } [WorkItem(16820, "https://github.com/dotnet/roslyn/issues/16820")] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithMultipleStringConcatinations() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -379,7 +386,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithMultipleStringConcatinations2() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -400,7 +407,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithMultipleStringConcatinations3() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -421,44 +428,47 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithMultipleStringConcatinations4() { - await TestMissingInRegularAndScriptAsync( -@"public class C + var code = @"public class C { void M() { var v = ""A"" + 1 + [||]""B"" + @""C""; } -}"); +}"; + + await VerifyCS.VerifyRefactoringAsync(code, code); } [WorkItem(20943, "https://github.com/dotnet/roslyn/issues/20943")] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestMissingWithDynamic1() { - await TestMissingInRegularAndScriptAsync( -@"class C + var code = @"class C { void M() { dynamic a = ""b""; string c = [||]""d"" + a + ""e""; } -}"); +}"; + + await VerifyCS.VerifyRefactoringAsync(code, code); } [WorkItem(20943, "https://github.com/dotnet/roslyn/issues/20943")] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestMissingWithDynamic2() { - await TestMissingInRegularAndScriptAsync( -@"class C + var code = @"class C { void M() { dynamic dynamic = null; var x = dynamic.someVal + [||]"" $""; } -}"); +}"; + + await VerifyCS.VerifyRefactoringAsync(code, code); } [WorkItem(23536, "https://github.com/dotnet/roslyn/issues/23536")] @@ -466,7 +476,7 @@ void M() public async Task TestWithStringLiteralWithBraces() { { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -489,7 +499,7 @@ void M() public async Task TestWithStringLiteralWithDoubleBraces() { { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -512,7 +522,7 @@ void M() public async Task TestWithMultipleStringLiteralsWithBraces() { { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -534,7 +544,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithVerbatimStringWithBraces() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -555,7 +565,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithMultipleVerbatimStringsWithBraces() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -577,7 +587,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithSelectionOnEntireToBeInterpolatedString() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -598,15 +608,16 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestMissingWithSelectionOnPartOfToBeInterpolatedStringPrefix() { - // see comment in AbstractConvertConcatenationToInterpolatedStringRefactoringProvider:ComputeRefactoringsAsync - await TestMissingInRegularAndScriptAsync( -@"public class C + var code = @"public class C { void M() { var v = [|""string"" + 1|] + ""string""; } -}"); +}"; + + // see comment in AbstractConvertConcatenationToInterpolatedStringRefactoringProvider:ComputeRefactoringsAsync + await VerifyCS.VerifyRefactoringAsync(code, code); } [WorkItem(16981, "https://github.com/dotnet/roslyn/issues/16981")] @@ -614,15 +625,16 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestMissingWithSelectionOnPartOfToBeInterpolatedStringSuffix() { - // see comment in AbstractConvertConcatenationToInterpolatedStringRefactoringProvider:ComputeRefactoringsAsync - await TestMissingInRegularAndScriptAsync( -@"public class C + var code = @"public class C { void M() { var v = ""string"" + [|1 + ""string""|]; } -}"); +}"; + + // see comment in AbstractConvertConcatenationToInterpolatedStringRefactoringProvider:ComputeRefactoringsAsync + await VerifyCS.VerifyRefactoringAsync(code, code); } [WorkItem(16981, "https://github.com/dotnet/roslyn/issues/16981")] @@ -630,22 +642,23 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestMissingWithSelectionOnMiddlePartOfToBeInterpolatedString() { - // see comment in AbstractConvertConcatenationToInterpolatedStringRefactoringProvider:ComputeRefactoringsAsync - await TestMissingInRegularAndScriptAsync( -@"public class C + var code = @"public class C { void M() { var v = ""a"" + [|1 + ""string""|] + ""b""; } -}"); +}"; + + // see comment in AbstractConvertConcatenationToInterpolatedStringRefactoringProvider:ComputeRefactoringsAsync + await VerifyCS.VerifyRefactoringAsync(code, code); } [WorkItem(16981, "https://github.com/dotnet/roslyn/issues/16981")] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithSelectionExceedingToBeInterpolatedString() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -666,7 +679,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithCaretBeforeNonStringToken() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -687,7 +700,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithCaretAfterNonStringToken() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -708,7 +721,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithCaretBeforePlusToken() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -729,7 +742,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithCaretAfterPlusToken() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -750,7 +763,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithCaretBeforeLastPlusToken() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -771,7 +784,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithCaretAfterLastPlusToken() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -792,7 +805,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestConcatenationWithNoStringLiterals() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -813,7 +826,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestConcatenationWithChar() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -838,7 +851,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestConcatenationWithCharAfterStringLiteral() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -861,7 +874,7 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestConcatenationWithCharBeforeStringLiteral() { - await TestInRegularAndScriptAsync( + await VerifyCS.VerifyRefactoringAsync( @"public class C { void M() @@ -884,20 +897,22 @@ void M() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestConcatenationWithConstMember() { - await TestMissingAsync(@" + var code = @" class C { const string Hello = ""Hello""; const string World = ""World""; const string Message = Hello + "" "" + [||]World; -}"); +}"; + + await VerifyCS.VerifyRefactoringAsync(code, code); } [WorkItem(40413, "https://github.com/dotnet/roslyn/issues/40413")] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestConcatenationWithConstDeclaration() { - await TestMissingAsync(@" + var code = @" class C { void M() { @@ -905,14 +920,16 @@ void M() { const string World = ""World""; const string Message = Hello + "" "" + [||]World; } -}"); +}"; + + await VerifyCS.VerifyRefactoringAsync(code, code); } [WorkItem(40413, "https://github.com/dotnet/roslyn/issues/40413")] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestConcatenationWithInlineString() { - await TestInRegularAndScriptAsync(@" + await VerifyCS.VerifyRefactoringAsync(@" class C { void M() { @@ -968,7 +985,7 @@ void M() {{ {after} }} }}"; - await TestInRegularAndScriptAsync(initialMarkup, expected); + await VerifyCS.VerifyRefactoringAsync(initialMarkup, expected); } [WorkItem(49229, "https://github.com/dotnet/roslyn/issues/49229")] @@ -999,7 +1016,7 @@ void M() {{ {after} }} }}"; - await TestInRegularAndScriptAsync(initialMarkup, expected); + await VerifyCS.VerifyRefactoringAsync(initialMarkup, expected); } [WorkItem(49229, "https://github.com/dotnet/roslyn/issues/49229")] @@ -1028,7 +1045,7 @@ void M() {{ {after} }} }}"; - await TestInRegularAndScriptAsync(initialMarkup, expected); + await VerifyCS.VerifyRefactoringAsync(initialMarkup, expected); } } } diff --git a/src/EditorFeatures/VisualBasicTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.vb b/src/EditorFeatures/VisualBasicTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.vb index da4c34c472261..ca361804d9cc7 100644 --- a/src/EditorFeatures/VisualBasicTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.vb +++ b/src/EditorFeatures/VisualBasicTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.vb @@ -2,32 +2,26 @@ ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. -Imports Microsoft.CodeAnalysis.CodeRefactorings -Imports Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.CodeRefactorings -Imports Microsoft.CodeAnalysis.VisualBasic.ConvertToInterpolatedString +Imports VerifyVB = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.VisualBasicCodeRefactoringVerifier(Of + Microsoft.CodeAnalysis.VisualBasic.ConvertToInterpolatedString.VisualBasicConvertConcatenationToInterpolatedStringRefactoringProvider) Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.ConvertToInterpolatedString Public Class ConvertConcatenationToInterpolatedStringTests - Inherits AbstractVisualBasicCodeActionTest - - Protected Overrides Function CreateCodeRefactoringProvider(workspace As Workspace, parameters As TestParameters) As CodeRefactoringProvider - Return New VisualBasicConvertConcatenationToInterpolatedStringRefactoringProvider() - End Function - Public Async Function TestMissingOnSimpleString() As Task - Await TestMissingInRegularAndScriptAsync( -" + Dim code = " Public Class C Sub M() dim v = [||]""string"" End Sub -End Class") +End Class" + + Await VerifyVB.VerifyRefactoringAsync(code, code) End Function Public Async Function TestWithStringOnLeft() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -44,7 +38,7 @@ End Class") Public Async Function TestRightSideOfString() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -61,7 +55,7 @@ End Class") Public Async Function TestWithStringOnRight() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -78,7 +72,7 @@ End Class") Public Async Function TestWithComplexExpressionOnLeft() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -95,7 +89,7 @@ End Class") Public Async Function TestWithTrivia1() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -112,7 +106,7 @@ End Class") Public Async Function TestWithComplexExpressions() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -129,7 +123,7 @@ End Class") Public Async Function TestWithEscapes1() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -146,7 +140,7 @@ End Class") Public Async Function TestWithEscapes2() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -163,7 +157,7 @@ End Class") Public Async Function TestWithOverloadedOperator() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " public class D public shared operator&(D d, string s) as boolean @@ -196,8 +190,7 @@ End Class") Public Async Function TestWithOverloadedOperator2() As Task - Await TestMissingInRegularAndScriptAsync( -" + Dim code = " public class D public shared operator&(D d, string s) as boolean end operator @@ -210,13 +203,15 @@ Public Class C dim d as D = nothing dim v = d & [||]""string"" & 1 End Sub -End Class") +End Class" + + Await VerifyVB.VerifyRefactoringAsync(code, code) End Function Public Async Function TestWithMultipleStringConcatinations() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -234,7 +229,7 @@ End Class") Public Async Function TestWithMultipleStringConcatinations2() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -252,7 +247,7 @@ End Class") Public Async Function TestWithMultipleStringConcatinations3() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -270,7 +265,7 @@ End Class") Public Async Function TestWithStringLiteralWithBraces() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -288,7 +283,7 @@ End Class") Public Async Function TestWithStringLiteralWithDoubleBraces() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -306,7 +301,7 @@ End Class") Public Async Function TestWithMultipleStringLiteralsWithBraces() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -325,7 +320,7 @@ End Class") Public Async Function TestWithSelectionOnEntireToBeInterpolatedString() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -343,20 +338,21 @@ End Class") Public Async Function TestMissingWithSelectionOnPartOfToBeInterpolatedString() As Task - Await TestMissingInRegularAndScriptAsync( -" + Dim code = " Public Class C Sub M() dim v = [|""string"" & 1|] & ""string"" End Sub -End Class") +End Class" + + Await VerifyVB.VerifyRefactoringAsync(code, code) End Function Public Async Function TestWithSelectionExceedingToBeInterpolatedString() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -374,7 +370,7 @@ End Class") Public Async Function TestWithCaretBeforeNonStringToken() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -392,7 +388,7 @@ End Class") Public Async Function TestWithCaretAfterNonStringToken() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -410,7 +406,7 @@ End Class") Public Async Function TestWithCaretBeforeAmpersandToken() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -428,7 +424,7 @@ End Class") Public Async Function TestWithCaretAfterAmpersandToken() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -446,7 +442,7 @@ End Class") Public Async Function TestWithCaretBeforeLastAmpersandToken() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -464,7 +460,7 @@ End Class") Public Async Function TestWithCaretAfterLastAmpersandToken() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Sub M() @@ -482,7 +478,7 @@ End Class") Public Async Function TestConcatenationWithChar() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Private Sub M() @@ -504,7 +500,7 @@ End Class") Public Async Function TestConcatenationWithCharAfterStringLiteral() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Private Sub M() @@ -524,7 +520,7 @@ End Class") Public Async Function TestConcatenationWithCharBeforeStringLiteral() As Task - Await TestInRegularAndScriptAsync( + Await VerifyVB.VerifyRefactoringAsync( " Public Class C Private Sub M() @@ -544,31 +540,35 @@ End Class") Public Async Function TestConcatenationWithConstMember() As Task - Await TestMissingAsync(" + Dim code = " Public Class C Private Const Hello As String = ""Hello"" Private Const World As String = ""World"" Private Const Message As String = Hello + "" "" + World[||] -End Class") +End Class" + + Await VerifyVB.VerifyRefactoringAsync(code, code) End Function Public Async Function TestConcatenationWithConstDeclaration() As Task - Await TestMissingAsync(" + Dim code = " Public Class C Private Sub M() Const Hello As String = ""Hello"" Const World As String = ""World"" Const Message As String = Hello + "" "" + World[||] End Sub -End Class") +End Class" + + Await VerifyVB.VerifyRefactoringAsync(code, code) End Function Public Async Function TestConcatenationWithInlineString() As Task - Await TestInRegularAndScriptAsync(" + Await VerifyVB.VerifyRefactoringAsync(" Public Class C Private Sub M() Const Hello As String = ""Hello"" @@ -606,7 +606,7 @@ Public Class C Dim s = {after} End Sub End Class" - Await TestInRegularAndScriptAsync(initialMarkup, expected) + Await VerifyVB.VerifyRefactoringAsync(initialMarkup, expected) End Function End Class End Namespace From 6337502a911505857ade65256d0e9e157abaa18f Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Fri, 26 Feb 2021 09:17:48 -0800 Subject: [PATCH 2/7] Fix failure to set value text for interpolated strings --- ...tConcatenationToInterpolatedStringTests.cs | 23 +++++++++++++++++++ ...ToInterpolatedStringRefactoringProvider.cs | 14 +++++++---- ...ToInterpolatedStringRefactoringProvider.cs | 5 ++-- ...ddParameterCheckCodeRefactoringProvider.cs | 2 +- .../Core/Portable/Editing/SyntaxGenerator.cs | 4 ++-- .../CSharpSyntaxGeneratorInternal.cs | 4 ++-- .../SyntaxGeneratorInternal.cs | 2 +- .../VisualBasicSyntaxGeneratorInternal.vb | 4 ++-- 8 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs b/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs index 64b769e352a53..199858c828ad5 100644 --- a/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs +++ b/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs @@ -494,6 +494,29 @@ void M() } } + [WorkItem(23536, "https://github.com/dotnet/roslyn/issues/23536")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] + public async Task TestWithStringLiteralWithBraces2() + { + { + await VerifyCS.VerifyRefactoringAsync( + @"public class C +{ + void M() + { + var v = 1 + [||]""{string}"" + ""{string}""; + } +}", + @"public class C +{ + void M() + { + var v = $""{1}{{string}}{{string}}""; + } +}"); + } + } + [WorkItem(23536, "https://github.com/dotnet/roslyn/issues/23536")] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertToInterpolatedString)] public async Task TestWithStringLiteralWithDoubleBraces() diff --git a/src/Features/Core/Portable/ConvertToInterpolatedString/AbstractConvertConcatenationToInterpolatedStringRefactoringProvider.cs b/src/Features/Core/Portable/ConvertToInterpolatedString/AbstractConvertConcatenationToInterpolatedStringRefactoringProvider.cs index 71fc775e75ae4..e5a9aeecfede2 100644 --- a/src/Features/Core/Portable/ConvertToInterpolatedString/AbstractConvertConcatenationToInterpolatedStringRefactoringProvider.cs +++ b/src/Features/Core/Portable/ConvertToInterpolatedString/AbstractConvertConcatenationToInterpolatedStringRefactoringProvider.cs @@ -135,7 +135,9 @@ protected SyntaxNode CreateInterpolatedString( if (currentContentIsStringOrCharacterLiteral) { var text = piece.GetFirstToken().Text; + var value = piece.GetFirstToken().Value?.ToString() ?? piece.GetFirstToken().ValueText; var textWithEscapedBraces = text.Replace("{", "{{").Replace("}", "}}"); + var valueTextWithEscapedBraces = value.Replace("{", "{{").Replace("}", "}}"); var textWithoutQuotes = GetTextWithoutQuotes(textWithEscapedBraces, isVerbatimStringLiteral, isCharacterLiteral); if (previousContentWasStringLiteralExpression) { @@ -147,14 +149,14 @@ protected SyntaxNode CreateInterpolatedString( // not: // {InterpolatedStringText}{Interpolation}{InterpolatedStringText}{InterpolatedStringText} var existingInterpolatedStringTextNode = content.Last(); - var newText = ConcatenateTextToTextNode(generator, existingInterpolatedStringTextNode, textWithoutQuotes); + var newText = ConcatenateTextToTextNode(generator, existingInterpolatedStringTextNode, textWithoutQuotes, valueTextWithEscapedBraces); content[^1] = newText; } else { // This is either the first string literal we have encountered or it is the most recent one we've seen // after adding an interpolation. Add a new interpolated-string-text-node to the list. - content.Add(generator.InterpolatedStringText(generator.InterpolatedStringTextToken(textWithoutQuotes))); + content.Add(generator.InterpolatedStringText(generator.InterpolatedStringTextToken(textWithoutQuotes, valueTextWithEscapedBraces))); } } else if (syntaxFacts.IsInterpolatedStringExpression(piece) && @@ -173,7 +175,7 @@ protected SyntaxNode CreateInterpolatedString( { // if piece starts with a text and the previous part was a string, merge the two parts (see also above) // "a" + $"b{1 + 1}" -> "a" and "b" get merged - var newText = ConcatenateTextToTextNode(generator, content.Last(), contentPart.GetFirstToken().Text); + var newText = ConcatenateTextToTextNode(generator, content.Last(), contentPart.GetFirstToken().Text, contentPart.GetFirstToken().ValueText); content[^1] = newText; } else @@ -202,11 +204,13 @@ protected SyntaxNode CreateInterpolatedString( return generator.InterpolatedStringExpression(startToken, content, endToken); } - private static SyntaxNode ConcatenateTextToTextNode(SyntaxGenerator generator, SyntaxNode interpolatedStringTextNode, string textWithoutQuotes) + private static SyntaxNode ConcatenateTextToTextNode(SyntaxGenerator generator, SyntaxNode interpolatedStringTextNode, string textWithoutQuotes, string value) { var existingText = interpolatedStringTextNode.GetFirstToken().Text; + var existingValue = interpolatedStringTextNode.GetFirstToken().ValueText; var newText = existingText + textWithoutQuotes; - return generator.InterpolatedStringText(generator.InterpolatedStringTextToken(newText)); + var newValue = existingValue + value; + return generator.InterpolatedStringText(generator.InterpolatedStringTextToken(newText, newValue)); } protected abstract string GetTextWithoutQuotes(string text, bool isVerbatimStringLiteral, bool isCharacterLiteral); diff --git a/src/Features/Core/Portable/ConvertToInterpolatedString/ConvertRegularStringToInterpolatedStringRefactoringProvider.cs b/src/Features/Core/Portable/ConvertToInterpolatedString/ConvertRegularStringToInterpolatedStringRefactoringProvider.cs index 8dfef6c9076fe..95e94fc74f7b6 100644 --- a/src/Features/Core/Portable/ConvertToInterpolatedString/ConvertRegularStringToInterpolatedStringRefactoringProvider.cs +++ b/src/Features/Core/Portable/ConvertToInterpolatedString/ConvertRegularStringToInterpolatedStringRefactoringProvider.cs @@ -85,10 +85,11 @@ private static SyntaxNode CreateInterpolatedString(Document document, SyntaxNode { var generator = SyntaxGenerator.GetGenerator(document); var text = literalExpression.GetFirstToken().Text; + var valueText = literalExpression.GetFirstToken().ValueText; var newNode = generator.InterpolatedStringText( generator.InterpolatedStringTextToken( - GetTextWithoutQuotes(text.Replace("{", "{{").Replace("}", "}}"), - isVerbatim))); + GetTextWithoutQuotes(text.Replace("{", "{{").Replace("}", "}}"), isVerbatim), + valueText)); return generator.InterpolatedStringExpression( generator.CreateInterpolatedStringStartToken(isVerbatim), diff --git a/src/Features/Core/Portable/InitializeParameter/AbstractAddParameterCheckCodeRefactoringProvider.cs b/src/Features/Core/Portable/InitializeParameter/AbstractAddParameterCheckCodeRefactoringProvider.cs index 26c85e6018afb..b27dba4fff1f5 100644 --- a/src/Features/Core/Portable/InitializeParameter/AbstractAddParameterCheckCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/InitializeParameter/AbstractAddParameterCheckCodeRefactoringProvider.cs @@ -582,7 +582,7 @@ private static SyntaxNode CreateArgumentException( private static SyntaxNode InterpolatedStringText(SyntaxGenerator generator, string text) { - return generator.InterpolatedStringText(generator.InterpolatedStringTextToken(text)); + return generator.InterpolatedStringText(generator.InterpolatedStringTextToken(text, text)); } } } diff --git a/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs b/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs index 792c5046e80ff..0c35682d73566 100644 --- a/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs +++ b/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs @@ -1550,8 +1550,8 @@ public SyntaxNode CatchClause(ITypeSymbol type, string identifier, IEnumerable SyntaxGeneratorInternal.InterpolatedStringTextToken(content); + internal SyntaxToken InterpolatedStringTextToken(string content, string value) + => SyntaxGeneratorInternal.InterpolatedStringTextToken(content, value); internal SyntaxNode InterpolatedStringText(SyntaxToken textToken) => SyntaxGeneratorInternal.InterpolatedStringText(textToken); internal SyntaxNode Interpolation(SyntaxNode syntaxNode) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxGeneratorInternal.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxGeneratorInternal.cs index f6123ca5d996e..675cd6ca71d44 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxGeneratorInternal.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxGeneratorInternal.cs @@ -95,11 +95,11 @@ internal override SyntaxNode InterpolatedStringExpression(SyntaxToken startToken internal override SyntaxNode InterpolatedStringText(SyntaxToken textToken) => SyntaxFactory.InterpolatedStringText(textToken); - internal override SyntaxToken InterpolatedStringTextToken(string content) + internal override SyntaxToken InterpolatedStringTextToken(string content, string value) => SyntaxFactory.Token( SyntaxFactory.TriviaList(), SyntaxKind.InterpolatedStringTextToken, - content, "", + content, value, SyntaxFactory.TriviaList()); internal override SyntaxNode Interpolation(SyntaxNode syntaxNode) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs index b9762e6b4ef2b..86d20ee5c4377 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxGeneratorInternalExtensions/SyntaxGeneratorInternal.cs @@ -66,7 +66,7 @@ internal SyntaxNode LocalDeclarationStatement(SyntaxToken name, SyntaxNode initi /// internal abstract bool RequiresLocalDeclarationType(); - internal abstract SyntaxToken InterpolatedStringTextToken(string content); + internal abstract SyntaxToken InterpolatedStringTextToken(string content, string value); internal abstract SyntaxNode InterpolatedStringText(SyntaxToken textToken); internal abstract SyntaxNode Interpolation(SyntaxNode syntaxNode); internal abstract SyntaxNode InterpolatedStringExpression(SyntaxToken startToken, IEnumerable content, SyntaxToken endToken); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxGeneratorInternal.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxGeneratorInternal.vb index 0ca1085d9dd37..a1fc6954474e3 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxGeneratorInternal.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxGeneratorInternal.vb @@ -96,8 +96,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration Return SyntaxFactory.InterpolatedStringText(textToken) End Function - Friend Overrides Function InterpolatedStringTextToken(content As String) As SyntaxToken - Return SyntaxFactory.InterpolatedStringTextToken(content, "") + Friend Overrides Function InterpolatedStringTextToken(content As String, value As String) As SyntaxToken + Return SyntaxFactory.InterpolatedStringTextToken(content, value) End Function Friend Overrides Function Interpolation(syntaxNode As SyntaxNode) As SyntaxNode From 835d117c2f7b6b988d577130fc8d453236b074be Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Fri, 26 Feb 2021 09:33:39 -0800 Subject: [PATCH 3/7] Fix errors in test inputs --- ...tConcatenationToInterpolatedStringTests.cs | 18 ++++---- ...tConcatenationToInterpolatedStringTests.vb | 41 +++++++++++++++---- 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs b/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs index 199858c828ad5..c0e1465ebb2e6 100644 --- a/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs +++ b/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs @@ -345,8 +345,8 @@ public async Task TestWithOverloadedOperator2() { var code = @"public class D { - public static bool operator +(D d, string s) => false; - public static bool operator +(string s, D d) => false; + public static int operator +(D d, string s) => 0; + public static int operator +(string s, D d) => 0; } public class C @@ -953,6 +953,7 @@ void M() { public async Task TestConcatenationWithInlineString() { await VerifyCS.VerifyRefactoringAsync(@" +using System; class C { void M() { @@ -962,6 +963,7 @@ void M() { } }", @" +using System; class C { void M() { @@ -998,14 +1000,14 @@ public async Task TestInliningOfInterpolatedString(string before, string after) class C {{ void M() {{ - {before} + _ = {before}; }} }}"; var expected = $@" class C {{ void M() {{ - {after} + _ = {after}; }} }}"; await VerifyCS.VerifyRefactoringAsync(initialMarkup, expected); @@ -1029,14 +1031,14 @@ public async Task TestUnicodeAndEscapeHandling(string before, string after) class C {{ void M() {{ - {before} + _ = {before}; }} }}"; var expected = $@" class C {{ void M() {{ - {after} + _ = {after}; }} }}"; await VerifyCS.VerifyRefactoringAsync(initialMarkup, expected); @@ -1058,14 +1060,14 @@ public async Task TestRemovalOfSuperflousParenthesis(string before, string after class C {{ void M() {{ - {before} + _ = {before}; }} }}"; var expected = $@" class C {{ void M() {{ - {after} + _ = {after}; }} }}"; await VerifyCS.VerifyRefactoringAsync(initialMarkup, expected); diff --git a/src/EditorFeatures/VisualBasicTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.vb b/src/EditorFeatures/VisualBasicTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.vb index ca361804d9cc7..c1ae68bfe723b 100644 --- a/src/EditorFeatures/VisualBasicTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.vb +++ b/src/EditorFeatures/VisualBasicTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.vb @@ -160,9 +160,11 @@ End Class") Await VerifyVB.VerifyRefactoringAsync( " public class D - public shared operator&(D d, string s) as boolean + public shared operator &(d As D, s As String) as boolean + Return False end operator - public shared operator&(string s, D d) as boolean + public shared operator &(s As String, d As D) as boolean + Return False end operator end class @@ -174,9 +176,11 @@ Public Class C End Class", " public class D - public shared operator&(D d, string s) as boolean + public shared operator &(d As D, s As String) as boolean + Return False end operator - public shared operator&(string s, D d) as boolean + public shared operator &(s As String, d As D) as boolean + Return False end operator end class @@ -190,11 +194,14 @@ End Class") Public Async Function TestWithOverloadedOperator2() As Task - Dim code = " + Await VerifyVB.VerifyRefactoringAsync( +" public class D - public shared operator&(D d, string s) as boolean + public shared operator &(d As D, s As String) as boolean + Return False end operator - public shared operator&(string s, D d) as boolean + public shared operator &(s As String, d As D) as boolean + Return False end operator end class @@ -203,9 +210,23 @@ Public Class C dim d as D = nothing dim v = d & [||]""string"" & 1 End Sub -End Class" +End Class", +" +public class D + public shared operator &(d As D, s As String) as boolean + Return False + end operator + public shared operator &(s As String, d As D) as boolean + Return False + end operator +end class - Await VerifyVB.VerifyRefactoringAsync(code, code) +Public Class C + Sub M() + dim d as D = nothing + dim v = $""{d & ""string""}{1}"" + End Sub +End Class") End Function @@ -569,6 +590,7 @@ End Class" Public Async Function TestConcatenationWithInlineString() As Task Await VerifyVB.VerifyRefactoringAsync(" +Imports System Public Class C Private Sub M() Const Hello As String = ""Hello"" @@ -576,6 +598,7 @@ Public Class C Console.WriteLine(Hello + "" "" + World[||]) End Sub End Class", " +Imports System Public Class C Private Sub M() Const Hello As String = ""Hello"" From cd34c7592aaa4bd9818aa076e907d11d485dda46 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Fri, 26 Feb 2021 10:23:34 -0800 Subject: [PATCH 4/7] Support constant interpolated strings --- ...tConcatenationToInterpolatedStringTests.cs | 45 ++++++++++++++++++- ...ToInterpolatedStringRefactoringProvider.cs | 4 ++ ...ToInterpolatedStringRefactoringProvider.cs | 17 ++++--- ...ToInterpolatedStringRefactoringProvider.vb | 4 ++ .../Extensions/LanguageVersionExtensions.cs | 8 +++- 5 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs b/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs index c0e1465ebb2e6..a6dc239781c0c 100644 --- a/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs +++ b/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; +using CSharpLanguageVersion = Microsoft.CodeAnalysis.CSharp.LanguageVersion; using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeRefactoringVerifier< Microsoft.CodeAnalysis.CSharp.ConvertToInterpolatedString.CSharpConvertConcatenationToInterpolatedStringRefactoringProvider>; @@ -927,8 +928,27 @@ class C const string World = ""World""; const string Message = Hello + "" "" + [||]World; }"; + var fixedCode = @" +class C +{ + const string Hello = ""Hello""; + const string World = ""World""; + const string Message = $""{Hello} {World}""; +}"; - await VerifyCS.VerifyRefactoringAsync(code, code); + await new VerifyCS.Test + { + LanguageVersion = CSharpLanguageVersion.CSharp9, + TestCode = code, + FixedCode = code, + }.RunAsync(); + + await new VerifyCS.Test + { + LanguageVersion = CSharpLanguageVersion.Preview, + TestCode = code, + FixedCode = fixedCode, + }.RunAsync(); } [WorkItem(40413, "https://github.com/dotnet/roslyn/issues/40413")] @@ -944,8 +964,29 @@ void M() { const string Message = Hello + "" "" + [||]World; } }"; + var fixedCode = @" +class C +{ + void M() { + const string Hello = ""Hello""; + const string World = ""World""; + const string Message = $""{Hello} {World}""; + } +}"; - await VerifyCS.VerifyRefactoringAsync(code, code); + await new VerifyCS.Test + { + LanguageVersion = CSharpLanguageVersion.CSharp9, + TestCode = code, + FixedCode = code, + }.RunAsync(); + + await new VerifyCS.Test + { + LanguageVersion = CSharpLanguageVersion.Preview, + TestCode = code, + FixedCode = fixedCode, + }.RunAsync(); } [WorkItem(40413, "https://github.com/dotnet/roslyn/issues/40413")] diff --git a/src/Features/CSharp/Portable/ConvertToInterpolatedString/CSharpConvertConcatenationToInterpolatedStringRefactoringProvider.cs b/src/Features/CSharp/Portable/ConvertToInterpolatedString/CSharpConvertConcatenationToInterpolatedStringRefactoringProvider.cs index c63e9c22c5caa..dee14a7cc1c82 100644 --- a/src/Features/CSharp/Portable/ConvertToInterpolatedString/CSharpConvertConcatenationToInterpolatedStringRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/ConvertToInterpolatedString/CSharpConvertConcatenationToInterpolatedStringRefactoringProvider.cs @@ -6,6 +6,7 @@ using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.ConvertToInterpolatedString; +using Microsoft.CodeAnalysis.CSharp.Shared.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Microsoft.CodeAnalysis.CSharp.ConvertToInterpolatedString @@ -20,6 +21,9 @@ public CSharpConvertConcatenationToInterpolatedStringRefactoringProvider() { } + protected override bool SupportsConstantInterpolatedStrings(Document document) + => ((CSharpParseOptions)document.Project.ParseOptions!).LanguageVersion.HasConstantInterpolatedStrings(); + protected override string GetTextWithoutQuotes(string text, bool isVerbatim, bool isCharacterLiteral) => isVerbatim ? text.Substring("@'".Length, text.Length - "@''".Length) diff --git a/src/Features/Core/Portable/ConvertToInterpolatedString/AbstractConvertConcatenationToInterpolatedStringRefactoringProvider.cs b/src/Features/Core/Portable/ConvertToInterpolatedString/AbstractConvertConcatenationToInterpolatedStringRefactoringProvider.cs index e5a9aeecfede2..335af31bfcba3 100644 --- a/src/Features/Core/Portable/ConvertToInterpolatedString/AbstractConvertConcatenationToInterpolatedStringRefactoringProvider.cs +++ b/src/Features/Core/Portable/ConvertToInterpolatedString/AbstractConvertConcatenationToInterpolatedStringRefactoringProvider.cs @@ -27,6 +27,8 @@ namespace Microsoft.CodeAnalysis.ConvertToInterpolatedString internal abstract class AbstractConvertConcatenationToInterpolatedStringRefactoringProvider : CodeRefactoringProvider where TExpressionSyntax : SyntaxNode { + protected abstract bool SupportsConstantInterpolatedStrings(Document document); + public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var (document, textSpan, cancellationToken) = context; @@ -45,14 +47,17 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte return; } - // if there is a const keyword, the refactoring shouldn't show because interpolated string is not const string - var declarator = top.FirstAncestorOrSelf(syntaxFacts.IsVariableDeclarator); - if (declarator != null) + if (!SupportsConstantInterpolatedStrings(context.Document)) { - var generator = SyntaxGenerator.GetGenerator(document); - if (generator.GetModifiers(declarator).IsConst) + // if there is a const keyword, the refactoring shouldn't show because interpolated string is not const string + var declarator = top.FirstAncestorOrSelf(syntaxFacts.IsVariableDeclarator); + if (declarator != null) { - return; + var generator = SyntaxGenerator.GetGenerator(document); + if (generator.GetModifiers(declarator).IsConst) + { + return; + } } } diff --git a/src/Features/VisualBasic/Portable/ConvertToInterpolatedString/VisualBasicConvertConcatenationToInterpolatedStringRefactoringProvider.vb b/src/Features/VisualBasic/Portable/ConvertToInterpolatedString/VisualBasicConvertConcatenationToInterpolatedStringRefactoringProvider.vb index 827ac77ea7514..319cc24c9b8e5 100644 --- a/src/Features/VisualBasic/Portable/ConvertToInterpolatedString/VisualBasicConvertConcatenationToInterpolatedStringRefactoringProvider.vb +++ b/src/Features/VisualBasic/Portable/ConvertToInterpolatedString/VisualBasicConvertConcatenationToInterpolatedStringRefactoringProvider.vb @@ -18,6 +18,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ConvertToInterpolatedString Public Sub New() End Sub + Protected Overrides Function SupportsConstantInterpolatedStrings(document As Document) As Boolean + Return False + End Function + 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) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/LanguageVersionExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/LanguageVersionExtensions.cs index 0c4d4b470efc1..7c1df6fa80aa5 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/LanguageVersionExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/LanguageVersionExtensions.cs @@ -2,13 +2,17 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - namespace Microsoft.CodeAnalysis.CSharp.Shared.Extensions { internal static class LanguageVersionExtensions { public static bool IsCSharp9OrAbove(this LanguageVersion languageVersion) => languageVersion >= LanguageVersion.CSharp9; + + public static bool IsCSharp10OrAbove(this LanguageVersion languageVersion) + => languageVersion >= LanguageVersion.Preview; + + public static bool HasConstantInterpolatedStrings(this LanguageVersion languageVersion) + => languageVersion.IsCSharp10OrAbove(); } } From d1f0412179dd2b0985446dbe0c1c1a2368f0fb6f Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Fri, 26 Feb 2021 21:10:00 -0800 Subject: [PATCH 5/7] Cleanup MEF attributes --- ...rtConcatenationToInterpolatedStringRefactoringProvider.cs | 5 +++-- ...rtConcatenationToInterpolatedStringRefactoringProvider.vb | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Features/CSharp/Portable/ConvertToInterpolatedString/CSharpConvertConcatenationToInterpolatedStringRefactoringProvider.cs b/src/Features/CSharp/Portable/ConvertToInterpolatedString/CSharpConvertConcatenationToInterpolatedStringRefactoringProvider.cs index dee14a7cc1c82..289404392cd0e 100644 --- a/src/Features/CSharp/Portable/ConvertToInterpolatedString/CSharpConvertConcatenationToInterpolatedStringRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/ConvertToInterpolatedString/CSharpConvertConcatenationToInterpolatedStringRefactoringProvider.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Composition; -using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.ConvertToInterpolatedString; using Microsoft.CodeAnalysis.CSharp.Shared.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Host.Mef; namespace Microsoft.CodeAnalysis.CSharp.ConvertToInterpolatedString { @@ -16,7 +17,7 @@ internal class CSharpConvertConcatenationToInterpolatedStringRefactoringProvider AbstractConvertConcatenationToInterpolatedStringRefactoringProvider { [ImportingConstructor] - [SuppressMessage("RoslynDiagnosticsReliability", "RS0033:Importing constructor should be [Obsolete]", Justification = "Used in test code: https://github.com/dotnet/roslyn/issues/42814")] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public CSharpConvertConcatenationToInterpolatedStringRefactoringProvider() { } diff --git a/src/Features/VisualBasic/Portable/ConvertToInterpolatedString/VisualBasicConvertConcatenationToInterpolatedStringRefactoringProvider.vb b/src/Features/VisualBasic/Portable/ConvertToInterpolatedString/VisualBasicConvertConcatenationToInterpolatedStringRefactoringProvider.vb index 319cc24c9b8e5..6f7abf352b305 100644 --- a/src/Features/VisualBasic/Portable/ConvertToInterpolatedString/VisualBasicConvertConcatenationToInterpolatedStringRefactoringProvider.vb +++ b/src/Features/VisualBasic/Portable/ConvertToInterpolatedString/VisualBasicConvertConcatenationToInterpolatedStringRefactoringProvider.vb @@ -3,9 +3,9 @@ ' See the LICENSE file in the project root for more information. Imports System.Composition -Imports System.Diagnostics.CodeAnalysis Imports Microsoft.CodeAnalysis.CodeRefactorings Imports Microsoft.CodeAnalysis.ConvertToInterpolatedString +Imports Microsoft.CodeAnalysis.Host.Mef Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.ConvertToInterpolatedString @@ -14,7 +14,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ConvertToInterpolatedString Inherits AbstractConvertConcatenationToInterpolatedStringRefactoringProvider(Of ExpressionSyntax) - + Public Sub New() End Sub From 34cb7476e25d527c248948da8b536e22348e9367 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sun, 28 Feb 2021 15:39:25 -0800 Subject: [PATCH 6/7] Enable nullable reference types --- ...enationToInterpolatedStringRefactoringProvider.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Features/Core/Portable/ConvertToInterpolatedString/AbstractConvertConcatenationToInterpolatedStringRefactoringProvider.cs b/src/Features/Core/Portable/ConvertToInterpolatedString/AbstractConvertConcatenationToInterpolatedStringRefactoringProvider.cs index 335af31bfcba3..d1d055584013b 100644 --- a/src/Features/Core/Portable/ConvertToInterpolatedString/AbstractConvertConcatenationToInterpolatedStringRefactoringProvider.cs +++ b/src/Features/Core/Portable/ConvertToInterpolatedString/AbstractConvertConcatenationToInterpolatedStringRefactoringProvider.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System; using System.Collections.Immutable; using System.Linq; @@ -34,8 +32,8 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte var (document, textSpan, cancellationToken) = context; var possibleExpressions = await context.GetRelevantNodesAsync().ConfigureAwait(false); - var syntaxFacts = document.GetLanguageService(); - var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); + var syntaxFacts = document.GetRequiredLanguageService(); + var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); // let's take the largest (last) StringConcat we can given current textSpan var top = possibleExpressions @@ -107,7 +105,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte } } - var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var interpolatedString = CreateInterpolatedString(document, isVerbatimStringLiteral, pieces); context.RegisterRefactoring( new MyCodeAction( @@ -124,7 +122,7 @@ private static Task UpdateDocumentAsync(Document document, SyntaxNode protected SyntaxNode CreateInterpolatedString( Document document, bool isVerbatimStringLiteral, ArrayBuilder pieces) { - var syntaxFacts = document.GetLanguageService(); + var syntaxFacts = document.GetRequiredLanguageService(); var generator = SyntaxGenerator.GetGenerator(document); var startToken = generator.CreateInterpolatedStringStartToken(isVerbatimStringLiteral) .WithLeadingTrivia(pieces.First().GetLeadingTrivia()); @@ -240,7 +238,7 @@ private void CollectPiecesDown( } private static bool IsStringConcat( - ISyntaxFactsService syntaxFacts, SyntaxNode expression, + ISyntaxFactsService syntaxFacts, SyntaxNode? expression, SemanticModel semanticModel, CancellationToken cancellationToken) { if (!syntaxFacts.IsBinaryExpression(expression)) From 478adbc6624774e081b122acbd2d8787741bbbbf Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 1 Mar 2021 14:39:39 +0000 Subject: [PATCH 7/7] Update dependencies from https://github.com/dotnet/roslyn build 20210301.4 (#51555) [master] Update dependencies from dotnet/roslyn --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index c02e857ee30fd..9e54cbc1cd6e8 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -7,9 +7,9 @@ https://github.com/dotnet/arcade 4957a6f3dd5f6fd1ca9ff06f9c50402f2e3b17e8 - + https://github.com/dotnet/roslyn - 686f13c61b1e26071ae89e107b0a3407a6b93a74 + c933ed58c3edd70916d2fd676db49c40035b5cac https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index d4c63bf331387..627f9c4682421 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -23,7 +23,7 @@ - 3.10.0-2.21122.2 + 3.10.0-2.21151.4 @@ -246,15 +246,12 @@ 1.0.51 $(xunitVersion) $(xunitVersion) - $(ILAsmPackageVersion) $(ILAsmPackageVersion) $(ILAsmPackageVersion) - $(ILDAsmPackageVersion) $(ILDAsmPackageVersion) $(ILDAsmPackageVersion) -