1
+ using System ;
1
2
using System . Collections . Immutable ;
2
3
using Microsoft . CodeAnalysis ;
3
4
using Microsoft . CodeAnalysis . CSharp ;
@@ -21,13 +22,58 @@ public class ExceptionsAnalyzer : DiagnosticAnalyzer
21
22
22
23
public override ImmutableArray < DiagnosticDescriptor > SupportedDiagnostics { get ; } = ImmutableArray . Create ( Rule , StandartRules . FailedRule ) ;
23
24
24
- public override void Initialize ( AnalysisContext context ) => context . RegisterSafeSyntaxNodeAction ( AnalyzeInvoke , SyntaxKind . InvocationExpression ) ;
25
+ public override void Initialize ( AnalysisContext context )
26
+ {
27
+ context . RegisterCompilationStartAction ( compilationContext =>
28
+ {
29
+
30
+ INamedTypeSymbol interfaceType = compilationContext . Compilation . GetType < Exception > ( ) ;
31
+ if ( interfaceType == null )
32
+ {
33
+ return ;
34
+ }
35
+
36
+ compilationContext . RegisterSyntaxNodeAction (
37
+ symbolContext => { AnalyzeInvoke ( symbolContext , interfaceType ) ; } , SyntaxKind . InvocationExpression ) ;
38
+ }
39
+ ) ;
40
+ }
25
41
26
42
private static readonly ImmutableHashSet < string > LogMethodNames =
27
43
new [ ] { "Error" , "Warn" , "Warning" , "Info" , "Information" , "Debug" , "Trace" }
28
44
. ToImmutableHashSet ( ) ;
29
45
30
- private void AnalyzeInvoke ( SyntaxNodeAnalysisContext context )
46
+ private class FindExceptionMessageVisitor : CSharpSyntaxWalker
47
+ {
48
+ public FindExceptionMessageVisitor ( SyntaxNodeAnalysisContext context ,
49
+ INamedTypeSymbol systemExceptionType )
50
+ {
51
+ Context = context ;
52
+ SystemExceptionType = systemExceptionType ;
53
+ }
54
+
55
+ public bool ExceptionMessagePresent { get ; private set ; } = false ;
56
+ private SyntaxNodeAnalysisContext Context { get ; }
57
+ private INamedTypeSymbol SystemExceptionType { get ; }
58
+
59
+ public override void VisitMemberAccessExpression ( MemberAccessExpressionSyntax member )
60
+ {
61
+ if ( ExceptionMessagePresent )
62
+ {
63
+ return ; // Skip
64
+ }
65
+
66
+ if (
67
+ member . Expression . IsExpressionOfTypeOrDerived ( Context , SystemExceptionType ) &&
68
+ member . Name . Identifier . Text == "Message" )
69
+ {
70
+ ExceptionMessagePresent = true ;
71
+ }
72
+ }
73
+ }
74
+
75
+ private static void AnalyzeInvoke ( SyntaxNodeAnalysisContext context ,
76
+ INamedTypeSymbol systemExceptionType )
31
77
{
32
78
if ( ! ( context . Node is InvocationExpressionSyntax invocation ) )
33
79
{
@@ -38,18 +84,40 @@ private void AnalyzeInvoke(SyntaxNodeAnalysisContext context)
38
84
39
85
if ( methodName != null && LogMethodNames . Contains ( methodName ) )
40
86
{
41
- foreach ( var argument in invocation . ArgumentList . Arguments )
87
+ if ( IsExceptionMessagePassedToMethod ( context , invocation , systemExceptionType ) && ! IsExceptionFullyPassedToMethod ( context , invocation , systemExceptionType ) )
42
88
{
43
- if ( argument . Expression is MemberAccessExpressionSyntax member )
44
- {
45
- var x = member . Name . Identifier . Text ;
46
- if ( x == "Message" )
47
- {
48
- context . ReportDiagnostic ( Diagnostic . Create ( Rule , member . GetLocation ( ) ) ) ;
49
- }
50
- }
89
+ context . ReportDiagnostic ( Diagnostic . Create ( Rule , invocation . GetLocation ( ) ) ) ;
90
+ }
91
+ }
92
+ }
93
+
94
+ private static bool IsExceptionFullyPassedToMethod ( SyntaxNodeAnalysisContext context , InvocationExpressionSyntax invocationExpressionSyntax , INamedTypeSymbol systemExceptionType )
95
+ {
96
+ foreach ( var argument in invocationExpressionSyntax . ArgumentList . Arguments )
97
+ {
98
+ if ( argument . Expression . IsExpressionOfTypeOrDerived ( context , systemExceptionType ) )
99
+ {
100
+ return true ;
101
+ }
102
+ }
103
+
104
+ return false ;
105
+ }
106
+
107
+ private static bool IsExceptionMessagePassedToMethod ( SyntaxNodeAnalysisContext context ,
108
+ InvocationExpressionSyntax invocationExpressionSyntax , INamedTypeSymbol systemExceptionType )
109
+ {
110
+ foreach ( var argument in invocationExpressionSyntax . ArgumentList . Arguments )
111
+ {
112
+ var analyzer = new FindExceptionMessageVisitor ( context , systemExceptionType ) ;
113
+ analyzer . Visit ( argument . Expression ) ;
114
+ if ( analyzer . ExceptionMessagePresent )
115
+ {
116
+ return true ;
51
117
}
52
118
}
119
+
120
+ return false ;
53
121
}
54
122
}
55
123
}
0 commit comments