Skip to content

Commit a759f41

Browse files
sebastien-marichalsonartech
authored andcommitted
NET-1323 Fix S3267 AD0001: Support empty return and lambdas
1 parent 99a7f78 commit a759f41

File tree

3 files changed

+78
-3
lines changed

3 files changed

+78
-3
lines changed

analyzers/src/SonarAnalyzer.CSharp/Rules/LoopsAndLinq.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,17 @@ private static bool CanBeSimplifiedUsingWhere(SyntaxNode statement, SonarSyntaxN
6161

6262
private static bool RequiresNullableConversion(SyntaxNode returnOrAssignment, SonarSyntaxNodeReportingContext context)
6363
{
64-
var typeInfo = context.Model.GetTypeInfo(returnOrAssignment switch
64+
var expression = returnOrAssignment switch
6565
{
6666
ReturnStatementSyntax returnStatement => returnStatement.Expression,
6767
AssignmentExpressionSyntax assignment => assignment.Right,
6868
_ => throw new InvalidOperationException("Unreachable")
69-
});
70-
return context.Compilation.ClassifyConversion(typeInfo.Type, typeInfo.ConvertedType).IsNullable;
69+
};
70+
71+
// expression can be null if the return statement is empty
72+
return expression is not null
73+
&& context.Model.GetTypeInfo(expression) is { Type: { } type, ConvertedType: { } convertedType }
74+
&& context.Compilation.ClassifyConversion(type, convertedType).IsNullable;
7175
}
7276

7377
private static SyntaxNode SingleReturnOrBreakingAssignment(IfStatementSyntax ifStatementSyntax)

analyzers/tests/SonarAnalyzer.Test/TestCases/LoopsAndLinq.Latest.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,4 +263,43 @@ void IndexTest(List<string> strings)
263263
}
264264
}
265265
}
266+
267+
class ReturnNull
268+
{
269+
interface IInterface { }
270+
271+
private IInterface? ReturnNullInterface(IEnumerable<int> enumerable, Predicate<int> predicate)
272+
{
273+
foreach (var element in enumerable) // Noncompliant
274+
{
275+
if (predicate(element)) // Secondary
276+
{
277+
return null;
278+
}
279+
}
280+
281+
return null;
282+
}
283+
284+
private int? ReturnDefault(IEnumerable<int> enumerable, Predicate<int> predicate)
285+
{
286+
foreach (var element in enumerable) // Noncompliant
287+
{
288+
if (predicate(element)) // Secondary
289+
{
290+
return default;
291+
}
292+
}
293+
294+
foreach (var element in enumerable) // Noncompliant
295+
{
296+
if (predicate(element)) // Secondary
297+
{
298+
return null;
299+
}
300+
}
301+
302+
return null;
303+
}
304+
}
266305
}

analyzers/tests/SonarAnalyzer.Test/TestCases/LoopsAndLinq.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,4 +548,36 @@ public int Integer
548548
}
549549
}
550550
}
551+
552+
class EmptyReturn
553+
{
554+
public static void MyMethod<T>(IEnumerable<T> enumerable, Predicate<T> predicate) where T : struct
555+
{
556+
foreach (var element in enumerable) // Noncompliant
557+
{
558+
if (predicate(element)) // Secondary
559+
{
560+
return;
561+
}
562+
}
563+
}
564+
}
565+
566+
class Lambda
567+
{
568+
private Predicate<Object> LambdaMethod(IEnumerable<int> enumerable, Predicate<int> predicate)
569+
{
570+
Predicate<Object> lambda = null;
571+
foreach (var element in enumerable) // Noncompliant
572+
{
573+
if (predicate(element)) // Secondary
574+
{
575+
lambda = instance => false;
576+
break;
577+
}
578+
}
579+
580+
return lambda;
581+
}
582+
}
551583
}

0 commit comments

Comments
 (0)