From 1f4686b6d76ef790b67e36401af2b67958495bcb Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 4 Jun 2024 10:39:29 -0500 Subject: [PATCH 1/3] Use built-in features for marking unnecessary code --- .../UseObjectInitializerTests.cs | 571 ++++++++++++------ ...tUseObjectInitializerDiagnosticAnalyzer.cs | 38 +- .../UseObjectInitializerTests.vb | 393 ++++++++---- 3 files changed, 676 insertions(+), 326 deletions(-) diff --git a/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs b/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs index 8a81aa0efa2b9..3948eb163f1b4 100644 --- a/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs +++ b/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs @@ -20,17 +20,6 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UseObjectInitializer; [Trait(Traits.Feature, Traits.Features.CodeActionsUseObjectInitializer)] public partial class UseObjectInitializerTests { - private static async Task TestInRegularAndScriptAsync(string testCode, string fixedCode, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary) - { - await new VerifyCS.Test - { - TestCode = testCode, - FixedCode = fixedCode, - LanguageVersion = LanguageVersion.CSharp12, - TestState = { OutputKind = outputKind } - }.RunAsync(); - } - private static async Task TestMissingInRegularAndScriptAsync(string testCode, LanguageVersion? languageVersion = null) { var test = new VerifyCS.Test @@ -48,20 +37,19 @@ private static async Task TestMissingInRegularAndScriptAsync(string testCode, La [Fact] public async Task TestOnVariableDeclarator() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ class C { int i; void M() { - var c = [|new|] C(); - [|c.|]i = 1; + var c = {|#1:{|#0:new|} C()|}; + {|#2:c.|}i = 1{|#3:;|} } } - """, - """ + """; + var fixedCode = """ class C { int i; @@ -74,7 +62,19 @@ void M() }; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(6,19): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact] @@ -142,21 +142,20 @@ class C [Fact] public async Task TestDoNotUpdateAssignmentThatReferencesInitializedValue1Async() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ class C { int i; void M() { - var c = [|new|] C(); - [|c.|]i = 1; + var c = {|#1:{|#0:new|} C()|}; + {|#2:c.|}i = 1{|#3:;|} c.i = c.i + 1; } } - """, - """ + """; + var fixedCode = """ class C { int i; @@ -170,7 +169,19 @@ void M() c.i = c.i + 1; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(7,17): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact] @@ -194,8 +205,7 @@ void M() [Fact] public async Task TestDoNotUpdateAssignmentThatReferencesInitializedValue3Async() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ class C { int i; @@ -203,13 +213,13 @@ class C void M() { C c; - c = [|new|] C(); - [|c.|]i = 1; + c = {|#1:{|#0:new|} C()|}; + {|#2:c.|}i = 1{|#3:;|} c.i = c.i + 1; } } - """, - """ + """; + var fixedCode = """ class C { int i; @@ -224,7 +234,19 @@ void M() c.i = c.i + 1; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(6,19): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact] @@ -249,8 +271,7 @@ void M() [Fact] public async Task TestOnAssignmentExpression() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ class C { int i; @@ -258,12 +279,12 @@ class C void M() { C c = null; - c = [|new|] C(); - [|c.|]i = 1; + c = {|#1:{|#0:new|} C()|}; + {|#2:c.|}i = 1{|#3:;|} } } - """, - """ + """; + var fixedCode = """ class C { int i; @@ -277,27 +298,38 @@ void M() }; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(8,13): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact] public async Task TestStopOnDuplicateMember() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ class C { int i; void M() { - var c = [|new|] C(); - [|c.|]i = 1; + var c = {|#1:{|#0:new|} C()|}; + {|#2:c.|}i = 1{|#3:;|} c.i = 2; } } - """, - """ + """; + var fixedCode = """ class C { int i; @@ -311,14 +343,25 @@ void M() c.i = 2; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(7,17): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact] public async Task TestComplexInitializer() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ class C { int i; @@ -326,13 +369,13 @@ class C void M(C[] array) { - array[0] = [|new|] C(); - [|array[0].|]i = 1; - [|array[0].|]j = 2; + array[0] = {|#1:{|#0:new|} C()|}; + {|#2:array[0].|}i = 1{|#3:;|} + {|#4:array[0].|}j = 2{|#5:;|} } } - """, - """ + """; + var fixedCode = """ class C { int i; @@ -347,14 +390,25 @@ void M(C[] array) }; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(8,20): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3).WithLocation(4).WithLocation(5), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact] public async Task TestNotOnCompoundAssignment() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ class C { int i; @@ -362,13 +416,13 @@ class C void M() { - var c = [|new|] C(); - [|c.|]i = 1; + var c = {|#1:{|#0:new|} C()|}; + {|#2:c.|}i = 1{|#3:;|} c.j += 1; } } - """, - """ + """; + var fixedCode = """ class C { int i; @@ -383,14 +437,25 @@ void M() c.j += 1; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(8,17): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/39146")] public async Task TestWithExistingInitializer() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ class C { int i; @@ -398,12 +463,12 @@ class C void M() { - var c = [|new|] C() { i = 1 }; - [|c.|]j = 1; + var c = {|#1:{|#0:new|} C() { i = 1 }|}; + {|#2:c.|}j = 1{|#3:;|} } } - """, - """ + """; + var fixedCode = """ class C { int i; @@ -411,21 +476,32 @@ class C void M() { - var c = [||]new C + var c = new C { i = 1, j = 1 }; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(8,17): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/39146")] public async Task TestWithExistingInitializerComma() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ class C { int i; @@ -433,15 +509,15 @@ class C void M() { - var c = [|new|] C() + var c = {|#1:{|#0:new|} C() { i = 1, - }; - [|c.|]j = 1; + }|}; + {|#2:c.|}j = 1{|#3:;|} } } - """, - """ + """; + var fixedCode = """ class C { int i; @@ -449,21 +525,32 @@ class C void M() { - var c = [||]new C + var c = new C { i = 1, j = 1 }; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(8,17): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/39146")] public async Task TestWithExistingInitializerNotIfAlreadyInitialized() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ class C { int i; @@ -471,16 +558,16 @@ class C void M() { - var c = [|new|] C() + var c = {|#1:{|#0:new|} C() { i = 1, - }; - [|c.|]j = 1; + }|}; + {|#2:c.|}j = 1{|#3:;|} c.i = 2; } } - """, - """ + """; + var fixedCode = """ class C { int i; @@ -488,7 +575,7 @@ class C void M() { - var c = [||]new C + var c = new C { i = 1, j = 1 @@ -496,7 +583,19 @@ void M() c.i = 2; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(8,17): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact] @@ -521,8 +620,7 @@ void M() [Fact] public async Task TestFixAllInDocument1() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ class C { int i; @@ -533,15 +631,15 @@ public C(System.Action a) { } void M() { - var v = [|new|] C(() => { - var v2 = [|new|] C(); - [|v2.|]i = 1; - }); - [|v.|]j = 2; + var v = {|#1:{|#0:new|} C(() => { + var v2 = {|#5:{|#4:new|} C()|}; + {|#6:v2.|}i = 1{|#7:;|} + })|}; + {|#2:v.|}j = 2{|#3:;|} } } - """, - """ + """; + var fixedCode = """ class C { int i; @@ -564,14 +662,27 @@ void M() }; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(11,17): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3), + // /0/Test0.cs(12,22): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(4).WithLocation(5).WithLocation(6).WithLocation(7), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact] public async Task TestFixAllInDocument2() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ class C { int i; @@ -579,15 +690,15 @@ class C void M() { - var v = [|new|] C(); - [|v.|]j = () => { - var v2 = [|new|] C(); - [|v2.|]i = 1; - }; + var v = {|#1:{|#0:new|} C()|}; + {|#2:v.|}j = () => { + var v2 = {|#5:{|#4:new|} C()|}; + {|#6:v2.|}i = 1{|#7:;|} + }{|#3:;|} } } - """, - """ + """; + var fixedCode = """ class C { int i; @@ -607,14 +718,27 @@ void M() }; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(8,17): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3), + // /0/Test0.cs(10,22): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(4).WithLocation(5).WithLocation(6).WithLocation(7), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact] public async Task TestFixAllInDocument3() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ class C { int i; @@ -622,16 +746,16 @@ class C void M(C[] array) { - array[0] = [|new|] C(); - [|array[0].|]i = 1; - [|array[0].|]j = 2; - array[1] = [|new|] C(); - [|array[1].|]i = 3; - [|array[1].|]j = 4; + array[0] = {|#1:{|#0:new|} C()|}; + {|#2:array[0].|}i = 1{|#3:;|} + {|#4:array[0].|}j = 2{|#5:;|} + array[1] = {|#7:{|#6:new|} C()|}; + {|#8:array[1].|}i = 3{|#9:;|} + {|#10:array[1].|}j = 4{|#11:;|} } } - """, - """ + """; + var fixedCode = """ class C { int i; @@ -651,27 +775,40 @@ void M(C[] array) }; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(8,20): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3).WithLocation(4).WithLocation(5), + // /0/Test0.cs(11,20): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(6).WithLocation(7).WithLocation(8).WithLocation(9).WithLocation(10).WithLocation(11), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact] public async Task TestTrivia1() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ class C { int i; int j; void M() { - var c = [|new|] C(); - [|c.|]i = 1; // Goo - [|c.|]j = 2; // Bar + var c = {|#1:{|#0:new|} C()|}; + {|#2:c.|}i = 1{|#3:;|} // Goo + {|#4:c.|}j = 2{|#5:;|} // Bar } } - """, - """ + """; + var fixedCode = """ class C { int i; @@ -685,31 +822,42 @@ void M() }; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(7,17): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3).WithLocation(4).WithLocation(5), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/46670")] public async Task TestTriviaRemoveLeadingBlankLinesForFirstProperty() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ class C { int i; int j; void M() { - var c = [|new|] C(); + var c = {|#1:{|#0:new|} C()|}; //Goo - [|c.|]i = 1; + {|#2:c.|}i = 1{|#3:;|} //Bar - [|c.|]j = 2; + {|#4:c.|}j = 2{|#5:;|} } } - """, - """ + """; + var fixedCode = """ class C { int i; @@ -726,7 +874,19 @@ void M() }; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(7,17): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3).WithLocation(4).WithLocation(5), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/15459")] @@ -786,22 +946,21 @@ public void M() [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17953")] public async Task TestAvailableInsidePreprocessorDirective() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ public class Goo { public void M() { #if true - var goo = [|new|] Goo(); - [|goo.|]Value = ""; + var goo = {|#1:{|#0:new|} Goo()|}; + {|#2:goo.|}Value = ""{|#3:;|} #endif } public string Value { get; set; } } - """, - """ + """; + var fixedCode = """ public class Goo { public void M() @@ -816,14 +975,25 @@ public void M() public string Value { get; set; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(6,19): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/19253")] public async Task TestKeepBlankLinesAfter() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ class Goo { public int Bar { get; set; } @@ -833,14 +1003,14 @@ class MyClass { public void Main() { - var goo = [|new|] Goo(); - [|goo.|]Bar = 1; + var goo = {|#1:{|#0:new|} Goo()|}; + {|#2:goo.|}Bar = 1{|#3:;|} int horse = 1; } } - """, - """ + """; + var fixedCode = """ class Goo { public int Bar { get; set; } @@ -858,7 +1028,19 @@ public void Main() int horse = 1; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(6,19): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23368")] @@ -915,8 +1097,7 @@ public void Main() [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23368")] public async Task TestWithExplicitImplementedInterfaceMembers3() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ interface IExample { string Name { get; set; } string LastName { get; set; } @@ -931,13 +1112,13 @@ class MyClass { public void Main() { - IExample e = [|new|] C(); - [|e.|]LastName = string.Empty; + IExample e = {|#1:{|#0:new|} C()|}; + {|#2:e.|}LastName = string.Empty{|#3:;|} e.Name = string.Empty; } } - """, - """ + """; + var fixedCode = """ interface IExample { string Name { get; set; } string LastName { get; set; } @@ -959,7 +1140,19 @@ public void Main() e.Name = string.Empty; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(15,22): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37675")] @@ -987,20 +1180,19 @@ public void Dispose() [Fact] public async Task TestImplicitObject() { - await TestInRegularAndScriptAsync( - """ + var testCode = """ class C { int i; void M() { - C c = [|new|](); - [|c.|]i = 1; + C c = {|#1:{|#0:new|}()|}; + {|#2:c.|}i = 1{|#3:;|} } } - """, - """ + """; + var fixedCode = """ class C { int i; @@ -1013,23 +1205,34 @@ void M() }; } } - """); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(6,19): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/61066")] public async Task TestInTopLevelStatements() { - await TestInRegularAndScriptAsync( - """ - MyClass cl = [|new|](); - [|cl.|]MyProperty = 5; + var testCode = """ + MyClass cl = {|#1:{|#0:new|}()|}; + {|#2:cl.|}MyProperty = 5{|#3:;|} class MyClass { public int MyProperty { get; set; } } - """, - """ + """; + var fixedCode = """ MyClass cl = new() { MyProperty = 5 @@ -1039,7 +1242,20 @@ class MyClass { public int MyProperty { get; set; } } - """, OutputKind.ConsoleApplication); + """; + + await new VerifyCS.Test + { + TestCode = testCode, + ExpectedDiagnostics = + { + // /0/Test0.cs(6,19): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3), + }, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp12, + TestState = { OutputKind = OutputKind.ConsoleApplication }, + }.RunAsync(); } [Theory] @@ -1061,8 +1277,8 @@ class C void M() { - var c = [|new|] C(); - c.i = 1; + var c = {|#1:{|#0:new|} C()|}; + {|#2:c.|}i = 1{|#3:;|} } } """; @@ -1111,7 +1327,7 @@ void M() build_property.EffectiveAnalysisLevelStyle = {analysisLevel} """; - await new VerifyCS.Test + var test = new VerifyCS.Test { TestState = { @@ -1123,6 +1339,15 @@ void M() }, FixedState = { Sources = { fixedCode } }, LanguageVersion = LanguageVersion.CSharp12, - }.RunAsync(); + }; + + if (enabled) + { + test.ExpectedDiagnostics.Add( + // /0/Test0.cs(7,17): info IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3)); + } + + await test.RunAsync(); } } diff --git a/src/Analyzers/Core/Analyzers/UseObjectInitializer/AbstractUseObjectInitializerDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseObjectInitializer/AbstractUseObjectInitializerDiagnosticAnalyzer.cs index aabbb18b1eb49..74d6e02d130d5 100644 --- a/src/Analyzers/Core/Analyzers/UseObjectInitializer/AbstractUseObjectInitializerDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseObjectInitializer/AbstractUseObjectInitializerDiagnosticAnalyzer.cs @@ -49,14 +49,6 @@ internal abstract partial class AbstractUseObjectInitializerDiagnosticAnalyzer< new LocalizableResourceString(nameof(AnalyzersResources.Object_initialization_can_be_simplified), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)), isUnnecessary: false); - private static readonly DiagnosticDescriptor s_unnecessaryCodeDescriptor = CreateDescriptorWithId( - IDEDiagnosticIds.UseObjectInitializerDiagnosticId, - EnforceOnBuildValues.UseObjectInitializer, - hasAnyCodeStyleOption: true, - new LocalizableResourceString(nameof(AnalyzersResources.Simplify_object_initialization), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)), - new LocalizableResourceString(nameof(AnalyzersResources.Object_initialization_can_be_simplified), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)), - isUnnecessary: true); - protected abstract bool FadeOutOperatorToken { get; } protected abstract TAnalyzer GetAnalyzer(); @@ -130,25 +122,25 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context) var locations = ImmutableArray.Create(objectCreationExpression.GetLocation()); - context.ReportDiagnostic(DiagnosticHelper.Create( + var unnecessaryLocations = FadeOutCode(context, matches); + + context.ReportDiagnostic(DiagnosticHelper.CreateWithLocationTags( s_descriptor, objectCreationExpression.GetFirstToken().GetLocation(), option.Notification, context.Options, locations, - properties: null)); - - FadeOutCode(context, matches, locations); + additionalUnnecessaryLocations: unnecessaryLocations)); } - private void FadeOutCode( + private ImmutableArray FadeOutCode( SyntaxNodeAnalysisContext context, - ImmutableArray> matches, - ImmutableArray locations) + ImmutableArray> matches) { var syntaxTree = context.Node.SyntaxTree; var syntaxFacts = GetSyntaxFacts(); + using var locations = TemporaryArray.Empty; foreach (var match in matches) { @@ -158,23 +150,15 @@ private void FadeOutCode( var location1 = Location.Create(syntaxTree, TextSpan.FromBounds( match.MemberAccessExpression.SpanStart, end)); + locations.Add(location1); if (match.Statement.Span.End > match.Initializer.FullSpan.End) { - context.ReportDiagnostic(DiagnosticHelper.CreateWithLocationTags( - s_unnecessaryCodeDescriptor, - location1, - NotificationOption2.ForSeverity(s_unnecessaryCodeDescriptor.DefaultSeverity), - context.Options, - additionalLocations: locations, - additionalUnnecessaryLocations: [syntaxTree.GetLocation(TextSpan.FromBounds(match.Initializer.FullSpan.End, match.Statement.Span.End))])); - } - else - { - context.ReportDiagnostic(Diagnostic.Create( - s_unnecessaryCodeDescriptor, location1, additionalLocations: locations)); + locations.Add(syntaxTree.GetLocation(TextSpan.FromBounds(match.Initializer.FullSpan.End, match.Statement.Span.End))); } } + + return locations.ToImmutableAndClear(); } public sealed override DiagnosticAnalyzerCategory GetAnalyzerCategory() diff --git a/src/Analyzers/VisualBasic/Tests/UseObjectInitializer/UseObjectInitializerTests.vb b/src/Analyzers/VisualBasic/Tests/UseObjectInitializer/UseObjectInitializerTests.vb index 9621cfb8cb6de..0f6022a2a48b0 100644 --- a/src/Analyzers/VisualBasic/Tests/UseObjectInitializer/UseObjectInitializerTests.vb +++ b/src/Analyzers/VisualBasic/Tests/UseObjectInitializer/UseObjectInitializerTests.vb @@ -9,13 +9,6 @@ Imports VerifyVB = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.VisualBas Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.UseObjectInitializer Public Class UseObjectInitializerTests - Private Shared Async Function TestInRegularAndScriptAsync(testCode As String, fixedCode As String) As Task - Await New VerifyVB.Test With { - .TestCode = testCode, - .FixedCode = fixedCode - }.RunAsync() - End Function - Private Shared Async Function TestMissingInRegularAndScriptAsync(testCode As String) As Task Await New VerifyVB.Test With { .TestCode = testCode, @@ -25,16 +18,15 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.UseObj Public Async Function TestOnVariableDeclarator() As Task - Await TestInRegularAndScriptAsync( -" + Dim testCode = " Class C Dim i As Integer Sub M() - Dim c = [|New|] C() - [|c|].i = 1 + Dim c = {|#1:{|#0:New|} C()|} + {|#2:c|}.i = 1 End Sub -End Class", -" +End Class" + Dim fixedCode = " Class C Dim i As Integer Sub M() @@ -42,21 +34,30 @@ Class C .i = 1 } End Sub -End Class") +End Class" + Dim test = New VerifyVB.Test With { + .TestCode = testCode, + .FixedCode = fixedCode + } + + test.ExpectedDiagnostics.Add( + _ ' /0/Test0.vb(5,17): info IDE0017: Object initialization can be simplified + VerifyVB.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2)) + + Await test.RunAsync() End Function Public Async Function TestOnVariableDeclarator2() As Task - Await TestInRegularAndScriptAsync( -" + Dim testCode = " Class C Dim i As Integer Sub M() - Dim c As [|New|] C() - [|c|].i = 1 + Dim c As {|#1:{|#0:New|} C()|} + {|#2:c|}.i = 1 End Sub -End Class", -" +End Class" + Dim fixedCode = " Class C Dim i As Integer Sub M() @@ -64,22 +65,31 @@ Class C .i = 1 } End Sub -End Class") +End Class" + Dim test = New VerifyVB.Test With { + .TestCode = testCode, + .FixedCode = fixedCode + } + + test.ExpectedDiagnostics.Add( + _ ' /0/Test0.vb(5,18): info IDE0017: Object initialization can be simplified + VerifyVB.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2)) + + Await test.RunAsync() End Function Public Async Function TestOnAssignmentExpression() As Task - Await TestInRegularAndScriptAsync( -" + Dim testCode = " Class C Dim i As Integer Sub M() Dim c as C = Nothing - c = [|New|] C() - [|c|].i = 1 + c = {|#1:{|#0:New|} C()|} + {|#2:c|}.i = 1 End Sub -End Class", -" +End Class" + Dim fixedCode = " Class C Dim i As Integer Sub M() @@ -88,22 +98,31 @@ Class C .i = 1 } End Sub -End Class") +End Class" + Dim test = New VerifyVB.Test With { + .TestCode = testCode, + .FixedCode = fixedCode + } + + test.ExpectedDiagnostics.Add( + _ ' /0/Test0.vb(6,13): info IDE0017: Object initialization can be simplified + VerifyVB.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2)) + + Await test.RunAsync() End Function Public Async Function TestStopOnDuplicateMember() As Task - Await TestInRegularAndScriptAsync( -" + Dim testCode = " Class C Dim i As Integer Sub M() - Dim c = [|New|] C() - [|c|].i = 1 + Dim c = {|#1:{|#0:New|} C()|} + {|#2:c|}.i = 1 c.i = 2 End Sub -End Class", -" +End Class" + Dim fixedCode = " Class C Dim i As Integer Sub M() @@ -112,25 +131,34 @@ Class C } c.i = 2 End Sub -End Class") +End Class" + Dim test = New VerifyVB.Test With { + .TestCode = testCode, + .FixedCode = fixedCode + } + + test.ExpectedDiagnostics.Add( + _ ' /0/Test0.vb(5,17): info IDE0017: Object initialization can be simplified + VerifyVB.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2)) + + Await test.RunAsync() End Function Public Async Function TestComplexInitializer() As Task - Await TestInRegularAndScriptAsync( -" + Dim testCode = " Class C Dim i As Integer Dim j As Integer Sub M() Dim array As C() - array(0) = [|New|] C() - [|array(0)|].i = 1 - [|array(0)|].j = 2 + array(0) = {|#1:{|#0:New|} C()|} + {|#2:array(0)|}.i = 1 + {|#3:array(0)|}.j = 2 End Sub -End Class", -" +End Class" + Dim fixedCode = " Class C Dim i As Integer Dim j As Integer @@ -142,23 +170,32 @@ Class C .j = 2 } End Sub -End Class") +End Class" + Dim test = New VerifyVB.Test With { + .TestCode = testCode, + .FixedCode = fixedCode + } + + test.ExpectedDiagnostics.Add( + _ ' /0/Test0.vb(8,20): info IDE0017: Object initialization can be simplified + VerifyVB.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3)) + + Await test.RunAsync() End Function Public Async Function TestNotOnCompoundAssignment() As Task - Await TestInRegularAndScriptAsync( -" + Dim testCode = " Class C Dim i As Integer Dim j As Integer Sub M() - Dim c = [|New|] C() - [|c|].i = 1 + Dim c = {|#1:{|#0:New|} C()|} + {|#2:c|}.i = 1 c.j += 1 End Sub -End Class", -" +End Class" + Dim fixedCode = " Class C Dim i As Integer Dim j As Integer @@ -168,63 +205,91 @@ Class C } c.j += 1 End Sub -End Class") +End Class" + Dim test = New VerifyVB.Test With { + .TestCode = testCode, + .FixedCode = fixedCode + } + + test.ExpectedDiagnostics.Add( + _ ' /0/Test0.vb(6,17): info IDE0017: Object initialization can be simplified + VerifyVB.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2)) + + Await test.RunAsync() End Function Public Async Function TestWithExistingInitializer() As Task - Await TestInRegularAndScriptAsync( -" + Dim testCode = " Class C Dim i As Integer Dim j As Integer Sub M() - Dim c = [|New|] C() With { + Dim c = {|#1:{|#0:New|} C() With { .i = 1 - } - [|c|].j = 1 + }|} + {|#2:c|}.j = 1 End Sub -End Class", -" +End Class" + Dim fixedCode = " Class C Dim i As Integer Dim j As Integer Sub M() - Dim c = [|New|] C With { + Dim c = New C With { .i = 1, .j = 1 } End Sub -End Class") +End Class" + Dim test = New VerifyVB.Test With { + .TestCode = testCode, + .FixedCode = fixedCode + } + + test.ExpectedDiagnostics.Add( + _ ' /0/Test0.vb(6,17): info IDE0017: Object initialization can be simplified + VerifyVB.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2)) + + Await test.RunAsync() End Function Public Async Function TestWithExistingInitializerNotIfAlreadyInitialized() As Task - Await TestInRegularAndScriptAsync( -" + Dim testCode = " Class C Dim i As Integer Dim j As Integer Sub M() - Dim c = [|New|] C() With { + Dim c = {|#1:{|#0:New|} C() With { .i = 1 - } - [|c|].j = 1 + }|} + {|#2:c|}.j = 1 c.i = 2 End Sub -End Class", -" +End Class" + Dim fixedCode = " Class C Dim i As Integer Dim j As Integer Sub M() - Dim c = [|New|] C With { + Dim c = New C With { .i = 1, .j = 1 } c.i = 2 End Sub -End Class") +End Class" + Dim test = New VerifyVB.Test With { + .TestCode = testCode, + .FixedCode = fixedCode + } + + test.ExpectedDiagnostics.Add( + _ ' /0/Test0.vb(6,17): info IDE0017: Object initialization can be simplified + VerifyVB.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2)) + + Await test.RunAsync() End Function @@ -245,21 +310,20 @@ End Class") Public Async Function TestIfImplicitMemberAccessWouldNotChange() As Task - Await TestInRegularAndScriptAsync( -" + Dim testCode = " imports system.diagnostics Class C Sub M() - Dim x As ProcessStartInfo = [|New|] ProcessStartInfo() - [|x|].Arguments = {|BC30491:Sub() + Dim x As ProcessStartInfo = {|#1:{|#0:New|} ProcessStartInfo()|} + {|#2:x|}.Arguments = {|BC30491:Sub() With New String(Nothing) Dim a = .Length.ToString() End With End Sub()|} End Sub -End Class", -" +End Class" + Dim fixedCode = " imports system.diagnostics Class C @@ -272,29 +336,38 @@ Class C End Sub()|} } End Sub -End Class") +End Class" + Dim test = New VerifyVB.Test With { + .TestCode = testCode, + .FixedCode = fixedCode + } + + test.ExpectedDiagnostics.Add( + _ ' /0/Test0.vb(6,37): info IDE0017: Object initialization can be simplified + VerifyVB.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2)) + + Await test.RunAsync() End Function Public Async Function TestFixAllInDocument() As Task - Await TestInRegularAndScriptAsync( -" + Dim testCode = " Class C Dim i As Integer Dim j As Integer Sub M() Dim array As C() - array(0) = [|New|] C() - [|array(0)|].i = 1 - [|array(0)|].j = 2 + array(0) = {|#1:{|#0:New|} C()|} + {|#2:array(0)|}.i = 1 + {|#3:array(0)|}.j = 2 - array(1) = [|New|] C() - [|array(1)|].i = 3 - [|array(1)|].j = 4 + array(1) = {|#5:{|#4:New|} C()|} + {|#6:array(1)|}.i = 3 + {|#7:array(1)|}.j = 4 End Sub -End Class", -" +End Class" + Dim fixedCode = " Class C Dim i As Integer Dim j As Integer @@ -311,23 +384,36 @@ Class C .j = 4 } End Sub -End Class") +End Class" + Dim test = New VerifyVB.Test With { + .TestCode = testCode, + .FixedCode = fixedCode + } + + test.ExpectedDiagnostics.Add( + _ ' /0/Test0.vb(8,20): info IDE0017: Object initialization can be simplified + VerifyVB.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3)) + + test.ExpectedDiagnostics.Add( + _ ' /0/Test0.vb(12,20): info IDE0017: Object initialization can be simplified + VerifyVB.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(4).WithLocation(5).WithLocation(6).WithLocation(7)) + + Await test.RunAsync() End Function Public Async Function TestTrivia1() As Task - Await TestInRegularAndScriptAsync( -" + Dim testCode = " Class C Dim i As Integer Dim j As Integer Sub M() - Dim c = [|New|] C() - [|c|].i = 1 ' Goo - [|c|].j = 2 ' Bar + Dim c = {|#1:{|#0:New|} C()|} + {|#2:c|}.i = 1 ' Goo + {|#3:c|}.j = 2 ' Bar End Sub -End Class", -" +End Class" + Dim fixedCode = " Class C Dim i As Integer Dim j As Integer @@ -337,20 +423,29 @@ Class C .j = 2 ' Bar } End Sub -End Class") +End Class" + Dim test = New VerifyVB.Test With { + .TestCode = testCode, + .FixedCode = fixedCode + } + + test.ExpectedDiagnostics.Add( + _ ' /0/Test0.vb(6,17): info IDE0017: Object initialization can be simplified + VerifyVB.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3)) + + Await test.RunAsync() End Function Public Async Function TestTrivia2() As Task - Await TestInRegularAndScriptAsync( -" + Dim testCode = " Class C Sub M(Reader as String) - Dim XmlAppConfigReader As [|New|] XmlTextReader(Reader) + Dim XmlAppConfigReader As {|#1:{|#0:New|} XmlTextReader(Reader)|} ' Required by Fxcop rule CA3054 - DoNotAllowDTDXmlTextReader - [|XmlAppConfigReader|].x = 0 - [|XmlAppConfigReader|].y = 1 + {|#2:XmlAppConfigReader|}.x = 0 + {|#3:XmlAppConfigReader|}.y = 1 End Sub End Class @@ -361,8 +456,8 @@ class XmlTextReader public x as integer public y as integer end class -", " + Dim fixedCode = " Class C Sub M(Reader as String) ' Required by Fxcop rule CA3054 - DoNotAllowDTDXmlTextReader @@ -380,22 +475,31 @@ class XmlTextReader public x as integer public y as integer end class -") +" + Dim test = New VerifyVB.Test With { + .TestCode = testCode, + .FixedCode = fixedCode + } + + test.ExpectedDiagnostics.Add( + _ ' /0/Test0.vb(4,35): info IDE0017: Object initialization can be simplified + VerifyVB.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3)) + + Await test.RunAsync() End Function Public Async Function TestTrivia3() As Task - Await TestInRegularAndScriptAsync( -" + Dim testCode = " Class C Sub M(Reader as String) - Dim XmlAppConfigReader As [|New|] XmlTextReader(Reader) + Dim XmlAppConfigReader As {|#1:{|#0:New|} XmlTextReader(Reader)|} ' Required by Fxcop rule CA3054 - DoNotAllowDTDXmlTextReader - [|XmlAppConfigReader|].x = 0 + {|#2:XmlAppConfigReader|}.x = 0 ' Bar - [|XmlAppConfigReader|].y = 1 + {|#3:XmlAppConfigReader|}.y = 1 End Sub End Class @@ -406,8 +510,8 @@ class XmlTextReader public x as integer public y as integer end class -", " + Dim fixedCode = " Class C Sub M(Reader as String) ' Required by Fxcop rule CA3054 - DoNotAllowDTDXmlTextReader @@ -426,25 +530,34 @@ class XmlTextReader public x as integer public y as integer end class -") +" + Dim test = New VerifyVB.Test With { + .TestCode = testCode, + .FixedCode = fixedCode + } + + test.ExpectedDiagnostics.Add( + _ ' /0/Test0.vb(4,35): info IDE0017: Object initialization can be simplified + VerifyVB.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3)) + + Await test.RunAsync() End Function Public Async Function TestSharedMember() As Task - Await TestInRegularAndScriptAsync( -" + Dim testCode = " Class C Dim x As Integer Shared y As Integer Sub M() - Dim z = [|New|] C() - [|z|].x = 1 + Dim z = {|#1:{|#0:New|} C()|} + {|#2:z|}.x = 1 z.y = 2 End Sub End Class -", " + Dim fixedCode = " Class C Dim x As Integer Shared y As Integer @@ -456,7 +569,17 @@ Class C z.y = 2 End Sub End Class -") +" + Dim test = New VerifyVB.Test With { + .TestCode = testCode, + .FixedCode = fixedCode + } + + test.ExpectedDiagnostics.Add( + _ ' /0/Test0.vb(7,17): info IDE0017: Object initialization can be simplified + VerifyVB.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2)) + + Await test.RunAsync() End Function @@ -512,12 +635,11 @@ End Class Public Async Function TestWithExplicitImplementedInterfaceMembers3() As Task - Await TestInRegularAndScriptAsync( -" + Dim testCode = " class C Sub Bar() - Dim c As IExample = [|New|] Goo - [|c|].LastName = String.Empty + Dim c As IExample = {|#1:{|#0:New|} Goo|} + {|#2:c|}.LastName = String.Empty c.Name = String.Empty End Sub End Class @@ -533,8 +655,8 @@ Class Goo Private Property Name As String Implements IExample.Name Public Property LastName As String Implements IExample.LastName End Class -", " + Dim fixedCode = " class C Sub Bar() Dim c As IExample = New Goo With { @@ -555,17 +677,26 @@ Class Goo Private Property Name As String Implements IExample.Name Public Property LastName As String Implements IExample.LastName End Class -") +" + Dim test = New VerifyVB.Test With { + .TestCode = testCode, + .FixedCode = fixedCode + } + + test.ExpectedDiagnostics.Add( + _ ' /0/Test0.vb(4,29): info IDE0017: Object initialization can be simplified + VerifyVB.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2)) + + Await test.RunAsync() End Function Public Async Function TestWithExplicitImplementedInterfaceMembers4() As Task - Await TestInRegularAndScriptAsync( -" + Dim testCode = " class C Sub Bar() - Dim c As IExample = [|New|] Goo - [|c|].LastName = String.Empty + Dim c As IExample = {|#1:{|#0:New|} Goo|} + {|#2:c|}.LastName = String.Empty c.Name = String.Empty End Sub End Class @@ -581,8 +712,8 @@ Class Goo Private Property Name As String Implements IExample.Name Public Property MyLastName As String Implements IExample.LastName End Class -", " + Dim fixedCode = " class C Sub Bar() Dim c As IExample = New Goo With { @@ -603,7 +734,17 @@ Class Goo Private Property Name As String Implements IExample.Name Public Property MyLastName As String Implements IExample.LastName End Class -") +" + Dim test = New VerifyVB.Test With { + .TestCode = testCode, + .FixedCode = fixedCode + } + + test.ExpectedDiagnostics.Add( + _ ' /0/Test0.vb(4,29): info IDE0017: Object initialization can be simplified + VerifyVB.Diagnostic().WithSeverity(DiagnosticSeverity.Info).WithLocation(0).WithLocation(1).WithLocation(2)) + + Await test.RunAsync() End Function End Class End Namespace From 04236bc66d699055a2695c3e8a1f9a607b5ae42c Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 4 Jun 2024 10:40:01 -0500 Subject: [PATCH 2/3] Verify missing code style severity falls back to old behavior --- .../UseObjectInitializerTests.cs | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs b/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs index 3948eb163f1b4..32211a23341c7 100644 --- a/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs +++ b/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs @@ -1350,4 +1350,69 @@ void M() await test.RunAsync(); } + + [Theory] + [InlineData(8.0)] + [InlineData(9.0)] + public async Task TestFallbackSeverityConfiguration(double analysisLevel) + { + var testCode = + """ + class C + { + int i; + + void M() + { + var c = {|#1:{|#0:new|} C()|}; + {|#2:c.|}i = 1{|#3:;|} + } + } + """; + + var fixedCode = + """ + class C + { + int i; + + void M() + { + var c = new C + { + i = 1 + }; + } + } + """; + + var globalConfig = + $""" + is_global = true + + dotnet_style_object_initializer = true + dotnet_diagnostic.IDE0017.severity = warning + + build_property.EffectiveAnalysisLevelStyle = {analysisLevel} + """; + + await new VerifyCS.Test + { + TestState = + { + Sources = { testCode }, + ExpectedDiagnostics = + { + // /0/Test0.cs(7,17): warning IDE0017: Object initialization can be simplified + VerifyCS.Diagnostic().WithSeverity(DiagnosticSeverity.Warning).WithLocation(0).WithLocation(1).WithLocation(2).WithLocation(3), + }, + AnalyzerConfigFiles = + { + ("/.globalconfig", globalConfig), + } + }, + FixedState = { Sources = { fixedCode } }, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); + } } From 7cbb1f43ee766d60f49530fbbe42d5de45ca57c9 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 4 Jun 2024 17:11:05 -0500 Subject: [PATCH 3/3] Use EnableCodeStyleSeverity instead of AnalysisLevel to control new diagnostic severity behavior --- .../UseObjectInitializerTests.cs | 18 +++++++----------- .../Core/Analyzers/Helpers/DiagnosticHelper.cs | 4 ++-- src/CodeStyle/Tools/Program.cs | 3 ++- .../AnalyzerConfigOptionsExtensions.cs | 9 +++++++++ 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs b/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs index 32211a23341c7..252322bd3d60e 100644 --- a/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs +++ b/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs @@ -1259,15 +1259,12 @@ class MyClass } [Theory] - [InlineData(8.0)] - [InlineData(9.0)] + [CombinatorialData] [WorkItem("https://github.com/dotnet/roslyn/issues/72094")] - public async Task TestWithConflictingSeverityConfigurationEntries(double analysisLevel) + public async Task TestWithConflictingSeverityConfigurationEntries(bool enabled) { - var expectFix = analysisLevel >= 9.0; - string testCode, fixedCode; - if (expectFix) + if (enabled) { testCode = """ @@ -1324,7 +1321,7 @@ void M() dotnet_style_object_initializer = true:suggestion dotnet_diagnostic.IDE0017.severity = none - build_property.EffectiveAnalysisLevelStyle = {analysisLevel} + build_property.EnableCodeStyleSeverity = {enabled} """; var test = new VerifyCS.Test @@ -1352,9 +1349,8 @@ void M() } [Theory] - [InlineData(8.0)] - [InlineData(9.0)] - public async Task TestFallbackSeverityConfiguration(double analysisLevel) + [CombinatorialData] + public async Task TestFallbackSeverityConfiguration(bool enabled) { var testCode = """ @@ -1393,7 +1389,7 @@ void M() dotnet_style_object_initializer = true dotnet_diagnostic.IDE0017.severity = warning - build_property.EffectiveAnalysisLevelStyle = {analysisLevel} + build_property.EnableCodeStyleSeverity = {enabled} """; await new VerifyCS.Test diff --git a/src/Analyzers/Core/Analyzers/Helpers/DiagnosticHelper.cs b/src/Analyzers/Core/Analyzers/Helpers/DiagnosticHelper.cs index 151a02031558b..a3fd71e19508c 100644 --- a/src/Analyzers/Core/Analyzers/Helpers/DiagnosticHelper.cs +++ b/src/Analyzers/Core/Analyzers/Helpers/DiagnosticHelper.cs @@ -269,8 +269,8 @@ public static Diagnostic CreateWithMessage( static IEnumerable GetEffectiveCustomTags(DiagnosticDescriptor descriptor, NotificationOption2 notificationOption, AnalyzerOptions analyzerOptions) { - // 'CustomSeverityConfigurable' is only enabled when AnalysisLevel >= 9. - var skipCustomConfiguration = !analyzerOptions.AnalyzerConfigOptionsProvider.GlobalOptions.IsAnalysisLevelGreaterThanOrEquals(9); + // 'CustomSeverityConfigurable' is only enabled when EnableCodeStyleSeverity is true. + var skipCustomConfiguration = !analyzerOptions.AnalyzerConfigOptionsProvider.GlobalOptions.IsCodeStyleSeverityEnabled(); if (skipCustomConfiguration) { foreach (var customTag in descriptor.CustomTags) diff --git a/src/CodeStyle/Tools/Program.cs b/src/CodeStyle/Tools/Program.cs index 6a289be8b28f7..adbc52aa691ee 100644 --- a/src/CodeStyle/Tools/Program.cs +++ b/src/CodeStyle/Tools/Program.cs @@ -264,9 +264,10 @@ and an implied numerical option (such as '4') --> - + + diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/AnalyzerConfigOptionsExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/AnalyzerConfigOptionsExtensions.cs index b6c2e8e03d430..d4f598d420175 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/AnalyzerConfigOptionsExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/AnalyzerConfigOptionsExtensions.cs @@ -53,6 +53,15 @@ public static bool TryGetEditorConfigOption(this AnalyzerConfigOptions analyz return false; } + public static bool IsCodeStyleSeverityEnabled(this AnalyzerConfigOptions analyzerConfigOptions) + { + const string EnableCodeStyleSeverityKey = "build_property.EnableCodeStyleSeverity"; + + return analyzerConfigOptions.TryGetValue(EnableCodeStyleSeverityKey, out var value) + && bool.TryParse(value, out var parsedValue) + && parsedValue; + } + public static bool IsAnalysisLevelGreaterThanOrEquals(this AnalyzerConfigOptions analyzerConfigOptions, int minAnalysisLevel) { // See https://github.com/dotnet/roslyn/pull/70794 for details.