-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Close issue #20 - Find and remove public empty ctor's with no comments.
- Loading branch information
Showing
5 changed files
with
242 additions
and
0 deletions.
There are no files selected for viewing
137 changes: 137 additions & 0 deletions
137
...ics/VSDiagnostics/VSDiagnostics.Test/Tests/General/SingleEmptyConstructorAnalyzerTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
using Microsoft.CodeAnalysis.CodeFixes; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
using RoslynTester.Helpers.CSharp; | ||
using VSDiagnostics.Diagnostics.General.SingleEmptyConstructor; | ||
|
||
namespace VSDiagnostics.Test.Tests.General | ||
{ | ||
[TestClass] | ||
public class SingleEmptyConstructorAnalyzerTests : CSharpCodeFixVerifier | ||
{ | ||
protected override DiagnosticAnalyzer DiagnosticAnalyzer => new SingleEmptyConstructorAnalyzer(); | ||
|
||
protected override CodeFixProvider CodeFixProvider => new SingleEmptyConstructorCodeFix(); | ||
|
||
[TestMethod] | ||
public void SingleEmptyConstructorAnalyzer_WithEmptyConstructor_InvokesWarning () | ||
{ | ||
var original = @" | ||
namespace ConsoleApplication1 | ||
{ | ||
public class MyClass | ||
{ | ||
public MyClass() | ||
{ | ||
} | ||
} | ||
}"; | ||
|
||
var result = @" | ||
namespace ConsoleApplication1 | ||
{ | ||
public class MyClass | ||
{ | ||
} | ||
}"; | ||
|
||
VerifyDiagnostic (original, SingleEmptyConstructorAnalyzer.Rule.MessageFormat.ToString()); | ||
VerifyFix(original, result); | ||
} | ||
|
||
[TestMethod] | ||
public void SingleEmptyConstructorAnalyzer_WithCommentInConstructor_DoesNotInvokeWarning () | ||
{ | ||
var original = @" | ||
namespace ConsoleApplication1 | ||
{ | ||
public class MyClass | ||
{ | ||
public MyClass() | ||
{ | ||
// ctor has comment | ||
} | ||
} | ||
}"; | ||
|
||
VerifyDiagnostic(original); | ||
} | ||
|
||
[TestMethod] | ||
public void SingleEmptyConstructorAnalyzer_WithConstructorParameters_DoesNotInvokeWarning () | ||
{ | ||
var original = @" | ||
namespace ConsoleApplication1 | ||
{ | ||
public class MyClass | ||
{ | ||
public MyClass(int foo) | ||
{ | ||
} | ||
} | ||
}"; | ||
|
||
VerifyDiagnostic(original); | ||
} | ||
|
||
[TestMethod] | ||
public void SingleEmptyConstructorAnalyzer_WithConstructorBody_DoesNotInvokeWarning () | ||
{ | ||
var original = @" | ||
namespace ConsoleApplication1 | ||
{ | ||
public class MyClass | ||
{ | ||
public int Foo { get; } | ||
public MyClass() | ||
{ | ||
Foo = 0; | ||
} | ||
} | ||
}"; | ||
|
||
VerifyDiagnostic(original); | ||
} | ||
|
||
[TestMethod] | ||
public void SingleEmptyConstructorAnalyzer_WithImplicitPrivateConstructor_DoesNotInvokeWarning () | ||
{ | ||
var original = @" | ||
namespace ConsoleApplication1 | ||
{ | ||
public class MyClass | ||
{ | ||
public int Foo { get; } | ||
MyClass() | ||
{ | ||
Foo = 0; | ||
} | ||
} | ||
}"; | ||
|
||
VerifyDiagnostic(original); | ||
} | ||
|
||
[TestMethod] | ||
public void SingleEmptyConstructorAnalyzer_WithExplicitInternalConstructor_DoesNotInvokeWarning () | ||
{ | ||
var original = @" | ||
namespace ConsoleApplication1 | ||
{ | ||
public class MyClass | ||
{ | ||
public int Foo { get; } | ||
internal MyClass() | ||
{ | ||
Foo = 0; | ||
} | ||
} | ||
}"; | ||
|
||
VerifyDiagnostic(original); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
64 changes: 64 additions & 0 deletions
64
...SDiagnostics/Diagnostics/General/SingleEmptyConstructor/SingleEmptyConstructorAnalyzer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
using System.Collections.Immutable; | ||
using System.Linq; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CSharp; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
|
||
namespace VSDiagnostics.Diagnostics.General.SingleEmptyConstructor | ||
{ | ||
[DiagnosticAnalyzer(LanguageNames.CSharp)] | ||
class SingleEmptyConstructorAnalyzer : DiagnosticAnalyzer | ||
{ | ||
private const string Category = "General"; | ||
private const string DiagnosticId = nameof(SingleEmptyConstructorAnalyzer); | ||
private const string Message = "Use default constructor."; | ||
private const DiagnosticSeverity Severity = DiagnosticSeverity.Warning; | ||
private const string Title = "Your constructor is the same as a default constructor and can be removed."; | ||
|
||
internal static DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, Severity, true); | ||
|
||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule); | ||
|
||
public override void Initialize (AnalysisContext context) | ||
{ | ||
context.RegisterSyntaxNodeAction(AnalyzeSymbol, SyntaxKind.ConstructorDeclaration); | ||
} | ||
|
||
private void AnalyzeSymbol (SyntaxNodeAnalysisContext context) | ||
{ | ||
var ctorExpression = context.Node as ConstructorDeclarationSyntax; | ||
if (ctorExpression == null) | ||
{ | ||
return; | ||
} | ||
|
||
// ctor must be public | ||
if (ctorExpression.Modifiers.ToImmutableList().All(m => m.Text != "public")) | ||
{ | ||
return; | ||
} | ||
|
||
// ctor must not have parameters | ||
if (ctorExpression.ParameterList.Parameters.Any()) | ||
{ | ||
return; | ||
} | ||
|
||
// ctor must have no body statements | ||
if (ctorExpression.Body.Statements.Any()) | ||
{ | ||
return; | ||
} | ||
|
||
// ctor must not have comment - ignore empty brace pairs | ||
var text = ctorExpression.Body.GetText().ToString().ToCharArray(); | ||
if (text.Any(ch => !char.IsWhiteSpace(ch) && ch != '{' && ch != '}')) | ||
{ | ||
return; | ||
} | ||
|
||
context.ReportDiagnostic(Diagnostic.Create(Rule, ctorExpression.GetLocation())); | ||
} | ||
} | ||
} |
38 changes: 38 additions & 0 deletions
38
...VSDiagnostics/Diagnostics/General/SingleEmptyConstructor/SingleEmptyConstructorCodeFix.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CodeFixes; | ||
using System.Composition; | ||
using System.Collections.Immutable; | ||
using System.Threading.Tasks; | ||
using System.Linq; | ||
using Microsoft.CodeAnalysis.CodeActions; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
|
||
namespace VSDiagnostics.Diagnostics.General.SingleEmptyConstructor | ||
{ | ||
[ExportCodeFixProvider("SingleEmptyConstructorCodeFix", LanguageNames.CSharp), Shared] | ||
class SingleEmptyConstructorCodeFix : CodeFixProvider | ||
{ | ||
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(SingleEmptyConstructorAnalyzer.Rule.Id); | ||
|
||
public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; | ||
|
||
public override async Task RegisterCodeFixesAsync(CodeFixContext context) | ||
{ | ||
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); | ||
var diagnostic = context.Diagnostics.First(); | ||
var diagnosticSpan = diagnostic.Location.SourceSpan; | ||
|
||
var statement = root.FindNode(diagnosticSpan); | ||
context.RegisterCodeFix(CodeAction.Create("Simplify expression", x => RemoveConstructorAsync(context.Document, root, statement), nameof(SingleEmptyConstructorAnalyzer)), diagnostic); | ||
} | ||
|
||
private Task<Solution> RemoveConstructorAsync(Document document, SyntaxNode root, SyntaxNode statement) | ||
{ | ||
var ctorDeclarationExpression = (ConstructorDeclarationSyntax) statement; | ||
var newRoot = root.RemoveNode(ctorDeclarationExpression, SyntaxRemoveOptions.KeepNoTrivia); | ||
|
||
var newDocument = document.WithSyntaxRoot(newRoot); | ||
return Task.FromResult(newDocument.Project.Solution); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters