-
Notifications
You must be signed in to change notification settings - Fork 179
/
UnusedReturnValueAnalyzer.cs
88 lines (75 loc) · 3.41 KB
/
UnusedReturnValueAnalyzer.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
namespace FakeItEasy.Analyzer
{
using System;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class UnusedReturnValueAnalyzer : DiagnosticAnalyzer
{
private static readonly ImmutableDictionary<string, DiagnosticDescriptor> DiagnosticsMap = CreateDiagnosticsMap();
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } =
DiagnosticsMap.Values.ToImmutableArray();
public override void Initialize(AnalysisContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
context.RegisterSyntaxNodeAction(AnalyzeCall, SyntaxKind.InvocationExpression);
}
private static void AnalyzeCall(SyntaxNodeAnalysisContext context)
{
var call = context.Node as InvocationExpressionSyntax;
if (call == null)
{
return;
}
var methodSymbol = GetCalledMethodSymbol(call, context);
if (methodSymbol == null)
{
return;
}
var methodFullName =
string.Concat(methodSymbol.ContainingType.GetFullName(), ".", methodSymbol.GetDecoratedName());
var descriptor = DiagnosticsMap.GetValueOrDefault(methodFullName);
if (descriptor == null)
{
return;
}
if (call.Parent is StatementSyntax)
{
var diagnostic = Diagnostic.Create(descriptor, call.GetLocation(), call.ToString());
context.ReportDiagnostic(diagnostic);
}
}
private static IMethodSymbol GetCalledMethodSymbol(InvocationExpressionSyntax call, SyntaxNodeAnalysisContext context)
{
var name = (call?.Expression as MemberAccessExpressionSyntax)?.Name
?? call?.Expression as IdentifierNameSyntax;
return name == null
? null
: context.SemanticModel.GetSymbolInfo(name).Symbol as IMethodSymbol;
}
private static ImmutableDictionary<string, DiagnosticDescriptor> CreateDiagnosticsMap()
{
var callSpecMemberNames = new[]
{
"FakeItEasy.A.CallTo",
"FakeItEasy.A.CallTo`1",
"FakeItEasy.A.CallToSet`1",
"FakeItEasy.Fake`1.CallsTo`1",
"FakeItEasy.Fake`1.AnyCall",
"FakeItEasy.ArgumentValidationConfigurationExtensions.WithAnyArguments`1",
"FakeItEasy.WhereConfigurationExtensions.Where`1",
"FakeItEasy.Configuration.IAnyCallConfigurationWithNoReturnTypeSpecified.WithReturnType`1",
"FakeItEasy.Configuration.IArgumentValidationConfiguration`1.WhenArgumentsMatch",
"FakeItEasy.Configuration.IPropertySetterAnyValueConfiguration`1.To",
"FakeItEasy.Configuration.IWhereConfiguration`1.Where"
};
return callSpecMemberNames.ToImmutableDictionary(name => name, name => DiagnosticDefinitions.UnusedCallSpecification);
}
}
}