Skip to content

Commit a025665

Browse files
apply comments and codestyle fixes
Revert "apply comments and codestyle fixes" This reverts commit 35c6c8f. minor cleanup revert accidental change
1 parent a687f6d commit a025665

File tree

3 files changed

+223
-230
lines changed

3 files changed

+223
-230
lines changed

analyzers/src/SonarAnalyzer.CSharp/Rules/InfiniteRecursion.RoslynCfg.cs

Lines changed: 103 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -21,145 +21,137 @@
2121
using SonarAnalyzer.CFG.Roslyn;
2222
using CfgAllPathValidator = SonarAnalyzer.CFG.Roslyn.CfgAllPathValidator;
2323

24-
namespace SonarAnalyzer.Rules.CSharp
24+
namespace SonarAnalyzer.Rules.CSharp;
25+
26+
public partial class InfiniteRecursion
2527
{
26-
public partial class InfiniteRecursion
28+
private sealed class RoslynChecker : IChecker
2729
{
28-
private sealed class RoslynChecker : IChecker
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)
2949
{
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)
50+
if (eventDeclaration.AccessorList is not null)
4951
{
50-
if (eventDeclaration.AccessorList != null)
52+
foreach (var accessor in eventDeclaration.AccessorList.Accessors.Where(x => x.HasBodyOrExpressionBody()))
5153
{
52-
foreach (var accessor in eventDeclaration.AccessorList.Accessors.Where(a => a.HasBodyOrExpressionBody()))
53-
{
54-
var cfg = ControlFlowGraph.Create(accessor, c.SemanticModel, c.Cancel);
55-
var context = new RecursionContext<ControlFlowGraph>(c, cfg, eventSymbol, accessor.Keyword.GetLocation(), "event accessor's recursion");
56-
var walker = new RecursionSearcher(context);
57-
walker.CheckPaths();
58-
}
54+
var cfg = ControlFlowGraph.Create(accessor, c.SemanticModel, c.Cancel);
55+
var context = new RecursionContext<ControlFlowGraph>(c, cfg, eventSymbol, accessor.Keyword.GetLocation(), "event accessor's recursion");
56+
var walker = new RecursionSearcher(context);
57+
walker.CheckPaths();
5958
}
6059
}
60+
}
6161

