From bc5e3787925dad7aa4435ec16485952ee4ea9ae9 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Fri, 24 Nov 2023 19:24:27 +0100 Subject: [PATCH 1/5] Handle OnSerializedAttribute (RCS1163) --- .../UnusedParameterAnalyzer.cs | 43 ++++++++++++++++--- .../MetadataNameSet.cs | 14 ++++++ .../RCS1163UnusedParameterTests.cs | 17 ++++++++ 3 files changed, 69 insertions(+), 5 deletions(-) rename src/{Workspaces.Core => Core}/MetadataNameSet.cs (79%) diff --git a/src/Analyzers/CSharp/Analysis/UnusedParameter/UnusedParameterAnalyzer.cs b/src/Analyzers/CSharp/Analysis/UnusedParameter/UnusedParameterAnalyzer.cs index 4419054879..79082c1dd4 100644 --- a/src/Analyzers/CSharp/Analysis/UnusedParameter/UnusedParameterAnalyzer.cs +++ b/src/Analyzers/CSharp/Analysis/UnusedParameter/UnusedParameterAnalyzer.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -14,6 +15,14 @@ namespace Roslynator.CSharp.Analysis.UnusedParameter; [DiagnosticAnalyzer(LanguageNames.CSharp)] public sealed class UnusedParameterAnalyzer : BaseDiagnosticAnalyzer { + private static readonly MetadataNameSet _attributes = new(new[] + { + MetadataName.Parse("System.Runtime.Serialization.OnSerializedAttribute"), + MetadataName.Parse("System.Runtime.Serialization.OnDeserializedAttribute"), + MetadataName.Parse("System.Runtime.Serialization.OnSerializingAttribute"), + MetadataName.Parse("System.Runtime.Serialization.OnDeserializingAttribute"), + }); + private static ImmutableArray _supportedDiagnostics; public override ImmutableArray SupportedDiagnostics @@ -134,7 +143,7 @@ private static void AnalyzeMethodDeclaration(SyntaxNodeAnalysisContext context) walker.SetValues(context.SemanticModel, context.CancellationToken); - FindUnusedNodes(parameterInfo, walker); + FindUnusedNodes(parameterInfo, walker, methodSymbol); if (walker.Nodes.Count > 0 && !MethodReferencedAsMethodGroupWalker.IsReferencedAsMethodGroup(methodDeclaration, methodSymbol, context.SemanticModel, context.CancellationToken)) @@ -331,19 +340,21 @@ private static void Analyze(SyntaxNodeAnalysisContext context, in ParameterInfo } } - private static void FindUnusedNodes(in ParameterInfo parameterInfo, UnusedParameterWalker walker) + private static void FindUnusedNodes(in ParameterInfo parameterInfo, UnusedParameterWalker walker, IMethodSymbol methodSymbol = null) { if (parameterInfo.Parameter is not null && !IsArgListOrDiscard(parameterInfo.Parameter)) { - walker.AddParameter(parameterInfo.Parameter); + AddParameter(walker, parameterInfo.Parameter, 0, methodSymbol); } else { - foreach (ParameterSyntax parameter in parameterInfo.Parameters) + for (int i = 0; i < parameterInfo.Parameters.Count; i++) { + ParameterSyntax parameter = parameterInfo.Parameters[i]; + if (!IsArgListOrDiscard(parameter)) - walker.AddParameter(parameter); + AddParameter(walker, parameter, i, methodSymbol); } } @@ -357,6 +368,28 @@ private static void FindUnusedNodes(in ParameterInfo parameterInfo, UnusedParame walker.Visit(parameterInfo.Node); } + private static void AddParameter(UnusedParameterWalker walker, ParameterSyntax parameter, int index, IMethodSymbol methodSymbol) + { + if (methodSymbol is not null) + { + if (index >= methodSymbol.Parameters.Length) + { + Debug.Fail($"{index} {methodSymbol.Parameters.Length}"); + return; + } + + IParameterSymbol parameterSymbol = methodSymbol.Parameters[index]; + + if (parameterSymbol.Type.HasMetadataName(MetadataNames.System_Runtime_Serialization_StreamingContext) + && _attributes.ContainsAny(methodSymbol.GetAttributes())) + { + return; + } + } + + walker.AddParameter(parameter); + } + private static bool IsArgListOrDiscard(ParameterSyntax parameter) { return parameter.Identifier.IsKind(SyntaxKind.ArgListKeyword) diff --git a/src/Workspaces.Core/MetadataNameSet.cs b/src/Core/MetadataNameSet.cs similarity index 79% rename from src/Workspaces.Core/MetadataNameSet.cs rename to src/Core/MetadataNameSet.cs index 58238bbb44..3395905a93 100644 --- a/src/Workspaces.Core/MetadataNameSet.cs +++ b/src/Core/MetadataNameSet.cs @@ -44,4 +44,18 @@ public bool Contains(ISymbol symbol) return false; } + + public bool ContainsAny(ImmutableArray attributes) + { + foreach (AttributeData attributeData in attributes) + { + if (attributeData.AttributeClass is not null + && Contains(attributeData.AttributeClass)) + { + return true; + } + } + + return false; + } } diff --git a/src/Tests/Analyzers.Tests/RCS1163UnusedParameterTests.cs b/src/Tests/Analyzers.Tests/RCS1163UnusedParameterTests.cs index bd698d7ac6..e5155b0288 100644 --- a/src/Tests/Analyzers.Tests/RCS1163UnusedParameterTests.cs +++ b/src/Tests/Analyzers.Tests/RCS1163UnusedParameterTests.cs @@ -234,6 +234,23 @@ namespace System.Windows public class DependencyPropertyChangedEventArgs { } +} + "); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UnusedParameter)] + public async Task TestNoDiagnostic_StreamingContextAttributes() + { + await VerifyNoDiagnosticAsync(@" +using System.Runtime.Serialization; + +class C +{ + [Obsolete] + [OnSerialized] + void M(string p, StreamingContext context) + { + } } "); } From 211ec2ae0e838ef6ff098f2133cba40c30214b72 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Fri, 24 Nov 2023 19:25:15 +0100 Subject: [PATCH 2/5] update --- ChangeLog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog.md b/ChangeLog.md index 1d4b9847c4..5a13189614 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - Fix analyzer [RCS1124](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1124) ([PR](https://github.com/dotnet/roslynator/pull/1279)) +- Fix analyzer [RCS1163](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1163) ([PR](https://github.com/dotnet/roslynator/pull/1280)) ## [4.6.4] - 2023-11-24 From 18df7657172f32d834eccc00bc3eece9b40ea8f4 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Fri, 24 Nov 2023 19:30:22 +0100 Subject: [PATCH 3/5] update --- .../RCS1163UnusedParameterTests.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Tests/Analyzers.Tests/RCS1163UnusedParameterTests.cs b/src/Tests/Analyzers.Tests/RCS1163UnusedParameterTests.cs index e5155b0288..c322b27ac7 100644 --- a/src/Tests/Analyzers.Tests/RCS1163UnusedParameterTests.cs +++ b/src/Tests/Analyzers.Tests/RCS1163UnusedParameterTests.cs @@ -251,6 +251,21 @@ class C void M(string p, StreamingContext context) { } + + [OnDeserialized] + void M(StreamingContext context, string p) + { + } + + [OnSerializing] + void M(string p, StreamingContext context) + { + } + + [OnDeserializing] + void M(StreamingContext context, string p) + { + } } "); } From 9c410aeda471c0e083ef7cef3f865ca38b836943 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Fri, 24 Nov 2023 19:32:13 +0100 Subject: [PATCH 4/5] update --- .../Analysis/UnusedParameter/UnusedParameterAnalyzer.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Analyzers/CSharp/Analysis/UnusedParameter/UnusedParameterAnalyzer.cs b/src/Analyzers/CSharp/Analysis/UnusedParameter/UnusedParameterAnalyzer.cs index 79082c1dd4..b8e4ac1d07 100644 --- a/src/Analyzers/CSharp/Analysis/UnusedParameter/UnusedParameterAnalyzer.cs +++ b/src/Analyzers/CSharp/Analysis/UnusedParameter/UnusedParameterAnalyzer.cs @@ -378,9 +378,7 @@ private static void AddParameter(UnusedParameterWalker walker, ParameterSyntax p return; } - IParameterSymbol parameterSymbol = methodSymbol.Parameters[index]; - - if (parameterSymbol.Type.HasMetadataName(MetadataNames.System_Runtime_Serialization_StreamingContext) + if (methodSymbol.Parameters[index].Type.HasMetadataName(MetadataNames.System_Runtime_Serialization_StreamingContext) && _attributes.ContainsAny(methodSymbol.GetAttributes())) { return; From afb9d06627355d3c1c04433053d34bc6bc61ae90 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Fri, 24 Nov 2023 19:51:21 +0100 Subject: [PATCH 5/5] update --- .../Analyzers.Tests/RCS1163UnusedParameterTests.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Tests/Analyzers.Tests/RCS1163UnusedParameterTests.cs b/src/Tests/Analyzers.Tests/RCS1163UnusedParameterTests.cs index c322b27ac7..f85aecd673 100644 --- a/src/Tests/Analyzers.Tests/RCS1163UnusedParameterTests.cs +++ b/src/Tests/Analyzers.Tests/RCS1163UnusedParameterTests.cs @@ -242,28 +242,31 @@ public class DependencyPropertyChangedEventArgs public async Task TestNoDiagnostic_StreamingContextAttributes() { await VerifyNoDiagnosticAsync(@" +using System; using System.Runtime.Serialization; class C { [Obsolete] [OnSerialized] - void M(string p, StreamingContext context) + void M1(string p, StreamingContext context) { + var x = p; } [OnDeserialized] - void M(StreamingContext context, string p) + void M2(StreamingContext context, string p) { + var x = p; } [OnSerializing] - void M(string p, StreamingContext context) + void M3(StreamingContext context) { } [OnDeserializing] - void M(StreamingContext context, string p) + void M4(StreamingContext context) { } }