@@ -27,21 +27,33 @@ public partial class InfiniteRecursion
2727 {
2828 private sealed class RoslynChecker : IChecker
2929 {
30- public void CheckForNoExitProperty ( SonarSyntaxNodeReportingContext c , PropertyDeclarationSyntax property , IPropertySymbol propertySymbol )
30+ public void CheckForNoExitProperty ( SonarSyntaxNodeReportingContext c , PropertyDeclarationSyntax property , IPropertySymbol propertySymbol ) =>
31+ CheckForNoExit ( c ,
32+ propertySymbol ,
33+ property . ExpressionBody ,
34+ property . AccessorList ,
35+ property . Identifier . GetLocation ( ) ,
36+ "property's recursion" ,
37+ "property accessor's recursion" ) ;
38+
39+ public void CheckForNoExitIndexer ( SonarSyntaxNodeReportingContext c , IndexerDeclarationSyntax indexer , IPropertySymbol propertySymbol ) =>
40+ CheckForNoExit ( c ,
41+ propertySymbol ,
42+ indexer . ExpressionBody ,
43+ indexer . AccessorList ,
44+ indexer . ThisKeyword . GetLocation ( ) ,
45+ "indexer's recursion" ,
46+ "indexer accessor's recursion" ) ;
47+
48+ public void CheckForNoExitEvent ( SonarSyntaxNodeReportingContext c , EventDeclarationSyntax eventDeclaration , IEventSymbol eventSymbol )
3149 {
32- if ( property . ExpressionBody ? . Expression != null )
33- {
34- var cfg = ControlFlowGraph . Create ( property . ExpressionBody , c . SemanticModel , c . Cancel ) ;
35- var walker = new RecursionSearcher ( new RecursionContext < ControlFlowGraph > ( c , cfg , propertySymbol , property . Identifier . GetLocation ( ) , "property's recursion" ) ) ;
36- walker . CheckPaths ( ) ;
37- }
38- else if ( property . AccessorList != null )
50+ if ( eventDeclaration . AccessorList != null )
3951 {
40- foreach ( var accessor in property . AccessorList . Accessors . Where ( a => a . HasBodyOrExpressionBody ( ) ) )
52+ foreach ( var accessor in eventDeclaration . AccessorList . Accessors . Where ( a => a . HasBodyOrExpressionBody ( ) ) )
4153 {
4254 var cfg = ControlFlowGraph . Create ( accessor , c . SemanticModel , c . Cancel ) ;
43- var context = new RecursionContext < ControlFlowGraph > ( c , cfg , propertySymbol , accessor . Keyword . GetLocation ( ) , "property accessor's recursion" ) ;
44- var walker = new RecursionSearcher ( context , ! accessor . Keyword . IsAnyKind ( SyntaxKind . SetKeyword , SyntaxKindEx . InitKeyword ) ) ;
55+ var context = new RecursionContext < ControlFlowGraph > ( c , cfg , eventSymbol , accessor . Keyword . GetLocation ( ) , "event accessor's recursion" ) ;
56+ var walker = new RecursionSearcher ( context ) ;
4557 walker . CheckPaths ( ) ;
4658 }
4759 }
@@ -57,6 +69,32 @@ public void CheckForNoExitMethod(SonarSyntaxNodeReportingContext c, SyntaxNode b
5769 }
5870 }
5971
72+ private static void CheckForNoExit ( SonarSyntaxNodeReportingContext c ,
73+ IPropertySymbol propertySymbol ,
74+ ArrowExpressionClauseSyntax expressionBody ,
75+ AccessorListSyntax accessorList ,
76+ Location location ,
77+ string arrowExpressionMessageArg ,
78+ string accessorMessageArg )
79+ {
80+ if ( expressionBody ? . Expression != null )
81+ {
82+ var cfg = ControlFlowGraph . Create ( expressionBody , c . SemanticModel , c . Cancel ) ;
83+ var walker = new RecursionSearcher ( new RecursionContext < ControlFlowGraph > ( c , cfg , propertySymbol , location , arrowExpressionMessageArg ) ) ;
84+ walker . CheckPaths ( ) ;
85+ }
86+ else if ( accessorList != null )
87+ {
88+ foreach ( var accessor in accessorList . Accessors . Where ( a => a . HasBodyOrExpressionBody ( ) ) )
89+ {
90+ var cfg = ControlFlowGraph . Create ( accessor , c . SemanticModel , c . Cancel ) ;
91+ var context = new RecursionContext < ControlFlowGraph > ( c , cfg , propertySymbol , accessor . Keyword . GetLocation ( ) , accessorMessageArg ) ;
92+ var walker = new RecursionSearcher ( context , ! accessor . Keyword . IsAnyKind ( SyntaxKind . SetKeyword , SyntaxKindEx . InitKeyword ) ) ;
93+ walker . CheckPaths ( ) ;
94+ }
95+ }
96+ }
97+
6098 private sealed class RecursionSearcher : CfgAllPathValidator
6199 {
62100 private readonly RecursionContext < ControlFlowGraph > context ;
@@ -97,18 +135,18 @@ when IPropertyReferenceOperationWrapper.FromOperation(operation) is var property
97135 OperationKindEx . Invocation
98136 when IInvocationOperationWrapper . FromOperation ( operation ) is var invocation && ( ! invocation . IsVirtual || InstanceReferencesThis ( invocation . Instance ) ) =>
99137 invocation . TargetMethod ,
100- OperationKindEx . Binary
101- when IBinaryOperationWrapper . FromOperation ( operation ) is var binaryOperation =>
102- binaryOperation . OperatorMethod ,
103- OperationKindEx . Decrement
104- when IIncrementOrDecrementOperationWrapper . FromOperation ( operation ) is var decrementOperation =>
105- decrementOperation . OperatorMethod ,
106- OperationKindEx . Increment
107- when IIncrementOrDecrementOperationWrapper . FromOperation ( operation ) is var incrementOperation =>
108- incrementOperation . OperatorMethod ,
109- OperationKindEx . Unary
110- when IUnaryOperationWrapper . FromOperation ( operation ) is var unaryOperation =>
111- unaryOperation . OperatorMethod ,
138+ OperationKindEx . Binary =>
139+ IBinaryOperationWrapper . FromOperation ( operation ) . OperatorMethod ,
140+ OperationKindEx . Decrement =>
141+ IIncrementOrDecrementOperationWrapper . FromOperation ( operation ) . OperatorMethod ,
142+ OperationKindEx . Increment =>
143+ IIncrementOrDecrementOperationWrapper . FromOperation ( operation ) . OperatorMethod ,
144+ OperationKindEx . Unary =>
145+ IUnaryOperationWrapper . FromOperation ( operation ) . OperatorMethod ,
146+ OperationKindEx . Conversion =>
147+ IConversionOperationWrapper . FromOperation ( operation ) . OperatorMethod ,
148+ OperationKindEx . EventReference =>
149+ IEventReferenceOperationWrapper . FromOperation ( operation ) . Member ,
112150 _ => null
113151 } ;
114152
0 commit comments