diff --git a/ChangeLog.md b/ChangeLog.md index c926de0e61..03866bf2a0 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix [RCS1228](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1228) ([PR](https://github.com/dotnet/roslynator/pull/1249)) - Fix [RCS1213](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1213) ([PR](https://github.com/dotnet/roslynator/pull/1254)) +- Fix [RCS1055](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1055) ([PR](https://github.com/dotnet/roslynator/pull/1253)) ## [4.6.2] - 2023-11-10 diff --git a/src/Analyzers.CodeFixes/CSharp/CodeFixes/MemberDeclarationCodeFixProvider.cs b/src/Analyzers.CodeFixes/CSharp/CodeFixes/MemberDeclarationCodeFixProvider.cs index 9638603ce8..cca38609a9 100644 --- a/src/Analyzers.CodeFixes/CSharp/CodeFixes/MemberDeclarationCodeFixProvider.cs +++ b/src/Analyzers.CodeFixes/CSharp/CodeFixes/MemberDeclarationCodeFixProvider.cs @@ -29,7 +29,7 @@ public override ImmutableArray FixableDiagnosticIds DiagnosticIdentifiers.RemoveRedundantOverridingMember, DiagnosticIdentifiers.AddOrRemoveAccessibilityModifiers, DiagnosticIdentifiers.RemoveRedundantSealedModifier, - DiagnosticIdentifiers.AvoidSemicolonAtEndOfDeclaration, + DiagnosticIdentifiers.UnnecessarySemicolonAtEndOfDeclaration, DiagnosticIdentifiers.OrderModifiers, DiagnosticIdentifiers.MakeFieldReadOnly, DiagnosticIdentifiers.UseConstantInsteadOfField, @@ -97,11 +97,11 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, memberDeclaration, SyntaxKind.SealedKeyword); break; } - case DiagnosticIdentifiers.AvoidSemicolonAtEndOfDeclaration: + case DiagnosticIdentifiers.UnnecessarySemicolonAtEndOfDeclaration: { CodeAction codeAction = CodeAction.Create( "Remove unnecessary semicolon", - ct => AvoidSemicolonAtEndOfDeclarationRefactoring.RefactorAsync(context.Document, memberDeclaration, ct), + ct => RemoveSemicolonAtEndOfDeclarationRefactoring.RefactorAsync(context.Document, memberDeclaration, ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); diff --git a/src/Analyzers.CodeFixes/CSharp/Refactorings/AvoidSemicolonAtEndOfDeclarationRefactoring.cs b/src/Analyzers.CodeFixes/CSharp/Refactorings/RemoveSemicolonAtEndOfDeclarationRefactoring.cs similarity index 98% rename from src/Analyzers.CodeFixes/CSharp/Refactorings/AvoidSemicolonAtEndOfDeclarationRefactoring.cs rename to src/Analyzers.CodeFixes/CSharp/Refactorings/RemoveSemicolonAtEndOfDeclarationRefactoring.cs index a803197e0f..0cecb69afe 100644 --- a/src/Analyzers.CodeFixes/CSharp/Refactorings/AvoidSemicolonAtEndOfDeclarationRefactoring.cs +++ b/src/Analyzers.CodeFixes/CSharp/Refactorings/RemoveSemicolonAtEndOfDeclarationRefactoring.cs @@ -8,7 +8,7 @@ namespace Roslynator.CSharp.Refactorings; -internal static class AvoidSemicolonAtEndOfDeclarationRefactoring +internal static class RemoveSemicolonAtEndOfDeclarationRefactoring { public static Task RefactorAsync( Document document, diff --git a/src/Analyzers.xml b/src/Analyzers.xml index 8e14a83a93..9a8276ad02 100644 --- a/src/Analyzers.xml +++ b/src/Analyzers.xml @@ -2811,9 +2811,8 @@ public void Foo() RCS1055 - AvoidSemicolonAtEndOfDeclaration - Avoid semicolon at the end of declaration. - Remove semicolon from the end of declaration. + UnnecessarySemicolonAtEndOfDeclaration + Unnecessary semicolon at the end of declaration. Hidden true true diff --git a/src/Analyzers/CSharp/Analysis/AvoidSemicolonAtEndOfDeclarationAnalyzer.cs b/src/Analyzers/CSharp/Analysis/UnnecessarySemicolonAtEndOfDeclarationAnalyzer.cs similarity index 69% rename from src/Analyzers/CSharp/Analysis/AvoidSemicolonAtEndOfDeclarationAnalyzer.cs rename to src/Analyzers/CSharp/Analysis/UnnecessarySemicolonAtEndOfDeclarationAnalyzer.cs index dab32bd137..10ded52782 100644 --- a/src/Analyzers/CSharp/Analysis/AvoidSemicolonAtEndOfDeclarationAnalyzer.cs +++ b/src/Analyzers/CSharp/Analysis/UnnecessarySemicolonAtEndOfDeclarationAnalyzer.cs @@ -9,7 +9,7 @@ namespace Roslynator.CSharp.Analysis; [DiagnosticAnalyzer(LanguageNames.CSharp)] -public sealed class AvoidSemicolonAtEndOfDeclarationAnalyzer : BaseDiagnosticAnalyzer +public sealed class UnnecessarySemicolonAtEndOfDeclarationAnalyzer : BaseDiagnosticAnalyzer { private static ImmutableArray _supportedDiagnostics; @@ -18,7 +18,7 @@ public override ImmutableArray SupportedDiagnostics get { if (_supportedDiagnostics.IsDefault) - Immutable.InterlockedInitialize(ref _supportedDiagnostics, DiagnosticRules.AvoidSemicolonAtEndOfDeclaration); + Immutable.InterlockedInitialize(ref _supportedDiagnostics, DiagnosticRules.UnnecessarySemicolonAtEndOfDeclaration); return _supportedDiagnostics; } @@ -45,7 +45,7 @@ private static void AnalyzeNamespaceDeclaration(SyntaxNodeAnalysisContext contex if (semicolon.Parent is not null && !semicolon.IsMissing) { - DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.AvoidSemicolonAtEndOfDeclaration, semicolon); + DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UnnecessarySemicolonAtEndOfDeclaration, semicolon); } } @@ -53,12 +53,15 @@ private static void AnalyzeClassDeclaration(SyntaxNodeAnalysisContext context) { var declaration = (ClassDeclarationSyntax)context.Node; - SyntaxToken semicolon = declaration.SemicolonToken; - - if (semicolon.Parent is not null - && !semicolon.IsMissing) + if (declaration.CloseBraceToken.IsKind(SyntaxKind.CloseBraceToken)) { - DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.AvoidSemicolonAtEndOfDeclaration, semicolon); + SyntaxToken semicolon = declaration.SemicolonToken; + + if (semicolon.Parent is not null + && !semicolon.IsMissing) + { + DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UnnecessarySemicolonAtEndOfDeclaration, semicolon); + } } } @@ -66,12 +69,15 @@ private static void AnalyzeInterfaceDeclaration(SyntaxNodeAnalysisContext contex { var declaration = (InterfaceDeclarationSyntax)context.Node; - SyntaxToken semicolon = declaration.SemicolonToken; - - if (semicolon.Parent is not null - && !semicolon.IsMissing) + if (declaration.CloseBraceToken.IsKind(SyntaxKind.CloseBraceToken)) { - DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.AvoidSemicolonAtEndOfDeclaration, semicolon); + SyntaxToken semicolon = declaration.SemicolonToken; + + if (semicolon.Parent is not null + && !semicolon.IsMissing) + { + DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UnnecessarySemicolonAtEndOfDeclaration, semicolon); + } } } @@ -79,12 +85,15 @@ private static void AnalyzeStructDeclaration(SyntaxNodeAnalysisContext context) { var declaration = (StructDeclarationSyntax)context.Node; - SyntaxToken semicolon = declaration.SemicolonToken; - - if (semicolon.Parent is not null - && !semicolon.IsMissing) + if (declaration.CloseBraceToken.IsKind(SyntaxKind.CloseBraceToken)) { - DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.AvoidSemicolonAtEndOfDeclaration, semicolon); + SyntaxToken semicolon = declaration.SemicolonToken; + + if (semicolon.Parent is not null + && !semicolon.IsMissing) + { + DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UnnecessarySemicolonAtEndOfDeclaration, semicolon); + } } } @@ -99,7 +108,7 @@ private static void AnalyzeRecordDeclaration(SyntaxNodeAnalysisContext context) if (semicolon.Parent is not null && !semicolon.IsMissing) { - DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.AvoidSemicolonAtEndOfDeclaration, semicolon); + DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UnnecessarySemicolonAtEndOfDeclaration, semicolon); } } } @@ -113,7 +122,7 @@ private static void AnalyzeEnumDeclaration(SyntaxNodeAnalysisContext context) if (semicolon.Parent is not null && !semicolon.IsMissing) { - DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.AvoidSemicolonAtEndOfDeclaration, semicolon); + DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UnnecessarySemicolonAtEndOfDeclaration, semicolon); } } } diff --git a/src/Analyzers/CSharp/DiagnosticIdentifiers.Generated.cs b/src/Analyzers/CSharp/DiagnosticIdentifiers.Generated.cs index 0b82d84940..dad9952e2c 100644 --- a/src/Analyzers/CSharp/DiagnosticIdentifiers.Generated.cs +++ b/src/Analyzers/CSharp/DiagnosticIdentifiers.Generated.cs @@ -48,7 +48,7 @@ public static partial class DiagnosticIdentifiers public const string IncludeParenthesesWhenCreatingNewObject = "RCS1050"; public const string AddOrRemoveParenthesesFromConditionInConditionalOperator = "RCS1051"; public const string DeclareEachAttributeSeparately = "RCS1052"; - public const string AvoidSemicolonAtEndOfDeclaration = "RCS1055"; + public const string UnnecessarySemicolonAtEndOfDeclaration = "RCS1055"; public const string AvoidUsageOfUsingAliasDirective = "RCS1056"; public const string UseCompoundAssignment = "RCS1058"; public const string AvoidLockingOnPubliclyAccessibleInstance = "RCS1059"; diff --git a/src/Analyzers/CSharp/DiagnosticRules.Generated.cs b/src/Analyzers/CSharp/DiagnosticRules.Generated.cs index 5b2157255a..494d14069a 100644 --- a/src/Analyzers/CSharp/DiagnosticRules.Generated.cs +++ b/src/Analyzers/CSharp/DiagnosticRules.Generated.cs @@ -512,15 +512,15 @@ public static partial class DiagnosticRules customTags: Array.Empty()); /// RCS1055 - public static readonly DiagnosticDescriptor AvoidSemicolonAtEndOfDeclaration = DiagnosticDescriptorFactory.Create( - id: DiagnosticIdentifiers.AvoidSemicolonAtEndOfDeclaration, - title: "Avoid semicolon at the end of declaration.", - messageFormat: "Remove semicolon from the end of declaration.", + public static readonly DiagnosticDescriptor UnnecessarySemicolonAtEndOfDeclaration = DiagnosticDescriptorFactory.Create( + id: DiagnosticIdentifiers.UnnecessarySemicolonAtEndOfDeclaration, + title: "Unnecessary semicolon at the end of declaration.", + messageFormat: "Unnecessary semicolon at the end of declaration.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Hidden, isEnabledByDefault: true, description: null, - helpLinkUri: DiagnosticIdentifiers.AvoidSemicolonAtEndOfDeclaration, + helpLinkUri: DiagnosticIdentifiers.UnnecessarySemicolonAtEndOfDeclaration, customTags: WellKnownDiagnosticTags.Unnecessary); /// RCS1056 diff --git a/src/Tests/Analyzers.Tests/RCS1055UnnecessarySemicolonAtEndOfDeclarationAnalyzerTests.cs b/src/Tests/Analyzers.Tests/RCS1055UnnecessarySemicolonAtEndOfDeclarationAnalyzerTests.cs new file mode 100644 index 0000000000..80cb0deb7f --- /dev/null +++ b/src/Tests/Analyzers.Tests/RCS1055UnnecessarySemicolonAtEndOfDeclarationAnalyzerTests.cs @@ -0,0 +1,38 @@ +// Copyright (c) .NET Foundation and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Roslynator.CSharp.CodeFixes; +using Roslynator.Testing.CSharp; +using Xunit; + +namespace Roslynator.CSharp.Analysis.Tests; + +public class RCS1055UnnecessarySemicolonAtEndOfDeclarationAnalyzerTests : AbstractCSharpDiagnosticVerifier +{ + public override DiagnosticDescriptor Descriptor { get; } = DiagnosticRules.UnnecessarySemicolonAtEndOfDeclaration; + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UnnecessarySemicolonAtEndOfDeclaration)] + public async Task TestNoDiagnostic_Class() + { + await VerifyNoDiagnosticAsync(@" +class C; +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UnnecessarySemicolonAtEndOfDeclaration)] + public async Task TestNoDiagnostic_Struct() + { + await VerifyNoDiagnosticAsync(@" +struct C; +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UnnecessarySemicolonAtEndOfDeclaration)] + public async Task TestNoDiagnostic_Interface() + { + await VerifyNoDiagnosticAsync(@" +interface C; +"); + } +} diff --git a/src/VisualStudioCode/package/src/configurationFiles.generated.ts b/src/VisualStudioCode/package/src/configurationFiles.generated.ts index 25d6d21ff5..d02bde47e6 100644 --- a/src/VisualStudioCode/package/src/configurationFiles.generated.ts +++ b/src/VisualStudioCode/package/src/configurationFiles.generated.ts @@ -414,7 +414,7 @@ roslynator_analyzers.enabled_by_default = true|false # Declare each attribute separately #dotnet_diagnostic.rcs1052.severity = none -# Avoid semicolon at the end of declaration +# Unnecessary semicolon at the end of declaration #dotnet_diagnostic.rcs1055.severity = silent # Avoid usage of using alias directive