From 73281d88ebb869b91d5b481a7a66c360d39cb4f0 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sat, 2 Sep 2023 13:50:38 +0200 Subject: [PATCH] Fix RCS1241 (#1197) --- ChangeLog.md | 1 + ...entNonGenericCounterpartCodeFixProvider.cs | 12 +++++ .../Analysis/NamedTypeSymbolAnalyzer.cs | 22 ++++----- ...1241ImplementNonGenericCounterpartTests.cs | 45 +++++++++++++++++++ 4 files changed, 70 insertions(+), 10 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 4938abea90..a9168f2f3c 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fix [RCS1164](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1164) ([#1196](https://github.com/JosefPihrt/Roslynator/pull/1196)). +- Fix [RCS1241](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1241) ([#1197](https://github.com/JosefPihrt/Roslynator/pull/1197)). ## [4.5.0] - 2023-08-27 diff --git a/src/Analyzers.CodeFixes/CSharp/CodeFixes/ImplementNonGenericCounterpartCodeFixProvider.cs b/src/Analyzers.CodeFixes/CSharp/CodeFixes/ImplementNonGenericCounterpartCodeFixProvider.cs index 39376f7687..3afaed84f3 100644 --- a/src/Analyzers.CodeFixes/CSharp/CodeFixes/ImplementNonGenericCounterpartCodeFixProvider.cs +++ b/src/Analyzers.CodeFixes/CSharp/CodeFixes/ImplementNonGenericCounterpartCodeFixProvider.cs @@ -290,6 +290,18 @@ private static async Task RefactorAsync( newTypeDeclaration = classDeclaration.WithBaseList(baseList.WithTypes(baseTypes)); } + else if (kind == SyntaxKind.RecordDeclaration) + { + var recordDeclaration = (RecordDeclarationSyntax)newTypeDeclaration; + + BaseListSyntax baseList = recordDeclaration.BaseList; + + SeparatedSyntaxList baseTypes = baseList.Types; + + baseTypes = AddBaseType(baseTypes, baseType); + + newTypeDeclaration = recordDeclaration.WithBaseList(baseList.WithTypes(baseTypes)); + } else if (kind == SyntaxKind.StructDeclaration || kind == SyntaxKind.RecordStructDeclaration) { diff --git a/src/Analyzers/CSharp/Analysis/NamedTypeSymbolAnalyzer.cs b/src/Analyzers/CSharp/Analysis/NamedTypeSymbolAnalyzer.cs index 609958b7ab..30238f8bd5 100644 --- a/src/Analyzers/CSharp/Analysis/NamedTypeSymbolAnalyzer.cs +++ b/src/Analyzers/CSharp/Analysis/NamedTypeSymbolAnalyzer.cs @@ -1,9 +1,11 @@ // Copyright (c) Josef Pihrt and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -130,19 +132,19 @@ private static void AnalyzeNamedType(SymbolAnalysisContext context) private static void ReportDiagnostic(SymbolAnalysisContext context, INamedTypeSymbol symbol, string interfaceName, string genericInterfaceName) { - SyntaxToken identifier = default; + SyntaxNode node = symbol.GetSyntax(context.CancellationToken); - if (symbol.TypeKind == TypeKind.Class) - { - var classDeclaration = (ClassDeclarationSyntax)symbol.GetSyntax(context.CancellationToken); + SyntaxToken identifier = GetIdentifier(); - identifier = classDeclaration.Identifier; - } - else if (symbol.TypeKind == TypeKind.Struct) + SyntaxToken GetIdentifier() { - var structDeclaration = (StructDeclarationSyntax)symbol.GetSyntax(context.CancellationToken); - - identifier = structDeclaration.Identifier; + return node switch + { + ClassDeclarationSyntax classDeclaration => classDeclaration.Identifier, + StructDeclarationSyntax structDeclaration => structDeclaration.Identifier, + RecordDeclarationSyntax recordDeclaration => recordDeclaration.Identifier, + _ => throw new InvalidOperationException($"Unknown syntax node kind '{node.Kind()}'."), + }; } DiagnosticHelpers.ReportDiagnostic( diff --git a/src/Tests/Analyzers.Tests/RCS1241ImplementNonGenericCounterpartTests.cs b/src/Tests/Analyzers.Tests/RCS1241ImplementNonGenericCounterpartTests.cs index 5e41c6b5bb..2b1950c66b 100644 --- a/src/Tests/Analyzers.Tests/RCS1241ImplementNonGenericCounterpartTests.cs +++ b/src/Tests/Analyzers.Tests/RCS1241ImplementNonGenericCounterpartTests.cs @@ -64,6 +64,51 @@ public int CompareTo(object obj) ", equivalenceKey: EquivalenceKey.Create(Descriptor.Id)); } + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.ImplementNonGenericCounterpart)] + public async Task Test_Record_IComparable() + { + await VerifyDiagnosticAndFixAsync(@" +using System; +using System.Collections.Generic; + +public class C +{ +} + +public abstract record class [|Comparable|] : IComparable +{ + public abstract int CompareTo(C other); +} +", @" +using System; +using System.Collections.Generic; + +public class C +{ +} + +public abstract record class Comparable : IComparable, IComparable +{ + public abstract int CompareTo(C other); + + public int CompareTo(object obj) + { + if (obj == null) + { + return 1; + } + + if (obj is C x) + { + return CompareTo(x); + } + + throw new ArgumentException("""", nameof(obj)); + } +} +", equivalenceKey: EquivalenceKey.Create(Descriptor.Id)); + } + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.ImplementNonGenericCounterpart)] public async Task Test_IComparable_Explicit() {