-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add HLQ009_RemoveOptionalMethods (#30)
* Add HLQ009 * Add IsEmptyDispose and IsEmptyReset methods * Refactor and test methods IsEmptyMethod and IsEmptyAsyncMethod * Cleanup * Implement rule * Add documentation
- Loading branch information
Showing
40 changed files
with
838 additions
and
65 deletions.
There are no files selected for viewing
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
File renamed without changes.
55 changes: 55 additions & 0 deletions
55
NetFabric.Hyperlinq.Analyzer.UnitTests/HLQ009_RemoveOptionalMethodsAnalyzerTests.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,55 @@ | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CodeFixes; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
using System.IO; | ||
using System.Linq; | ||
using TestHelper; | ||
using Xunit; | ||
|
||
namespace NetFabric.Hyperlinq.Analyzer.UnitTests | ||
{ | ||
public class RemoveOptionalMethodsAnalyzerTests : DiagnosticVerifier | ||
{ | ||
protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer() => | ||
new RemoveOptionalMethodsAnalyzer(); | ||
|
||
[Theory] | ||
[InlineData("TestData/HLQ009/NoDiagnostic/AsyncEnumerable.cs")] | ||
[InlineData("TestData/HLQ009/NoDiagnostic/Dispose.cs")] | ||
[InlineData("TestData/HLQ009/NoDiagnostic/DisposeAsync.cs")] | ||
[InlineData("TestData/HLQ009/NoDiagnostic/Enumerable.cs")] | ||
[InlineData("TestData/HLQ009/NoDiagnostic/Reset.cs")] | ||
public void Verify_NoDiagnostics(string path) | ||
{ | ||
var paths = new[] | ||
{ | ||
path, | ||
}; | ||
VerifyCSharpDiagnostic(paths.Select(path => File.ReadAllText(path)).ToArray()); | ||
} | ||
|
||
[Theory] | ||
[InlineData("TestData/HLQ009/Diagnostic/Dispose.cs", "Dispose", 16, 25)] | ||
[InlineData("TestData/HLQ009/Diagnostic/DisposeAsync.cs", "DisposeAsync", 18, 30)] | ||
[InlineData("TestData/HLQ009/Diagnostic/Reset.cs", "Reset", 16, 25)] | ||
public void Verify_Diagnostic(string path, string name, int line, int column) | ||
{ | ||
var paths = new[] | ||
{ | ||
path, | ||
}; | ||
var sources = paths.Select(path => File.ReadAllText(path)).ToArray(); | ||
var expected = new DiagnosticResult | ||
{ | ||
Id = "HLQ009", | ||
Message = $"Consider removing the empty optional enumerator method '{name}'.", | ||
Severity = DiagnosticSeverity.Info, | ||
Locations = new[] { | ||
new DiagnosticResultLocation("Test0.cs", line, column) | ||
}, | ||
}; | ||
|
||
VerifyCSharpDiagnostic(paths.Select(path => File.ReadAllText(path)).ToArray(), expected); | ||
} | ||
} | ||
} |
76 changes: 76 additions & 0 deletions
76
NetFabric.Hyperlinq.Analyzer.UnitTests/MethodDeclarationSyntaxExtensionsTests.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,76 @@ | ||
using Microsoft.CodeAnalysis.CSharp; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
using System; | ||
using System.IO; | ||
using System.Linq; | ||
using Xunit; | ||
|
||
namespace NetFabric.Hyperlinq.Analyzer.UnitTests | ||
{ | ||
public class MethodDeclarationSyntaxExtensionsTests | ||
{ | ||
[Theory] | ||
[InlineData("TestData/MethodDeclarationSyntaxExtensions/ReturnsVoid.cs", nameof(global::ReturnsVoid.ReturnsVoidMethod), true)] | ||
[InlineData("TestData/MethodDeclarationSyntaxExtensions/ReturnsVoid.cs", nameof(global::ReturnsVoid.ReturnsTypeMethod), false)] | ||
public void ReturnsVoid_Should_Succeed(string path, string methodName, bool expected) | ||
{ | ||
// Arrange | ||
var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(path)); | ||
var method = tree.GetRoot() | ||
.DescendantNodes().OfType<MethodDeclarationSyntax>() | ||
.FirstOrDefault(method => method.Identifier.ValueText == methodName); | ||
|
||
// Act | ||
var result = method.ReturnsVoid(); | ||
|
||
// Assert | ||
Assert.Equal(expected, result); | ||
} | ||
|
||
[Theory] | ||
[InlineData("TestData/MethodDeclarationSyntaxExtensions/IsEmptyAsyncMethod.cs", nameof(global::IsEmptyAsyncMethod.EmptyArrowDefaultAsync), true)] | ||
[InlineData("TestData/MethodDeclarationSyntaxExtensions/IsEmptyAsyncMethod.cs", nameof(global::IsEmptyAsyncMethod.EmptyArrowNewAsync), true)] | ||
[InlineData("TestData/MethodDeclarationSyntaxExtensions/IsEmptyAsyncMethod.cs", nameof(global::IsEmptyAsyncMethod.EmptyArrowThrowAsync), true)] | ||
[InlineData("TestData/MethodDeclarationSyntaxExtensions/IsEmptyAsyncMethod.cs", nameof(global::IsEmptyAsyncMethod.EmptyBlockDefaultAsync), true)] | ||
[InlineData("TestData/MethodDeclarationSyntaxExtensions/IsEmptyAsyncMethod.cs", nameof(global::IsEmptyAsyncMethod.EmptyBlockNewAsync), true)] | ||
[InlineData("TestData/MethodDeclarationSyntaxExtensions/IsEmptyAsyncMethod.cs", nameof(global::IsEmptyAsyncMethod.EmptyBlockThrowAsync), true)] | ||
[InlineData("TestData/MethodDeclarationSyntaxExtensions/IsEmptyAsyncMethod.cs", nameof(global::IsEmptyAsyncMethod.NotEmptyBlockDefaultAsync), false)] | ||
[InlineData("TestData/MethodDeclarationSyntaxExtensions/IsEmptyAsyncMethod.cs", nameof(global::IsEmptyAsyncMethod.NotEmptyBlockNewAsync), false)] | ||
[InlineData("TestData/MethodDeclarationSyntaxExtensions/IsEmptyAsyncMethod.cs", nameof(global::IsEmptyAsyncMethod.NotEmptyBlockThrowAsync), false)] | ||
public void IsEmptyAsyncMethod_Should_Succeed(string path, string methodName, bool expected) | ||
{ | ||
// Arrange | ||
var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(path)); | ||
var method = tree.GetRoot() | ||
.DescendantNodes().OfType<MethodDeclarationSyntax>() | ||
.FirstOrDefault(method => method.Identifier.ValueText == methodName); | ||
|
||
// Act | ||
var result = method.IsEmptyAsyncMethod(); | ||
|
||
// Assert | ||
Assert.Equal(expected, result); | ||
} | ||
|
||
[Theory] | ||
[InlineData("TestData/MethodDeclarationSyntaxExtensions/IsEmptyMethod.cs", nameof(global::IsEmptyMethod.EmptyArrowThrow), true)] | ||
[InlineData("TestData/MethodDeclarationSyntaxExtensions/IsEmptyMethod.cs", nameof(global::IsEmptyMethod.EmptyBlock), true)] | ||
[InlineData("TestData/MethodDeclarationSyntaxExtensions/IsEmptyMethod.cs", nameof(global::IsEmptyMethod.EmptyBlockThrow), true)] | ||
[InlineData("TestData/MethodDeclarationSyntaxExtensions/IsEmptyMethod.cs", nameof(global::IsEmptyMethod.NotEmptyBlock), false)] | ||
[InlineData("TestData/MethodDeclarationSyntaxExtensions/IsEmptyMethod.cs", nameof(global::IsEmptyMethod.NotEmptyBlockThrow), false)] | ||
public void IsEmptyMethod_Should_Succeed(string path, string methodName, bool expected) | ||
{ | ||
// Arrange | ||
var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(path)); | ||
var method = tree.GetRoot() | ||
.DescendantNodes().OfType<MethodDeclarationSyntax>() | ||
.FirstOrDefault(method => method.Identifier.ValueText == methodName); | ||
|
||
// Act | ||
var result = method.IsEmptyMethod(); | ||
|
||
// Assert | ||
Assert.Equal(expected, result); | ||
} | ||
} | ||
} |
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
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
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
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
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
30 changes: 30 additions & 0 deletions
30
NetFabric.Hyperlinq.Analyzer.UnitTests/TestData/HLQ009/Diagnostic/Dispose.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,30 @@ | ||
using NetFabric.Hyperlinq.Analyzer.UnitTests.TestData; | ||
using System; | ||
|
||
namespace HLQ009.Diagnostics | ||
{ | ||
readonly struct DisposeEnumerable<T> | ||
{ | ||
public Enumerator GetEnumerator() => new Enumerator(); | ||
|
||
public struct Enumerator : IDisposable | ||
{ | ||
public T Current => default; | ||
|
||
public bool MoveNext() => false; | ||
|
||
public void Dispose() { } | ||
} | ||
} | ||
|
||
partial class C | ||
{ | ||
public void Test_DisposeEnumerable() | ||
{ | ||
foreach (var _ in new DisposeEnumerable<TestType>()) | ||
{ | ||
|
||
} | ||
} | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
NetFabric.Hyperlinq.Analyzer.UnitTests/TestData/HLQ009/Diagnostic/DisposeAsync.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,32 @@ | ||
using NetFabric.Hyperlinq.Analyzer.UnitTests.TestData; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Threading.Tasks; | ||
|
||
namespace HLQ009.Diagnostics.Async | ||
{ | ||
readonly struct DisposeAsyncEnumerable<T> | ||
{ | ||
public Enumerator GetAsyncEnumerator() => new Enumerator(); | ||
|
||
public struct Enumerator : IAsyncDisposable | ||
{ | ||
public T Current => default; | ||
|
||
public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(false); | ||
|
||
public ValueTask DisposeAsync() => new ValueTask(); | ||
} | ||
} | ||
|
||
partial class C | ||
{ | ||
public async ValueTask Test_DisposeAsyncEnumerable() | ||
{ | ||
await foreach (var _ in new DisposeAsyncEnumerable<TestType>()) | ||
{ | ||
|
||
} | ||
} | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
NetFabric.Hyperlinq.Analyzer.UnitTests/TestData/HLQ009/Diagnostic/Reset.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,30 @@ | ||
using NetFabric.Hyperlinq.Analyzer.UnitTests.TestData; | ||
using System; | ||
|
||
namespace HLQ009.Diagnostics | ||
{ | ||
readonly struct ResetEnumerable<T> | ||
{ | ||
public Enumerator GetEnumerator() => new Enumerator(); | ||
|
||
public struct Enumerator | ||
{ | ||
public T Current => default; | ||
|
||
public bool MoveNext() => false; | ||
|
||
public void Reset() => throw new NotImplementedException(); | ||
} | ||
} | ||
|
||
partial class C | ||
{ | ||
public void Test_ResetEnumerable() | ||
{ | ||
foreach (var _ in new ResetEnumerable<TestType>()) | ||
{ | ||
|
||
} | ||
} | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
NetFabric.Hyperlinq.Analyzer.UnitTests/TestData/HLQ009/NoDiagnostic/AsyncEnumerable.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,28 @@ | ||
using NetFabric.Hyperlinq.Analyzer.UnitTests.TestData; | ||
using System.Threading.Tasks; | ||
|
||
namespace HLQ009.NoDiagnostics | ||
{ | ||
readonly struct AsyncEnumerable<T> | ||
{ | ||
public Enumerator GetAsyncEnumerator() => new Enumerator(); | ||
|
||
public struct Enumerator | ||
{ | ||
public T Current => default; | ||
|
||
public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(false); | ||
} | ||
} | ||
|
||
partial class C | ||
{ | ||
public async ValueTask Test_AsyncEnumerable() | ||
{ | ||
await foreach (var _ in new AsyncEnumerable<TestType>()) | ||
{ | ||
|
||
} | ||
} | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
NetFabric.Hyperlinq.Analyzer.UnitTests/TestData/HLQ009/NoDiagnostic/Dispose.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,37 @@ | ||
using NetFabric.Hyperlinq.Analyzer.UnitTests.TestData; | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
|
||
namespace HLQ009.NoDiagnostics | ||
{ | ||
readonly struct DisposeEnumerable<T> : IEnumerable<T> | ||
{ | ||
public Enumerator GetEnumerator() => new Enumerator(); | ||
IEnumerator<T> IEnumerable<T>.GetEnumerator() => new Enumerator(); | ||
IEnumerator IEnumerable.GetEnumerator() => new Enumerator(); | ||
|
||
public struct Enumerator : IEnumerator<T> | ||
{ | ||
public T Current => default; | ||
object IEnumerator.Current => default; | ||
|
||
public bool MoveNext() => false; | ||
|
||
public void Reset() => throw new NotImplementedException(); | ||
|
||
public void Dispose() { } | ||
} | ||
} | ||
|
||
partial class C | ||
{ | ||
public void Test_DisposeEnumerable() | ||
{ | ||
foreach (var _ in new DisposeEnumerable<TestType>()) | ||
{ | ||
|
||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.