diff --git a/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedParametersTests.cs b/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedParametersTests.cs index c5dfbd10f2c03..cea8b72d00069 100644 --- a/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedParametersTests.cs +++ b/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedParametersTests.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeFixes; @@ -14,6 +15,7 @@ using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.CodeAnalysis.Testing; using Roslyn.Test.Utilities; using Xunit; using Xunit.Abstractions; @@ -21,6 +23,10 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.RemoveUnusedParametersAndValues; +using VerifyCS = CSharpCodeFixVerifier< + CSharpRemoveUnusedParametersAndValuesDiagnosticAnalyzer, + CSharpRemoveUnusedValuesCodeFixProvider>; + [Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedParameters)] public class RemoveUnusedParametersTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest_NoEditor { @@ -37,16 +43,49 @@ private OptionsCollection NonPublicMethodsOnly new CodeStyleOption2(UnusedParametersPreference.NonPublicMethods, NotificationOption2.Suggestion)); // Ensure that we explicitly test missing UnusedParameterDiagnosticId, which has no corresponding code fix (non-fixable diagnostic). - private Task TestDiagnosticMissingAsync(string initialMarkup, ParseOptions? parseOptions = null) - => TestDiagnosticMissingAsync(initialMarkup, options: null, parseOptions); - private Task TestDiagnosticsAsync(string initialMarkup, params DiagnosticDescription[] expectedDiagnostics) - => TestDiagnosticsAsync(initialMarkup, options: null, parseOptions: null, expectedDiagnostics); - private Task TestDiagnosticMissingAsync(string initialMarkup, OptionsCollection? options, ParseOptions? parseOptions = null) - => TestDiagnosticMissingAsync(initialMarkup, new TestParameters(parseOptions, options: options, retainNonFixableDiagnostics: true)); - private Task TestDiagnosticsAsync(string initialMarkup, OptionsCollection options, params DiagnosticDescription[] expectedDiagnostics) - => TestDiagnosticsAsync(initialMarkup, options, parseOptions: null, expectedDiagnostics); - private Task TestDiagnosticsAsync(string initialMarkup, OptionsCollection? options, ParseOptions? parseOptions, params DiagnosticDescription[] expectedDiagnostics) - => TestDiagnosticsAsync(initialMarkup, new TestParameters(parseOptions, options: options, retainNonFixableDiagnostics: true), expectedDiagnostics); + private static Task TestDiagnosticMissingAsync([StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string initialMarkup) + => TestDiagnosticMissingAsync(initialMarkup, options: null); + private static Task TestDiagnosticsAsync([StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string initialMarkup) + => TestDiagnosticsAsync(initialMarkup, options: null); + private static async Task TestDiagnosticMissingAsync([StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string initialMarkup, OptionsCollection? options) + { + var test = new VerifyCS.Test + { + LanguageVersion = LanguageVersion.Preview, + ReferenceAssemblies = ReferenceAssemblies.Net.Net90, + TestCode = initialMarkup, + DisabledDiagnostics = + { + IDEDiagnosticIds.ExpressionValueIsUnusedDiagnosticId, + IDEDiagnosticIds.ValueAssignedIsUnusedDiagnosticId, + }, + }; + + if (options is not null) + test.Options.AddRange(options); + + await test.RunAsync(); + } + + private static async Task TestDiagnosticsAsync([StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string initialMarkup, OptionsCollection? options) + { + var test = new VerifyCS.Test + { + LanguageVersion = LanguageVersion.Preview, + ReferenceAssemblies = ReferenceAssemblies.Net.Net90, + TestCode = initialMarkup, + DisabledDiagnostics = + { + IDEDiagnosticIds.ExpressionValueIsUnusedDiagnosticId, + IDEDiagnosticIds.ValueAssignedIsUnusedDiagnosticId, + }, + }; + + if (options is not null) + test.Options.AddRange(options); + + await test.RunAsync(); + } [Fact] public async Task Parameter_Used() @@ -55,7 +94,7 @@ await TestDiagnosticMissingAsync( """ class C { - void M(int [|p|]) + void M(int p) { var x = p; } @@ -70,12 +109,11 @@ await TestDiagnosticsAsync( """ class C { - void M(int [|p|]) + void M(int {|IDE0060:p|}) { } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Theory] @@ -87,7 +125,7 @@ await TestDiagnosticMissingAsync( $$""" {{typeAccessibility}} class C { - {{methodAccessibility}} void M(int [|p|]) + {{methodAccessibility}} void M(int p) { } } @@ -107,12 +145,11 @@ await TestDiagnosticsAsync( $$""" {{typeAccessibility}} class C { - {{methodAccessibility}} void M(int [|p|]) + {{methodAccessibility}} void M(int {|IDE0060:p|}) { } } - """, NonPublicMethodsOnly, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """, NonPublicMethodsOnly); } [Fact] @@ -125,7 +162,7 @@ await TestDiagnosticMissingAsync( """ class C { - void M(int [|p|]) + void M(int p) { var x = p; } @@ -140,13 +177,12 @@ await TestDiagnosticsAsync( """ class C { - void M(int [|p|]) + void M(int {|IDE0060:p|}) { p = 1; } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact] @@ -156,14 +192,13 @@ await TestDiagnosticsAsync( """ class C { - void M(int [|p|]) + void M(int {|IDE0060:p|}) { p = 1; var x = p; } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact] @@ -173,7 +208,7 @@ await TestDiagnosticsAsync( """ class C { - void M(int [|p|], bool flag) + void M(int {|IDE0060:p|}, bool flag) { if (flag) { @@ -187,8 +222,7 @@ void M(int [|p|], bool flag) var x = p; } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact] @@ -198,7 +232,7 @@ await TestDiagnosticMissingAsync( """ class C { - void M(int [|p|], bool flag, bool flag2) + void M(int p, bool flag, bool flag2) { if (flag) { @@ -225,12 +259,11 @@ await TestDiagnosticsAsync( """ class C { - void M(int [|p|] = 0) + void M(int {|IDE0060:p|} = 0) { } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact] @@ -240,12 +273,12 @@ await TestDiagnosticMissingAsync( """ class B { - protected B(int p) { } + protected B(int _) { } } class C: B { - C(int [|p|]) + C(int p) : base(p) { } @@ -260,12 +293,12 @@ await TestDiagnosticMissingAsync( """ class B { - protected B(int p) { } + protected B(int _) { } } class C: B { - C(int [|p|]) + C(int p) : base(0) { var x = p; @@ -281,12 +314,12 @@ await TestDiagnosticMissingAsync( """ class B { - protected B(int p) { } + protected B(int _) { } } class C: B { - C(int [|p|]) + C(int p) : base(p) { var x = p; @@ -305,13 +338,12 @@ class C void M(int y) { LocalFunction(y); - void LocalFunction(int [|p|]) + void LocalFunction(int {|IDE0060:p|}) { } } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact] @@ -324,13 +356,12 @@ class C void M() { LocalFunction(0); - void LocalFunction(int [|p|]) + void LocalFunction(int {|IDE0060:p|}) { } } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact] @@ -343,7 +374,7 @@ class C void M() { LocalFunction(0); - void LocalFunction(int [|_|]) + void LocalFunction(int _) { } } @@ -363,7 +394,7 @@ class C void M() { M2(LocalFunction); - void LocalFunction(int [|p|]) + void LocalFunction(int p) { } } @@ -383,7 +414,7 @@ await TestDiagnosticMissingAsync( class C { - private static Action M(object [|p|] = null, Action myDelegate) + private static Action M(object p, Action myDelegate) { return d => { myDelegate(p); }; } @@ -402,13 +433,12 @@ await TestDiagnosticsAsync( class C { - private static Action M(object [|p|]) + private static Action M(object {|IDE0060:p|}) { return () => { }; } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact] @@ -422,15 +452,14 @@ await TestDiagnosticsAsync( class C { - private static void M(object [|p|]) + private static void M(object {|IDE0060:p|}) { M2(() => { }); } - private static void M2(Action a) { } + private static void M2(Action _) { } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact] @@ -442,14 +471,14 @@ await TestDiagnosticMissingAsync( class C { - private static void M(object [|p|]) + private static void M(object p) { M2(() => { M3(p); }); } - private static void M2(Action a) { } + private static void M2(Action _) { } - private static void M3(object o) { } + private static void M3(object _) { } } """); } @@ -463,12 +492,12 @@ await TestDiagnosticMissingAsync( class C { - private static void M(object [|p|]) + private static void M(object p) { M2(() => { M3(out p); }); } - private static void M2(Action a) { } + private static void M2(Action _) { } private static void M3(out object o) { o = null; } } @@ -485,16 +514,15 @@ await TestDiagnosticsAsync( class C { - public static void M1(object [|p|]) + public static void M1(object {|IDE0060:p|}) { M2(x => x.M3()); } - private static C M2(Expression> a) { return null; } + private static C M2(Expression> _) { return null; } private int M3() { return 0; } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/31744")] @@ -507,13 +535,13 @@ await TestDiagnosticMissingAsync( class C { - public static void M1(object [|p|]) + public static void M1(object p) { M2(x => x.M3(p)); } - private static C M2(Expression> a) { return null; } - private int M3(object o) { return 0; } + private static C M2(Expression> _) { return null; } + private int M3(object _) { return 0; } } """); } @@ -528,12 +556,12 @@ await TestDiagnosticMissingAsync( class C { - public static void M1(object [|p|]) + public static void M1(object p) { M2(x => x.M3(out p)); } - private static C M2(Expression> a) { return null; } + private static C M2(Expression> _) { return null; } private int M3(out object o) { o = null; return 0; } } """); @@ -550,8 +578,8 @@ await TestDiagnosticMissingAsync( class C { - private Action _field; - private static void M(object [|p|]) + private static Action _field; + private static void M(object p) { _field = () => { Console.WriteLine(p); }; } @@ -570,7 +598,7 @@ class C { private static readonly object s_gate = new object(); - public static C M(object [|p|], bool flag, C c1, C c2) + public static C M(object p, int flag, C c1, C c2) { C c; lock (s_gate) @@ -582,7 +610,7 @@ public static C M(object [|p|], bool flag, C c1, C c2) return c; } - private void M2(object p) { } + private void M2(object _) { } } """); } @@ -598,7 +626,7 @@ class C { void M(int y) { - Action myLambda = [|p|] => + Action myLambda = p => { }; @@ -619,7 +647,7 @@ class C { void M(int y) { - Action myLambda = [|_|] => + Action myLambda = _ => { }; @@ -640,7 +668,7 @@ class C { void M(int y) { - Action myLambda = ([|_|], _) => + Action myLambda = (_, _) => { }; @@ -661,7 +689,7 @@ class C { void M(int y) { - void local([|_|], _) + void local(int _1, int _2) { } @@ -680,7 +708,7 @@ await TestDiagnosticMissingAsync( class C { - void M([|_|], _) + void M(int _1, int _2) { } @@ -702,7 +730,7 @@ class C void M(int y) { LocalFunction(y); - void LocalFunction(int [|p|]) + void LocalFunction(int p) { var x = p; } @@ -722,10 +750,10 @@ class C { void M(int y) { - Action myLambda = [|p|] => + Action myLambda = p => { var x = p; - } + }; myLambda(y); } @@ -740,7 +768,7 @@ await TestDiagnosticMissingAsync( """ class C { - void M(int [|p = 0|]) + void M(int p = 0) { var x = p; } @@ -755,12 +783,11 @@ await TestDiagnosticsAsync( """ class C { - void M(in int [|p|]) + void M(in int {|IDE0060:p|}) { } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact] @@ -770,12 +797,11 @@ await TestDiagnosticsAsync( """ class C { - void M(ref int [|p|]) + void M(ref int {|IDE0060:p|}) { } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact] @@ -785,7 +811,7 @@ await TestDiagnosticMissingAsync( """ class C { - void M(ref int [|p|]) + void M(ref int p) { p = 0; } @@ -800,7 +826,7 @@ await TestDiagnosticMissingAsync( """ class C { - void M(ref int [|p|]) + void M(ref int p) { var x = p; } @@ -815,7 +841,7 @@ await TestDiagnosticMissingAsync( """ class C { - void M(ref int [|p|]) + void M(ref int p) { var x = p; p = 1; @@ -831,7 +857,7 @@ await TestDiagnosticMissingAsync( """ class C { - void M(ref int [|p|]) + void M(ref int p) { p = 1; var x = p; @@ -847,7 +873,7 @@ await TestDiagnosticMissingAsync( """ class C { - void M(ref int [|p|]) + void M(ref int p) { p = 0; p = 1; @@ -863,12 +889,11 @@ await TestDiagnosticsAsync( """ class C { - void M(out int [|p|]) + void {|CS0177:M|}(out int {|IDE0060:p|}) { } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact] @@ -878,7 +903,7 @@ await TestDiagnosticMissingAsync( """ class C { - void M(out int [|p|]) + void M(out int p) { p = 0; } @@ -893,7 +918,7 @@ await TestDiagnosticMissingAsync( """ class C { - void M(out int [|p|]) + void M(out int p) { p = 0; var x = p; @@ -909,7 +934,7 @@ await TestDiagnosticMissingAsync( """ class C { - void M(out int [|p|]) + void M(out int p) { p = 0; p = 1; @@ -926,7 +951,7 @@ await TestDiagnosticMissingAsync( class C { [System.Runtime.InteropServices.DllImport(nameof(M))] - static extern void M(int [|p|]); + static extern void M(int p); } """); } @@ -938,7 +963,7 @@ await TestDiagnosticMissingAsync( """ abstract class C { - protected abstract void M(int [|p|]); + protected abstract void M(int p); } """); } @@ -950,7 +975,7 @@ await TestDiagnosticMissingAsync( """ class C { - protected virtual void M(int [|p|]) + protected virtual void M(int p) { } } @@ -972,7 +997,7 @@ protected virtual void M(int p) class D : C { - protected override void M(int [|p|]) + protected override void M(int p) { } } @@ -990,7 +1015,7 @@ interface I } class C: I { - public void M(int [|p|]) + public void M(int p) { } } @@ -1008,7 +1033,7 @@ interface I } class C: I { - void I.M(int [|p|]) + void I.M(int p) { } } @@ -1022,7 +1047,7 @@ await TestDiagnosticMissingAsync( """ class C { - int this[int [|p|]] + int this[int p] { get { return 0; } } @@ -1037,7 +1062,7 @@ await TestDiagnosticMissingAsync( """ class C { - void M(int [|p|]) + void M(int p) { #if DEBUG System.Console.WriteLine(p); @@ -1054,7 +1079,7 @@ await TestDiagnosticMissingAsync( """ class C { - public void MyHandler(object [|obj|], System.EventArgs args) + public void MyHandler(object obj, System.EventArgs args) { } } @@ -1068,7 +1093,7 @@ await TestDiagnosticMissingAsync( """ class C { - public void MyHandler(object obj, System.EventArgs [|args|]) + public void MyHandler(object obj, System.EventArgs args) { } } @@ -1093,7 +1118,7 @@ void M(C c) c.myDel += Handler; } - void Handler(int [|x|]) + void Handler(int x) { } } @@ -1111,7 +1136,7 @@ public class CustomEventArgs : System.EventArgs { } - public void MyHandler(object [|obj|], CustomEventArgs args) + public void MyHandler(object obj, CustomEventArgs args) { } } @@ -1132,7 +1157,7 @@ await TestDiagnosticMissingAsync( class C { {{attribute}} - void M(int [|p|]) + void M(int p) { } } @@ -1154,7 +1179,7 @@ public class {{attributeName}} : System.Attribute { } class C { [{{attributeNamespace}}.{{attributeName}}()] - public C(int [|p|]) + public C(int p) { } } @@ -1181,7 +1206,7 @@ internal sealed class CustomSerializingType : ISerializable { private readonly NonSerializable _nonSerializable; - public CustomSerializingType(SerializationInfo info, StreamingContext [|context|]) + public CustomSerializingType(SerializationInfo info, StreamingContext context) { _nonSerializable = new NonSerializable(info.GetString("KEY")); } @@ -1241,6 +1266,42 @@ void M3(int p5) Assert.Equal("Parameter 'p5' can be removed; its initial value is never used", sortedDiagnostics[4].GetMessage()); } + [Theory] + [InlineData("int[]")] + [InlineData("Span")] + public async Task Parameter_ArrayLikeUsedForReading(string arrayLikeType) + { + await TestDiagnosticMissingAsync( + $$""" + using System; + class C + { + void M({{arrayLikeType}} p) + { + var x = p[0]; + } + } + """); + } + + [Theory] + [InlineData("int[]")] + [InlineData("Span")] + public async Task Parameter_ArrayLikeUsedForWriting(string arrayLikeType) + { + await TestDiagnosticMissingAsync( + $$""" + using System; + class C + { + void M({{arrayLikeType}} p) + { + p[0] = new(); + } + } + """); + } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32287")] public async Task Parameter_DeclarationPatternWithNullDeclaredSymbol() { @@ -1248,7 +1309,7 @@ await TestDiagnosticMissingAsync( """ class C { - void M(object [|o|]) + void M(object o) { if (o is int _) { @@ -1265,7 +1326,7 @@ await TestDiagnosticMissingAsync( """ class C { - [|void M(int _, char _1, C _3)|] + void M(int _, char _1, C _3) { } } @@ -1279,12 +1340,12 @@ await TestDiagnosticMissingAsync( """ class C { - void M(int [|x|]) + void M(int x) { // CS1662: Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type. Invoke(() => x); - T Invoke(Func a) { return a(); } + T Invoke({|CS0246:Func|} a) { return a(); } } } """); @@ -1297,16 +1358,15 @@ await TestDiagnosticsAsync( """ class C { - void M(int [|x|]) + void M(int {|IDE0060:x|}) { // CS1662: Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type. Invoke(() => 0); - T Invoke(Func a) { return a(); } + T Invoke({|CS0246:Func|} a) { return a(); } } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32973")] @@ -1320,7 +1380,7 @@ public static bool M(out int x) { return LocalFunction(out x); - bool LocalFunction(out int [|y|]) + bool LocalFunction(out int y) { y = 0; return true; @@ -1341,14 +1401,13 @@ public static bool M(ref int x) { return LocalFunction(ref x); - bool LocalFunction(ref int [|y|]) + bool LocalFunction(ref int {|IDE0060:y|}) { return true; } } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32973")] @@ -1362,7 +1421,7 @@ public static bool M(ref int x) { return LocalFunction(ref x); - bool LocalFunction(ref int [|y|]) + bool LocalFunction(ref int y) { y = 0; return true; @@ -1379,12 +1438,12 @@ await TestDiagnosticMissingAsync( """ class C { - public static void M(C [|x|]) + public static void M(C x) { x ??= new C(); } } - """, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/34301")] @@ -1398,13 +1457,12 @@ void M() { LocalFunc(0); - void LocalFunc(T [|value|]) + void LocalFunc(T {|IDE0060:value|}) { } } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36715")] @@ -1416,7 +1474,7 @@ await TestDiagnosticsAsync( class C { - void M(object [|value|]) + void M(object {|IDE0060:value|}) { try { @@ -1435,21 +1493,20 @@ IEnumerable LocalFunc(T value) } } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36715")] public async Task GenericLocalFunction_03() { - await TestDiagnosticsAsync( + await TestDiagnosticMissingAsync( """ using System; using System.Collections.Generic; class C { - void M(object [|value|]) + void M(object value) { Func> myDel = LocalFunc; try @@ -1489,7 +1546,7 @@ public sealed class C : IDisposable { private readonly Task task; - public C(Task [|task|]) + public C(Task task) { this.task = task; Task.Run(async () => (await task).MyAction += myAction); @@ -1545,7 +1602,7 @@ await TestDiagnosticMissingAsync( public partial class C { - private void M(int [|x|]) + private void M(int x) { } } @@ -1569,7 +1626,7 @@ await TestDiagnosticMissingAsync( public partial class C { [System.CodeDom.Compiler.GeneratedCodeAttribute("", "")] - private void M(int [|x|]) + private void M(int x) { } } @@ -1589,7 +1646,7 @@ public partial class C public partial class C { - public partial void M(int [|x|]) + public partial void M(int x) { } } @@ -1603,7 +1660,7 @@ await TestDiagnosticMissingAsync( """ public partial class C { - public partial void M(int [|x|]); + partial void M(int x); } """); } @@ -1615,7 +1672,7 @@ await TestDiagnosticMissingAsync( """ public class C { - public void M[|(int )|] + public void M(int {|CS1001:)|} { } } @@ -1631,7 +1688,7 @@ await TestDiagnosticMissingAsync( class C { - private void Goo(int [|i|]) + private void Goo(int i) { throw new NotImplementedException(); } @@ -1648,7 +1705,7 @@ await TestDiagnosticMissingAsync( class C { - private void Goo(int [|i|]) + private void Goo(int i) => throw new NotImplementedException(); } """); @@ -1663,7 +1720,7 @@ await TestDiagnosticMissingAsync( class C { - public C(int [|i|]) + public C(int i) => throw new NotImplementedException(); } """); @@ -1678,7 +1735,7 @@ await TestDiagnosticMissingAsync( class C { - private int Goo(int [|i|]) + private int Goo(int i) => throw new NotImplementedException(); } """); @@ -1693,7 +1750,7 @@ await TestDiagnosticMissingAsync( class C { - private int Goo(int [|i|]) + private int Goo(int i) { throw new NotImplementedException(); } @@ -1710,14 +1767,13 @@ await TestDiagnosticsAsync( class C { - private void Goo(int [|i|]) + private void Goo(int {|IDE0060:i|}) { throw new NotImplementedException(); return; } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/41236")] @@ -1729,14 +1785,13 @@ await TestDiagnosticsAsync( class C { - private void Goo(int [|i|]) + private void Goo(int {|IDE0060:i|}) { if (true) throw new NotImplementedException(); } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/47142")] @@ -1753,12 +1808,11 @@ await TestDiagnosticsAsync( """ record A { - public A(int [|X|]) + public A(int {|IDE0060:X|}) { } } - """, -Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/47142")] @@ -1767,7 +1821,7 @@ public async Task Record_DelegatingPrimaryConstructorParameter() await TestDiagnosticMissingAsync( """ record A(int X); - record B(int X, int [|Y|]) : A(X); + record B(int X, int Y) : A(X); """); } @@ -1777,7 +1831,7 @@ public async Task RecordPrimaryConstructorParameter_PublicRecord() await TestDiagnosticMissingAsync( """ public record Base(int I) { } - public record Derived(string [|S|]) : Base(42) { } + public record Derived(string S) : Base(42) { } """); } @@ -1806,7 +1860,7 @@ public IntPtr MarshalManagedToNative(object ManagedObj) public object MarshalNativeToManaged(IntPtr pNativeData) => throw new NotImplementedException(); - public static ICustomMarshaler GetInstance(string [|s|]) + public static ICustomMarshaler GetInstance(string s) => null; } """); @@ -1819,7 +1873,7 @@ await TestDiagnosticMissingAsync( """ public class Class { - public void Method(int [|x|]) => throw new System.Exception(); + public void Method(int x) => throw new System.Exception(); } """); } @@ -1831,7 +1885,7 @@ await TestDiagnosticMissingAsync( """ public class Class { - public void Method(int [|x|]) + public void Method(int x) { throw new System.Exception(); } @@ -1846,7 +1900,7 @@ await TestDiagnosticMissingAsync( """ public class Class { - public Class(int [|x|]) + public Class(int x) { throw new System.Exception(); } @@ -1861,7 +1915,7 @@ await TestDiagnosticMissingAsync( """ public class Class { - public Class(int [|x|]) => throw new System.Exception(); + public Class(int x) => throw new System.Exception(); } """); } @@ -1875,7 +1929,7 @@ public class Class { public void Method() { - void LocalMethod(int [|x|]) => throw new System.Exception(); + void LocalMethod(int x) => throw new System.Exception(); } } """); @@ -1888,7 +1942,7 @@ await TestDiagnosticMissingAsync( """ using System; - class C(int [|a100|]) + class C(int a100) { } """); @@ -1901,7 +1955,7 @@ await TestDiagnosticMissingAsync( """ using System; - class C(int [|a100|]) : Object() + class C(int a100) : Object() { int M1() => a100; } @@ -1914,32 +1968,27 @@ public async Task TestMethodWithNameOf() await TestDiagnosticsAsync(""" class C { - void M(int [|x|]) + void M(int {|IDE0060:x|}) { const string y = nameof(C); } } - """, Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/58168")] public async Task TestInterpolatedStringHandler_TwoIntParameters_FirstParameter() { await TestDiagnosticMissingAsync(""" - - - using System.Runtime.CompilerServices; + using System.Runtime.CompilerServices; [InterpolatedStringHandler] public struct MyInterpolatedStringHandler { - public MyInterpolatedStringHandler(int [|literalLength|], int formattedCount) + public MyInterpolatedStringHandler(int literalLength, int formattedCount) { } } - - - """); } @@ -1947,20 +1996,15 @@ public MyInterpolatedStringHandler(int [|literalLength|], int formattedCount) public async Task TestInterpolatedStringHandler_TwoIntParameters_SecondParameter() { await TestDiagnosticMissingAsync(""" - - - using System.Runtime.CompilerServices; + using System.Runtime.CompilerServices; [InterpolatedStringHandler] public struct MyInterpolatedStringHandler { - public MyInterpolatedStringHandler(int literalLength, int [|formattedCount|]) + public MyInterpolatedStringHandler(int literalLength, int formattedCount) { } } - - - """); } @@ -1969,21 +2013,16 @@ public MyInterpolatedStringHandler(int literalLength, int [|formattedCount|]) public async Task TestInterpolatedStringHandler_TwoParameters_FirstNonIntParameter(string nonIntType) { await TestDiagnosticsAsync($$""" - - - using System.Runtime.CompilerServices; + using System.Runtime.CompilerServices; [InterpolatedStringHandler] public struct MyInterpolatedStringHandler { - public MyInterpolatedStringHandler({{nonIntType}} [|literalLength|], int formattedCount) + public MyInterpolatedStringHandler({{nonIntType}} {|IDE0060:literalLength|}, int formattedCount) { } } - - - - """, Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/58168")] @@ -1991,41 +2030,31 @@ public MyInterpolatedStringHandler({{nonIntType}} [|literalLength|], int formatt public async Task TestInterpolatedStringHandler_TwoParameters_SecondNonIntParameter(string nonIntType) { await TestDiagnosticsAsync($$""" - - - using System.Runtime.CompilerServices; + using System.Runtime.CompilerServices; [InterpolatedStringHandler] public struct MyInterpolatedStringHandler { - public MyInterpolatedStringHandler(int literalLength, {{nonIntType}} [|formattedCount|]) + public MyInterpolatedStringHandler(int literalLength, {{nonIntType}} {|IDE0060:formattedCount|}) { } } - - - - """, Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/58168")] public async Task TestInterpolatedStringHandler_OneIntParameter() { await TestDiagnosticMissingAsync(""" - - - using System.Runtime.CompilerServices; + using System.Runtime.CompilerServices; [InterpolatedStringHandler] public struct MyInterpolatedStringHandler { - public MyInterpolatedStringHandler(int [|literalLength|]) + public MyInterpolatedStringHandler(int literalLength) { } } - - - """); } @@ -2034,21 +2063,16 @@ public MyInterpolatedStringHandler(int [|literalLength|]) public async Task TestInterpolatedStringHandler_OneNonIntParameter(string nonIntType) { await TestDiagnosticsAsync($$""" - - - using System.Runtime.CompilerServices; + using System.Runtime.CompilerServices; [InterpolatedStringHandler] public struct MyInterpolatedStringHandler { - public MyInterpolatedStringHandler({{nonIntType}} [|p|]) + public MyInterpolatedStringHandler({{nonIntType}} {|IDE0060:p|}) { } } - - - - """, Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); + """); } public static IEnumerable NonIntTypes() diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/OperationExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/OperationExtensions.cs index eeea1ca2ba754..cedc0a32aab41 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/OperationExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/OperationExtensions.cs @@ -207,9 +207,10 @@ where void Foo(in T v) } else if (operation is { Type.IsValueType: true, Parent: IPropertyReferenceOperation }) { - // accessing an indexer/property off of a value type will read/write the value type depending on how the - // indexer/property itself is used. - return GetValueUsageInfo(operation.Parent, containingSymbol); + // Accessing an indexer/property off of a value type will read/write the value type depending on how the + // indexer/property itself is used. We add ValueUsageInfo.Read to the result since the value on which we are + // accessing a property is always read. + return ValueUsageInfo.Read | GetValueUsageInfo(operation.Parent, containingSymbol); } else if (operation.Parent is IVariableInitializerOperation variableInitializerOperation) {