diff --git a/src/EditorFeatures/VisualBasicTest/SimplifyInterpolation/SimplifyInterpolationTests.vb b/src/EditorFeatures/VisualBasicTest/SimplifyInterpolation/SimplifyInterpolationTests.vb new file mode 100644 index 0000000000000000000000000000000000000000..9b78a94aa02ea99ad2eefb1afd9ad5f25413bd1c --- /dev/null +++ b/src/EditorFeatures/VisualBasicTest/SimplifyInterpolation/SimplifyInterpolationTests.vb @@ -0,0 +1,516 @@ +' Licensed to the .NET Foundation under one or more agreements. +' 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.CodeFixes +Imports Microsoft.CodeAnalysis.Diagnostics +Imports Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics +Imports Microsoft.CodeAnalysis.VisualBasic.SimplifyInterpolation + +Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.SimplifyInterpolation + + Public Class SimplifyInterpolationTests + Inherits AbstractVisualBasicDiagnosticProviderBasedUserDiagnosticTest + + Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As (DiagnosticAnalyzer, CodeFixProvider) + Return (New VisualBasicSimplifyInterpolationDiagnosticAnalyzer(), + New VisualBasicSimplifyInterpolationCodeFixProvider()) + End Function + + + Public Async Function SubsequentUnnecessarySpansDoNotRepeatTheSmartTag() As Task + Dim parameters = New TestParameters(retainNonFixableDiagnostics:=True, includeDiagnosticsOutsideSelection:=True) + + Using workspace = CreateWorkspaceFromOptions(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue{|Unnecessary:[||].ToString()|}{|Unnecessary:.PadLeft(|}{|Unnecessary:3|})} suffix"" + End Sub +End Class", parameters) + + Dim diagnostics = Await GetDiagnosticsWorkerAsync(workspace, parameters) + + Assert.Equal( + { + ("IDE0071", DiagnosticSeverity.Info), + ("IDE0071WithoutSuggestion", DiagnosticSeverity.Hidden), + ("IDE0071WithoutSuggestion", DiagnosticSeverity.Hidden) + }, + diagnostics.Select(Function(d) (d.Descriptor.Id, d.Severity))) + End Using + End Function + + + Public Async Function ToStringWithNoParameter() As Task + Await TestInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue{|Unnecessary:[||].ToString()|}} suffix"" + End Sub +End Class", " +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue} suffix"" + End Sub +End Class") + End Function + + + Public Async Function ToStringWithParameter() As Task + Await TestInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue{|Unnecessary:[||].ToString(""|}g{|Unnecessary:"")|}} suffix"" + End Sub +End Class", " +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue:g} suffix"" + End Sub +End Class") + End Function + + + Public Async Function ToStringWithEscapeSequences() As Task + Await TestInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue{|Unnecessary:[||].ToString(""|}""""d""""{|Unnecessary:"")|}} suffix"" + End Sub +End Class", " +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue:""""d""""} suffix"" + End Sub +End Class") + End Function + + + Public Async Function ToStringWithStringConstantParameter() As Task + Await TestMissingInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Const someConst As String = ""some format code"" + Dim v = $""prefix {someValue[||].ToString(someConst)} suffix"" + End Sub +End Class") + End Function + + + Public Async Function ToStringWithCharacterLiteralParameter() As Task + Await TestMissingInRegularAndScriptAsync(" +Class C + Sub M(someValue As C) + Dim v = $""prefix {someValue[||].ToString(""f""c)} suffix"" + End Sub + + Function ToString(_ As Object) As String + Return ""Goobar"" + End Function +End Class") + End Function + + + Public Async Function ToStringWithFormatProvider() As Task + Await TestMissingInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue[||].ToString(""some format code"", System.Globalization.CultureInfo.CurrentCulture)} suffix"" + End Sub +End Class") + End Function + + + Public Async Function PadLeftWithIntegerLiteral() As Task + Await TestInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue{|Unnecessary:[||].PadLeft(|}3{|Unnecessary:)|}} suffix"" + End Sub +End Class", " +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue,3} suffix"" + End Sub +End Class") + End Function + + + Public Async Function PadRightWithIntegerLiteral() As Task + Await TestInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue{|Unnecessary:[||].PadRight(|}3{|Unnecessary:)|}} suffix"" + End Sub +End Class", " +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue,-3} suffix"" + End Sub +End Class") + End Function + + + Public Async Function PadLeftWithComplexConstantExpression() As Task + Await TestInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Const someConstant As Integer = 1 + Dim v = $""prefix {someValue{|Unnecessary:[||].PadLeft(|}CByte(3.3) + someConstant{|Unnecessary:)|}} suffix"" + End Sub +End Class", " +Class C + Sub M(someValue As String) + Const someConstant As Integer = 1 + Dim v = $""prefix {someValue,CByte(3.3) + someConstant} suffix"" + End Sub +End Class") + End Function + + + Public Async Function PadLeftWithSpaceChar() As Task + Await TestInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue{|Unnecessary:[||].PadLeft(|}3{|Unnecessary:, "" ""c)|}} suffix"" + End Sub +End Class", " +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue,3} suffix"" + End Sub +End Class") + End Function + + + Public Async Function PadRightWithSpaceChar() As Task + Await TestInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue{|Unnecessary:[||].PadRight(|}3{|Unnecessary:, "" ""c)|}} suffix"" + End Sub +End Class", " +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue,-3} suffix"" + End Sub +End Class") + End Function + + + Public Async Function PadLeftWithNonSpaceChar() As Task + Await TestMissingInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue[||].PadLeft(3, ""x""c)} suffix"" + End Sub +End Class") + End Function + + + Public Async Function PadRightWithNonSpaceChar() As Task + Await TestMissingInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue[||].PadRight(3, ""x""c)} suffix"" + End Sub +End Class") + End Function + + + Public Async Function PadRightWithComplexConstantExpressionRequiringParentheses() As Task + Await TestInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Const someConstant As Integer = 1 + Dim v = $""prefix {someValue{|Unnecessary:[||].PadRight(|}CByte(3.3) + someConstant{|Unnecessary:)|}} suffix"" + End Sub +End Class", " +Class C + Sub M(someValue As String) + Const someConstant As Integer = 1 + Dim v = $""prefix {someValue,-(CByte(3.3) + someConstant)} suffix"" + End Sub +End Class") + End Function + + + Public Async Function ToStringWithNoParameterWhenFormattingComponentIsSpecified() As Task + Await TestMissingInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue[||].ToString():goo} suffix"" + End Sub +End Class") + End Function + + + Public Async Function ToStringWithStringLiteralParameterWhenFormattingComponentIsSpecified() As Task + Await TestMissingInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue[||].ToString(""bar""):goo} suffix"" + End Sub +End Class") + End Function + + + Public Async Function ToStringWithNoParameterWhenAlignmentComponentIsSpecified() As Task + Await TestInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue{|Unnecessary:[||].ToString()|},3} suffix"" + End Sub +End Class", " +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue,3} suffix"" + End Sub +End Class") + End Function + + + Public Async Function ToStringWithNoParameterWhenBothComponentsAreSpecified() As Task + Await TestMissingInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue[||].ToString(),3:goo} suffix"" + End Sub +End Class") + End Function + + + Public Async Function ToStringWithStringLiteralParameterWhenBothComponentsAreSpecified() As Task + Await TestMissingInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue[||].ToString(""some format code""),3:goo} suffix"" + End Sub +End Class") + End Function + + + Public Async Function PadLeftWhenFormattingComponentIsSpecified() As Task + Await TestInRegularAndScript1Async(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue[||].PadLeft(3):goo} suffix"" + End Sub +End Class", " +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue,3:goo} suffix"" + End Sub +End Class") + End Function + + + Public Async Function PadRightWhenFormattingComponentIsSpecified() As Task + Await TestInRegularAndScript1Async(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue[||].PadRight(3):goo} suffix"" + End Sub +End Class", " +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue,-3:goo} suffix"" + End Sub +End Class") + End Function + + + Public Async Function PadLeftWhenAlignmentComponentIsSpecified() As Task + Await TestMissingInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue[||].PadLeft(3),3} suffix"" + End Sub +End Class") + End Function + + + Public Async Function PadRightWhenAlignmentComponentIsSpecified() As Task + Await TestMissingInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue[||].PadRight(3),3} suffix"" + End Sub +End Class") + End Function + + + Public Async Function PadLeftWhenBothComponentsAreSpecified() As Task + Await TestMissingInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue[||].PadLeft(3),3:goo} suffix"" + End Sub +End Class") + End Function + + + Public Async Function PadRightWhenBothComponentsAreSpecified() As Task + Await TestMissingInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue[||].PadRight(3),3:goo} suffix"" + End Sub +End Class") + End Function + + + Public Async Function ToStringWithoutFormatThenPadLeft() As Task + Await TestInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue{|Unnecessary:[||].ToString()|}{|Unnecessary:.PadLeft(|}3{|Unnecessary:)|}} suffix"" + End Sub +End Class", " +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue,3} suffix"" + End Sub +End Class") + End Function + + + Public Async Function PadLeftThenToStringWithoutFormat() As Task + Await TestInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue.PadLeft(3){|Unnecessary:[||].ToString()|}} suffix"" + End Sub +End Class", " +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue.PadLeft(3)} suffix"" + End Sub +End Class") + End Function + + + Public Async Function PadLeftThenToStringWithoutFormatWhenAlignmentComponentIsSpecified() As Task + Await TestInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue.PadLeft(3){|Unnecessary:[||].ToString()|},3} suffix"" + End Sub +End Class", " +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue.PadLeft(3),3} suffix"" + End Sub +End Class") + End Function + + + Public Async Function PadLeftThenPadRight_WithoutAlignment() As Task + Await TestInRegularAndScriptAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue.PadLeft(3){|Unnecessary:[||].PadRight(|}3{|Unnecessary:)|}} suffix"" + End Sub +End Class", " +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue.PadLeft(3),-3} suffix"" + End Sub +End Class") + End Function + + + Public Async Function PadLeftThenPadRight_WithAlignment() As Task + Await TestMissingAsync(" +Class C + Sub M(someValue As String) + Dim v = $""prefix {someValue.PadLeft(3)[||].PadRight(3),3} suffix"" + End Sub +End Class") + End Function + + + Public Async Function MissingOnImplicitToStringReceiver() As Task + Await TestMissingAsync(" +Class C + Public Overrides Function ToString() As String + Return ""Goobar"" + End Function + + Function GetViaInterpolation() As String + Return $""Hello {ToString[||]()}"" + End Function +End Class") + End Function + + + Public Async Function MissingOnImplicitToStringReceiverWithArg() As Task + Await TestMissingAsync(" +Class C + Function ToString(arg As String) As String + Return ""Goobar"" + End Function + + Function GetViaInterpolation() As String + Return $""Hello {ToString[||](""g"")}"" + End Function +End Class") + End Function + + + Public Async Function MissingOnStaticToStringReceiver() As Task + Await TestMissingAsync(" +Class C + Shared Function ToString() As String + Return ""Goobar"" + End Function + + Function GetViaInterpolation() As String + Return $""Hello {ToString[||]()}"" + End Function +End Class") + End Function + + + Public Async Function MissingOnStaticToStringReceiverWithArg() As Task + Await TestMissingAsync(" +Class C + Shared Function ToString(arg As String) As String + Return ""Goobar"" + End Function + + Function GetViaInterpolation() As String + Return $""Hello {ToString[||](""g"")}"" + End Function +End Class") + End Function + + + Public Async Function MissingOnImplicitPadLeft() As Task + Await TestMissingAsync(" +Class C + Function PadLeft(ByVal val As Integer) As String + Return """" + End Function + + Sub M(someValue As String) + Dim v = $""prefix {[||]PadLeft(3)} suffix"" + End Sub +End Class") + End Function + + + Public Async Function MissingOnStaticPadLeft() As Task + Await TestMissingAsync(" +Class C + Shared Function PadLeft(ByVal val As Integer) As String + Return """" + End Function + + Sub M(someValue As String) + Dim v = $""prefix {[||]PadLeft(3)} suffix"" + End Sub +End Class") + End Function + End Class +End Namespace