Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add analyzer RemoveEmptySyntax #913

Merged
merged 31 commits into from
Aug 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
7ef646a
Add analyzer RemoveEmptySyntax
josefpihrt Jun 4, 2022
8df36aa
Update Analyzers.xml
josefpihrt Jun 4, 2022
44dc12d
Merge branch 'master' into feature/empty-syntax
josefpihrt Jun 5, 2022
8fcb706
Merge branch 'main' into feature/empty-syntax
josefpihrt Jul 16, 2022
7ead933
Merge branch 'main' into feature/empty-syntax
josefpihrt Aug 10, 2022
26040d1
Merge branch 'main' into feature/empty-syntax
josefpihrt Aug 22, 2022
7a66de9
Update
josefpihrt Aug 22, 2022
ed8af3b
Disable by default
josefpihrt Aug 22, 2022
eeb41e0
Merge branch 'main' into feature/empty-syntax
josefpihrt Oct 31, 2022
aef06c8
update
josefpihrt Nov 6, 2022
8ed6e69
Merge branch 'main' into feature/empty-syntax
josefpihrt Nov 17, 2022
7d56061
Merge branch 'main' into feature/empty-syntax
josefpihrt Nov 19, 2022
5e1cd65
update
josefpihrt Nov 19, 2022
d69ee93
Merge branch 'main' into feature/empty-syntax
josefpihrt Nov 26, 2022
e65aecb
Merge branch 'main' into feature/empty-syntax
josefpihrt Dec 18, 2022
981ddde
update
josefpihrt Dec 18, 2022
28525fb
Merge branch 'main' into feature/empty-syntax
josefpihrt Jul 16, 2023
d61a4a2
fixes
josefpihrt Jul 16, 2023
2e42988
Merge main
josefpihrt Aug 17, 2023
26cd6b9
Merge branch 'main' into feature/empty-syntax
josefpihrt Aug 18, 2023
7d67391
Merge branch 'main' into feature/empty-syntax
josefpihrt Aug 19, 2023
b0fcb76
update
josefpihrt Aug 19, 2023
1a88bbe
update
josefpihrt Aug 19, 2023
accc225
update
josefpihrt Aug 19, 2023
e586f52
update
josefpihrt Aug 19, 2023
27869db
update
josefpihrt Aug 19, 2023
ef61f84
Merge branch 'main' into feature/empty-syntax
josefpihrt Aug 19, 2023
a4d92b6
Merge branch 'main' into feature/empty-syntax
josefpihrt Aug 19, 2023
05a5003
update
josefpihrt Aug 20, 2023
7f28cf7
update
josefpihrt Aug 20, 2023
cf7e821
update
josefpihrt Aug 20, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 20 additions & 11 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,28 @@ 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)).
- This analyzer replaces following analyzers:
- 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

- 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

Expand Down Expand Up @@ -51,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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
}
}

private static async Task<Document> RemoveEmptyElseClauseAsync(
internal static async Task<Document> RemoveEmptyElseClauseAsync(
Document document,
ElseClauseSyntax elseClause,
CancellationToken cancellationToken)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
context.RegisterCodeFix(codeAction, context.Diagnostics[0]);
}

