forked from DotNetAnalyzers/ReflectionAnalyzers
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Attribute.IsDefined check that second arg is attribute type. Fix DotN…
- Loading branch information
1 parent
be33eb7
commit 14b30ff
Showing
8 changed files
with
194 additions
and
52 deletions.
There are no files selected for viewing
30 changes: 0 additions & 30 deletions
30
ReflectionAnalyzers.Tests/REFL044ExpectedAttributeTypeTests/CodeFix.cs
This file was deleted.
Oops, something went wrong.
33 changes: 33 additions & 0 deletions
33
...ectionAnalyzers.Tests/REFL044ExpectedAttributeTypeTests/Diagnostics.GetCustomAttribute.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,33 @@ | ||
namespace ReflectionAnalyzers.Tests.REFL044ExpectedAttributeTypeTests | ||
{ | ||
using Gu.Roslyn.Asserts; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
using NUnit.Framework; | ||
|
||
public partial class Diagnostics | ||
{ | ||
public class GetCustomAttribute | ||
{ | ||
private static readonly DiagnosticAnalyzer Analyzer = new GetCustomAttributeAnalyzer(); | ||
private static readonly ExpectedDiagnostic ExpectedDiagnostic = ExpectedDiagnostic.Create(REFL044ExpectedAttributeType.DiagnosticId); | ||
|
||
[Test] | ||
public void AttributeGetCustomAttribute() | ||
{ | ||
var code = @" | ||
namespace RoslynSandbox | ||
{ | ||
using System; | ||
class C | ||
{ | ||
public static bool Bar() => Attribute.GetCustomAttribute(typeof(C), ↓typeof(string)) == null; | ||
} | ||
}"; | ||
|
||
var message = "Expected attribute type."; | ||
AnalyzerAssert.Diagnostics(Analyzer, ExpectedDiagnostic.WithMessage(message), code); | ||
} | ||
} | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
ReflectionAnalyzers.Tests/REFL044ExpectedAttributeTypeTests/Diagnostics.IsDefined.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,51 @@ | ||
namespace ReflectionAnalyzers.Tests.REFL044ExpectedAttributeTypeTests | ||
{ | ||
using Gu.Roslyn.Asserts; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
using NUnit.Framework; | ||
|
||
public partial class Diagnostics | ||
{ | ||
public class IsDefined | ||
{ | ||
private static readonly DiagnosticAnalyzer Analyzer = new IsDefinedAnalyzer(); | ||
private static readonly ExpectedDiagnostic ExpectedDiagnostic = ExpectedDiagnostic.Create(REFL044ExpectedAttributeType.DiagnosticId); | ||
|
||
[Test] | ||
public void AttributeIsDefined() | ||
{ | ||
var code = @" | ||
namespace RoslynSandbox | ||
{ | ||
using System; | ||
class C | ||
{ | ||
public static bool M() => Attribute.IsDefined(typeof(C), ↓typeof(string)); | ||
} | ||
}"; | ||
|
||
var message = "Expected attribute type."; | ||
AnalyzerAssert.Diagnostics(Analyzer, ExpectedDiagnostic.WithMessage(message), code); | ||
} | ||
|
||
[Test] | ||
public void IsDefinedExtensionMethod() | ||
{ | ||
var code = @" | ||
namespace RoslynSandbox | ||
{ | ||
using System.Reflection; | ||
class C | ||
{ | ||
public static bool M() => typeof(C).IsDefined(↓typeof(string)); | ||
} | ||
}"; | ||
|
||
var message = "Expected attribute type."; | ||
AnalyzerAssert.Diagnostics(Analyzer, ExpectedDiagnostic.WithMessage(message), code); | ||
} | ||
} | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
namespace ReflectionAnalyzers | ||
{ | ||
using System.Collections.Immutable; | ||
using Gu.Roslyn.AnalyzerExtensions; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CSharp; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
|
||
internal class IsDefinedAnalyzer : DiagnosticAnalyzer | ||
{ | ||
/// <inheritdoc/> | ||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create( | ||
REFL044ExpectedAttributeType.Descriptor); | ||
|
||
/// <inheritdoc/> | ||
public override void Initialize(AnalysisContext context) | ||
{ | ||
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); | ||
context.EnableConcurrentExecution(); | ||
context.RegisterSyntaxNodeAction(Handle, SyntaxKind.InvocationExpression); | ||
} | ||
|
||
private static void Handle(SyntaxNodeAnalysisContext context) | ||
{ | ||
if (!context.IsExcludedFromAnalysis() && | ||
context.Node is InvocationExpressionSyntax invocation && | ||
TryGetArgs(invocation, context, out _, out _, out var attributeType, out _)) | ||
{ | ||
if (!attributeType.Value.IsAssignableTo(context.Compilation.GetTypeByMetadataName("System.Attribute"), context.Compilation)) | ||
{ | ||
context.ReportDiagnostic( | ||
Diagnostic.Create( | ||
REFL044ExpectedAttributeType.Descriptor, | ||
attributeType.Argument.GetLocation())); | ||
} | ||
} | ||
} | ||
|
||
private static bool TryGetArgs(InvocationExpressionSyntax invocation, SyntaxNodeAnalysisContext context, out IMethodSymbol target, out ExpressionSyntax member, out ArgumentAndValue<ITypeSymbol> attributeType, out ArgumentSyntax inheritsArg) | ||
{ | ||
if ((invocation.TryGetTarget(KnownSymbol.Attribute.IsDefined, context.SemanticModel, context.CancellationToken, out target) || | ||
invocation.TryGetTarget(KnownSymbol.CustomAttributeExtensions.IsDefined, context.SemanticModel, context.CancellationToken, out target)) && | ||
target.TryFindParameter("attributeType", out var attributeTypeParameter) && | ||
invocation.TryFindArgument(attributeTypeParameter, out var attributeTypeArg) && | ||
attributeTypeArg.Expression is TypeOfExpressionSyntax typeOf && | ||
context.SemanticModel.TryGetType(typeOf.Type, context.CancellationToken, out var typeSymbol)) | ||
{ | ||
attributeType = new ArgumentAndValue<ITypeSymbol>(attributeTypeArg, typeSymbol); | ||
if (!target.TryFindParameter("inherit", out var inheritParameter) || | ||
!invocation.TryFindArgument(inheritParameter, out inheritsArg)) | ||
{ | ||
inheritsArg = null; | ||
} | ||
|
||
if (target.IsExtensionMethod && | ||
invocation.Expression is MemberAccessExpressionSyntax memberAccess) | ||
{ | ||
member = memberAccess.Expression; | ||
return true; | ||
} | ||
|
||
if (target.TryFindParameter("element", out var elementParameter) && | ||
invocation.TryFindArgument(elementParameter, out var elementArg)) | ||
{ | ||
member = elementArg.Expression; | ||
return true; | ||
} | ||
} | ||
|
||
member = null; | ||
attributeType = default(ArgumentAndValue<ITypeSymbol>); | ||
inheritsArg = null; | ||
return false; | ||
} | ||
} | ||
} |
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