From 7ef646adda5ac75327e57b3bca8de134a63601b2 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sat, 4 Jun 2022 16:27:23 +0200 Subject: [PATCH 01/16] Add analyzer RemoveEmptySyntax --- docs/Configuration.md | 3 + .../CodeFixes/ElseClauseCodeFixProvider.cs | 2 +- .../CodeFixes/FinallyClauseCodeFixProvider.cs | 2 +- .../RemoveEmptySyntaxCodeFixProvider.cs | 136 +++++ src/Analyzers/Analyzers.RemoveEmptySyntax.xml | 21 + .../RemoveEmptyInitializerAnalyzer.cs | 1 - .../Analysis/RemoveEmptySyntaxAnalyzer.cs | 217 ++++++++ .../CSharp/DiagnosticIdentifiers.Generated.cs | 1 + .../CSharp/DiagnosticRules.Generated.cs | 12 + .../RemoveEmptyDestructor.cs | 31 -- .../RemoveEmptyElseClause.cs | 20 - .../RemoveEmptyInitializer.cs | 38 -- .../RemoveEmptyNamespaceDeclaration.cs | 8 - .../Analyzers.Tests.Old/RemoveEmptyRegion.cs | 20 - .../RemoveRedundantEmptyStatement.cs | 12 - .../RCS1260RemoveEmptySyntaxTests.cs | 496 ++++++++++++++++++ .../src/configurationFiles.generated.ts | 3 + 17 files changed, 891 insertions(+), 132 deletions(-) create mode 100644 src/Analyzers.CodeFixes/CSharp/CodeFixes/RemoveEmptySyntaxCodeFixProvider.cs create mode 100644 src/Analyzers/Analyzers.RemoveEmptySyntax.xml create mode 100644 src/Analyzers/CSharp/Analysis/RemoveEmptySyntaxAnalyzer.cs delete mode 100644 src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyDestructor.cs delete mode 100644 src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyElseClause.cs delete mode 100644 src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyInitializer.cs delete mode 100644 src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyNamespaceDeclaration.cs delete mode 100644 src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyRegion.cs delete mode 100644 src/Tests.Old/Analyzers.Tests.Old/RemoveRedundantEmptyStatement.cs create mode 100644 src/Tests/Analyzers.Tests/RCS1260RemoveEmptySyntaxTests.cs diff --git a/docs/Configuration.md b/docs/Configuration.md index e265f9bce3..6d1d77575c 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -933,6 +933,9 @@ dotnet_diagnostic.rcs1253.severity = none dotnet_diagnostic.rcs1254.severity = suggestion # Options: roslynator_enum_flag_value_style +# Remove empty syntax +dotnet_diagnostic.rcs1260.severity = suggestion + # Use pattern matching dotnet_diagnostic.rcs9001.severity = silent diff --git a/src/Analyzers.CodeFixes/CSharp/CodeFixes/ElseClauseCodeFixProvider.cs b/src/Analyzers.CodeFixes/CSharp/CodeFixes/ElseClauseCodeFixProvider.cs index 60254503d3..93da534e2f 100644 --- a/src/Analyzers.CodeFixes/CSharp/CodeFixes/ElseClauseCodeFixProvider.cs +++ b/src/Analyzers.CodeFixes/CSharp/CodeFixes/ElseClauseCodeFixProvider.cs @@ -62,7 +62,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) } } - private static async Task RemoveEmptyElseClauseAsync( + internal static async Task RemoveEmptyElseClauseAsync( Document document, ElseClauseSyntax elseClause, CancellationToken cancellationToken) diff --git a/src/Analyzers.CodeFixes/CSharp/CodeFixes/FinallyClauseCodeFixProvider.cs b/src/Analyzers.CodeFixes/CSharp/CodeFixes/FinallyClauseCodeFixProvider.cs index 883966787f..a79bd087ed 100644 --- a/src/Analyzers.CodeFixes/CSharp/CodeFixes/FinallyClauseCodeFixProvider.cs +++ b/src/Analyzers.CodeFixes/CSharp/CodeFixes/FinallyClauseCodeFixProvider.cs @@ -38,7 +38,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) context.RegisterCodeFix(codeAction, context.Diagnostics[0]); } - private static async Task RemoveEmptyFinallyClauseAsync( + internal static async Task RemoveEmptyFinallyClauseAsync( Document document, FinallyClauseSyntax finallyClause, CancellationToken cancellationToken) diff --git a/src/Analyzers.CodeFixes/CSharp/CodeFixes/RemoveEmptySyntaxCodeFixProvider.cs b/src/Analyzers.CodeFixes/CSharp/CodeFixes/RemoveEmptySyntaxCodeFixProvider.cs new file mode 100644 index 0000000000..ec4f700fbd --- /dev/null +++ b/src/Analyzers.CodeFixes/CSharp/CodeFixes/RemoveEmptySyntaxCodeFixProvider.cs @@ -0,0 +1,136 @@ +// 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.Collections.Generic; +using System.Collections.Immutable; +using System.Composition; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Roslynator.CodeFixes; +using Roslynator.CSharp.Refactorings; + +namespace Roslynator.CSharp.CodeFixes +{ + [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(RemoveEmptySyntaxCodeFixProvider))] + [Shared] + public sealed class RemoveEmptySyntaxCodeFixProvider : BaseCodeFixProvider + { + public override ImmutableArray FixableDiagnosticIds + { + get { return ImmutableArray.Create(DiagnosticIdentifiers.RemoveEmptySyntax); } + } + + public override async Task RegisterCodeFixesAsync(CodeFixContext context) + { + SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); + + if (!TryFindFirstAncestorOrSelf( + root, + context.Span, + out SyntaxNode node, + findInsideTrivia: true, + predicate: f => + { + switch (f.Kind()) + { + case SyntaxKind.DestructorDeclaration: + case SyntaxKind.ElseClause: + case SyntaxKind.EmptyStatement: + case SyntaxKind.FinallyClause: + case SyntaxKind.NamespaceDeclaration: + case SyntaxKind.ObjectCreationExpression: + case SyntaxKind.RegionDirectiveTrivia: + return true; + default: + return false; + } + })) + { + return; + } + + Document document = context.Document; + Diagnostic diagnostic = context.Diagnostics[0]; + + switch (node) + { + case DestructorDeclarationSyntax destructorDeclaration: + { + CodeAction codeAction = CodeActionFactory.RemoveMemberDeclaration( + document, + destructorDeclaration, + title: "Remove empty destructor", + equivalenceKey: GetEquivalenceKey(diagnostic)); + + context.RegisterCodeFix(codeAction, diagnostic); + break; + } + case ElseClauseSyntax elseClause: + { + CodeAction codeAction = CodeAction.Create( + "Remove empty 'else' clause", + ct => ElseClauseCodeFixProvider.RemoveEmptyElseClauseAsync(document, elseClause, ct), + GetEquivalenceKey(diagnostic)); + + context.RegisterCodeFix(codeAction, diagnostic); + break; + } + case FinallyClauseSyntax finallyClause: + { + CodeAction codeAction = CodeAction.Create( + "Remove empty 'finally' clause", + ct => FinallyClauseCodeFixProvider.RemoveEmptyFinallyClauseAsync(document, finallyClause, ct), + equivalenceKey: GetEquivalenceKey(diagnostic)); + + context.RegisterCodeFix(codeAction, diagnostic); + break; + } + case ObjectCreationExpressionSyntax objectCreationExpression: + { + CodeAction codeAction = CodeAction.Create( + "Remove empty initializer", + ct => RemoveEmptyInitializerRefactoring.RefactorAsync(document, objectCreationExpression, ct), + GetEquivalenceKey(diagnostic)); + + context.RegisterCodeFix(codeAction, diagnostic); + break; + } + case NamespaceDeclarationSyntax namespaceDeclaration: + { + CodeAction codeAction = CodeAction.Create( + "Remove empty namespace declaration", + ct => RemoveEmptyNamespaceDeclarationRefactoring.RefactorAsync(document, namespaceDeclaration, ct), + GetEquivalenceKey(diagnostic)); + + context.RegisterCodeFix(codeAction, diagnostic); + break; + } + case RegionDirectiveTriviaSyntax regionDirective: + { + CodeAction codeAction = CodeAction.Create( + "Remove empty region", + ct => RemoveEmptyRegionRefactoring.RefactorAsync(document, SyntaxInfo.RegionInfo(regionDirective), ct), + GetEquivalenceKey(diagnostic)); + + context.RegisterCodeFix(codeAction, diagnostic); + break; + } + case EmptyStatementSyntax emptyStatement: + { + CodeAction codeAction = CodeAction.Create( + "Remove empty statement", + ct => RemoveEmptyStatementRefactoring.RefactorAsync(document, emptyStatement, ct), + GetEquivalenceKey(diagnostic)); + + context.RegisterCodeFix(codeAction, diagnostic); + break; + } + } + } + } +} diff --git a/src/Analyzers/Analyzers.RemoveEmptySyntax.xml b/src/Analyzers/Analyzers.RemoveEmptySyntax.xml new file mode 100644 index 0000000000..5aafcf6127 --- /dev/null +++ b/src/Analyzers/Analyzers.RemoveEmptySyntax.xml @@ -0,0 +1,21 @@ + + + + RCS1260 + Remove empty syntax. + Remove empty {0}. + General + Info + true + true + This analyzer reports empty syntax that can be safely removed such as: +* empty destructor +* empty 'else' clause +* empty 'finally' clause +* empty object initializer +* empty namespace declaration +* empty region directive +* empty empty statement + + + \ No newline at end of file diff --git a/src/Analyzers/CSharp/Analysis/RemoveEmptyInitializerAnalyzer.cs b/src/Analyzers/CSharp/Analysis/RemoveEmptyInitializerAnalyzer.cs index 3ed80f4697..3862459ad2 100644 --- a/src/Analyzers/CSharp/Analysis/RemoveEmptyInitializerAnalyzer.cs +++ b/src/Analyzers/CSharp/Analysis/RemoveEmptyInitializerAnalyzer.cs @@ -1,6 +1,5 @@ // 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.Immutable; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; diff --git a/src/Analyzers/CSharp/Analysis/RemoveEmptySyntaxAnalyzer.cs b/src/Analyzers/CSharp/Analysis/RemoveEmptySyntaxAnalyzer.cs new file mode 100644 index 0000000000..a60f6a829b --- /dev/null +++ b/src/Analyzers/CSharp/Analysis/RemoveEmptySyntaxAnalyzer.cs @@ -0,0 +1,217 @@ +// 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.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; +using Roslynator.CSharp.Syntax; + +namespace Roslynator.CSharp.Analysis +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + public sealed class RemoveEmptySyntaxAnalyzer : BaseDiagnosticAnalyzer + { + private static ImmutableArray _supportedDiagnostics; + + public override ImmutableArray SupportedDiagnostics + { + get + { + if (_supportedDiagnostics.IsDefault) + Immutable.InterlockedInitialize(ref _supportedDiagnostics, DiagnosticRules.RemoveEmptySyntax); + + return _supportedDiagnostics; + } + } + + public override void Initialize(AnalysisContext context) + { + base.Initialize(context); + + context.RegisterSyntaxNodeAction(f => AnalyzeDestructorDeclaration(f), SyntaxKind.DestructorDeclaration); + context.RegisterSyntaxNodeAction(f => AnalyzeElseClause(f), SyntaxKind.ElseClause); + context.RegisterSyntaxNodeAction(f => AnalyzeFinallyClause(f), SyntaxKind.FinallyClause); + context.RegisterSyntaxNodeAction(f => AnalyzeObjectCreationExpression(f), SyntaxKind.ObjectCreationExpression); + context.RegisterSyntaxNodeAction(f => AnalyzeNamespaceDeclaration(f), SyntaxKind.NamespaceDeclaration); + context.RegisterSyntaxNodeAction(f => AnalyzeRegionDirective(f), SyntaxKind.RegionDirectiveTrivia); + context.RegisterSyntaxNodeAction(f => AnalyzeEmptyStatement(f), SyntaxKind.EmptyStatement); + } + + private static void AnalyzeDestructorDeclaration(SyntaxNodeAnalysisContext context) + { + var destructor = (DestructorDeclarationSyntax)context.Node; + + if (!destructor.ContainsDiagnostics + && !destructor.ContainsUnbalancedIfElseDirectives() + && !destructor.AttributeLists.Any() + && destructor.Body?.Statements.Count == 0) + { + ReportDiagnostic(context, destructor, "destructor"); + } + } + + private static void AnalyzeElseClause(SyntaxNodeAnalysisContext context) + { + var elseClause = (ElseClauseSyntax)context.Node; + + StatementSyntax statement = elseClause.Statement; + + if (statement is not BlockSyntax block) + return; + + if (block.Statements.Any()) + return; + + IfStatementSyntax topmostIf = elseClause.GetTopmostIf(); + + if (topmostIf.Parent is IfStatementSyntax parentIf + && parentIf.Else != null) + { + return; + } + + if (!elseClause.ElseKeyword.TrailingTrivia.IsEmptyOrWhitespace()) + return; + + if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(block.OpenBraceToken)) + return; + + if (!block.CloseBraceToken.LeadingTrivia.IsEmptyOrWhitespace()) + return; + + ReportDiagnostic(context, elseClause, "'else' clause"); + } + + private static void AnalyzeFinallyClause(SyntaxNodeAnalysisContext context) + { + var finallyClause = (FinallyClauseSyntax)context.Node; + + if (finallyClause.Parent is not TryStatementSyntax tryStatement) + return; + + BlockSyntax finallyBlock = finallyClause.Block; + + if (finallyBlock?.Statements.Any() != false) + return; + + if (!finallyClause.FinallyKeyword.TrailingTrivia.IsEmptyOrWhitespace()) + return; + + if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(finallyBlock.OpenBraceToken)) + return; + + if (!finallyBlock.CloseBraceToken.LeadingTrivia.IsEmptyOrWhitespace()) + return; + + if (tryStatement.Catches.Any()) + { + ReportDiagnostic(context, finallyClause, "'finally' clause"); + } + else + { + BlockSyntax tryBlock = tryStatement.Block; + + if (tryBlock?.Statements.Any() != true) + return; + + if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(tryStatement.TryKeyword)) + return; + + if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(tryBlock.OpenBraceToken)) + return; + + if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(tryBlock.CloseBraceToken)) + return; + + if (!finallyClause.FinallyKeyword.LeadingTrivia.IsEmptyOrWhitespace()) + return; + + ReportDiagnostic(context, finallyClause, "'finally' clause"); + + //TODO: JP + //DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveEmptyFinallyClauseFadeOut, tryStatement.TryKeyword); + //DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveEmptyFinallyClauseFadeOut, tryBlock.OpenBraceToken); + //DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveEmptyFinallyClauseFadeOut, tryBlock.CloseBraceToken); + } + } + + private static void AnalyzeObjectCreationExpression(SyntaxNodeAnalysisContext context) + { + var objectCreationExpression = (ObjectCreationExpressionSyntax)context.Node; + + if (objectCreationExpression.ContainsDiagnostics) + return; + + InitializerExpressionSyntax initializer = objectCreationExpression.Initializer; + + if (initializer?.Expressions.Any() != false) + return; + + if (!initializer.OpenBraceToken.TrailingTrivia.IsEmptyOrWhitespace()) + return; + + if (!initializer.CloseBraceToken.LeadingTrivia.IsEmptyOrWhitespace()) + return; + + if (initializer.IsInExpressionTree(context.SemanticModel, context.CancellationToken)) + return; + + ReportDiagnostic(context, initializer, "initializer"); + } + + private static void AnalyzeNamespaceDeclaration(SyntaxNodeAnalysisContext context) + { + var declaration = (NamespaceDeclarationSyntax)context.Node; + + if (declaration.Members.Any()) + return; + + SyntaxToken openBrace = declaration.OpenBraceToken; + SyntaxToken closeBrace = declaration.CloseBraceToken; + + if (openBrace.IsMissing) + return; + + if (closeBrace.IsMissing) + return; + + if (!openBrace.TrailingTrivia.IsEmptyOrWhitespace()) + return; + + if (!closeBrace.LeadingTrivia.IsEmptyOrWhitespace()) + return; + + ReportDiagnostic(context, declaration, "namespace declaration"); + } + + private static void AnalyzeRegionDirective(SyntaxNodeAnalysisContext context) + { + var regionDirective = (RegionDirectiveTriviaSyntax)context.Node; + + RegionInfo region = SyntaxInfo.RegionInfo(regionDirective); + + if (region.Success + && region.IsEmpty) + { + ReportDiagnostic(context, regionDirective, "#region"); + } + } + + private static void AnalyzeEmptyStatement(SyntaxNodeAnalysisContext context) + { + SyntaxNode emptyStatement = context.Node; + + if (emptyStatement.Parent?.IsKind(SyntaxKind.LabeledStatement) == false + && !CSharpFacts.CanHaveEmbeddedStatement(emptyStatement.Parent.Kind())) + { + ReportDiagnostic(context, emptyStatement, "statement"); + } + } + + private static void ReportDiagnostic(SyntaxNodeAnalysisContext context, SyntaxNode node, string name) + { + DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveEmptySyntax, node, name); + } + } +} diff --git a/src/Analyzers/CSharp/DiagnosticIdentifiers.Generated.cs b/src/Analyzers/CSharp/DiagnosticIdentifiers.Generated.cs index 7cb72d0735..eba6a450e1 100644 --- a/src/Analyzers/CSharp/DiagnosticIdentifiers.Generated.cs +++ b/src/Analyzers/CSharp/DiagnosticIdentifiers.Generated.cs @@ -211,5 +211,6 @@ public static partial class DiagnosticIdentifiers public const string NormalizeUsageOfInfiniteLoop = "RCS1252"; public const string FormatDocumentationCommentSummary = "RCS1253"; public const string NormalizeFormatOfEnumFlagValue = "RCS1254"; + public const string RemoveEmptySyntax = "RCS1260"; } } \ No newline at end of file diff --git a/src/Analyzers/CSharp/DiagnosticRules.Generated.cs b/src/Analyzers/CSharp/DiagnosticRules.Generated.cs index 0ece7cd9fa..95599e813c 100644 --- a/src/Analyzers/CSharp/DiagnosticRules.Generated.cs +++ b/src/Analyzers/CSharp/DiagnosticRules.Generated.cs @@ -2497,5 +2497,17 @@ public static partial class DiagnosticRules helpLinkUri: DiagnosticIdentifiers.NormalizeFormatOfEnumFlagValue, customTags: Array.Empty()); + /// RCS1260 + public static readonly DiagnosticDescriptor RemoveEmptySyntax = DiagnosticDescriptorFactory.Create( + id: DiagnosticIdentifiers.RemoveEmptySyntax, + title: "Remove empty syntax.", + messageFormat: "Remove empty {0}.", + category: DiagnosticCategories.Roslynator, + defaultSeverity: DiagnosticSeverity.Info, + isEnabledByDefault: true, + description: null, + helpLinkUri: DiagnosticIdentifiers.RemoveEmptySyntax, + customTags: WellKnownDiagnosticTags.Unnecessary); + } } \ No newline at end of file diff --git a/src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyDestructor.cs b/src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyDestructor.cs deleted file mode 100644 index 959cdeb4c7..0000000000 --- a/src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyDestructor.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Josef Pihrt and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Roslynator.CSharp.Analyzers.Tests -{ - public static class RemoveEmptyDestructor - { - public class Foo - { - ~Foo() - { - } - } - - public class Foo2 - { - ~Foo2() - { -#if DEBUG - } -#endif - } - - public class Foo3 - { - ~Foo3() - { - object x = null; - } - } - } -} diff --git a/src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyElseClause.cs b/src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyElseClause.cs deleted file mode 100644 index ec5c8600e5..0000000000 --- a/src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyElseClause.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Josef Pihrt and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Roslynator.CSharp.Analyzers.Tests -{ - internal static class RemoveEmptyElseClause - { - private static void Foo() - { - bool condition = false; - - if (condition) - { - Foo(); - } - else - { - } - } - } -} diff --git a/src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyInitializer.cs b/src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyInitializer.cs deleted file mode 100644 index 0427ee4d78..0000000000 --- a/src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyInitializer.cs +++ /dev/null @@ -1,38 +0,0 @@ -// 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.Text; - -#pragma warning disable RCS1050, RCS1067 - -namespace Roslynator.CSharp.Analyzers.Tests -{ - internal static class RemoveEmptyInitializer - { - private static void Foo(StringBuilder x) - { - x = new StringBuilder() { }; - - x = new StringBuilder { }; - - x = new StringBuilder() - { - }; - - x = new StringBuilder - { - }; - - x = new StringBuilder() /**/ { }; //x - - x = new StringBuilder /**/ { }; //x - - x = new StringBuilder() //x - { - }; //x - - x = new StringBuilder //x - { - }; //x - } - } -} diff --git a/src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyNamespaceDeclaration.cs b/src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyNamespaceDeclaration.cs deleted file mode 100644 index f6e63d1bc8..0000000000 --- a/src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyNamespaceDeclaration.cs +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) Josef Pihrt and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Roslynator.CSharp.Analyzers.Tests -{ - namespace RemoveEmptyNamespaceDeclaration - { - } -} diff --git a/src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyRegion.cs b/src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyRegion.cs deleted file mode 100644 index 5155ce7640..0000000000 --- a/src/Tests.Old/Analyzers.Tests.Old/RemoveEmptyRegion.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Josef Pihrt and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Roslynator.CSharp.Analyzers.Tests -{ - internal static class RemoveEmptyRegion - { - #region Methods - public static void Foo() - #endregion - { - #region Empty - - #endregion - } - #region Empty - - - #endregion - } -} diff --git a/src/Tests.Old/Analyzers.Tests.Old/RemoveRedundantEmptyStatement.cs b/src/Tests.Old/Analyzers.Tests.Old/RemoveRedundantEmptyStatement.cs deleted file mode 100644 index aeb312d632..0000000000 --- a/src/Tests.Old/Analyzers.Tests.Old/RemoveRedundantEmptyStatement.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Josef Pihrt and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Roslynator.CSharp.Analyzers.Tests -{ - internal static class RemoveRedundantEmptyStatement - { - private static void Foo() - { - ; - } - } -} diff --git a/src/Tests/Analyzers.Tests/RCS1260RemoveEmptySyntaxTests.cs b/src/Tests/Analyzers.Tests/RCS1260RemoveEmptySyntaxTests.cs new file mode 100644 index 0000000000..517ac493a7 --- /dev/null +++ b/src/Tests/Analyzers.Tests/RCS1260RemoveEmptySyntaxTests.cs @@ -0,0 +1,496 @@ +// 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.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Roslynator.CSharp.CodeFixes; +using Roslynator.Testing.CSharp; +using Xunit; + +namespace Roslynator.CSharp.Analysis.Tests +{ + public class RCS1260RemoveEmptySyntaxTests : AbstractCSharpDiagnosticVerifier + { + public override DiagnosticDescriptor Descriptor { get; } = DiagnosticRules.RemoveEmptySyntax; + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task Test_Destructor() + { + await VerifyDiagnosticAndFixAsync(@" +class C +{ + void M() + { + } + + [|~C() + { +#if DEBUG +#endif + }|] +} +", @" +class C +{ + void M() + { + } +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task TestNoDiagnostic_Destructor_IfDirective() + { + await VerifyNoDiagnosticAsync(@" +#define A +class C +{ + ~C() + { +#if A + } +#endif +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task TestNoDiagnostic_Destructor_NotEmpty() + { + await VerifyNoDiagnosticAsync(@" +class C +{ + void M() + { + } + + ~C() + { + M(); + } +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task Test_ElseClause() + { + await VerifyDiagnosticAndFixAsync(@" +class C +{ + void M() + { + bool f = false; + + if (f) + { + } + [|else + { + }|] + } +} +", @" +class C +{ + void M() + { + bool f = false; + + if (f) + { + } + } +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task TestNoDiagnostic_ElseClause_ElseIf() + { + await VerifyNoDiagnosticAsync(@" +class C +{ + void M() + { + bool f = false; + + if (f) + { + } + else if (f) + { + } +} +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task TestNoDiagnostic_ElseClause_NonEmptyElse() + { + await VerifyNoDiagnosticAsync(@" +class C +{ + void M() + { + bool f = false; + + if (f) + { + } + else + { + M(); + } +} +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task TestNoDiagnostic_ElseClause_IfElseEmbeddedInIfWithElse() + { + await VerifyNoDiagnosticAsync(@" +class C +{ + void M() + { + bool f = false; + + if (f) + if (f) M(); else { } + else + { + M(); + } + } +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task TestNoDiagnostic_ElseClause_IfElseEmbeddedInIfWithElse2() + { + await VerifyNoDiagnosticAsync(@" +class C +{ + void M() + { + bool f = false; + + if (f) + if (f) M(); else if (f) M(); else { } + else + { + M(); + } + } +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task Test_FinallyClause_TryCatchFinally() + { + await VerifyDiagnosticAndFixAsync(@" +class C +{ + void M() + { + try + { + } + catch + { + } + [|finally + { + }|] + } +} +", @" +class C +{ + void M() + { + try + { + } + catch + { + } + } +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task Test_FinallyClause_TryFinally() + { + await VerifyDiagnosticAndFixAsync(@" +class C +{ + void M() + { + try + { + //x + M(); + M2(); + } + [|finally + { + }|] + } + + string M2() => null; +} +", @" +class C +{ + void M() + { + //x + M(); + M2(); + } + + string M2() => null; +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task TestNoDiagnostic_FinallyClause_NonEmptyFinally() + { + await VerifyNoDiagnosticAsync(@" +class C +{ + void M() + { + try + { + } + catch + { + } + finally + { + string foo = null; + } + } +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task Test_ObjectInitializer() + { + await VerifyDiagnosticAndFixAsync(@" +class C +{ + void M() + { + var x = new C [|{ }|]; + } +} +", @" +class C +{ + void M() + { + var x = new C(); + } +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task Test_ObjectInitializer2() + { + await VerifyDiagnosticAndFixAsync(@" +using System.Text; + +class C +{ + void M() + { + var x = new StringBuilder(); + + x = new StringBuilder() [|{ }|]; + + x = new StringBuilder [|{ }|]; + + x = new StringBuilder() + [|{ + }|]; + + x = new StringBuilder + [|{ + }|]; + + x = new StringBuilder() /**/ [|{ }|]; //x + + x = new StringBuilder /**/ [|{ }|]; //x + + x = new StringBuilder() //x + [|{ + }|]; //x + + x = new StringBuilder //x + [|{ + }|]; //x + } +} +", @" +using System.Text; + +class C +{ + void M() + { + var x = new StringBuilder(); + + x = new StringBuilder(); + + x = new StringBuilder(); + + x = new StringBuilder(); + + x = new StringBuilder(); + + x = new StringBuilder() /**/ ; //x + + x = new StringBuilder() /**/ ; //x + + x = new StringBuilder() //x + + ; //x + + x = new StringBuilder() //x + + ; //x + } +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task TestNoDiagnostic_ObjectInitializer_ExpressionTree() + { + await VerifyNoDiagnosticAsync(@" +using System; +using System.Linq.Expressions; + +class C +{ + public void M(Expression> e) + { + M(() => new C { }); + } +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task Test_Namespace() + { + await VerifyDiagnosticAndFixAsync(@" +using System; +using System.Linq.Expressions; + +namespace N1 +{ + class C + { + } +} + +[|namespace N2 +{ +}|] +", @" +using System; +using System.Linq.Expressions; + +namespace N1 +{ + class C + { + } +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task Test_RegionDirective() + { + await VerifyDiagnosticAndFixAsync(@" +namespace N1 +{ + class C + { +[|#region|] +#endregion + } +} +", @" +namespace N1 +{ + class C + { + } +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task Test_EmptyStatement() + { + await VerifyDiagnosticAndFixAsync(@" +namespace N1 +{ + class C + { + void M() + { + M(); + [|;|] + } + } +} +", @" +namespace N1 +{ + class C + { + void M() + { + M(); + + } + } +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task TestNoDiagnostic_EmptyStatement() + { + await VerifyNoDiagnosticAsync(@" +namespace N1 +{ + class C + { + void M(bool p) + { + if (p) + ; + } + } +} +", options: Options.AddAllowedCompilerDiagnosticId("CS0642")); + } + } +} diff --git a/src/VisualStudioCode/package/src/configurationFiles.generated.ts b/src/VisualStudioCode/package/src/configurationFiles.generated.ts index 249d8ae86d..14f71e3f92 100644 --- a/src/VisualStudioCode/package/src/configurationFiles.generated.ts +++ b/src/VisualStudioCode/package/src/configurationFiles.generated.ts @@ -905,6 +905,9 @@ roslynator_analyzers.enabled_by_default = true|false #dotnet_diagnostic.rcs1254.severity = suggestion # Options: roslynator_enum_flag_value_style +# Remove empty syntax +#dotnet_diagnostic.rcs1260.severity = suggestion + # Use pattern matching #dotnet_diagnostic.rcs9001.severity = silent From 8df36aa0790d588c70232f3e03655c1efac39ed2 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sat, 4 Jun 2022 16:38:01 +0200 Subject: [PATCH 02/16] Update Analyzers.xml --- src/Analyzers/Analyzers.xml | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Analyzers/Analyzers.xml b/src/Analyzers/Analyzers.xml index 92ead79b4c..5979331429 100644 --- a/src/Analyzers/Analyzers.xml +++ b/src/Analyzers/Analyzers.xml @@ -901,11 +901,12 @@ if (f) RCS1038 - Remove empty statement. + ([deprecated] use RCS1260 instead) Remove empty statement. Redundancy Info true true + HideFromConfiguration RCS1040 - Remove empty 'else' clause. + ([deprecated] use RCS1260 instead) Remove empty 'else' clause. Redundancy Hidden true true + HideFromConfiguration RCS1041 - Remove empty initializer. + ([deprecated] use RCS1260 instead) Remove empty initializer. Redundancy Info true true + HideFromConfiguration () { };]]> @@ -1548,12 +1551,13 @@ while (true);]]> RCS1066 - Remove empty 'finally' clause. + ([deprecated] use RCS1260 instead) Remove empty 'finally' clause. Redundancy Hidden true true true + HideFromConfiguration RCS1072 - Remove empty namespace declaration. + ([deprecated] use RCS1260 instead) Remove empty namespace declaration. Redundancy Info true true + HideFromConfiguration RCS1091 - Remove empty region. + ([deprecated] use RCS1260 instead) Remove empty region. Redundancy Hidden true true + HideFromConfiguration RCS1106 - Remove empty destructor. + ([deprecated] use RCS1260 instead) Remove empty destructor. Redundancy Info true true + HideFromConfiguration Date: Mon, 22 Aug 2022 17:56:30 +0200 Subject: [PATCH 03/16] Update --- ChangeLog.md | 9 ++++++ src/Analyzers/Analyzers.RemoveEmptySyntax.xml | 8 ++--- src/Analyzers/Analyzers.xml | 14 ++++----- .../CSharp/DiagnosticIdentifiers.Generated.cs | 2 +- .../CSharp/DiagnosticRules.Generated.cs | 30 +++++++++---------- ...ts.cs => RCS1255RemoveEmptySyntaxTests.cs} | 2 +- 6 files changed, 37 insertions(+), 28 deletions(-) rename src/Tests/Analyzers.Tests/{RCS1260RemoveEmptySyntaxTests.cs => RCS1255RemoveEmptySyntaxTests.cs} (99%) diff --git a/ChangeLog.md b/ChangeLog.md index 256a8add26..46c5202a2e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -13,6 +13,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add code fix for CS0037 ([#929](https://github.com/josefpihrt/roslynator/pull/929)). - [CLI] Generate reference documentation that can be published with Docusaurus ([#918](https://github.com/josefpihrt/roslynator/pull/918)). - `roslynator generate-doc --host docusaurus` +- Analyzer 'Remove empty syntax' ([RCS1255](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1255.md)) ([#913](https://github.com/josefpihrt/roslynator/pull/913)). + - This analyzer consolidates following existing analyzers: + - Remove empty empty statement ([RCS1038](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1038.md)) + - Remove empty 'else' clause ([RCS1040](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1040.md)) + - Remove empty object initializer ([RCS1041](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1041.md)) + - Remove empty 'finally' clause ([RCS1066](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1066.md)) + - Remove empty namespace declaration ([RCS1072](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1072.md)) + - Remove empty region directive ([RCS1091](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1091.md)) + - Remove empty destructor ([RCS1106](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1106.md)) ### Changed diff --git a/src/Analyzers/Analyzers.RemoveEmptySyntax.xml b/src/Analyzers/Analyzers.RemoveEmptySyntax.xml index 5aafcf6127..9b989a03e5 100644 --- a/src/Analyzers/Analyzers.RemoveEmptySyntax.xml +++ b/src/Analyzers/Analyzers.RemoveEmptySyntax.xml @@ -1,7 +1,7 @@ - RCS1260 + RCS1255 Remove empty syntax. Remove empty {0}. General @@ -11,11 +11,11 @@ This analyzer reports empty syntax that can be safely removed such as: * empty destructor * empty 'else' clause +* empty empty statement * empty 'finally' clause -* empty object initializer * empty namespace declaration -* empty region directive -* empty empty statement +* empty object initializer +* empty region directive \ No newline at end of file diff --git a/src/Analyzers/Analyzers.xml b/src/Analyzers/Analyzers.xml index 5979331429..e3ecb6a686 100644 --- a/src/Analyzers/Analyzers.xml +++ b/src/Analyzers/Analyzers.xml @@ -901,7 +901,7 @@ if (f) RCS1038 - ([deprecated] use RCS1260 instead) Remove empty statement. + ([deprecated] use RCS1255 instead) Remove empty statement. Redundancy Info true @@ -941,7 +941,7 @@ public void Foo() RCS1040 - ([deprecated] use RCS1260 instead) Remove empty 'else' clause. + ([deprecated] use RCS1255 instead) Remove empty 'else' clause. Redundancy Hidden true @@ -965,7 +965,7 @@ else // [|Id|] RCS1041 - ([deprecated] use RCS1260 instead) Remove empty initializer. + ([deprecated] use RCS1255 instead) Remove empty initializer. Redundancy Info true @@ -1551,7 +1551,7 @@ while (true);]]> RCS1066 - ([deprecated] use RCS1260 instead) Remove empty 'finally' clause. + ([deprecated] use RCS1255 instead) Remove empty 'finally' clause. Redundancy Hidden true @@ -1706,7 +1706,7 @@ catch (Exception ex) RCS1072 - ([deprecated] use RCS1260 instead) Remove empty namespace declaration. + ([deprecated] use RCS1255 instead) Remove empty namespace declaration. Redundancy Info true @@ -2128,7 +2128,7 @@ public string Foo // [|Id|] RCS1091 - ([deprecated] use RCS1260 instead) Remove empty region. + ([deprecated] use RCS1255 instead) Remove empty region. Redundancy Hidden true @@ -2453,7 +2453,7 @@ else RCS1106 - ([deprecated] use RCS1260 instead) Remove empty destructor. + ([deprecated] use RCS1255 instead) Remove empty destructor. Redundancy Info true diff --git a/src/Analyzers/CSharp/DiagnosticIdentifiers.Generated.cs b/src/Analyzers/CSharp/DiagnosticIdentifiers.Generated.cs index eba6a450e1..c3e9b8e822 100644 --- a/src/Analyzers/CSharp/DiagnosticIdentifiers.Generated.cs +++ b/src/Analyzers/CSharp/DiagnosticIdentifiers.Generated.cs @@ -211,6 +211,6 @@ public static partial class DiagnosticIdentifiers public const string NormalizeUsageOfInfiniteLoop = "RCS1252"; public const string FormatDocumentationCommentSummary = "RCS1253"; public const string NormalizeFormatOfEnumFlagValue = "RCS1254"; - public const string RemoveEmptySyntax = "RCS1260"; + public const string RemoveEmptySyntax = "RCS1255"; } } \ No newline at end of file diff --git a/src/Analyzers/CSharp/DiagnosticRules.Generated.cs b/src/Analyzers/CSharp/DiagnosticRules.Generated.cs index 95599e813c..31c07e29c4 100644 --- a/src/Analyzers/CSharp/DiagnosticRules.Generated.cs +++ b/src/Analyzers/CSharp/DiagnosticRules.Generated.cs @@ -340,8 +340,8 @@ public static partial class DiagnosticRules /// RCS1038 public static readonly DiagnosticDescriptor RemoveEmptyStatement = DiagnosticDescriptorFactory.Create( id: DiagnosticIdentifiers.RemoveEmptyStatement, - title: "Remove empty statement.", - messageFormat: "Remove empty statement.", + title: "([deprecated] use RCS1255 instead) Remove empty statement.", + messageFormat: "([deprecated] use RCS1255 instead) Remove empty statement.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Info, isEnabledByDefault: true, @@ -364,8 +364,8 @@ public static partial class DiagnosticRules /// RCS1040 public static readonly DiagnosticDescriptor RemoveEmptyElseClause = DiagnosticDescriptorFactory.Create( id: DiagnosticIdentifiers.RemoveEmptyElseClause, - title: "Remove empty 'else' clause.", - messageFormat: "Remove empty 'else' clause.", + title: "([deprecated] use RCS1255 instead) Remove empty 'else' clause.", + messageFormat: "([deprecated] use RCS1255 instead) Remove empty 'else' clause.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Hidden, isEnabledByDefault: true, @@ -376,8 +376,8 @@ public static partial class DiagnosticRules /// RCS1041 public static readonly DiagnosticDescriptor RemoveEmptyInitializer = DiagnosticDescriptorFactory.Create( id: DiagnosticIdentifiers.RemoveEmptyInitializer, - title: "Remove empty initializer.", - messageFormat: "Remove empty initializer.", + title: "([deprecated] use RCS1255 instead) Remove empty initializer.", + messageFormat: "([deprecated] use RCS1255 instead) Remove empty initializer.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Info, isEnabledByDefault: true, @@ -626,8 +626,8 @@ public static partial class DiagnosticRules /// RCS1066 public static readonly DiagnosticDescriptor RemoveEmptyFinallyClause = DiagnosticDescriptorFactory.Create( id: DiagnosticIdentifiers.RemoveEmptyFinallyClause, - title: "Remove empty 'finally' clause.", - messageFormat: "Remove empty 'finally' clause.", + title: "([deprecated] use RCS1255 instead) Remove empty 'finally' clause.", + messageFormat: "([deprecated] use RCS1255 instead) Remove empty 'finally' clause.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Hidden, isEnabledByDefault: true, @@ -688,8 +688,8 @@ public static partial class DiagnosticRules /// RCS1072 public static readonly DiagnosticDescriptor RemoveEmptyNamespaceDeclaration = DiagnosticDescriptorFactory.Create( id: DiagnosticIdentifiers.RemoveEmptyNamespaceDeclaration, - title: "Remove empty namespace declaration.", - messageFormat: "Remove empty namespace declaration.", + title: "([deprecated] use RCS1255 instead) Remove empty namespace declaration.", + messageFormat: "([deprecated] use RCS1255 instead) Remove empty namespace declaration.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Info, isEnabledByDefault: true, @@ -850,8 +850,8 @@ public static partial class DiagnosticRules /// RCS1091 public static readonly DiagnosticDescriptor RemoveEmptyRegion = DiagnosticDescriptorFactory.Create( id: DiagnosticIdentifiers.RemoveEmptyRegion, - title: "Remove empty region.", - messageFormat: "Remove empty region.", + title: "([deprecated] use RCS1255 instead) Remove empty region.", + messageFormat: "([deprecated] use RCS1255 instead) Remove empty region.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Hidden, isEnabledByDefault: true, @@ -1008,8 +1008,8 @@ public static partial class DiagnosticRules /// RCS1106 public static readonly DiagnosticDescriptor RemoveEmptyDestructor = DiagnosticDescriptorFactory.Create( id: DiagnosticIdentifiers.RemoveEmptyDestructor, - title: "Remove empty destructor.", - messageFormat: "Remove empty destructor.", + title: "([deprecated] use RCS1255 instead) Remove empty destructor.", + messageFormat: "([deprecated] use RCS1255 instead) Remove empty destructor.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Info, isEnabledByDefault: true, @@ -2497,7 +2497,7 @@ public static partial class DiagnosticRules helpLinkUri: DiagnosticIdentifiers.NormalizeFormatOfEnumFlagValue, customTags: Array.Empty()); - /// RCS1260 + /// RCS1255 public static readonly DiagnosticDescriptor RemoveEmptySyntax = DiagnosticDescriptorFactory.Create( id: DiagnosticIdentifiers.RemoveEmptySyntax, title: "Remove empty syntax.", diff --git a/src/Tests/Analyzers.Tests/RCS1260RemoveEmptySyntaxTests.cs b/src/Tests/Analyzers.Tests/RCS1255RemoveEmptySyntaxTests.cs similarity index 99% rename from src/Tests/Analyzers.Tests/RCS1260RemoveEmptySyntaxTests.cs rename to src/Tests/Analyzers.Tests/RCS1255RemoveEmptySyntaxTests.cs index 517ac493a7..7d9735528f 100644 --- a/src/Tests/Analyzers.Tests/RCS1260RemoveEmptySyntaxTests.cs +++ b/src/Tests/Analyzers.Tests/RCS1255RemoveEmptySyntaxTests.cs @@ -8,7 +8,7 @@ namespace Roslynator.CSharp.Analysis.Tests { - public class RCS1260RemoveEmptySyntaxTests : AbstractCSharpDiagnosticVerifier + public class RCS1255RemoveEmptySyntaxTests : AbstractCSharpDiagnosticVerifier { public override DiagnosticDescriptor Descriptor { get; } = DiagnosticRules.RemoveEmptySyntax; From ed8af3b8b9a0a6e8d075c1660e5720cd4d1a13ef Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Mon, 22 Aug 2022 17:59:56 +0200 Subject: [PATCH 04/16] Disable by default --- src/Analyzers/Analyzers.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Analyzers/Analyzers.xml b/src/Analyzers/Analyzers.xml index e3ecb6a686..4b382f9384 100644 --- a/src/Analyzers/Analyzers.xml +++ b/src/Analyzers/Analyzers.xml @@ -904,7 +904,7 @@ if (f) ([deprecated] use RCS1255 instead) Remove empty statement. Redundancy Info - true + false true HideFromConfiguration @@ -944,7 +944,7 @@ public void Foo() ([deprecated] use RCS1255 instead) Remove empty 'else' clause. Redundancy Hidden - true + false true HideFromConfiguration @@ -968,7 +968,7 @@ else // [|Id|] ([deprecated] use RCS1255 instead) Remove empty initializer. Redundancy Info - true + false true HideFromConfiguration @@ -1554,7 +1554,7 @@ while (true);]]> ([deprecated] use RCS1255 instead) Remove empty 'finally' clause. Redundancy Hidden - true + false true true HideFromConfiguration @@ -1709,7 +1709,7 @@ catch (Exception ex) ([deprecated] use RCS1255 instead) Remove empty namespace declaration. Redundancy Info - true + false true HideFromConfiguration @@ -2131,7 +2131,7 @@ public string Foo // [|Id|] ([deprecated] use RCS1255 instead) Remove empty region. Redundancy Hidden - true + false true HideFromConfiguration @@ -2456,7 +2456,7 @@ else ([deprecated] use RCS1255 instead) Remove empty destructor. Redundancy Info - true + false true HideFromConfiguration From aef06c89417260f64e6aaeceb39a4ccc6e06754e Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sun, 6 Nov 2022 13:51:28 +0100 Subject: [PATCH 05/16] update --- docs/Configuration.md | 23 +------------------ .../CSharp/DiagnosticRules.Generated.cs | 14 +++++------ .../src/configurationFiles.generated.ts | 23 +------------------ 3 files changed, 9 insertions(+), 51 deletions(-) diff --git a/docs/Configuration.md b/docs/Configuration.md index d3819a0c51..8dcc13bf47 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -408,18 +408,9 @@ dotnet_diagnostic.rcs1036.severity = suggestion # Remove trailing white-space dotnet_diagnostic.rcs1037.severity = suggestion -# Remove empty statement -dotnet_diagnostic.rcs1038.severity = suggestion - # Remove argument list from attribute dotnet_diagnostic.rcs1039.severity = silent -# Remove empty 'else' clause -dotnet_diagnostic.rcs1040.severity = silent - -# Remove empty initializer -dotnet_diagnostic.rcs1041.severity = suggestion - # Remove enum default underlying type dotnet_diagnostic.rcs1042.severity = silent @@ -470,9 +461,6 @@ dotnet_diagnostic.rcs1060.severity = none # Merge 'if' with nested 'if' dotnet_diagnostic.rcs1061.severity = silent -# Remove empty 'finally' clause -dotnet_diagnostic.rcs1066.severity = silent - # Simplify logical negation dotnet_diagnostic.rcs1068.severity = suggestion @@ -485,9 +473,6 @@ dotnet_diagnostic.rcs1070.severity = silent # Remove redundant base constructor call dotnet_diagnostic.rcs1071.severity = silent -# Remove empty namespace declaration -dotnet_diagnostic.rcs1072.severity = suggestion - # Convert 'if' to 'return' statement dotnet_diagnostic.rcs1073.severity = suggestion @@ -526,9 +511,6 @@ dotnet_diagnostic.rcs1089.severity = suggestion dotnet_diagnostic.rcs1090.severity = none # Options: roslynator_configure_await -# Remove empty region -dotnet_diagnostic.rcs1091.severity = silent - # Remove file with no code dotnet_diagnostic.rcs1093.severity = suggestion @@ -560,9 +542,6 @@ dotnet_diagnostic.rcs1104.severity = suggestion # Unnecessary interpolation dotnet_diagnostic.rcs1105.severity = suggestion -# Remove empty destructor -dotnet_diagnostic.rcs1106.severity = suggestion - # Remove redundant 'ToCharArray' call dotnet_diagnostic.rcs1107.severity = suggestion @@ -934,7 +913,7 @@ dotnet_diagnostic.rcs1254.severity = suggestion # Options: roslynator_enum_flag_value_style # Remove empty syntax -dotnet_diagnostic.rcs1260.severity = suggestion +dotnet_diagnostic.rcs1255.severity = suggestion # Use pattern matching dotnet_diagnostic.rcs9001.severity = silent diff --git a/src/Analyzers/CSharp/DiagnosticRules.Generated.cs b/src/Analyzers/CSharp/DiagnosticRules.Generated.cs index 31c07e29c4..81ab4f454a 100644 --- a/src/Analyzers/CSharp/DiagnosticRules.Generated.cs +++ b/src/Analyzers/CSharp/DiagnosticRules.Generated.cs @@ -344,7 +344,7 @@ public static partial class DiagnosticRules messageFormat: "([deprecated] use RCS1255 instead) Remove empty statement.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Info, - isEnabledByDefault: true, + isEnabledByDefault: false, description: null, helpLinkUri: DiagnosticIdentifiers.RemoveEmptyStatement, customTags: WellKnownDiagnosticTags.Unnecessary); @@ -368,7 +368,7 @@ public static partial class DiagnosticRules messageFormat: "([deprecated] use RCS1255 instead) Remove empty 'else' clause.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Hidden, - isEnabledByDefault: true, + isEnabledByDefault: false, description: null, helpLinkUri: DiagnosticIdentifiers.RemoveEmptyElseClause, customTags: WellKnownDiagnosticTags.Unnecessary); @@ -380,7 +380,7 @@ public static partial class DiagnosticRules messageFormat: "([deprecated] use RCS1255 instead) Remove empty initializer.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Info, - isEnabledByDefault: true, + isEnabledByDefault: false, description: null, helpLinkUri: DiagnosticIdentifiers.RemoveEmptyInitializer, customTags: WellKnownDiagnosticTags.Unnecessary); @@ -630,7 +630,7 @@ public static partial class DiagnosticRules messageFormat: "([deprecated] use RCS1255 instead) Remove empty 'finally' clause.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Hidden, - isEnabledByDefault: true, + isEnabledByDefault: false, description: null, helpLinkUri: DiagnosticIdentifiers.RemoveEmptyFinallyClause, customTags: WellKnownDiagnosticTags.Unnecessary); @@ -692,7 +692,7 @@ public static partial class DiagnosticRules messageFormat: "([deprecated] use RCS1255 instead) Remove empty namespace declaration.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Info, - isEnabledByDefault: true, + isEnabledByDefault: false, description: null, helpLinkUri: DiagnosticIdentifiers.RemoveEmptyNamespaceDeclaration, customTags: WellKnownDiagnosticTags.Unnecessary); @@ -854,7 +854,7 @@ public static partial class DiagnosticRules messageFormat: "([deprecated] use RCS1255 instead) Remove empty region.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Hidden, - isEnabledByDefault: true, + isEnabledByDefault: false, description: null, helpLinkUri: DiagnosticIdentifiers.RemoveEmptyRegion, customTags: Array.Empty()); @@ -1012,7 +1012,7 @@ public static partial class DiagnosticRules messageFormat: "([deprecated] use RCS1255 instead) Remove empty destructor.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Info, - isEnabledByDefault: true, + isEnabledByDefault: false, description: null, helpLinkUri: DiagnosticIdentifiers.RemoveEmptyDestructor, customTags: WellKnownDiagnosticTags.Unnecessary); diff --git a/src/VisualStudioCode/package/src/configurationFiles.generated.ts b/src/VisualStudioCode/package/src/configurationFiles.generated.ts index 14f71e3f92..56c4cc3d8a 100644 --- a/src/VisualStudioCode/package/src/configurationFiles.generated.ts +++ b/src/VisualStudioCode/package/src/configurationFiles.generated.ts @@ -380,18 +380,9 @@ roslynator_analyzers.enabled_by_default = true|false # Remove trailing white-space #dotnet_diagnostic.rcs1037.severity = suggestion -# Remove empty statement -#dotnet_diagnostic.rcs1038.severity = suggestion - # Remove argument list from attribute #dotnet_diagnostic.rcs1039.severity = silent -# Remove empty 'else' clause -#dotnet_diagnostic.rcs1040.severity = silent - -# Remove empty initializer -#dotnet_diagnostic.rcs1041.severity = suggestion - # Remove enum default underlying type #dotnet_diagnostic.rcs1042.severity = silent @@ -442,9 +433,6 @@ roslynator_analyzers.enabled_by_default = true|false # Merge 'if' with nested 'if' #dotnet_diagnostic.rcs1061.severity = silent -# Remove empty 'finally' clause -#dotnet_diagnostic.rcs1066.severity = silent - # Simplify logical negation #dotnet_diagnostic.rcs1068.severity = suggestion @@ -457,9 +445,6 @@ roslynator_analyzers.enabled_by_default = true|false # Remove redundant base constructor call #dotnet_diagnostic.rcs1071.severity = silent -# Remove empty namespace declaration -#dotnet_diagnostic.rcs1072.severity = suggestion - # Convert 'if' to 'return' statement #dotnet_diagnostic.rcs1073.severity = suggestion @@ -498,9 +483,6 @@ roslynator_analyzers.enabled_by_default = true|false #dotnet_diagnostic.rcs1090.severity = none # Options: roslynator_configure_await -# Remove empty region -#dotnet_diagnostic.rcs1091.severity = silent - # Remove file with no code #dotnet_diagnostic.rcs1093.severity = suggestion @@ -532,9 +514,6 @@ roslynator_analyzers.enabled_by_default = true|false # Unnecessary interpolation #dotnet_diagnostic.rcs1105.severity = suggestion -# Remove empty destructor -#dotnet_diagnostic.rcs1106.severity = suggestion - # Remove redundant 'ToCharArray' call #dotnet_diagnostic.rcs1107.severity = suggestion @@ -906,7 +885,7 @@ roslynator_analyzers.enabled_by_default = true|false # Options: roslynator_enum_flag_value_style # Remove empty syntax -#dotnet_diagnostic.rcs1260.severity = suggestion +#dotnet_diagnostic.rcs1255.severity = suggestion # Use pattern matching #dotnet_diagnostic.rcs9001.severity = silent From 5e1cd65afdbe84128822612b5bc9cbc6ff5c0212 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sat, 19 Nov 2022 15:55:51 +0100 Subject: [PATCH 06/16] update --- .../CSharp/CodeFixes/ElseClauseCodeFixProvider.cs | 2 +- .../CSharp/CodeFixes/FinallyClauseCodeFixProvider.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Analyzers.CodeFixes/CSharp/CodeFixes/ElseClauseCodeFixProvider.cs b/src/Analyzers.CodeFixes/CSharp/CodeFixes/ElseClauseCodeFixProvider.cs index ee758ba8b2..ff1fd349d7 100644 --- a/src/Analyzers.CodeFixes/CSharp/CodeFixes/ElseClauseCodeFixProvider.cs +++ b/src/Analyzers.CodeFixes/CSharp/CodeFixes/ElseClauseCodeFixProvider.cs @@ -62,7 +62,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) } } - private static async Task RemoveEmptyElseClauseAsync( + internal static async Task RemoveEmptyElseClauseAsync( Document document, ElseClauseSyntax elseClause, CancellationToken cancellationToken) diff --git a/src/Analyzers.CodeFixes/CSharp/CodeFixes/FinallyClauseCodeFixProvider.cs b/src/Analyzers.CodeFixes/CSharp/CodeFixes/FinallyClauseCodeFixProvider.cs index 8aa176ceb0..1859f99b28 100644 --- a/src/Analyzers.CodeFixes/CSharp/CodeFixes/FinallyClauseCodeFixProvider.cs +++ b/src/Analyzers.CodeFixes/CSharp/CodeFixes/FinallyClauseCodeFixProvider.cs @@ -38,7 +38,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) context.RegisterCodeFix(codeAction, context.Diagnostics[0]); } - private static async Task RemoveEmptyFinallyClauseAsync( + internal static async Task RemoveEmptyFinallyClauseAsync( Document document, FinallyClauseSyntax finallyClause, CancellationToken cancellationToken) From 981dddeba376c43581b80d0a64ed59d5ba43b598 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sun, 18 Dec 2022 11:22:10 +0100 Subject: [PATCH 07/16] update --- ChangeLog.md | 21 +++++++++------- docs/Configuration.md | 6 ++--- src/Analyzers/Analyzers.RemoveEmptySyntax.xml | 17 +++++++++---- .../CSharp/DiagnosticIdentifiers.Generated.cs | 2 +- .../CSharp/DiagnosticRules.Generated.cs | 24 +++++++++---------- ...ts.cs => RCS1257RemoveEmptySyntaxTests.cs} | 2 +- .../src/configurationFiles.generated.ts | 6 ++--- 7 files changed, 45 insertions(+), 33 deletions(-) rename src/Tests/Analyzers.Tests/{RCS1255RemoveEmptySyntaxTests.cs => RCS1257RemoveEmptySyntaxTests.cs} (99%) diff --git a/ChangeLog.md b/ChangeLog.md index 66350d817a..518811ba89 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Analyzer 'Remove empty syntax' ([RCS1257](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1257.md)) ([#913](https://github.com/josefpihrt/roslynator/pull/913)). + - This analyzer replaces following analyzers: + - Remove empty empty statement ([RCS1038](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1038.md)) + - Remove empty 'else' clause ([RCS1040](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1040.md)) + - Remove empty object initializer ([RCS1041](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1041.md)) + - Remove empty 'finally' clause ([RCS1066](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1066.md)) + - Remove empty namespace declaration ([RCS1072](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1072.md)) + - Remove empty region directive ([RCS1091](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1091.md)) + - Remove empty destructor ([RCS1106](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1106.md)) + ### Fixed - Fix [RCS1084](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1084.md) ([#1006](https://github.com/josefpihrt/roslynator/pull/1006)). @@ -31,15 +43,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - annotated as nullable reference type. - optional and its default value is `null`. - Add package `Roslynator.Testing.CSharp.MSTest` ([#997](https://github.com/JosefPihrt/Roslynator/pull/997)). -- Analyzer 'Remove empty syntax' ([RCS1255](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1255.md)) ([#913](https://github.com/josefpihrt/roslynator/pull/913)). - - This analyzer consolidates following existing analyzers: - - Remove empty empty statement ([RCS1038](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1038.md)) - - Remove empty 'else' clause ([RCS1040](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1040.md)) - - Remove empty object initializer ([RCS1041](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1041.md)) - - Remove empty 'finally' clause ([RCS1066](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1066.md)) - - Remove empty namespace declaration ([RCS1072](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1072.md)) - - Remove empty region directive ([RCS1091](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1091.md)) - - Remove empty destructor ([RCS1106](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1106.md)) ### Changed diff --git a/docs/Configuration.md b/docs/Configuration.md index ca8ae41306..28f1563b90 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -922,12 +922,12 @@ dotnet_diagnostic.rcs1254.severity = suggestion # Simplify argument null check dotnet_diagnostic.rcs1255.severity = none -# Remove empty syntax -dotnet_diagnostic.rcs1255.severity = suggestion - # Invalid argument null check dotnet_diagnostic.rcs1256.severity = suggestion +# Remove empty syntax +dotnet_diagnostic.rcs1257.severity = suggestion + # Use pattern matching dotnet_diagnostic.rcs9001.severity = silent diff --git a/src/Analyzers/Analyzers.RemoveEmptySyntax.xml b/src/Analyzers/Analyzers.RemoveEmptySyntax.xml index 9b989a03e5..fa9d4d116e 100644 --- a/src/Analyzers/Analyzers.RemoveEmptySyntax.xml +++ b/src/Analyzers/Analyzers.RemoveEmptySyntax.xml @@ -1,21 +1,30 @@ - RCS1255 + RCS1257 Remove empty syntax. Remove empty {0}. General Info true true - This analyzer reports empty syntax that can be safely removed such as: + This analyzer reports unnecessary syntax that can be safely removed such as: * empty destructor * empty 'else' clause * empty empty statement * empty 'finally' clause * empty namespace declaration * empty object initializer -* empty region directive - +* empty region directive + + This analyzer replaces following analyzers: +* Remove empty empty statement ([RCS1038](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1038.md)) +* Remove empty 'else' clause ([RCS1040](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1040.md)) +* Remove empty object initializer ([RCS1041](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1041.md)) +* Remove empty 'finally' clause ([RCS1066](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1066.md)) +* Remove empty namespace declaration ([RCS1072](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1072.md)) +* Remove empty region directive ([RCS1091](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1091.md)) +* Remove empty destructor ([RCS1106](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1106.md)) + \ No newline at end of file diff --git a/src/Analyzers/CSharp/DiagnosticIdentifiers.Generated.cs b/src/Analyzers/CSharp/DiagnosticIdentifiers.Generated.cs index 1e0e10daa8..ec326d5f1c 100644 --- a/src/Analyzers/CSharp/DiagnosticIdentifiers.Generated.cs +++ b/src/Analyzers/CSharp/DiagnosticIdentifiers.Generated.cs @@ -213,6 +213,6 @@ public static partial class DiagnosticIdentifiers public const string NormalizeFormatOfEnumFlagValue = "RCS1254"; public const string SimplifyArgumentNullCheck = "RCS1255"; public const string InvalidArgumentNullCheck = "RCS1256"; - public const string RemoveEmptySyntax = "RCS1255"; + public const string RemoveEmptySyntax = "RCS1257"; } } \ No newline at end of file diff --git a/src/Analyzers/CSharp/DiagnosticRules.Generated.cs b/src/Analyzers/CSharp/DiagnosticRules.Generated.cs index 47ea8e6e0a..17cd6c89e4 100644 --- a/src/Analyzers/CSharp/DiagnosticRules.Generated.cs +++ b/src/Analyzers/CSharp/DiagnosticRules.Generated.cs @@ -2509,18 +2509,6 @@ public static partial class DiagnosticRules helpLinkUri: DiagnosticIdentifiers.SimplifyArgumentNullCheck, customTags: Array.Empty()); - /// RCS1255 - public static readonly DiagnosticDescriptor RemoveEmptySyntax = DiagnosticDescriptorFactory.Create( - id: DiagnosticIdentifiers.RemoveEmptySyntax, - title: "Remove empty syntax.", - messageFormat: "Remove empty {0}.", - category: DiagnosticCategories.Roslynator, - defaultSeverity: DiagnosticSeverity.Info, - isEnabledByDefault: true, - description: null, - helpLinkUri: DiagnosticIdentifiers.RemoveEmptySyntax, - customTags: WellKnownDiagnosticTags.Unnecessary); - /// RCS1256 public static readonly DiagnosticDescriptor InvalidArgumentNullCheck = DiagnosticDescriptorFactory.Create( id: DiagnosticIdentifiers.InvalidArgumentNullCheck, @@ -2533,5 +2521,17 @@ public static partial class DiagnosticRules helpLinkUri: DiagnosticIdentifiers.InvalidArgumentNullCheck, customTags: Array.Empty()); + /// RCS1257 + public static readonly DiagnosticDescriptor RemoveEmptySyntax = DiagnosticDescriptorFactory.Create( + id: DiagnosticIdentifiers.RemoveEmptySyntax, + title: "Remove empty syntax.", + messageFormat: "Remove empty {0}.", + category: DiagnosticCategories.Roslynator, + defaultSeverity: DiagnosticSeverity.Info, + isEnabledByDefault: true, + description: null, + helpLinkUri: DiagnosticIdentifiers.RemoveEmptySyntax, + customTags: WellKnownDiagnosticTags.Unnecessary); + } } \ No newline at end of file diff --git a/src/Tests/Analyzers.Tests/RCS1255RemoveEmptySyntaxTests.cs b/src/Tests/Analyzers.Tests/RCS1257RemoveEmptySyntaxTests.cs similarity index 99% rename from src/Tests/Analyzers.Tests/RCS1255RemoveEmptySyntaxTests.cs rename to src/Tests/Analyzers.Tests/RCS1257RemoveEmptySyntaxTests.cs index 7d9735528f..7d1ff78cbb 100644 --- a/src/Tests/Analyzers.Tests/RCS1255RemoveEmptySyntaxTests.cs +++ b/src/Tests/Analyzers.Tests/RCS1257RemoveEmptySyntaxTests.cs @@ -8,7 +8,7 @@ namespace Roslynator.CSharp.Analysis.Tests { - public class RCS1255RemoveEmptySyntaxTests : AbstractCSharpDiagnosticVerifier + public class RCS1257RemoveEmptySyntaxTests : AbstractCSharpDiagnosticVerifier { public override DiagnosticDescriptor Descriptor { get; } = DiagnosticRules.RemoveEmptySyntax; diff --git a/src/VisualStudioCode/package/src/configurationFiles.generated.ts b/src/VisualStudioCode/package/src/configurationFiles.generated.ts index 4b3d530eaa..c780080383 100644 --- a/src/VisualStudioCode/package/src/configurationFiles.generated.ts +++ b/src/VisualStudioCode/package/src/configurationFiles.generated.ts @@ -894,12 +894,12 @@ roslynator_analyzers.enabled_by_default = true|false # Simplify argument null check #dotnet_diagnostic.rcs1255.severity = none -# Remove empty syntax -#dotnet_diagnostic.rcs1255.severity = suggestion - # Invalid argument null check #dotnet_diagnostic.rcs1256.severity = suggestion +# Remove empty syntax +#dotnet_diagnostic.rcs1257.severity = suggestion + # Use pattern matching #dotnet_diagnostic.rcs9001.severity = silent From d61a4a263753daeed5b08c3e4d4bb24068de6422 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sun, 16 Jul 2023 13:39:05 +0200 Subject: [PATCH 08/16] fixes --- .../RemoveEmptySyntaxCodeFixProvider.cs | 205 ++++++------ .../Analysis/RemoveEmptySyntaxAnalyzer.cs | 291 +++++++++--------- .../RCS1257RemoveEmptySyntaxTests.cs | 187 ++++++----- 3 files changed, 340 insertions(+), 343 deletions(-) diff --git a/src/Analyzers.CodeFixes/CSharp/CodeFixes/RemoveEmptySyntaxCodeFixProvider.cs b/src/Analyzers.CodeFixes/CSharp/CodeFixes/RemoveEmptySyntaxCodeFixProvider.cs index ec4f700fbd..d9b3ee604b 100644 --- a/src/Analyzers.CodeFixes/CSharp/CodeFixes/RemoveEmptySyntaxCodeFixProvider.cs +++ b/src/Analyzers.CodeFixes/CSharp/CodeFixes/RemoveEmptySyntaxCodeFixProvider.cs @@ -14,123 +14,122 @@ using Roslynator.CodeFixes; using Roslynator.CSharp.Refactorings; -namespace Roslynator.CSharp.CodeFixes +namespace Roslynator.CSharp.CodeFixes; + +[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(RemoveEmptySyntaxCodeFixProvider))] +[Shared] +public sealed class RemoveEmptySyntaxCodeFixProvider : BaseCodeFixProvider { - [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(RemoveEmptySyntaxCodeFixProvider))] - [Shared] - public sealed class RemoveEmptySyntaxCodeFixProvider : BaseCodeFixProvider + public override ImmutableArray FixableDiagnosticIds { - public override ImmutableArray FixableDiagnosticIds - { - get { return ImmutableArray.Create(DiagnosticIdentifiers.RemoveEmptySyntax); } - } + get { return ImmutableArray.Create(DiagnosticIdentifiers.RemoveEmptySyntax); } + } - public override async Task RegisterCodeFixesAsync(CodeFixContext context) - { - SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); + public override async Task RegisterCodeFixesAsync(CodeFixContext context) + { + SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); - if (!TryFindFirstAncestorOrSelf( - root, - context.Span, - out SyntaxNode node, - findInsideTrivia: true, - predicate: f => - { - switch (f.Kind()) - { - case SyntaxKind.DestructorDeclaration: - case SyntaxKind.ElseClause: - case SyntaxKind.EmptyStatement: - case SyntaxKind.FinallyClause: - case SyntaxKind.NamespaceDeclaration: - case SyntaxKind.ObjectCreationExpression: - case SyntaxKind.RegionDirectiveTrivia: - return true; - default: - return false; - } - })) + if (!TryFindFirstAncestorOrSelf( + root, + context.Span, + out SyntaxNode node, + findInsideTrivia: true, + predicate: f => { - return; - } + switch (f.Kind()) + { + case SyntaxKind.DestructorDeclaration: + case SyntaxKind.ElseClause: + case SyntaxKind.EmptyStatement: + case SyntaxKind.FinallyClause: + case SyntaxKind.NamespaceDeclaration: + case SyntaxKind.ObjectCreationExpression: + case SyntaxKind.RegionDirectiveTrivia: + return true; + default: + return false; + } + })) + { + return; + } - Document document = context.Document; - Diagnostic diagnostic = context.Diagnostics[0]; + Document document = context.Document; + Diagnostic diagnostic = context.Diagnostics[0]; - switch (node) - { - case DestructorDeclarationSyntax destructorDeclaration: - { - CodeAction codeAction = CodeActionFactory.RemoveMemberDeclaration( - document, - destructorDeclaration, - title: "Remove empty destructor", - equivalenceKey: GetEquivalenceKey(diagnostic)); + switch (node) + { + case DestructorDeclarationSyntax destructorDeclaration: + { + CodeAction codeAction = CodeActionFactory.RemoveMemberDeclaration( + document, + destructorDeclaration, + title: "Remove empty destructor", + equivalenceKey: GetEquivalenceKey(diagnostic)); - context.RegisterCodeFix(codeAction, diagnostic); - break; - } - case ElseClauseSyntax elseClause: - { - CodeAction codeAction = CodeAction.Create( - "Remove empty 'else' clause", - ct => ElseClauseCodeFixProvider.RemoveEmptyElseClauseAsync(document, elseClause, ct), - GetEquivalenceKey(diagnostic)); + context.RegisterCodeFix(codeAction, diagnostic); + break; + } + case ElseClauseSyntax elseClause: + { + CodeAction codeAction = CodeAction.Create( + "Remove empty 'else' clause", + ct => ElseClauseCodeFixProvider.RemoveEmptyElseClauseAsync(document, elseClause, ct), + GetEquivalenceKey(diagnostic)); - context.RegisterCodeFix(codeAction, diagnostic); - break; - } - case FinallyClauseSyntax finallyClause: - { - CodeAction codeAction = CodeAction.Create( - "Remove empty 'finally' clause", - ct => FinallyClauseCodeFixProvider.RemoveEmptyFinallyClauseAsync(document, finallyClause, ct), - equivalenceKey: GetEquivalenceKey(diagnostic)); + context.RegisterCodeFix(codeAction, diagnostic); + break; + } + case FinallyClauseSyntax finallyClause: + { + CodeAction codeAction = CodeAction.Create( + "Remove empty 'finally' clause", + ct => FinallyClauseCodeFixProvider.RemoveEmptyFinallyClauseAsync(document, finallyClause, ct), + equivalenceKey: GetEquivalenceKey(diagnostic)); - context.RegisterCodeFix(codeAction, diagnostic); - break; - } - case ObjectCreationExpressionSyntax objectCreationExpression: - { - CodeAction codeAction = CodeAction.Create( - "Remove empty initializer", - ct => RemoveEmptyInitializerRefactoring.RefactorAsync(document, objectCreationExpression, ct), - GetEquivalenceKey(diagnostic)); + context.RegisterCodeFix(codeAction, diagnostic); + break; + } + case ObjectCreationExpressionSyntax objectCreationExpression: + { + CodeAction codeAction = CodeAction.Create( + "Remove empty initializer", + ct => RemoveEmptyInitializerRefactoring.RefactorAsync(document, objectCreationExpression, ct), + GetEquivalenceKey(diagnostic)); - context.RegisterCodeFix(codeAction, diagnostic); - break; - } - case NamespaceDeclarationSyntax namespaceDeclaration: - { - CodeAction codeAction = CodeAction.Create( - "Remove empty namespace declaration", - ct => RemoveEmptyNamespaceDeclarationRefactoring.RefactorAsync(document, namespaceDeclaration, ct), - GetEquivalenceKey(diagnostic)); + context.RegisterCodeFix(codeAction, diagnostic); + break; + } + case NamespaceDeclarationSyntax namespaceDeclaration: + { + CodeAction codeAction = CodeAction.Create( + "Remove empty namespace declaration", + ct => RemoveEmptyNamespaceDeclarationRefactoring.RefactorAsync(document, namespaceDeclaration, ct), + GetEquivalenceKey(diagnostic)); - context.RegisterCodeFix(codeAction, diagnostic); - break; - } - case RegionDirectiveTriviaSyntax regionDirective: - { - CodeAction codeAction = CodeAction.Create( - "Remove empty region", - ct => RemoveEmptyRegionRefactoring.RefactorAsync(document, SyntaxInfo.RegionInfo(regionDirective), ct), - GetEquivalenceKey(diagnostic)); + context.RegisterCodeFix(codeAction, diagnostic); + break; + } + case RegionDirectiveTriviaSyntax regionDirective: + { + CodeAction codeAction = CodeAction.Create( + "Remove empty region", + ct => RemoveEmptyRegionRefactoring.RefactorAsync(document, SyntaxInfo.RegionInfo(regionDirective), ct), + GetEquivalenceKey(diagnostic)); - context.RegisterCodeFix(codeAction, diagnostic); - break; - } - case EmptyStatementSyntax emptyStatement: - { - CodeAction codeAction = CodeAction.Create( - "Remove empty statement", - ct => RemoveEmptyStatementRefactoring.RefactorAsync(document, emptyStatement, ct), - GetEquivalenceKey(diagnostic)); + context.RegisterCodeFix(codeAction, diagnostic); + break; + } + case EmptyStatementSyntax emptyStatement: + { + CodeAction codeAction = CodeAction.Create( + "Remove empty statement", + ct => RemoveEmptyStatementRefactoring.RefactorAsync(document, emptyStatement, ct), + GetEquivalenceKey(diagnostic)); - context.RegisterCodeFix(codeAction, diagnostic); - break; - } - } + context.RegisterCodeFix(codeAction, diagnostic); + break; + } } } } diff --git a/src/Analyzers/CSharp/Analysis/RemoveEmptySyntaxAnalyzer.cs b/src/Analyzers/CSharp/Analysis/RemoveEmptySyntaxAnalyzer.cs index a60f6a829b..21f825c79e 100644 --- a/src/Analyzers/CSharp/Analysis/RemoveEmptySyntaxAnalyzer.cs +++ b/src/Analyzers/CSharp/Analysis/RemoveEmptySyntaxAnalyzer.cs @@ -7,211 +7,210 @@ using Microsoft.CodeAnalysis.Diagnostics; using Roslynator.CSharp.Syntax; -namespace Roslynator.CSharp.Analysis +namespace Roslynator.CSharp.Analysis; + +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public sealed class RemoveEmptySyntaxAnalyzer : BaseDiagnosticAnalyzer { - [DiagnosticAnalyzer(LanguageNames.CSharp)] - public sealed class RemoveEmptySyntaxAnalyzer : BaseDiagnosticAnalyzer - { - private static ImmutableArray _supportedDiagnostics; + private static ImmutableArray _supportedDiagnostics; - public override ImmutableArray SupportedDiagnostics + public override ImmutableArray SupportedDiagnostics + { + get { - get - { - if (_supportedDiagnostics.IsDefault) - Immutable.InterlockedInitialize(ref _supportedDiagnostics, DiagnosticRules.RemoveEmptySyntax); + if (_supportedDiagnostics.IsDefault) + Immutable.InterlockedInitialize(ref _supportedDiagnostics, DiagnosticRules.RemoveEmptySyntax); - return _supportedDiagnostics; - } + return _supportedDiagnostics; } + } + + public override void Initialize(AnalysisContext context) + { + base.Initialize(context); + + context.RegisterSyntaxNodeAction(f => AnalyzeDestructorDeclaration(f), SyntaxKind.DestructorDeclaration); + context.RegisterSyntaxNodeAction(f => AnalyzeElseClause(f), SyntaxKind.ElseClause); + context.RegisterSyntaxNodeAction(f => AnalyzeFinallyClause(f), SyntaxKind.FinallyClause); + context.RegisterSyntaxNodeAction(f => AnalyzeObjectCreationExpression(f), SyntaxKind.ObjectCreationExpression); + context.RegisterSyntaxNodeAction(f => AnalyzeNamespaceDeclaration(f), SyntaxKind.NamespaceDeclaration); + context.RegisterSyntaxNodeAction(f => AnalyzeRegionDirective(f), SyntaxKind.RegionDirectiveTrivia); + context.RegisterSyntaxNodeAction(f => AnalyzeEmptyStatement(f), SyntaxKind.EmptyStatement); + } + + private static void AnalyzeDestructorDeclaration(SyntaxNodeAnalysisContext context) + { + var destructor = (DestructorDeclarationSyntax)context.Node; - public override void Initialize(AnalysisContext context) + if (!destructor.ContainsDiagnostics + && !destructor.ContainsUnbalancedIfElseDirectives() + && !destructor.AttributeLists.Any() + && destructor.Body?.Statements.Count == 0) { - base.Initialize(context); - - context.RegisterSyntaxNodeAction(f => AnalyzeDestructorDeclaration(f), SyntaxKind.DestructorDeclaration); - context.RegisterSyntaxNodeAction(f => AnalyzeElseClause(f), SyntaxKind.ElseClause); - context.RegisterSyntaxNodeAction(f => AnalyzeFinallyClause(f), SyntaxKind.FinallyClause); - context.RegisterSyntaxNodeAction(f => AnalyzeObjectCreationExpression(f), SyntaxKind.ObjectCreationExpression); - context.RegisterSyntaxNodeAction(f => AnalyzeNamespaceDeclaration(f), SyntaxKind.NamespaceDeclaration); - context.RegisterSyntaxNodeAction(f => AnalyzeRegionDirective(f), SyntaxKind.RegionDirectiveTrivia); - context.RegisterSyntaxNodeAction(f => AnalyzeEmptyStatement(f), SyntaxKind.EmptyStatement); + ReportDiagnostic(context, destructor, "destructor"); } + } + + private static void AnalyzeElseClause(SyntaxNodeAnalysisContext context) + { + var elseClause = (ElseClauseSyntax)context.Node; + + StatementSyntax statement = elseClause.Statement; - private static void AnalyzeDestructorDeclaration(SyntaxNodeAnalysisContext context) + if (statement is not BlockSyntax block) + return; + + if (block.Statements.Any()) + return; + + IfStatementSyntax topmostIf = elseClause.GetTopmostIf(); + + if (topmostIf.Parent is IfStatementSyntax parentIf + && parentIf.Else != null) { - var destructor = (DestructorDeclarationSyntax)context.Node; - - if (!destructor.ContainsDiagnostics - && !destructor.ContainsUnbalancedIfElseDirectives() - && !destructor.AttributeLists.Any() - && destructor.Body?.Statements.Count == 0) - { - ReportDiagnostic(context, destructor, "destructor"); - } + return; } - private static void AnalyzeElseClause(SyntaxNodeAnalysisContext context) - { - var elseClause = (ElseClauseSyntax)context.Node; + if (!elseClause.ElseKeyword.TrailingTrivia.IsEmptyOrWhitespace()) + return; - StatementSyntax statement = elseClause.Statement; + if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(block.OpenBraceToken)) + return; - if (statement is not BlockSyntax block) - return; + if (!block.CloseBraceToken.LeadingTrivia.IsEmptyOrWhitespace()) + return; - if (block.Statements.Any()) - return; + ReportDiagnostic(context, elseClause, "'else' clause"); + } - IfStatementSyntax topmostIf = elseClause.GetTopmostIf(); + private static void AnalyzeFinallyClause(SyntaxNodeAnalysisContext context) + { + var finallyClause = (FinallyClauseSyntax)context.Node; - if (topmostIf.Parent is IfStatementSyntax parentIf - && parentIf.Else != null) - { - return; - } + if (finallyClause.Parent is not TryStatementSyntax tryStatement) + return; - if (!elseClause.ElseKeyword.TrailingTrivia.IsEmptyOrWhitespace()) - return; + BlockSyntax finallyBlock = finallyClause.Block; - if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(block.OpenBraceToken)) - return; + if (finallyBlock?.Statements.Any() != false) + return; - if (!block.CloseBraceToken.LeadingTrivia.IsEmptyOrWhitespace()) - return; + if (!finallyClause.FinallyKeyword.TrailingTrivia.IsEmptyOrWhitespace()) + return; - ReportDiagnostic(context, elseClause, "'else' clause"); - } + if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(finallyBlock.OpenBraceToken)) + return; + + if (!finallyBlock.CloseBraceToken.LeadingTrivia.IsEmptyOrWhitespace()) + return; - private static void AnalyzeFinallyClause(SyntaxNodeAnalysisContext context) + if (tryStatement.Catches.Any()) + { + ReportDiagnostic(context, finallyClause, "'finally' clause"); + } + else { - var finallyClause = (FinallyClauseSyntax)context.Node; + BlockSyntax tryBlock = tryStatement.Block; - if (finallyClause.Parent is not TryStatementSyntax tryStatement) + if (tryBlock?.Statements.Any() != true) return; - BlockSyntax finallyBlock = finallyClause.Block; - - if (finallyBlock?.Statements.Any() != false) + if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(tryStatement.TryKeyword)) return; - if (!finallyClause.FinallyKeyword.TrailingTrivia.IsEmptyOrWhitespace()) + if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(tryBlock.OpenBraceToken)) return; - if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(finallyBlock.OpenBraceToken)) + if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(tryBlock.CloseBraceToken)) return; - if (!finallyBlock.CloseBraceToken.LeadingTrivia.IsEmptyOrWhitespace()) + if (!finallyClause.FinallyKeyword.LeadingTrivia.IsEmptyOrWhitespace()) return; - if (tryStatement.Catches.Any()) - { - ReportDiagnostic(context, finallyClause, "'finally' clause"); - } - else - { - BlockSyntax tryBlock = tryStatement.Block; - - if (tryBlock?.Statements.Any() != true) - return; - - if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(tryStatement.TryKeyword)) - return; - - if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(tryBlock.OpenBraceToken)) - return; + ReportDiagnostic(context, finallyClause, "'finally' clause"); - if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(tryBlock.CloseBraceToken)) - return; - - if (!finallyClause.FinallyKeyword.LeadingTrivia.IsEmptyOrWhitespace()) - return; - - ReportDiagnostic(context, finallyClause, "'finally' clause"); - - //TODO: JP - //DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveEmptyFinallyClauseFadeOut, tryStatement.TryKeyword); - //DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveEmptyFinallyClauseFadeOut, tryBlock.OpenBraceToken); - //DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveEmptyFinallyClauseFadeOut, tryBlock.CloseBraceToken); - } + //TODO: JP + //DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveEmptyFinallyClauseFadeOut, tryStatement.TryKeyword); + //DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveEmptyFinallyClauseFadeOut, tryBlock.OpenBraceToken); + //DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveEmptyFinallyClauseFadeOut, tryBlock.CloseBraceToken); } + } - private static void AnalyzeObjectCreationExpression(SyntaxNodeAnalysisContext context) - { - var objectCreationExpression = (ObjectCreationExpressionSyntax)context.Node; + private static void AnalyzeObjectCreationExpression(SyntaxNodeAnalysisContext context) + { + var objectCreationExpression = (ObjectCreationExpressionSyntax)context.Node; - if (objectCreationExpression.ContainsDiagnostics) - return; + if (objectCreationExpression.ContainsDiagnostics) + return; - InitializerExpressionSyntax initializer = objectCreationExpression.Initializer; + InitializerExpressionSyntax initializer = objectCreationExpression.Initializer; - if (initializer?.Expressions.Any() != false) - return; + if (initializer?.Expressions.Any() != false) + return; - if (!initializer.OpenBraceToken.TrailingTrivia.IsEmptyOrWhitespace()) - return; + if (!initializer.OpenBraceToken.TrailingTrivia.IsEmptyOrWhitespace()) + return; - if (!initializer.CloseBraceToken.LeadingTrivia.IsEmptyOrWhitespace()) - return; + if (!initializer.CloseBraceToken.LeadingTrivia.IsEmptyOrWhitespace()) + return; - if (initializer.IsInExpressionTree(context.SemanticModel, context.CancellationToken)) - return; + if (initializer.IsInExpressionTree(context.SemanticModel, context.CancellationToken)) + return; - ReportDiagnostic(context, initializer, "initializer"); - } + ReportDiagnostic(context, initializer, "initializer"); + } - private static void AnalyzeNamespaceDeclaration(SyntaxNodeAnalysisContext context) - { - var declaration = (NamespaceDeclarationSyntax)context.Node; + private static void AnalyzeNamespaceDeclaration(SyntaxNodeAnalysisContext context) + { + var declaration = (NamespaceDeclarationSyntax)context.Node; - if (declaration.Members.Any()) - return; + if (declaration.Members.Any()) + return; - SyntaxToken openBrace = declaration.OpenBraceToken; - SyntaxToken closeBrace = declaration.CloseBraceToken; + SyntaxToken openBrace = declaration.OpenBraceToken; + SyntaxToken closeBrace = declaration.CloseBraceToken; - if (openBrace.IsMissing) - return; + if (openBrace.IsMissing) + return; - if (closeBrace.IsMissing) - return; - - if (!openBrace.TrailingTrivia.IsEmptyOrWhitespace()) - return; + if (closeBrace.IsMissing) + return; - if (!closeBrace.LeadingTrivia.IsEmptyOrWhitespace()) - return; + if (!openBrace.TrailingTrivia.IsEmptyOrWhitespace()) + return; - ReportDiagnostic(context, declaration, "namespace declaration"); - } + if (!closeBrace.LeadingTrivia.IsEmptyOrWhitespace()) + return; - private static void AnalyzeRegionDirective(SyntaxNodeAnalysisContext context) - { - var regionDirective = (RegionDirectiveTriviaSyntax)context.Node; + ReportDiagnostic(context, declaration, "namespace declaration"); + } - RegionInfo region = SyntaxInfo.RegionInfo(regionDirective); + private static void AnalyzeRegionDirective(SyntaxNodeAnalysisContext context) + { + var regionDirective = (RegionDirectiveTriviaSyntax)context.Node; - if (region.Success - && region.IsEmpty) - { - ReportDiagnostic(context, regionDirective, "#region"); - } - } + RegionInfo region = SyntaxInfo.RegionInfo(regionDirective); - private static void AnalyzeEmptyStatement(SyntaxNodeAnalysisContext context) + if (region.Success + && region.IsEmpty) { - SyntaxNode emptyStatement = context.Node; - - if (emptyStatement.Parent?.IsKind(SyntaxKind.LabeledStatement) == false - && !CSharpFacts.CanHaveEmbeddedStatement(emptyStatement.Parent.Kind())) - { - ReportDiagnostic(context, emptyStatement, "statement"); - } + ReportDiagnostic(context, regionDirective, "#region"); } + } + + private static void AnalyzeEmptyStatement(SyntaxNodeAnalysisContext context) + { + SyntaxNode emptyStatement = context.Node; - private static void ReportDiagnostic(SyntaxNodeAnalysisContext context, SyntaxNode node, string name) + if (emptyStatement.Parent?.IsKind(SyntaxKind.LabeledStatement) == false + && !CSharpFacts.CanHaveEmbeddedStatement(emptyStatement.Parent.Kind())) { - DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveEmptySyntax, node, name); + ReportDiagnostic(context, emptyStatement, "statement"); } } + + private static void ReportDiagnostic(SyntaxNodeAnalysisContext context, SyntaxNode node, string name) + { + DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveEmptySyntax, node, name); + } } diff --git a/src/Tests/Analyzers.Tests/RCS1257RemoveEmptySyntaxTests.cs b/src/Tests/Analyzers.Tests/RCS1257RemoveEmptySyntaxTests.cs index 7d1ff78cbb..bfafaffdbf 100644 --- a/src/Tests/Analyzers.Tests/RCS1257RemoveEmptySyntaxTests.cs +++ b/src/Tests/Analyzers.Tests/RCS1257RemoveEmptySyntaxTests.cs @@ -6,16 +6,16 @@ using Roslynator.Testing.CSharp; using Xunit; -namespace Roslynator.CSharp.Analysis.Tests +namespace Roslynator.CSharp.Analysis.Tests; + +public class RCS1257RemoveEmptySyntaxTests : AbstractCSharpDiagnosticVerifier { - public class RCS1257RemoveEmptySyntaxTests : AbstractCSharpDiagnosticVerifier - { - public override DiagnosticDescriptor Descriptor { get; } = DiagnosticRules.RemoveEmptySyntax; + public override DiagnosticDescriptor Descriptor { get; } = DiagnosticRules.RemoveEmptySyntax; - [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] - public async Task Test_Destructor() - { - await VerifyDiagnosticAndFixAsync(@" + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task Test_Destructor() + { + await VerifyDiagnosticAndFixAsync(@" class C { void M() @@ -36,12 +36,12 @@ void M() } } "); - } + } - [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] - public async Task TestNoDiagnostic_Destructor_IfDirective() - { - await VerifyNoDiagnosticAsync(@" + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task TestNoDiagnostic_Destructor_IfDirective() + { + await VerifyNoDiagnosticAsync(@" #define A class C { @@ -52,12 +52,12 @@ class C #endif } "); - } + } - [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] - public async Task TestNoDiagnostic_Destructor_NotEmpty() - { - await VerifyNoDiagnosticAsync(@" + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task TestNoDiagnostic_Destructor_NotEmpty() + { + await VerifyNoDiagnosticAsync(@" class C { void M() @@ -70,12 +70,12 @@ void M() } } "); - } + } - [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] - public async Task Test_ElseClause() - { - await VerifyDiagnosticAndFixAsync(@" + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task Test_ElseClause() + { + await VerifyDiagnosticAndFixAsync(@" class C { void M() @@ -103,12 +103,12 @@ void M() } } "); - } + } - [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] - public async Task TestNoDiagnostic_ElseClause_ElseIf() - { - await VerifyNoDiagnosticAsync(@" + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task TestNoDiagnostic_ElseClause_ElseIf() + { + await VerifyNoDiagnosticAsync(@" class C { void M() @@ -124,12 +124,12 @@ void M() } } "); - } + } - [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] - public async Task TestNoDiagnostic_ElseClause_NonEmptyElse() - { - await VerifyNoDiagnosticAsync(@" + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task TestNoDiagnostic_ElseClause_NonEmptyElse() + { + await VerifyNoDiagnosticAsync(@" class C { void M() @@ -146,12 +146,12 @@ void M() } } "); - } + } - [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] - public async Task TestNoDiagnostic_ElseClause_IfElseEmbeddedInIfWithElse() - { - await VerifyNoDiagnosticAsync(@" + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task TestNoDiagnostic_ElseClause_IfElseEmbeddedInIfWithElse() + { + await VerifyNoDiagnosticAsync(@" class C { void M() @@ -167,12 +167,12 @@ void M() } } "); - } + } - [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] - public async Task TestNoDiagnostic_ElseClause_IfElseEmbeddedInIfWithElse2() - { - await VerifyNoDiagnosticAsync(@" + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task TestNoDiagnostic_ElseClause_IfElseEmbeddedInIfWithElse2() + { + await VerifyNoDiagnosticAsync(@" class C { void M() @@ -188,12 +188,12 @@ void M() } } "); - } + } - [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] - public async Task Test_FinallyClause_TryCatchFinally() - { - await VerifyDiagnosticAndFixAsync(@" + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task Test_FinallyClause_TryCatchFinally() + { + await VerifyDiagnosticAndFixAsync(@" class C { void M() @@ -223,12 +223,12 @@ void M() } } "); - } + } - [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] - public async Task Test_FinallyClause_TryFinally() - { - await VerifyDiagnosticAndFixAsync(@" + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task Test_FinallyClause_TryFinally() + { + await VerifyDiagnosticAndFixAsync(@" class C { void M() @@ -259,12 +259,12 @@ void M() string M2() => null; } "); - } + } - [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] - public async Task TestNoDiagnostic_FinallyClause_NonEmptyFinally() - { - await VerifyNoDiagnosticAsync(@" + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task TestNoDiagnostic_FinallyClause_NonEmptyFinally() + { + await VerifyNoDiagnosticAsync(@" class C { void M() @@ -282,12 +282,12 @@ void M() } } "); - } + } - [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] - public async Task Test_ObjectInitializer() - { - await VerifyDiagnosticAndFixAsync(@" + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task Test_ObjectInitializer() + { + await VerifyDiagnosticAndFixAsync(@" class C { void M() @@ -304,12 +304,12 @@ void M() } } "); - } + } - [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] - public async Task Test_ObjectInitializer2() - { - await VerifyDiagnosticAndFixAsync(@" + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task Test_ObjectInitializer2() + { + await VerifyDiagnosticAndFixAsync(@" using System.Text; class C @@ -374,12 +374,12 @@ void M() } } "); - } + } - [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] - public async Task TestNoDiagnostic_ObjectInitializer_ExpressionTree() - { - await VerifyNoDiagnosticAsync(@" + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task TestNoDiagnostic_ObjectInitializer_ExpressionTree() + { + await VerifyNoDiagnosticAsync(@" using System; using System.Linq.Expressions; @@ -391,12 +391,12 @@ public void M(Expression> e) } } "); - } + } - [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] - public async Task Test_Namespace() - { - await VerifyDiagnosticAndFixAsync(@" + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task Test_Namespace() + { + await VerifyDiagnosticAndFixAsync(@" using System; using System.Linq.Expressions; @@ -421,12 +421,12 @@ class C } } "); - } + } - [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] - public async Task Test_RegionDirective() - { - await VerifyDiagnosticAndFixAsync(@" + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task Test_RegionDirective() + { + await VerifyDiagnosticAndFixAsync(@" namespace N1 { class C @@ -443,12 +443,12 @@ class C } } "); - } + } - [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] - public async Task Test_EmptyStatement() - { - await VerifyDiagnosticAndFixAsync(@" + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task Test_EmptyStatement() + { + await VerifyDiagnosticAndFixAsync(@" namespace N1 { class C @@ -473,12 +473,12 @@ void M() } } "); - } + } - [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] - public async Task TestNoDiagnostic_EmptyStatement() - { - await VerifyNoDiagnosticAsync(@" + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveEmptySyntax)] + public async Task TestNoDiagnostic_EmptyStatement() + { + await VerifyNoDiagnosticAsync(@" namespace N1 { class C @@ -491,6 +491,5 @@ void M(bool p) } } ", options: Options.AddAllowedCompilerDiagnosticId("CS0642")); - } } } From b0fcb76844aefe5b0190b5e8a6bfd341c4cc9658 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sat, 19 Aug 2023 19:35:57 +0200 Subject: [PATCH 09/16] update --- src/Analyzers.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Analyzers.xml b/src/Analyzers.xml index f51a4c5436..02c706f752 100644 --- a/src/Analyzers.xml +++ b/src/Analyzers.xml @@ -2436,7 +2436,7 @@ if (f) RCS1038 RemoveEmptyStatement Obsolete - Use RCS1255 instead + Use RCS1259 instead Remove empty statement. Info false @@ -2478,7 +2478,7 @@ public void Foo() RCS1040 RemoveEmptyElseClause Obsolete - Use RCS1255 instead + Use RCS1259 instead Remove empty 'else' clause. Hidden false @@ -2504,7 +2504,7 @@ else RCS1041 RemoveEmptyInitializer Obsolete - Use RCS1255 instead + Use RCS1259 instead Remove empty initializer. Info false @@ -3103,7 +3103,7 @@ while (true);]]> RCS1066 RemoveEmptyFinallyClause Obsolete - Use RCS1255 instead + Use RCS1259 instead Remove empty 'finally' clause. Hidden false @@ -3261,7 +3261,7 @@ catch (Exception ex) RCS1072 RemoveEmptyNamespaceDeclaration Obsolete - Use RCS1255 instead + Use RCS1259 instead Remove empty namespace declaration. Info false @@ -3691,7 +3691,7 @@ public string Foo RCS1091 RemoveEmptyRegion Obsolete - Use RCS1255 instead + Use RCS1259 instead Remove empty region. Hidden false @@ -4025,7 +4025,7 @@ else RCS1106 RemoveEmptyDestructor Obsolete - Use RCS1255 instead + Use RCS1259 instead Remove empty destructor. Info false From 1a88bbe96334d08225d58af1c59b7de1260aa751 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sat, 19 Aug 2023 19:37:02 +0200 Subject: [PATCH 10/16] update --- ChangeLog.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index e47720544d..c97684c649 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -16,6 +16,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Enabled by default. - Add analyzer "Unnecessary enum flag" [RCS1258](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1258.md) ([#886](https://github.com/JosefPihrt/Roslynator/pull/886)). - Enabled by default. +- Analyzer 'Remove empty syntax' ([RCS1259](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1259.md)) ([#913](https://github.com/josefpihrt/roslynator/pull/913)). + - This analyzer replaces following analyzers: + - Remove empty empty statement ([RCS1038](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1038.md)) + - Remove empty 'else' clause ([RCS1040](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1040.md)) + - Remove empty object initializer ([RCS1041](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1041.md)) + - Remove empty 'finally' clause ([RCS1066](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1066.md)) + - Remove empty namespace declaration ([RCS1072](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1072.md)) + - Remove empty region directive ([RCS1091](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1091.md)) + - Remove empty destructor ([RCS1106](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1106.md)) ### Fixed @@ -28,15 +37,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add GitHub workflow ([#1112](https://github.com/josefpihrt/roslynator/pull/1112)) -- Analyzer 'Remove empty syntax' ([RCS1257](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1257.md)) ([#913](https://github.com/josefpihrt/roslynator/pull/913)). - - This analyzer replaces following analyzers: - - Remove empty empty statement ([RCS1038](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1038.md)) - - Remove empty 'else' clause ([RCS1040](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1040.md)) - - Remove empty object initializer ([RCS1041](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1041.md)) - - Remove empty 'finally' clause ([RCS1066](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1066.md)) - - Remove empty namespace declaration ([RCS1072](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1072.md)) - - Remove empty region directive ([RCS1091](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1091.md)) - - Remove empty destructor ([RCS1106](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1106.md)) ### Changed From accc22599bd708af73934bd4c1afe03057dd53b6 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sat, 19 Aug 2023 19:40:23 +0200 Subject: [PATCH 11/16] update --- ChangeLog.md | 6 +++++- src/Analyzers/CSharp/DiagnosticRules.Generated.cs | 14 +++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index c97684c649..954f2afb1e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -145,7 +145,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add code fix for CS0037 ([#929](https://github.com/josefpihrt/roslynator/pull/929)). - [CLI] Generate reference documentation that can be published with Docusaurus ([#918](https://github.com/josefpihrt/roslynator/pull/918)). - `roslynator generate-doc --host docusaurus` -- Publish Roslynator to [Open VSX Registry](https://open-vsx.org/extension/josefpihrt-vscode/roslynator) ([#820](https://github.com/JosefPihrt/Roslynator/issues/820)). +- [CLI] Generate reference documentation that can be published with Sphinx ([#961](https://github.com/josefpihrt/roslynator/pull/961)). + - `roslynator generate-doc --host sphinx` +- [CLI] Basic support for `` when generating documentation (`generate-doc` command) ([#972](https://github.com/josefpihrt/roslynator/pull/972)). +- [CLI] Add option `ignored-title-parts` (`generate-doc` command) ([#975](https://github.com/josefpihrt/roslynator/pull/975)). +- - Publish Roslynator to [Open VSX Registry](https://open-vsx.org/extension/josefpihrt-vscode/roslynator) ([#820](https://github.com/JosefPihrt/Roslynator/issues/820)). ### Changed diff --git a/src/Analyzers/CSharp/DiagnosticRules.Generated.cs b/src/Analyzers/CSharp/DiagnosticRules.Generated.cs index a8cbe2e315..516fe48767 100644 --- a/src/Analyzers/CSharp/DiagnosticRules.Generated.cs +++ b/src/Analyzers/CSharp/DiagnosticRules.Generated.cs @@ -341,7 +341,7 @@ public static partial class DiagnosticRules public static readonly DiagnosticDescriptor RemoveEmptyStatement = DiagnosticDescriptorFactory.Create( id: DiagnosticIdentifiers.RemoveEmptyStatement, title: "Remove empty statement.", - messageFormat: "([deprecated] Use RCS1255 instead) Remove empty statement.", + messageFormat: "([deprecated] Use RCS1259 instead) Remove empty statement.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Info, isEnabledByDefault: false, @@ -365,7 +365,7 @@ public static partial class DiagnosticRules public static readonly DiagnosticDescriptor RemoveEmptyElseClause = DiagnosticDescriptorFactory.Create( id: DiagnosticIdentifiers.RemoveEmptyElseClause, title: "Remove empty 'else' clause.", - messageFormat: "([deprecated] Use RCS1255 instead) Remove empty 'else' clause.", + messageFormat: "([deprecated] Use RCS1259 instead) Remove empty 'else' clause.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Hidden, isEnabledByDefault: false, @@ -377,7 +377,7 @@ public static partial class DiagnosticRules public static readonly DiagnosticDescriptor RemoveEmptyInitializer = DiagnosticDescriptorFactory.Create( id: DiagnosticIdentifiers.RemoveEmptyInitializer, title: "Remove empty initializer.", - messageFormat: "([deprecated] Use RCS1255 instead) Remove empty initializer.", + messageFormat: "([deprecated] Use RCS1259 instead) Remove empty initializer.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Info, isEnabledByDefault: false, @@ -627,7 +627,7 @@ public static partial class DiagnosticRules public static readonly DiagnosticDescriptor RemoveEmptyFinallyClause = DiagnosticDescriptorFactory.Create( id: DiagnosticIdentifiers.RemoveEmptyFinallyClause, title: "Remove empty 'finally' clause.", - messageFormat: "([deprecated] Use RCS1255 instead) Remove empty 'finally' clause.", + messageFormat: "([deprecated] Use RCS1259 instead) Remove empty 'finally' clause.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Hidden, isEnabledByDefault: false, @@ -689,7 +689,7 @@ public static partial class DiagnosticRules public static readonly DiagnosticDescriptor RemoveEmptyNamespaceDeclaration = DiagnosticDescriptorFactory.Create( id: DiagnosticIdentifiers.RemoveEmptyNamespaceDeclaration, title: "Remove empty namespace declaration.", - messageFormat: "([deprecated] Use RCS1255 instead) Remove empty namespace declaration.", + messageFormat: "([deprecated] Use RCS1259 instead) Remove empty namespace declaration.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Info, isEnabledByDefault: false, @@ -851,7 +851,7 @@ public static partial class DiagnosticRules public static readonly DiagnosticDescriptor RemoveEmptyRegion = DiagnosticDescriptorFactory.Create( id: DiagnosticIdentifiers.RemoveEmptyRegion, title: "Remove empty region.", - messageFormat: "([deprecated] Use RCS1255 instead) Remove empty region.", + messageFormat: "([deprecated] Use RCS1259 instead) Remove empty region.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Hidden, isEnabledByDefault: false, @@ -1009,7 +1009,7 @@ public static partial class DiagnosticRules public static readonly DiagnosticDescriptor RemoveEmptyDestructor = DiagnosticDescriptorFactory.Create( id: DiagnosticIdentifiers.RemoveEmptyDestructor, title: "Remove empty destructor.", - messageFormat: "([deprecated] Use RCS1255 instead) Remove empty destructor.", + messageFormat: "([deprecated] Use RCS1259 instead) Remove empty destructor.", category: DiagnosticCategories.Roslynator, defaultSeverity: DiagnosticSeverity.Info, isEnabledByDefault: false, From e586f52dba8f359cadf16b99f69f94625e0dc4cd Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sat, 19 Aug 2023 19:41:20 +0200 Subject: [PATCH 12/16] update --- ChangeLog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 954f2afb1e..75768b9527 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -149,7 +149,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `roslynator generate-doc --host sphinx` - [CLI] Basic support for `` when generating documentation (`generate-doc` command) ([#972](https://github.com/josefpihrt/roslynator/pull/972)). - [CLI] Add option `ignored-title-parts` (`generate-doc` command) ([#975](https://github.com/josefpihrt/roslynator/pull/975)). -- - Publish Roslynator to [Open VSX Registry](https://open-vsx.org/extension/josefpihrt-vscode/roslynator) ([#820](https://github.com/JosefPihrt/Roslynator/issues/820)). +- Publish Roslynator to [Open VSX Registry](https://open-vsx.org/extension/josefpihrt-vscode/roslynator) ([#820](https://github.com/JosefPihrt/Roslynator/issues/820)). ### Changed From 27869db6b06c8aebb096199eb32dd27639dad4c1 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sat, 19 Aug 2023 19:46:02 +0200 Subject: [PATCH 13/16] update --- src/Analyzers/CSharp/Analysis/RemoveEmptySyntaxAnalyzer.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Analyzers/CSharp/Analysis/RemoveEmptySyntaxAnalyzer.cs b/src/Analyzers/CSharp/Analysis/RemoveEmptySyntaxAnalyzer.cs index 21f825c79e..03d5557cbc 100644 --- a/src/Analyzers/CSharp/Analysis/RemoveEmptySyntaxAnalyzer.cs +++ b/src/Analyzers/CSharp/Analysis/RemoveEmptySyntaxAnalyzer.cs @@ -128,11 +128,6 @@ private static void AnalyzeFinallyClause(SyntaxNodeAnalysisContext context) return; ReportDiagnostic(context, finallyClause, "'finally' clause"); - - //TODO: JP - //DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveEmptyFinallyClauseFadeOut, tryStatement.TryKeyword); - //DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveEmptyFinallyClauseFadeOut, tryBlock.OpenBraceToken); - //DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveEmptyFinallyClauseFadeOut, tryBlock.CloseBraceToken); } } From 05a5003042ec108d4f6ac810bbb8cda3c849ff9f Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sun, 20 Aug 2023 12:47:12 +0200 Subject: [PATCH 14/16] update --- src/Analyzers.xml | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/Analyzers.xml b/src/Analyzers.xml index 02c706f752..136339d3b9 100644 --- a/src/Analyzers.xml +++ b/src/Analyzers.xml @@ -7410,16 +7410,15 @@ void M() Info true true - - This analyzer reports unnecessary syntax that can be safely removed such as: - * empty destructor - * empty 'else' clause - * empty empty statement - * empty 'finally' clause - * empty namespace declaration - * empty object initializer - * empty region directive - + This analyzer reports unnecessary syntax that can be safely removed such as: + * empty destructor + * empty 'else' clause + * empty empty statement + * empty 'finally' clause + * empty namespace declaration + * empty object initializer + * empty region directive + RCS9001 From 7f28cf74b0d60ac20d14de0071b76011fb706d0d Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sun, 20 Aug 2023 12:50:06 +0200 Subject: [PATCH 15/16] update --- ChangeLog.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index fce1d50fdd..d40f35e760 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -17,15 +17,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add analyzer "Unnecessary enum flag" [RCS1258](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1258.md) ([#886](https://github.com/JosefPihrt/Roslynator/pull/886)). - Enabled by default. - Make `Roslynator.Rename.SymbolRenamer` public ([#1161](https://github.com/josefpihrt/roslynator/pull/1161)) -- Analyzer 'Remove empty syntax' ([RCS1259](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1259.md)) ([#913](https://github.com/josefpihrt/roslynator/pull/913)). +- Analyzer 'Remove empty syntax' ([RCS1259](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1259.md)) ([#913](https://github.com/josefpihrt/roslynator/pull/913)). - This analyzer replaces following analyzers: - - Remove empty empty statement ([RCS1038](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1038.md)) - - Remove empty 'else' clause ([RCS1040](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1040.md)) - - Remove empty object initializer ([RCS1041](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1041.md)) - - Remove empty 'finally' clause ([RCS1066](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1066.md)) - - Remove empty namespace declaration ([RCS1072](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1072.md)) - - Remove empty region directive ([RCS1091](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1091.md)) - - Remove empty destructor ([RCS1106](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1106.md)) + - Remove empty empty statement ([RCS1038](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1038.md)) + - Remove empty 'else' clause ([RCS1040](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1040.md)) + - Remove empty object initializer ([RCS1041](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1041.md)) + - Remove empty 'finally' clause ([RCS1066](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1066.md)) + - Remove empty namespace declaration ([RCS1072](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1072.md)) + - Remove empty region directive ([RCS1091](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1091.md)) + - Remove empty destructor ([RCS1106](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1106.md)) ### Fixed From cf7e821cd549fd735209a1d0730504b1d51fea9e Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sun, 20 Aug 2023 12:56:56 +0200 Subject: [PATCH 16/16] update --- ChangeLog.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index d40f35e760..1bd8336bba 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -10,11 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add SECURITY.md ([#1147](https://github.com/josefpihrt/roslynator/pull/1147)) -- Add custom FixAllProvider for [RCS1014](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1014.md) ([#1070](https://github.com/JosefPihrt/Roslynator/pull/1070)). -- Add more cases to [RCS1097](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1097.md) ([#1160](https://github.com/JosefPihrt/Roslynator/pull/1160)). +- Add custom FixAllProvider for [RCS1014](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1014.md) ([#1070](https://github.com/JosefPihrt/Roslynator/pull/1070)). +- Add more cases to [RCS1097](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1097.md) ([#1160](https://github.com/JosefPihrt/Roslynator/pull/1160)). - Add analyzer "Use enum field explicitly" ([RCS1257](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1257)) ([#889](https://github.com/josefpihrt/roslynator/pull/889)). - Enabled by default. -- Add analyzer "Unnecessary enum flag" [RCS1258](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1258.md) ([#886](https://github.com/JosefPihrt/Roslynator/pull/886)). +- Add analyzer "Unnecessary enum flag" [RCS1258](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1258.md) ([#886](https://github.com/JosefPihrt/Roslynator/pull/886)). - Enabled by default. - Make `Roslynator.Rename.SymbolRenamer` public ([#1161](https://github.com/josefpihrt/roslynator/pull/1161)) - Analyzer 'Remove empty syntax' ([RCS1259](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1259.md)) ([#913](https://github.com/josefpihrt/roslynator/pull/913)). @@ -29,9 +29,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- Fix [RCS1187](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1187.md) ([#1150](https://github.com/JosefPihrt/Roslynator/pull/1150)). -- Fix [RCS1056](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1056.md) ([#1154](https://github.com/JosefPihrt/Roslynator/pull/1154)). -- Fix [RCS1208](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1208.md) ([#1153](https://github.com/JosefPihrt/Roslynator/pull/1153)) +- Fix [RCS1187](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1187.md) ([#1150](https://github.com/JosefPihrt/Roslynator/pull/1150)). +- Fix [RCS1056](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1056.md) ([#1154](https://github.com/JosefPihrt/Roslynator/pull/1154)). +- Fix [RCS1208](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1208.md) ([#1153](https://github.com/JosefPihrt/Roslynator/pull/1153)) ## [4.4.0] - 2023-08-01 @@ -60,13 +60,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix [RCS1154](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1154) ([#1105](https://github.com/JosefPihrt/Roslynator/pull/1105)). - Fix [RCS1211](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1211) ([#1095](https://github.com/JosefPihrt/Roslynator/pull/1095)). - Fix [RCS0005](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS0005) ([#1114](https://github.com/JosefPihrt/Roslynator/pull/1114)). -- Fix [RCS1176](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1176.md) ([#1122](https://github.com/JosefPihrt/Roslynator/pull/1122), [#1140](https://github.com/JosefPihrt/Roslynator/pull/1140)). -- Fix [RCS1085](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1085.md) ([#1120](https://github.com/josefpihrt/roslynator/pull/1120)). -- Fix [RCS1208](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1208.md) ([#1119](https://github.com/JosefPihrt/Roslynator/pull/1119)). +- Fix [RCS1176](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1176.md) ([#1122](https://github.com/JosefPihrt/Roslynator/pull/1122), [#1140](https://github.com/JosefPihrt/Roslynator/pull/1140)). +- Fix [RCS1085](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1085.md) ([#1120](https://github.com/josefpihrt/roslynator/pull/1120)). +- Fix [RCS1208](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1208.md) ([#1119](https://github.com/JosefPihrt/Roslynator/pull/1119)). - [CLI] Fix member full declaration in generated documentation (command `generate-doc`) ([#1130](https://github.com/josefpihrt/roslynator/pull/1130)). - Append `?` to nullable reference types. -- Fix [RCS1179](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1179.md) ([#1129](https://github.com/JosefPihrt/Roslynator/pull/1129)). -- Fix [RCS0060](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS0060.md) ([#1139](https://github.com/JosefPihrt/Roslynator/pull/1139)). +- Fix [RCS1179](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1179.md) ([#1129](https://github.com/JosefPihrt/Roslynator/pull/1129)). +- Fix [RCS0060](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS0060.md) ([#1139](https://github.com/JosefPihrt/Roslynator/pull/1139)). ## [4.3.0] - 2023-04-24