Skip to content

Commit c5dd70b

Browse files
Bart KoelmanBart Koelman
authored andcommitted
AV1532: Fixed: do not descend into local functions
1 parent 5ef499c commit c5dd70b

File tree

2 files changed

+153
-0
lines changed

2 files changed

+153
-0
lines changed

src/CSharpGuidelinesAnalyzer/CSharpGuidelinesAnalyzer.Test/Specs/Maintainability/AvoidNestedLoopsSpecs.cs

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Linq;
12
using CSharpGuidelinesAnalyzer.Rules.Maintainability;
23
using CSharpGuidelinesAnalyzer.Test.TestDataBuilders;
34
using Microsoft.CodeAnalysis.Diagnostics;
@@ -101,6 +102,54 @@ void M()
101102
"Loop statement contains nested loop.");
102103
}
103104

105+
[Fact]
106+
internal void When_method_contains_single_deconstructing_foreach_loop_it_must_be_skipped()
107+
{
108+
// Arrange
109+
ParsedSourceCode source = new MemberSourceCodeBuilder()
110+
.Using(typeof(Enumerable).Namespace)
111+
.InDefaultClass(@"
112+
void M()
113+
{
114+
foreach (var (outer1, outer2) in Enumerable.Empty<(int, int)>())
115+
{
116+
}
117+
}
118+
")
119+
.Build();
120+
121+
// Act and assert
122+
VerifyGuidelineDiagnostic(source);
123+
}
124+
125+
[Fact]
126+
internal void When_method_contains_nested_deconstructing_foreach_loop_it_must_be_reported()
127+
{
128+
// Arrange
129+
ParsedSourceCode source = new MemberSourceCodeBuilder()
130+
.Using(typeof(Enumerable).Namespace)
131+
.InDefaultClass(@"
132+
void M()
133+
{
134+
foreach (var (outer1, outer2) in Enumerable.Empty<(int, int)>())
135+
{
136+
[|foreach|] (var (inner1, inner2) in Enumerable.Empty<(int, int)>())
137+
{
138+
[|foreach|] (var (nestedInner1, nestedInner2) in Enumerable.Empty<(int, int)>())
139+
{
140+
}
141+
}
142+
}
143+
}
144+
")
145+
.Build();
146+
147+
// Act and assert
148+
VerifyGuidelineDiagnostic(source,
149+
"Loop statement contains nested loop.",
150+
"Loop statement contains nested loop.");
151+
}
152+
104153
[Fact]
105154
internal void When_method_contains_single_while_loop_it_must_be_skipped()
106155
{
@@ -197,6 +246,106 @@ void M()
197246
"Loop statement contains nested loop.");
198247
}
199248

249+
[Fact]
250+
internal void When_method_contains_nested_loop_in_local_function_it_must_be_skipped()
251+
{
252+
// Arrange
253+
ParsedSourceCode source = new MemberSourceCodeBuilder()
254+
.InDefaultClass(@"
255+
void M()
256+
{
257+
for (int i = 0; i < 10; i++)
258+
{
259+
void Local()
260+
{
261+
for (int j = 0; j < 10; j++)
262+
{
263+
}
264+
}
265+
}
266+
}
267+
")
268+
.Build();
269+
270+
// Act and assert
271+
VerifyGuidelineDiagnostic(source);
272+
}
273+
274+
[Fact]
275+
internal void When_method_contains_nested_loop_in_lambda_block_it_must_be_skipped()
276+
{
277+
// Arrange
278+
ParsedSourceCode source = new MemberSourceCodeBuilder()
279+
.InDefaultClass(@"
280+
void M()
281+
{
282+
for (int i = 0; i < 10; i++)
283+
{
284+
Action<int> action = x =>
285+
{
286+
for (int j = 0; j < 10; j++)
287+
{
288+
}
289+
};
290+
}
291+
}
292+
")
293+
.Build();
294+
295+
// Act and assert
296+
VerifyGuidelineDiagnostic(source);
297+
}
298+
299+
[Fact]
300+
internal void When_method_contains_nested_loop_in_parenthesized_lambda_block_it_must_be_skipped()
301+
{
302+
// Arrange
303+
ParsedSourceCode source = new MemberSourceCodeBuilder()
304+
.InDefaultClass(@"
305+
void M()
306+
{
307+
for (int i = 0; i < 10; i++)
308+
{
309+
Action action = () =>
310+
{
311+
for (int j = 0; j < 10; j++)
312+
{
313+
}
314+
};
315+
}
316+
}
317+
")
318+
.Build();
319+
320+
// Act and assert
321+
VerifyGuidelineDiagnostic(source);
322+
}
323+
324+
[Fact]
325+
internal void When_method_contains_nested_loop_in_anonymous_method_it_must_be_skipped()
326+
{
327+
// Arrange
328+
ParsedSourceCode source = new MemberSourceCodeBuilder()
329+
.InDefaultClass(@"
330+
void M()
331+
{
332+
for (int i = 0; i < 10; i++)
333+
{
334+
Action action = delegate
335+
{
336+
for (int j = 0; j < 10; j++)
337+
{
338+
}
339+
};
340+
}
341+
}
342+
")
343+
.Build();
344+
345+
// Act and assert
346+
VerifyGuidelineDiagnostic(source);
347+
}
348+
200349
protected override DiagnosticAnalyzer CreateAnalyzer()
201350
{
202351
return new AvoidNestedLoopsAnalyzer();

src/CSharpGuidelinesAnalyzer/CSharpGuidelinesAnalyzer/Rules/Maintainability/AvoidNestedLoopsAnalyzer.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ public override void VisitForEachLoop([NotNull] IForEachLoopOperation operation)
7373
{
7474
LoopStatementLocation = operation.TryGetLocationForKeyword();
7575
}
76+
77+
public override void VisitLocalFunction([NotNull] ILocalFunctionOperation operation)
78+
{
79+
}
7680
}
7781
}
7882
}

0 commit comments

Comments
 (0)