62-
public void CheckForNoExitMethod(SonarSyntaxNodeReportingContext c, SyntaxNode body, SyntaxToken identifier, IMethodSymbol symbol)
62+
public void CheckForNoExitMethod(SonarSyntaxNodeReportingContext c, SyntaxNode body, SyntaxToken identifier, IMethodSymbol symbol)
63+
{
64+
if (body.CreateCfg(c.SemanticModel, c.Cancel) is { } cfg)
6365
{
64-
if (body.CreateCfg(c.SemanticModel, c.Cancel) is { } cfg)
65-
{
66-
var context = new RecursionContext<ControlFlowGraph>(c, cfg, symbol, identifier.GetLocation(), "method's recursion");
67-
var walker = new RecursionSearcher(context);
68-
walker.CheckPaths();
69-
}
66+
var context = new RecursionContext<ControlFlowGraph>(c, cfg, symbol, identifier.GetLocation(), "method's recursion");
67+
var walker = new RecursionSearcher(context);
68+
walker.CheckPaths();
7069
}
70+
}
7171

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)
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 is not 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 is not null)
7987
{
80-
if (expressionBody?.Expression != null)
88+
foreach (var accessor in accessorList.Accessors.Where(a => a.HasBodyOrExpressionBody()))
8189
{
82-
var cfg = ControlFlowGraph.Create(expressionBody, c.SemanticModel, c.Cancel);
83-
var walker = new RecursionSearcher(new RecursionContext<ControlFlowGraph>(c, cfg, propertySymbol, location, arrowExpressionMessageArg));
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));
8493
walker.CheckPaths();
8594
}
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-
}
9695
}
96+
}
97+
98+
private sealed class RecursionSearcher : CfgAllPathValidator
99+
{
100+
private readonly RecursionContext<ControlFlowGraph> context;
101+
private readonly bool isGetAccesor;
97102

98-
private sealed class RecursionSearcher : CfgAllPathValidator
103+
public RecursionSearcher(RecursionContext<ControlFlowGraph> context, bool isGetAccesor = true)
104+
: base(context.ControlFlowGraph)
99105
{
100-
private readonly RecursionContext<ControlFlowGraph> context;
101-
private readonly bool isGetAccesor;
106+
this.context = context;
107+
this.isGetAccesor = isGetAccesor;
108+
}
102109

103-
public RecursionSearcher(RecursionContext<ControlFlowGraph> context, bool isGetAccesor = true)
104-
: base(context.ControlFlowGraph)
110+
public void CheckPaths()
111+
{
112+
if (!CfgCanExit() || CheckAllPaths())
105113
{
106-
this.context = context;
107-
this.isGetAccesor = isGetAccesor;
114+
context.ReportIssue();
108115
}
116+
}
109117

110-
public void CheckPaths()
118+
protected override bool IsValid(BasicBlock block)
119+
{
120+
if (block.OperationsAndBranchValue.ToReversedExecutionOrder().FirstOrDefault(x => context.AnalyzedSymbol.Equals(MemberSymbol(x.Instance))) is { Instance: { } } operation)
111121
{
112-
if (!CfgCanExit() || CheckAllPaths())
113-
{
114-
context.ReportIssue();
115-
}
122+
var isWrite = operation.Parent is { Kind: OperationKindEx.SimpleAssignment } parent && ISimpleAssignmentOperationWrapper.FromOperation(parent).Target == operation.Instance;
123+
return isGetAccesor ^ isWrite;
116124
}
117125

118-
protected override bool IsValid(BasicBlock block)
119-
{
120-
if (block.OperationsAndBranchValue.ToReversedExecutionOrder().FirstOrDefault(x => context.AnalyzedSymbol.Equals(MemberSymbol(x.Instance))) is { Instance: { } } operation)
121-
{
122-
var isWrite = operation.Parent is { Kind: OperationKindEx.SimpleAssignment } parent
123-
&& ISimpleAssignmentOperationWrapper.FromOperation(parent).Target == operation.Instance;
124-
return isGetAccesor ^ isWrite;
125-
}
126-
127-
return false;
128-
129-
static ISymbol MemberSymbol(IOperation operation) =>
130-
operation.Kind switch
131-
{
132-
OperationKindEx.PropertyReference
133-
when IPropertyReferenceOperationWrapper.FromOperation(operation) is var propertyReference && InstanceReferencesThis(propertyReference.Instance) =>
134-
propertyReference.Property,
135-
OperationKindEx.Invocation
136-
when IInvocationOperationWrapper.FromOperation(operation) is var invocation && (!invocation.IsVirtual || InstanceReferencesThis(invocation.Instance)) =>
137-
invocation.TargetMethod,
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,
150-
_ => null
151-
};
152-
153-
static bool InstanceReferencesThis(IOperation instance) =>
154-
instance == null || instance.IsAnyKind(OperationKindEx.FlowCaptureReference, OperationKindEx.InstanceReference);
155-
}
126+
return false;
156127

157-
protected override bool IsInvalid(BasicBlock block) => false;
128+
static ISymbol MemberSymbol(IOperation operation) =>
129+
operation.Kind switch
130+
{
131+
OperationKindEx.PropertyReference
132+
when IPropertyReferenceOperationWrapper.FromOperation(operation) is var propertyReference && InstanceReferencesThis(propertyReference.Instance) =>
133+
propertyReference.Property,
134+
OperationKindEx.Invocation
135+
when IInvocationOperationWrapper.FromOperation(operation) is var invocation && (!invocation.IsVirtual || InstanceReferencesThis(invocation.Instance)) =>
136+
invocation.TargetMethod,
137+
OperationKindEx.Binary => IBinaryOperationWrapper.FromOperation(operation).OperatorMethod,
138+
OperationKindEx.Decrement => IIncrementOrDecrementOperationWrapper.FromOperation(operation).OperatorMethod,
139+
OperationKindEx.Increment => IIncrementOrDecrementOperationWrapper.FromOperation(operation).OperatorMethod,
140+
OperationKindEx.Unary => IUnaryOperationWrapper.FromOperation(operation).OperatorMethod,
141+
OperationKindEx.Conversion => IConversionOperationWrapper.FromOperation(operation).OperatorMethod,
142+
OperationKindEx.EventReference => IEventReferenceOperationWrapper.FromOperation(operation).Member,
143+
_ => null
144+
};
158145

159-
private bool CfgCanExit() =>
160-
context.ControlFlowGraph.ExitBlock.IsReachable
161-
|| context.ControlFlowGraph.Blocks.Any(x => x.FallThroughSuccessor?.Semantics == ControlFlowBranchSemantics.Throw && x.IsReachable);
146+
static bool InstanceReferencesThis(IOperation instance) =>
147+
instance is null || instance.IsAnyKind(OperationKindEx.FlowCaptureReference, OperationKindEx.InstanceReference);
162148
}
149+
150+
protected override bool IsInvalid(BasicBlock block) => false;
151+
152+
private bool CfgCanExit() =>
153+
context.ControlFlowGraph.ExitBlock.IsReachable
154+
|| context.ControlFlowGraph.Blocks.Any(x => x.FallThroughSuccessor?.Semantics == ControlFlowBranchSemantics.Throw && x.IsReachable);
163155
}
164156
}
165157
}

analyzers/src/SonarAnalyzer.CSharp/Rules/InfiniteRecursion.SonarCfg.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public RecursionSearcherForMethod(RecursionContext<IControlFlowGraph> context)
132132
protected override bool HasReferenceToDeclaringSymbol(Block block) =>
133133
block.Instructions.Any(x =>
134134
x is InvocationExpressionSyntax invocation
135-
&& IsInstructionOnThisAndMatchesDeclaringSymbol(invocation.Expression, context.AnalyzedSymbol, context.SemanticModel));
135+
&& IsInstructionOnThisAndMatchesDeclaringSymbol(invocation.Expression, context.AnalyzedSymbol, context.Model));
136136
}
137137

138138
private class RecursionSearcherForProperty : RecursionSearcher
@@ -149,7 +149,7 @@ protected override bool HasReferenceToDeclaringSymbol(Block block) =>
149149
block.Instructions.Any(x =>
150150
TypesForReference.Contains(x.GetType())
151151
&& MatchesAccessor(x)
152-
&& IsInstructionOnThisAndMatchesDeclaringSymbol(x, context.AnalyzedSymbol, context.SemanticModel));
152+
&& IsInstructionOnThisAndMatchesDeclaringSymbol(x, context.AnalyzedSymbol, context.Model));
153153

154154
private bool MatchesAccessor(SyntaxNode node)
155155
{

0 commit comments

Comments
 (0)