private static async Task<Document> RemoveEmptyFinallyClauseAsync(
internal static async Task<Document> RemoveEmptyFinallyClauseAsync(
Document document,
FinallyClauseSyntax finallyClause,
CancellationToken cancellationToken)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// 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<string> 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;
}
}
}
}
52 changes: 45 additions & 7 deletions src/Analyzers.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2435,10 +2435,13 @@ if (f)
<Analyzer>
<Id>RCS1038</Id>
<Identifier>RemoveEmptyStatement</Identifier>
<Status>Obsolete</Status>
<ObsoleteMessage>Use RCS1259 instead</ObsoleteMessage>
<Title>Remove empty statement.</Title>
<DefaultSeverity>Info</DefaultSeverity>
<IsEnabledByDefault>true</IsEnabledByDefault>
<IsEnabledByDefault>false</IsEnabledByDefault>
<SupportsFadeOut>true</SupportsFadeOut>
<Tags>HideFromConfiguration</Tags>
<Samples>
<Sample>
<Before><![CDATA[public void Foo()
Expand Down Expand Up @@ -2474,10 +2477,13 @@ public void Foo()
<Analyzer>
<Id>RCS1040</Id>
<Identifier>RemoveEmptyElseClause</Identifier>
<Status>Obsolete</Status>
<ObsoleteMessage>Use RCS1259 instead</ObsoleteMessage>
<Title>Remove empty 'else' clause.</Title>
<DefaultSeverity>Hidden</DefaultSeverity>
<IsEnabledByDefault>true</IsEnabledByDefault>
<IsEnabledByDefault>false</IsEnabledByDefault>
<SupportsFadeOut>true</SupportsFadeOut>
<Tags>HideFromConfiguration</Tags>
<Samples>
<Sample>
<Before><![CDATA[if (condition)
Expand All @@ -2497,10 +2503,13 @@ else
<Analyzer>
<Id>RCS1041</Id>
<Identifier>RemoveEmptyInitializer</Identifier>
<Status>Obsolete</Status>
<ObsoleteMessage>Use RCS1259 instead</ObsoleteMessage>
<Title>Remove empty initializer.</Title>
<DefaultSeverity>Info</DefaultSeverity>
<IsEnabledByDefault>true</IsEnabledByDefault>
<IsEnabledByDefault>false</IsEnabledByDefault>
<SupportsFadeOut>true</SupportsFadeOut>
<Tags>HideFromConfiguration</Tags>
<Samples>
<Sample>
<Before><![CDATA[var items = new List<object>() { };]]></Before>
Expand Down Expand Up @@ -3093,11 +3102,14 @@ while (true);]]></Before>
<Analyzer>
<Id>RCS1066</Id>
<Identifier>RemoveEmptyFinallyClause</Identifier>
<Status>Obsolete</Status>
<ObsoleteMessage>Use RCS1259 instead</ObsoleteMessage>
<Title>Remove empty 'finally' clause.</Title>
<DefaultSeverity>Hidden</DefaultSeverity>
<IsEnabledByDefault>true</IsEnabledByDefault>
<IsEnabledByDefault>false</IsEnabledByDefault>
<SupportsFadeOut>true</SupportsFadeOut>
<SupportsFadeOutAnalyzer>true</SupportsFadeOutAnalyzer>
<Tags>HideFromConfiguration</Tags>
<Samples>
<Sample>
<Before><![CDATA[try
Expand Down Expand Up @@ -3248,10 +3260,13 @@ catch (Exception ex)
<Analyzer>
<Id>RCS1072</Id>
<Identifier>RemoveEmptyNamespaceDeclaration</Identifier>
<Status>Obsolete</Status>
<ObsoleteMessage>Use RCS1259 instead</ObsoleteMessage>
<Title>Remove empty namespace declaration.</Title>
<DefaultSeverity>Info</DefaultSeverity>
<IsEnabledByDefault>true</IsEnabledByDefault>
<IsEnabledByDefault>false</IsEnabledByDefault>
<SupportsFadeOut>true</SupportsFadeOut>
<Tags>HideFromConfiguration</Tags>
<Samples>
<Sample>
<Before><![CDATA[namespace Foo
Expand Down Expand Up @@ -3675,10 +3690,13 @@ public string Foo
<Analyzer>
<Id>RCS1091</Id>
<Identifier>RemoveEmptyRegion</Identifier>
<Status>Obsolete</Status>
<ObsoleteMessage>Use RCS1259 instead</ObsoleteMessage>
<Title>Remove empty region.</Title>
<DefaultSeverity>Hidden</DefaultSeverity>
<IsEnabledByDefault>true</IsEnabledByDefault>
<IsEnabledByDefault>false</IsEnabledByDefault>
<SupportsFadeOutAnalyzer>true</SupportsFadeOutAnalyzer>
<Tags>HideFromConfiguration</Tags>
<Samples>
<Sample>
<Before><![CDATA[#region Region
Expand Down Expand Up @@ -4006,10 +4024,13 @@ else
<Analyzer>
<Id>RCS1106</Id>
<Identifier>RemoveEmptyDestructor</Identifier>
<Status>Obsolete</Status>
<ObsoleteMessage>Use RCS1259 instead</ObsoleteMessage>
<Title>Remove empty destructor.</Title>
<DefaultSeverity>Info</DefaultSeverity>
<IsEnabledByDefault>true</IsEnabledByDefault>
<IsEnabledByDefault>false</IsEnabledByDefault>
<SupportsFadeOut>true</SupportsFadeOut>
<Tags>HideFromConfiguration</Tags>
<Samples>
<Sample>
<Before><![CDATA[public class Foo
Expand Down Expand Up @@ -7382,6 +7403,23 @@ void M()
</Sample>
</Samples>
</Analyzer>
<Analyzer Identifier="RemoveEmptySyntax">
<Id>RCS1259</Id>
<Title>Remove empty syntax.</Title>
<MessageFormat>Remove empty {0}.</MessageFormat>
<DefaultSeverity>Info</DefaultSeverity>
<IsEnabledByDefault>true</IsEnabledByDefault>
<SupportsFadeOut>true</SupportsFadeOut>
<Summary>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
</Summary>
</Analyzer>
<Analyzer>
<Id>RCS9001</Id>
<Identifier>UsePatternMatching</Identifier>
Expand Down
Loading