Skip to content

Commit

Permalink
REFL044 Expected attribute type. DotNetAnalyzers#182.
Browse files Browse the repository at this point in the history
  • Loading branch information
JohanLarsson committed Nov 3, 2018
1 parent 155efec commit be33eb7
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 1 deletion.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,5 +176,9 @@ Analyzers checking System.Reflection
<td><a href="https://github.com/DotNetAnalyzers/ReflectionAnalyzers/tree/master/documentation/REFL043.md">REFL043</a></td>
<td>First argument must match type.</td>
</tr>
<tr>
<td><a href="https://github.com/DotNetAnalyzers/ReflectionAnalyzers/tree/master/documentation/REFL044.md">REFL044</a></td>
<td>Expected attribute type.</td>
</tr>
<table>
<!-- end generated table -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
namespace ReflectionAnalyzers.Tests.REFL044ExpectedAttributeTypeTests
{
using Gu.Roslyn.Asserts;
using Microsoft.CodeAnalysis.Diagnostics;
using NUnit.Framework;

internal class CodeFix
{
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);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
namespace ReflectionAnalyzers.Tests.REFL044ExpectedAttributeTypeTests
{
using Gu.Roslyn.Asserts;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using NUnit.Framework;

internal class ValidCode
{
private static readonly DiagnosticAnalyzer Analyzer = new GetCustomAttributeAnalyzer();
private static readonly DiagnosticDescriptor Descriptor = REFL044ExpectedAttributeType.Descriptor;

[Test]
public void WhenUsingGeneric()
{
var code = @"
namespace RoslynSandbox
{
using System;
using System.Reflection;
class C
{
public C()
{
var attribute = typeof(C).GetCustomAttribute<ObsoleteAttribute>();
}
}
}";
AnalyzerAssert.Valid(Analyzer, Descriptor, code);
}

[Test]
public void WhenGetCustomAttributeCast()
{
var code = @"
namespace RoslynSandbox
{
using System;
class C
{
public C()
{
var attribute = (ObsoleteAttribute)Attribute.GetCustomAttribute(typeof(C), typeof(ObsoleteAttribute));
}
}
}";
AnalyzerAssert.Valid(Analyzer, Descriptor, code);
}

[Test]
public void WhenGetCustomAttributeAs()
{
var code = @"
namespace RoslynSandbox
{
using System;
class C
{
public C()
{
var attribute = Attribute.GetCustomAttribute(typeof(C), typeof(ObsoleteAttribute)) as ObsoleteAttribute;
}
}
}";

AnalyzerAssert.Valid(Analyzer, Descriptor, code);
}
}
}
1 change: 1 addition & 0 deletions ReflectionAnalyzers.sln
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".docs", ".docs", "{1C271AF2
documentation\REFL041.md = documentation\REFL041.md
documentation\REFL042.md = documentation\REFL042.md
documentation\REFL043.md = documentation\REFL043.md
documentation\REFL044.md = documentation\REFL044.md
RELEASE_NOTES.md = RELEASE_NOTES.md
EndProjectSection
EndProject
Expand Down
11 changes: 10 additions & 1 deletion ReflectionAnalyzers/NodeAnalzers/GetCustomAttributeAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ internal class GetCustomAttributeAnalyzer : DiagnosticAnalyzer
/// <inheritdoc/>
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(
REFL010PreferGenericGetCustomAttribute.Descriptor,
REFL012PreferIsDefined.Descriptor);
REFL012PreferIsDefined.Descriptor,
REFL044ExpectedAttributeType.Descriptor);

/// <inheritdoc/>
public override void Initialize(AnalysisContext context)
Expand Down Expand Up @@ -51,6 +52,14 @@ context.Node is InvocationExpressionSyntax invocation &&
nameof(InvocationExpressionSyntax),
invocationText)));
}

if (!attributeType.Value.IsAssignableTo(context.Compilation.GetTypeByMetadataName("System.Attribute"), context.Compilation))
{
context.ReportDiagnostic(
Diagnostic.Create(
REFL044ExpectedAttributeType.Descriptor,
attributeType.Argument.GetLocation()));
}
}
}

Expand Down
19 changes: 19 additions & 0 deletions ReflectionAnalyzers/REFL044ExpectedAttributeType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace ReflectionAnalyzers
{
using Microsoft.CodeAnalysis;

internal static class REFL044ExpectedAttributeType
{
internal const string DiagnosticId = "REFL044";

internal static readonly DiagnosticDescriptor Descriptor = new DiagnosticDescriptor(
id: DiagnosticId,
title: "Expected attribute type.",
messageFormat: "Expected attribute type.",
category: AnalyzerCategory.SystemReflection,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true,
description: "Expected attribute type.",
helpLinkUri: HelpLink.ForId(DiagnosticId));
}
}
67 changes: 67 additions & 0 deletions documentation/REFL044.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# REFL044
## Expected attribute type.

<!-- start generated table -->
<table>
<tr>
<td>CheckId</td>
<td>REFL044</td>
</tr>
<tr>
<td>Severity</td>
<td>Warning</td>
</tr>
<tr>
<td>Enabled</td>
<td>true</td>
</tr>
<tr>
<td>Category</td>
<td>ReflectionAnalyzers.SystemReflection</td>
</tr>
<tr>
<td>Code</td>
<td><a href="https://github.com/DotNetAnalyzers/ReflectionAnalyzers/blob/master/ReflectionAnalyzers/NodeAnalzers/GetCustomAttributeAnalyzer.cs">GetCustomAttributeAnalyzer</a></td>
</tr>
</table>
<!-- end generated table -->

## Description

Expected attribute type.

## Motivation

ADD MOTIVATION HERE

## How to fix violations

ADD HOW TO FIX VIOLATIONS HERE

<!-- start generated config severity -->
## Configure severity

### Via ruleset file.

Configure the severity per project, for more info see [MSDN](https://msdn.microsoft.com/en-us/library/dd264949.aspx).

### Via #pragma directive.
```C#
#pragma warning disable REFL044 // Expected attribute type.
Code violating the rule here
#pragma warning restore REFL044 // Expected attribute type.
```

Or put this at the top of the file to disable all instances.
```C#
#pragma warning disable REFL044 // Expected attribute type.
```

### Via attribute `[SuppressMessage]`.

```C#
[System.Diagnostics.CodeAnalysis.SuppressMessage("ReflectionAnalyzers.SystemReflection",
"REFL044:Expected attribute type.",
Justification = "Reason...")]
```
<!-- end generated config severity -->

0 comments on commit be33eb7

Please sign in to comment.