This repository has been archived by the owner. It is now read-only.
/
ParameterOnlyAssignedAnalyzer.cs
82 lines (73 loc) · 3.35 KB
/
ParameterOnlyAssignedAnalyzer.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
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System.Collections.Immutable;
using System.Linq;
namespace RefactoringEssentials.CSharp.Diagnostics
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class ParameterOnlyAssignedAnalyzer : VariableOnlyAssignedAnalyzer
{
private static readonly DiagnosticDescriptor descriptor = new DiagnosticDescriptor(
CSharpDiagnosticIDs.ParameterOnlyAssignedAnalyzerID,
GettextCatalog.GetString("Parameter is assigned but its value is never used"),
GettextCatalog.GetString("Parameter is assigned but its value is never used"),
DiagnosticAnalyzerCategories.CodeQualityIssues,
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
helpLinkUri: HelpLink.CreateFor(CSharpDiagnosticIDs.ParameterOnlyAssignedAnalyzerID)
);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(descriptor);
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(
(nodeContext) =>
{
Diagnostic diagnostic;
if (TryGetDiagnostic(nodeContext, out diagnostic))
{
nodeContext.ReportDiagnostic(diagnostic);
}
},
SyntaxKind.Parameter
);
}
private static bool TryGetDiagnostic(SyntaxNodeAnalysisContext nodeContext, out Diagnostic diagnostic)
{
diagnostic = default(Diagnostic);
if (nodeContext.IsFromGeneratedCode())
return false;
var parameter = nodeContext.Node as ParameterSyntax;
if (parameter == null)
return false;
if (parameter.Modifiers.Any(SyntaxKind.OutKeyword) || parameter.Modifiers.Any(SyntaxKind.RefKeyword))
return false;
var localParamSymbol = nodeContext.SemanticModel.GetDeclaredSymbol(parameter);
if (localParamSymbol == null)
return false;
var method = parameter.Parent.Parent as MethodDeclarationSyntax;
if (method == null || method.Body == null)
return false;
var dataFlow = nodeContext.SemanticModel.AnalyzeDataFlow(method.Body);
if (dataFlow.AlwaysAssigned.Except(dataFlow.ReadInside).Contains(localParamSymbol))
{
var statements = method.Body.Statements;
foreach (var statement in statements)
{
var expression = statement as ExpressionStatementSyntax;
var assignment = expression?.Expression as AssignmentExpressionSyntax;
if (assignment == null)
continue;
var symbol = nodeContext.SemanticModel.GetSymbolInfo(assignment.Left).Symbol as IParameterSymbol;
if (localParamSymbol.Equals(symbol))
{
diagnostic = Diagnostic.Create(descriptor, assignment.GetLocation());
return true;
}
}
}
return false;
}
}
}