From cadd992eb623643b4e43ffe4e83ef217c07a84e9 Mon Sep 17 00:00:00 2001
From: Tim Pohlmann
Date: Fri, 4 Aug 2023 13:58:16 +0200
Subject: [PATCH 01/20] Reworked secondary locations
---
.../Roslyn/ConditionEvaluatesToConstant.cs | 17 +----
.../ConditionEvaluatesToConstantBase.cs | 67 ++++++++++---------
.../Roslyn/SymbolicRuleCheck.cs | 7 +-
.../ConditionEvaluatesToConstant.CSharp8.cs | 15 +++--
.../Roslyn/ConditionEvaluatesToConstant.cs | 15 +++--
5 files changed, 61 insertions(+), 60 deletions(-)
diff --git a/analyzers/src/SonarAnalyzer.CSharp/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs b/analyzers/src/SonarAnalyzer.CSharp/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
index 9ccf666951c..b0ebbf868f6 100644
--- a/analyzers/src/SonarAnalyzer.CSharp/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
+++ b/analyzers/src/SonarAnalyzer.CSharp/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
@@ -59,18 +59,7 @@ public override void Visit(SyntaxNode node)
}
}
- protected override bool IsLeftCoalesceExpression(SyntaxNode syntax) =>
- syntax.Parent is BinaryExpressionSyntax { } binary
- && binary.OperatorToken.IsKind(SyntaxKind.QuestionQuestionToken)
- && binary.Left == syntax;
-
- protected override bool IsConditionalAccessExpression(SyntaxNode syntax) =>
- syntax.Parent is ConditionalAccessExpressionSyntax conditional && conditional.Expression == syntax;
-
- protected override bool IsForLoopIncrementor(SyntaxNode syntax) =>
- syntax.Parent is ForStatementSyntax forStatement && forStatement.Incrementors.Contains(syntax);
-
- protected override bool IsUsing(SyntaxNode syntax) =>
- (syntax.IsKind(SyntaxKind.VariableDeclaration) && syntax.Parent.IsKind(SyntaxKind.UsingStatement))
- || (syntax is LocalDeclarationStatementSyntax local && local.UsingKeyword().IsKind(SyntaxKind.UsingKeyword));
+ protected override bool IsInsideUsingDeclaration(SyntaxNode node) =>
+ (node.IsKind(SyntaxKind.VariableDeclaration) && node.Parent.IsKind(SyntaxKind.UsingStatement))
+ || (node is LocalDeclarationStatementSyntax local && local.UsingKeyword().IsKind(SyntaxKind.UsingKeyword));
}
diff --git a/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/RuleChecks/ConditionEvaluatesToConstantBase.cs b/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/RuleChecks/ConditionEvaluatesToConstantBase.cs
index df3b3f0918b..fd6b6220be3 100644
--- a/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/RuleChecks/ConditionEvaluatesToConstantBase.cs
+++ b/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/RuleChecks/ConditionEvaluatesToConstantBase.cs
@@ -38,12 +38,9 @@ public abstract class ConditionEvaluatesToConstantBase : SymbolicRuleCheck
private readonly Dictionary trueOperations = new();
private readonly Dictionary falseOperations = new();
- private readonly HashSet reached = new();
+ private readonly List reached = new();
- protected abstract bool IsLeftCoalesceExpression(SyntaxNode syntax);
- protected abstract bool IsConditionalAccessExpression(SyntaxNode syntax);
- protected abstract bool IsForLoopIncrementor(SyntaxNode syntax);
- protected abstract bool IsUsing(SyntaxNode syntax);
+ protected abstract bool IsInsideUsingDeclaration(SyntaxNode node);
public override ProgramState[] PreProcess(SymbolicContext context)
{
@@ -55,7 +52,7 @@ public override ProgramState ConditionEvaluated(SymbolicContext context)
{
var operation = context.Operation.Instance;
if (operation.Kind is not OperationKindEx.Literal
- && !operation.Syntax.Ancestors().Any(IsUsing)
+ && !operation.Syntax.Ancestors().Any(IsInsideUsingDeclaration)
&& operation.TrackedSymbol(context.State) is not IFieldSymbol { IsConst: true }
&& !IsDiscardPattern(operation))
{
@@ -93,53 +90,54 @@ public override void ExecutionCompleted()
private void ReportIssue(IOperation operation, BasicBlock block, bool conditionValue)
{
var issueMessage = operation.Kind == OperationKindEx.IsNull ? MessageNull : string.Format(MessageBool, conditionValue);
- var secondaryLocations = SecondaryLocations(block, conditionValue);
+ var syntax = ToBranchValueCondition(operation.Syntax);
+ var secondaryLocations = SecondaryLocations(block, conditionValue, syntax);
if (secondaryLocations.Any())
{
- ReportIssue(Rule2583, operation, secondaryLocations, issueMessage, S2583MessageSuffix);
+ ReportIssue(Rule2583, syntax, secondaryLocations, issueMessage, S2583MessageSuffix);
}
else
{
- ReportIssue(Rule2589, operation, null, issueMessage, string.Empty);
+ ReportIssue(Rule2589, syntax, null, issueMessage, string.Empty);
}
}
- private List SecondaryLocations(BasicBlock block, bool conditionValue)
+ private List SecondaryLocations(BasicBlock block, bool conditionValue, SyntaxNode conditionSyntax)
{
List locations = new();
- IOperation currentStart = null;
- IOperation currentEnd = null;
- var unreachable = UnreachableOperations(block, conditionValue).Where(x => !IsIgnoredLocation(x.Syntax)).ToHashSet();
- foreach (var operation in unreachable.Concat(reached).OrderBy(x => x.Syntax.SpanStart))
+ var unreachable = UnreachableOperations(block, conditionValue).ToHashSet();
+ var currentStart = conditionSyntax.Span.End;
+ var reachedNodes = reached.Select(x => x.Syntax).Where(x => x.SpanStart > conditionSyntax.Span.End).OrderBy(x => x.SpanStart);
+
+ foreach (var reachedNode in reachedNodes)
{
- if (unreachable.Contains(operation))
- {
- currentStart ??= operation;
- currentEnd = operation;
- }
- else
+ if (AddLocation(reachedNode.SpanStart))
{
- AddCurrent();
+ currentStart = reachedNode.Span.End;
}
}
- AddCurrent();
+ AddLocation(int.MaxValue);
return locations;
- void AddCurrent()
+ bool AddLocation(int end)
{
- if (currentStart is not null)
+ var nodes = unreachable.Where(x => x.SpanStart > currentStart && x.Span.End < end);
+ if (nodes.Any())
{
- locations.Add(currentStart.Syntax.CreateLocation(currentEnd.Syntax));
- currentStart = null;
+ var first = nodes.OrderBy(x => x.SpanStart).First();
+ var last = nodes.OrderBy(x => x.Span.End).Last();
+ locations.Add(first.CreateLocation(last));
+ return true;
}
+ return false;
}
}
- private IEnumerable UnreachableOperations(BasicBlock block, bool conditionValue)
+ private IEnumerable UnreachableOperations(BasicBlock block, bool conditionValue)
{
if (block.SuccessorBlocks.Distinct().Count() != 2)
{
- return Enumerable.Empty();
+ return Enumerable.Empty();
}
HashSet reachable = new() { block };
HashSet unreachable = new();
@@ -147,7 +145,11 @@ private IEnumerable UnreachableOperations(BasicBlock block, bool con
var conditionalIsRechable = (block.ConditionKind == ControlFlowConditionKind.WhenTrue) == conditionValue;
Traverse(conditionalIsRechable ? block.ConditionalSuccessor : block.FallThroughSuccessor, reachable, new List());
Traverse(conditionalIsRechable ? block.FallThroughSuccessor : block.ConditionalSuccessor, unreachable, reachable);
- return unreachable.SelectMany(x => x.OperationsAndBranchValue).Except(reached);
+ return unreachable
+ .SelectMany(x => x.OperationsAndBranchValue)
+ .Except(reached)
+ .SelectMany(x => x.DescendantsAndSelf().Select(x => x.Syntax))
+ .ToList();
static void Traverse(ControlFlowBranch branch, HashSet result, ICollection excluded)
{
@@ -168,8 +170,7 @@ static void Traverse(ControlFlowBranch branch, HashSet result, IColl
}
}
- private bool IsIgnoredLocation(SyntaxNode x) =>
- IsForLoopIncrementor(x)
- || IsConditionalAccessExpression(x)
- || IsLeftCoalesceExpression(x);
+ // For SwitchExpressionArms like `true => 5` we are only interested in the left part (`true`).
+ private static SyntaxNode ToBranchValueCondition(SyntaxNode syntax) =>
+ syntax.IsKind(SyntaxKindEx.SwitchExpressionArm) ? ((SwitchExpressionArmSyntaxWrapper)syntax).Pattern : syntax;
}
diff --git a/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/SymbolicRuleCheck.cs b/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/SymbolicRuleCheck.cs
index f13eb966204..b867c9bbcc5 100644
--- a/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/SymbolicRuleCheck.cs
+++ b/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/SymbolicRuleCheck.cs
@@ -62,9 +62,12 @@ protected void ReportIssue(IOperation operation, IEnumerable additiona
ReportIssue(Rule, operation, additionalLocations, messageArgs);
}
- protected void ReportIssue(DiagnosticDescriptor rule, IOperation operation, IEnumerable additionalLocations, params object[] messageArgs)
+ protected void ReportIssue(DiagnosticDescriptor rule, IOperation operation, IEnumerable additionalLocations, params object[] messageArgs) =>
+ ReportIssue(rule, operation.Syntax, additionalLocations, messageArgs);
+
+ protected void ReportIssue(DiagnosticDescriptor rule, SyntaxNode syntax, IEnumerable additionalLocations, params object[] messageArgs)
{
- var location = operation.Syntax.GetLocation();
+ var location = syntax.GetLocation();
if (reportedDiagnostics.Add(location))
{
context.ReportIssue(Diagnostic.Create(rule, location, additionalLocations, messageArgs));
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.CSharp8.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.CSharp8.cs
index 86d8a9b665c..b5cf878241b 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.CSharp8.cs
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.CSharp8.cs
@@ -23,10 +23,11 @@ public class CSharp8
int SwitchExpression()
{
var a = false;
- return a switch // Secondary FP
+ return a switch
{
- true => 0, // Noncompliant: true branch is always false
- // Secondary@-1
+ true => 0,
+ // ^^^^ Noncompliant
+ // ^ Secondary@-1
false => 1 // Noncompliant: false branch is always true
};
}
@@ -234,8 +235,9 @@ void NullCoalesceAssignment_Useless(string a, string b, string c, string d)
//Left operand: Values notNull, notEmpty and ret are known to be not-null
ret = notNull;
- ret ??= a; // Noncompliant
- // Secondary@-1
+ ret ??= a;
+ // ^^^ Noncompliant
+ // ^ Secondary@-1
ret = notNull;
ret = "Lorem " + (ret ??= a) + " ipsum"; // Noncompliant
@@ -255,7 +257,6 @@ void NullCoalesceAssignment_Useless(string a, string b, string c, string d)
ret = null;
ret = "Lorem " + (ret ??= a) + " ipsum"; // Noncompliant
- // Secondary@-1
//Right operand: isNull is known to be null, therefore ?? is useless
ret = a;
@@ -460,7 +461,7 @@ void IfStatement()
void LogicalAndExpression()
{
- bool a = true;
+ bool a = false;
var b = a && true; // Noncompliant
// Secondary@-1
}
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
index 5f1b73b610f..57c96418abd 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
@@ -64,9 +64,10 @@ public void NotExecutedLoops(object o1, object o2, object o3)
// ^^
for (int i = 0; c3; i++) // Noncompliant {{Change this condition so that it does not always evaluate to 'False'. Some code paths are unreachable.}}
- // ^^
+ // Secondary@-1 ^33#239
{
- if (o3 != null) // Secondary
+ if (o3 != null)
+ // secondary location starts at incrementor and ends at the end of the above line
break;
}
}
@@ -176,6 +177,13 @@ public void Foo7(bool a, bool b)
}
}
+ public void Foo8(bool a, bool b)
+ {
+ a = true;
+ _ = a && b;
+ // ^ Noncompliant
+ }
+
void Pointer(int* a) // Error [CS0214]
{
if (a != null) // Error [CS0214]
@@ -1917,7 +1925,7 @@ public static void NonCompliant6()
S sObj = null;
if (sObj?.str?.Length > 2)
// ^^^^ Noncompliant
- // ^^^^^^^ Secondary@-1
+ // ^^^^^^^^^^^^ Secondary@-1
// ^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
{
Console.WriteLine("a"); // Secondary
@@ -2792,7 +2800,6 @@ void NullCoalesce_Useless(string a, string b, string c, string d)
ret = null ?? a; // Noncompliant
ret = isNull ?? a; // Noncompliant
ret = ((isNull)) ?? a; // Noncompliant
- // Secondary@-1 FP
ret = "Lorem " + (isNull ?? a) + " ipsum"; // Noncompliant
//Right operand: isNull is known to be null, therefore ?? is useless
From 0f4ff345fd14c3719631179dad27a71901aa7179 Mon Sep 17 00:00:00 2001
From: Tim Pohlmann
Date: Fri, 28 Jul 2023 08:49:00 +0200
Subject: [PATCH 02/20] VB Rule
---
.../SymbolicExecutionRunner.cs | 2 +
.../Roslyn/ConditionEvaluatesToConstant.cs | 41 +
.../ConditionEvaluatesToConstantTest.cs | 16 +
.../ConditionEvaluatesToConstant.VB14.vb | 205 ++
.../Roslyn/ConditionEvaluatesToConstant.vb | 2034 +++++++++++++++++
5 files changed, 2298 insertions(+)
create mode 100644 analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
create mode 100644 analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb
create mode 100644 analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
diff --git a/analyzers/src/SonarAnalyzer.VisualBasic/Rules/SymbolicExecution/SymbolicExecutionRunner.cs b/analyzers/src/SonarAnalyzer.VisualBasic/Rules/SymbolicExecution/SymbolicExecutionRunner.cs
index e15472796b0..79a696218c1 100644
--- a/analyzers/src/SonarAnalyzer.VisualBasic/Rules/SymbolicExecution/SymbolicExecutionRunner.cs
+++ b/analyzers/src/SonarAnalyzer.VisualBasic/Rules/SymbolicExecution/SymbolicExecutionRunner.cs
@@ -34,6 +34,8 @@ public SymbolicExecutionRunner() : base(AnalyzerConfiguration.AlwaysEnabled) { }
.Add(HashesShouldHaveUnpredictableSalt.S2053, CreateFactory())
.Add(LocksReleasedAllPaths.S2222, CreateFactory())
.Add(NullPointerDereference.S2259, CreateFactory())
+ .Add(ConditionEvaluatesToConstant.S2583, CreateFactory())
+ .Add(ConditionEvaluatesToConstant.S2589, CreateFactory())
.Add(InitializationVectorShouldBeRandom.S3329, CreateFactory())
.Add(EmptyNullableValueAccess.S3655, CreateFactory())
.Add(PublicMethodArgumentsShouldBeCheckedForNull.S3900, CreateFactory())
diff --git a/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs b/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
new file mode 100644
index 00000000000..54c9fbd7b25
--- /dev/null
+++ b/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
@@ -0,0 +1,41 @@
+/*
+ * SonarAnalyzer for .NET
+ * Copyright (C) 2015-2023 SonarSource SA
+ * mailto: contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+namespace SonarAnalyzer.SymbolicExecution.Roslyn.RuleChecks.VisualBasic;
+
+public class ConditionEvaluatesToConstant : ConditionEvaluatesToConstantBase
+{
+ public static readonly DiagnosticDescriptor S2583 = DescriptorFactory.Create(DiagnosticId2583, MessageFormat);
+ public static readonly DiagnosticDescriptor S2589 = DescriptorFactory.Create(DiagnosticId2589, MessageFormat);
+ protected override DiagnosticDescriptor Rule => null;
+ protected override DiagnosticDescriptor Rule2583 => S2583;
+ protected override DiagnosticDescriptor Rule2589 => S2589;
+
+ public override bool ShouldExecute() => true;
+ protected override bool IsConditionalAccessExpression(SyntaxNode syntax) =>
+ syntax.Parent is ConditionalAccessExpressionSyntax conditional && conditional.Expression == syntax;
+
+ protected override bool IsForLoopIncrementor(SyntaxNode syntax) => false; // Is is possible to have a boolean in a for loop in vb.net?
+ protected override bool IsLeftCoalesceExpression(SyntaxNode syntax) =>
+ syntax.Parent is BinaryConditionalExpressionSyntax { } binary
+ && binary.FirstExpression == syntax;
+ protected override bool IsUsing(SyntaxNode syntax) =>
+ syntax.IsKind(SyntaxKind.VariableDeclarator) && syntax.Parent.IsKind(SyntaxKind.UsingStatement);
+}
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/Rules/SymbolicExecution/ConditionEvaluatesToConstantTest.cs b/analyzers/tests/SonarAnalyzer.UnitTest/Rules/SymbolicExecution/ConditionEvaluatesToConstantTest.cs
index c607bc69370..fe3f8a43516 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/Rules/SymbolicExecution/ConditionEvaluatesToConstantTest.cs
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/Rules/SymbolicExecution/ConditionEvaluatesToConstantTest.cs
@@ -21,7 +21,9 @@
using SonarAnalyzer.SymbolicExecution.Sonar.Analyzers;
using ChecksCS = SonarAnalyzer.SymbolicExecution.Roslyn.RuleChecks.CSharp;
+using ChecksVB = SonarAnalyzer.SymbolicExecution.Roslyn.RuleChecks.VisualBasic;
using CS = SonarAnalyzer.Rules.CSharp;
+using VB = SonarAnalyzer.Rules.VisualBasic;
namespace SonarAnalyzer.UnitTest.Rules;
@@ -38,6 +40,10 @@ public class ConditionEvaluatesToConstantTest
.WithBasePath(@"SymbolicExecution\Roslyn")
.WithOnlyDiagnostics(ChecksCS.ConditionEvaluatesToConstant.S2583, ChecksCS.ConditionEvaluatesToConstant.S2589);
+ private readonly VerifierBuilder roslynVB = new VerifierBuilder()
+ .WithBasePath(@"SymbolicExecution\Roslyn")
+ .WithOnlyDiagnostics(ChecksVB.ConditionEvaluatesToConstant.S2583, ChecksVB.ConditionEvaluatesToConstant.S2589);
+
[DataTestMethod]
[DataRow(ProjectType.Product)]
[DataRow(ProjectType.Test)]
@@ -54,6 +60,16 @@ public void ConditionEvaluatesToConstant_Roslyn_CS(ProjectType projectType) =>
.AddReferences(NuGetMetadataReference.MicrosoftExtensionsPrimitives("3.1.7").Concat(TestHelper.ProjectTypeReference(projectType)))
.Verify();
+ [TestMethod]
+ public void ConditionEvaluatesToConstant_Roslyn_VB() =>
+ roslynVB.AddPaths("ConditionEvaluatesToConstant.vb").Verify();
+
+ [TestMethod]
+ public void ConditionEvaluatesToConstant_Roslyn_VB14() =>
+ roslynVB.AddPaths("ConditionEvaluatesToConstant.VB14.vb")
+ .WithOptions(ParseOptionsHelper.FromVisualBasic14)
+ .Verify();
+
[TestMethod]
public void ConditionEvaluatesToConstant_Sonar_CSharp7() =>
sonar.AddPaths("ConditionEvaluatesToConstant.CSharp7.cs")
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb
new file mode 100644
index 00000000000..d7d673f8474
--- /dev/null
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb
@@ -0,0 +1,205 @@
+Namespace Tests.Diagnostics
+ Public Class VB14
+
+ Private Sub ConditionalAccessNullPropagation(ByVal o As Object)
+ If o Is Nothing Then
+ If Equals(o?.ToString(), Nothing) Then ' Noncompliant
+ ' Secondary@-1
+ ' Noncompliant@-2
+ End If
+ If o?.GetHashCode() Is Nothing Then '' Noncompliant
+ ' Secondary@-1
+ ' Noncompliant@-2
+ End If
+ End If
+ End Sub
+
+ Friend Enum MyEnum
+ One
+ Two
+ End Enum
+
+ Friend Class MyClassWithEnum
+ Public myEnum As MyEnum
+ End Class
+
+ Public Sub EnumMemberAccess()
+ Dim m = New MyClassWithEnum()
+ Console.WriteLine(m.myEnum)
+ m = Nothing
+ If m?.myEnum = MyEnum.One Then ' Noncompliant
+ ' Secondary@-1
+ ' Noncompliant@-2
+ End If
+ End Sub
+
+ Friend Class FooContainer
+ Public Property Foo As Boolean
+ End Class
+
+ Friend Class TestNullConditional
+ Private Sub First(ByVal fooContainer As FooContainer, ByVal bar As Boolean)
+ If fooContainer?.Foo = False OrElse bar Then
+ Console.WriteLine(If(bar, "1", "2"))
+ Else
+ Console.WriteLine(If(fooContainer IsNot Nothing, "3", "4"))
+ End If
+ End Sub
+
+ Private Sub Second(ByVal fooContainer As FooContainer)
+ If fooContainer?.Foo <> True Then
+ Console.WriteLine("3")
+ If fooContainer IsNot Nothing Then
+ Console.WriteLine("4")
+ End If
+ End If
+ End Sub
+
+ Public Class Result
+ Public Property Succeed As Boolean
+
+ Public Shared Function Test() As Result
+ If Date.Now.Day = 17 Then ' swap value here to test both cases if needed
+ Return New Result()
+ End If
+ Return Nothing
+ End Function
+ End Class
+
+ Public Shared Sub Compliant1()
+ Dim result = TestNullConditional.Result.Test()
+
+ If result Is Nothing OrElse Not result.Succeed Then
+ Console.WriteLine("shorted")
+ If result IsNot Nothing Then
+ Console.WriteLine("other")
+ End If
+ End If
+
+ If result?.Succeed <> True Then
+ Console.WriteLine("shorted")
+ If result IsNot Nothing Then
+ Console.WriteLine("other")
+ End If
+ End If
+ End Sub
+
+ Public Shared Sub NonCompliant1()
+ Dim result As Result = Nothing
+ If result?.Succeed IsNot Nothing Then ' Noncompliant
+ ' Secondary@-1
+ ' Noncompliant@-2
+ Console.WriteLine("shorted") ' Secondary
+ If result IsNot Nothing Then
+ Console.WriteLine("other")
+ End If
+ End If
+ End Sub
+
+ Public Shared Sub NonCompliant2()
+ Dim result As Result = New Result()
+ If result?.Succeed IsNot Nothing Then ' Noncompliant
+ ' Noncompliant@-1
+ Console.WriteLine("shorted")
+ While result IsNot Nothing ' Noncompliant
+ Console.WriteLine("other")
+ End While
+ End If
+ End Sub
+
+ Public Class A
+ Public Property booleanVal As Boolean
+ End Class
+
+ Public Shared Sub Compliant2()
+ Dim aObj As A = Nothing
+ If If(aObj?.booleanVal, False) Then ' Noncompliant
+ ' Secondary@-1
+ ' Noncompliant@-2
+ Console.WriteLine("a")
+ End If
+ End Sub
+
+ Public Shared Sub NonCompliant3()
+ Dim aObj As A = Nothing
+ If aObj?.booleanVal Is Nothing Then ' Noncompliant
+ ' Secondary@-1
+ ' Noncompliant@-2
+ Console.WriteLine("a")
+ End If
+
+ If aObj?.booleanVal IsNot Nothing Then ' Noncompliant
+ ' Secondary@-1
+ ' Noncompliant@-2
+ Console.WriteLine("a") ' Secondary
+ End If
+ End Sub
+
+ Public Shared Sub Compliant3(ByVal a As A)
+
+ If a?.booleanVal = True Then
+ Console.WriteLine("Compliant")
+ Return
+ End If
+
+ If a IsNot Nothing Then ' Compliant
+ End If
+ End Sub
+
+ Public Shared Sub NonCompliant4(ByVal a As A)
+
+ If a?.booleanVal Is Nothing Then
+ Console.WriteLine("Compliant")
+ Return
+ End If
+
+ If a IsNot Nothing Then ' Noncompliant
+ End If
+ End Sub
+
+ Public Shared Sub Compliant4(ByVal a As A)
+ If a?.booleanVal Is Nothing Then
+ Console.WriteLine("Compliant")
+ End If
+
+ If a IsNot Nothing Then ' Compliant
+ End If
+ End Sub
+
+ Public Shared Sub Compliant5(ByVal a As A)
+ While If(a?.booleanVal Is Nothing, True, False) ' Compliant
+ Console.WriteLine("Compliant")
+ End While
+ End Sub
+
+ Public Shared Sub NonCompliant5()
+ Dim a As A = Nothing
+ While If(a?.booleanVal Is Nothing, True, False) ' Noncompliant
+ ' Secondary@-1
+ ' Noncompliant@-2
+ ' Secondary@-3
+ Console.WriteLine("Compliant")
+ End While
+ End Sub
+
+ Public Class S
+ Public str As String = Nothing
+ End Class
+
+ Public Shared Sub Compliant6(ByVal sObj As S)
+ If sObj?.str?.Length > 2 Then
+ Console.WriteLine("a")
+ End If
+ End Sub
+
+ Public Shared Sub NonCompliant6()
+ Dim sObj As S = Nothing
+ If sObj?.str?.Length > 2 Then ' Noncompliant
+ ' Secondary@-1
+ ' Noncompliant@-2
+ Console.WriteLine("a") ' Secondary
+ End If
+ End Sub
+ End Class
+ End Class
+End Namespace
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
new file mode 100644
index 00000000000..abdd7d8ea57
--- /dev/null
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
@@ -0,0 +1,2034 @@
+Imports System
+Imports System.Collections.Generic
+Imports System.Diagnostics
+Imports System.Threading.Tasks
+Imports System.IO
+Imports System.Linq
+Imports Microsoft.Extensions.Primitives
+Imports System.Runtime.InteropServices
+
+Namespace Tests.Diagnostics
+ Public Class ConditionEvaluatesToConstant
+ Private Const t As Boolean = True
+ Private Const f As Boolean = False
+
+ Public Sub LoopsWithBreak(ByVal o1 As Object, ByVal o2 As Object, ByVal o3 As Object)
+ Dim c1, c2 As Boolean
+ c1 = c2 = True
+ While c1 ' Noncompliant
+ If o1 IsNot Nothing Then Exit While ' Secondary
+ End While
+
+ Do
+ If o2 IsNot Nothing Then Exit Do
+ Loop While c2 ' Noncompliant
+
+ End Sub
+
+ Public Sub IfStatement()
+ Dim c1 = True
+ If c1 Then ' Noncompliant
+ Console.WriteLine("Always True")
+ End If
+ End Sub
+
+ Private Sub UsingStatement()
+ Using writer As TextWriter = Nothing
+ If writer IsNot Nothing Then ' Noncompliant
+ Console.WriteLine("Hello world") ' Secondary
+ End If
+ End Using
+ End Sub
+
+ Public Sub DoesNotRaiseForConst()
+ If t Then ' Compliant - no issue is raised for const fields.
+ Console.WriteLine("Do stuff")
+ End If
+ End Sub
+
+ Public Sub NotExecutedLoops(ByVal o1 As Object, ByVal o2 As Object, ByVal o3 As Object)
+ Dim c1, c2, c3 As Boolean
+ c1 = c2 = c3 = False
+
+ While c1 ' Noncompliant {{Change this condition so that it does not always evaluate to 'False'. Some code paths are unreachable.}}
+ If o1 IsNot Nothing Then Exit While ' Secondary
+ End While
+
+ Do
+ If o2 IsNot Nothing Then Exit Do
+
+ Loop While c2 ' Noncompliant {{Change this condition so that it does not always evaluate to 'False'.}}
+ ' ^^
+ End Sub
+
+ Public Sub BreakInLoop(ByVal o As Object)
+ Dim c = True
+ While c ' Noncompliant
+ If o IsNot Nothing Then Exit While
+ End While
+ End Sub
+
+ Public Sub ReturnInLoop(ByVal o As Object)
+ Dim c = True
+ While c ' Noncompliant
+ If o IsNot Nothing Then Return
+ End While
+ End Sub
+
+ Public Sub ThrowInLoop(ByVal o As Object)
+ Dim c = True
+ While c ' Noncompliant
+ If o IsNot Nothing Then Throw New Exception()
+ End While
+ End Sub
+
+ Public Sub ConstField(ByVal a As Boolean, ByVal b As Boolean)
+
+ Dim x = t OrElse a OrElse b ' Compliant t is const
+
+ If t = True Then ' Noncompliant
+ Console.WriteLine("")
+ End If
+
+ End Sub
+
+ Public Sub Foo1(ByVal a As Boolean, ByVal b As Boolean)
+ Dim l = True
+ Dim x = l OrElse a OrElse b
+ ' ^ Noncompliant
+ ' ^^^^^^^^^^ Secondary@-1
+ End Sub
+
+ Public Sub Foo2(ByVal a As Boolean, ByVal b As Boolean)
+ Dim l = True
+ Dim x = l OrElse a OrElse b
+ ' ^ Noncompliant
+ ' ^^^^^^^^^^ Secondary@-1
+
+ End Sub
+
+ Public Sub Foo3(ByVal a As Boolean, ByVal b As Boolean)
+ Dim l = True
+ Dim x = l OrElse a OrElse b
+ ' ^ Noncompliant
+ ' ^^^^^^^^^^ Secondary@-1
+ End Sub
+
+ Public Sub Foo4(ByVal a As Boolean, ByVal b As Boolean)
+ Dim l = True
+ Dim m = False
+ Dim x = m OrElse l OrElse a OrElse b
+ ' ^ Noncompliant
+ ' ^ Noncompliant@-1
+ ' ^^^^^^^^^^ Secondary@-2
+
+ End Sub
+
+ Public Sub Foo5(ByVal a As Boolean, ByVal b As Boolean)
+ Dim l = True
+ Dim m = False
+ Dim x = m AndAlso l OrElse a OrElse b
+ ' ^ Noncompliant
+ ' ^ Secondary@-1
+ End Sub
+
+ Public Sub Foo6(ByVal a As Boolean, ByVal b As Boolean)
+ Dim l = True
+ Dim x = If(l OrElse a, a, b)
+ ' ^ Noncompliant
+ ' ^ Secondary@-1
+ ' ^ Secondary@-2
+ End Sub
+
+ Public Sub Foo7(ByVal a As Boolean, ByVal b As Boolean)
+ Dim l = True
+ If If(l OrElse a, a, b) OrElse b Then
+ ' ^ Noncompliant
+ ' ^ Secondary@-1
+ ' ^ Secondary@-2
+ End If
+ End Sub
+
+ Private Sub TestNameof(ByVal s As String)
+ If Equals(Nothing, NameOf(Method1)) Then ' FN FIX
+ End If
+ End Sub
+
+ Public Sub Method1()
+ Dim b = True
+ If b Then ' Noncompliant
+ Console.WriteLine()
+ Else
+ ' secondary location covers all unreachable code blocks:
+ Console.WriteLine(1) ' Secondary ??????
+ While b
+ Console.WriteLine(2)
+ End While ' the secondary location ends at the end of the above line
+ End If
+
+ Console.WriteLine()
+ End Sub
+
+ Public Sub Method2()
+ Dim b = True
+ If b Then ' Noncompliant
+ Console.WriteLine()
+ End If
+
+ If Not b Then ' Noncompliant
+ Console.WriteLine() ' Secondary
+ End If
+
+ Console.WriteLine()
+ End Sub
+
+ Public Sub Method2Literals()
+ If True Then ' Compliant
+ Console.WriteLine()
+ End If
+
+ If False Then ' Compliant
+ Console.WriteLine()
+ End If
+
+ Console.WriteLine()
+ End Sub
+
+ Public Sub Method3()
+ Dim b As Boolean
+ TryGet(b)
+ If b Then
+ End If
+ End Sub
+
+ Private Sub TryGet( ByRef b As Boolean)
+ b = False
+ End Sub
+
+ Public Sub Method5(ByVal cond As Boolean)
+ While cond
+ Console.WriteLine()
+ End While
+
+ Dim b = True
+ While b ' Noncompliant
+ Console.WriteLine()
+ End While
+
+ Console.WriteLine() ' Secondary
+ End Sub
+
+ Public Sub Method6(ByVal cond As Boolean)
+ Dim i = 10
+ While i < 20
+ i = i + 1
+ End While
+
+ Dim b = True
+ While b ' Noncompliant
+ Console.WriteLine()
+ End While
+
+ Console.WriteLine() ' Secondary
+ End Sub
+
+ Public Sub Method7()
+ While True ' Compliant
+ Console.WriteLine()
+ End While
+
+ Console.WriteLine()
+ End Sub
+
+ Public Sub Method8(n)
+ For Each item In New Integer()() {New Integer() {1, 2, 3}}
+ For Each i In item
+ Console.WriteLine()
+ Next
+ Next
+ End Sub
+
+ Public Sub Method9_For(ByVal cond As Boolean)
+ While True ' Not reporting on this
+
+ End While
+ End Sub
+
+ Public Sub Method_Switch()
+ Dim i = 10
+ Dim b = True
+ Select Case i
+ Case 1 ' Noncompliant
+ b = False ' Secondary
+ End Select
+
+ If b Then ' Noncompliant
+ Else
+ End If
+ End Sub
+
+ Public Sub Method_Switch_Learn(ByVal cond As Boolean)
+ Select Case cond
+ Case True
+ If cond Then ' Noncompliant
+ Console.WriteLine()
+ End If
+ End Select
+ End Sub
+
+ Public Property Property1 As Boolean
+ Get
+ Dim a = New Action(Sub()
+ Dim b = True
+ If b Then ' Noncompliant
+ Console.WriteLine()
+ Else
+ Console.WriteLine() ' Secondary
+ End If
+ End Sub)
+ Return True
+ End Get
+ Set(ByVal value As Boolean)
+ value = True
+ If value Then ' Noncompliant
+ Console.WriteLine()
+ Else
+ Console.WriteLine() ' Secondary
+ End If
+ End Set
+ End Property
+
+ Public Shared ReadOnly Property Prop As Boolean
+ Get
+ Return Prop
+ End Get
+ End Property
+
+ Public Sub Method_Complex()
+ Dim guard1 = True
+ Dim guard2 = True
+ Dim guard3 = True
+
+ While GetCondition()
+ If guard1 Then
+ guard1 = False
+ Else
+ If guard2 Then ' Noncompliant FP: loop is only analyzed twice
+ guard2 = False
+ Else
+ guard3 = False ' Secondary FP
+ End If
+ End If
+ End While
+
+ If guard3 Then ' Noncompliant FP: loop is only analyzed twice
+ Console.WriteLine()
+ End If
+ End Sub
+
+ Public Sub Method_Complex_2()
+ Dim x = False
+ Dim y = False
+
+ While GetCondition()
+ While GetCondition()
+ If x Then
+ If y Then ' Noncompliant FP: loop is only analyzed twice
+ End If
+ End If
+ y = True
+ End While
+ x = True
+ End While
+ End Sub
+ Private Shared Function GetObject() As Object
+ Return Nothing
+ End Function
+ Public Sub M()
+
+ Dim o1 = GetObject()
+ Dim o2 As Object = Nothing
+
+ If o1 IsNot Nothing Then
+ If Not Equals(o1.ToString(), Nothing) Then
+ o2 = New Object()
+ End If
+ End If
+
+ If o2 Is Nothing Then
+ End If
+
+ End Sub
+
+ Public Sub NullableStructs()
+ Dim i As Integer? = Nothing
+
+ If i Is Nothing Then ' Noncompliant, always true
+ Console.WriteLine(i)
+ End If
+
+ i = New Integer?()
+ If i Is Nothing Then ' Noncompliant
+ End If
+
+ Dim ii = ""
+ If ii Is Nothing Then ' Noncompliant, always false
+ Console.WriteLine(ii) ' Secondary
+ End If
+ End Sub
+
+ Private Shared Function GetCondition() As Boolean
+ Return True
+ End Function
+
+ Public Sub Lambda(ByVal condition As Boolean)
+
+ Dim fail = False
+ Dim a As Action = New Action(Sub() fail = condition)
+ a()
+
+ If fail Then ' Noncompliant FP
+ End If
+ End Sub
+
+ Public Sub Constraint(ByVal cond As Boolean)
+ Dim a = cond
+ Dim b = a
+ If a Then
+ If b Then ' FN: requires relation support
+
+ End If
+ End If
+ End Sub
+
+ Public Sub Stack(ByVal cond As Boolean)
+ Dim a = cond
+ Dim b = a
+
+ If Not a Then
+ If b Then ' FN: requires relation support
+ End If
+ End If
+
+ Dim fail = False
+ Dim ac As Action = New Action(Sub() fail = cond)
+
+ ac()
+
+ If Not fail Then ' Noncompliant FP
+ End If
+ End Sub
+
+ Public Sub BooleanBinary(ByVal a As Boolean, ByVal b As Boolean)
+ If a And Not b Then
+ If a Then ' FN: engine doesn't learn BoolConstraints from binary operators
+ End If
+ If b Then ' FN: engine doesn't learn BoolConstraints from binary operators
+ End If
+
+ End If
+
+ If Not (a Or b) Then
+ If a Then ' FN: engine doesn't learn BoolConstraints from binary operators
+ End If
+
+ End If
+
+ If a Xor b Then
+ If Not a Xor Not b Then ' FN: engine doesn't learn BoolConstraints from binary operators
+ End If
+ End If
+
+ a = False
+ If a And b Then ' Noncompliant
+ End If
+
+ a = a Or True
+ If a Then ' Noncompliant
+ End If
+
+ a = a Or True
+ If a Then ' Noncompliant
+ End If
+
+ a = a Xor True
+ If a Then ' Noncompliant
+ End If
+
+ a = a Xor True
+ If a Then ' Noncompliant
+ End If
+ End Sub
+
+ Public Sub IsAsExpression(ByVal o As Object)
+
+ If TypeOf o Is String Then
+ End If
+
+ Dim oo As Object = TryCast(o, String)
+ If oo Is Nothing Then
+ End If
+
+ o = Nothing
+ If TypeOf o Is Object Then ' Noncompliant
+ End If
+
+ oo = TryCast(o, Object)
+ If oo Is Nothing Then ' Noncompliant
+ End If
+ End Sub
+
+ Public Overloads Sub Equals(ByVal b As Boolean)
+ Dim a = True
+ If a = b Then
+ If b Then ' Noncompliant
+ End If
+ Else
+ If b Then ' Noncompliant
+ End If
+ End If
+
+ If Not a = b Then
+ If b Then ' Noncompliant
+ End If
+ Else
+ If b Then ' Noncompliant
+ End If
+ End If
+ End Sub
+
+ Public Sub NotEquals(ByVal b As Boolean)
+ Dim a = True
+ If a <> b Then
+ If b Then ' Noncompliant
+ End If
+ Else
+ If b Then ' Noncompliant
+ End If
+ End If
+
+ If Not a <> b Then
+ If b Then ' Noncompliant
+ End If
+ Else
+ If b Then ' Noncompliant
+ End If
+ End If
+ End Sub
+
+ Public Sub EqRelations(ByVal a As Boolean, ByVal b As Boolean)
+ If a = b Then
+ If b = a Then ' FN: requires relation support
+ End If
+ If b = Not a Then ' FN: requires relation support
+ End If
+ If Not b = Not Not a Then ' FN: requires relation support
+ End If
+ If Not a = b Then ' FN: requires relation support
+ End If
+ Else
+ If b <> a Then ' FN: requires relation support
+ End If
+ If b <> Not a Then ' FN: requires relation support
+ End If
+ If Not b <> Not Not a Then ' FN: requires relation support
+ End If
+
+ End If
+
+ If a <> b Then
+ If b = a Then ' FN: requires relation support
+ End If
+ Else
+ If b <> a Then ' FN: requires relation support
+ End If
+ End If
+ End Sub
+
+ Private Shared Sub BackPropagation(ByVal a As Object, ByVal b As Object)
+ If a Is b AndAlso b Is Nothing Then
+ a.ToString()
+ End If
+ End Sub
+
+ Public Sub RefEqualsImpliesValueEquals(ByVal a As Object, ByVal b As Object)
+ If Object.ReferenceEquals(a, b) Then
+ If Equals(a, b) Then ' FN
+ End If
+ If Equals(a, b) Then ' FN
+ End If
+ If a.Equals(b) Then ' FN
+ End If
+ End If
+
+ If Me Is a Then
+ If Equals(a) Then ' FN
+ End If
+ If Equals(a) Then ' FN
+ End If
+ End If
+ End Sub
+
+ Public Sub ValueEqualsDoesNotImplyRefEquals(ByVal a As Object, ByVal b As Object)
+ If Equals(a, b) Then ' 'a' could override Equals, so this is not a ref equality check
+ If a Is b Then
+ End If ' Compliant
+ End If
+ End Sub
+
+ Public Sub ReferenceEqualsMethodCalls(ByVal a As Object, ByVal b As Object)
+ If Object.ReferenceEquals(a, b) Then
+ If a Is b Then
+ End If ' FN
+ End If
+
+ If a Is b Then
+ If Object.ReferenceEquals(a, b) Then
+ End If ' FN
+ End If
+ End Sub
+
+ Public Sub ReferenceEqualsMethodCallWithOpOverload(ByVal a As ConditionEvaluatesToConstant, ByVal b As ConditionEvaluatesToConstant)
+ If Object.ReferenceEquals(a, b) Then
+ If a Is b Then ' FN
+ End If
+ End If
+
+ If a Is b Then
+ If Object.ReferenceEquals(a, b) Then ' Compliant, == is doing a value comparison above. FIX
+ End If
+ End If
+ End Sub
+
+ Public Sub ReferenceEquals(ByVal a As Object, ByVal b As Object)
+ If Object.ReferenceEquals(a, b) Then
+ End If
+
+ If Object.ReferenceEquals(a, a) Then
+ End If ' FN
+
+ a = Nothing
+ If Object.ReferenceEquals(Nothing, a) Then ' Noncompliant
+ End If
+ If Object.ReferenceEquals(a, a) Then ' Noncompliant
+ End If
+
+ If Object.ReferenceEquals(Nothing, New Object()) Then ' Noncompliant
+ End If
+
+ ' Because of boxing:
+ Dim i = 10
+ If Object.ReferenceEquals(i, i) Then ' FN
+ End If
+
+ Dim ii As Integer? = Nothing
+ Dim jj As Integer? = Nothing
+ If Object.ReferenceEquals(ii, jj) Then ' Noncompliant
+ End If
+
+ jj = 10
+ If Object.ReferenceEquals(ii, jj) Then ' Noncompliant
+ End If
+ End Sub
+
+ Public Sub ReferenceEqualsBool()
+ Dim a, b As Boolean
+ a = b = True
+ If Object.ReferenceEquals(a, b) Then ' FN
+ End If
+ End Sub
+
+ Public Overrides Function Equals(ByVal obj As Object) As Boolean
+ Return MyBase.Equals(obj)
+ End Function
+
+ Public Shared Operator =(ByVal a As ConditionEvaluatesToConstant, ByVal b As ConditionEvaluatesToConstant) As Boolean
+ Return False
+ End Operator
+
+ Public Shared Operator <>(ByVal a As ConditionEvaluatesToConstant, ByVal b As ConditionEvaluatesToConstant) As Boolean
+ Return False
+ End Operator
+
+ Public Sub StringEmpty(ByVal s1 As String)
+ Dim s As String = Nothing
+ If String.IsNullOrEmpty(s) Then ' Noncompliant
+ End If
+ If String.IsNullOrWhiteSpace(s) Then ' Noncompliant
+ End If
+ If Not Equals(String.IsInterned(s), Nothing) Then ' FN FIX
+ End If
+ s = ""
+ If String.IsNullOrEmpty(s) Then ' FN
+ End If
+
+ If String.IsNullOrWhiteSpace(s) Then ' FN
+ End If
+
+ If String.IsNullOrEmpty(s1) Then ' Compliant, we don't know anything about the argument
+ End If
+
+ If String.IsNullOrWhiteSpace(s1) Then ' Compliant
+ End If
+
+ If String.IsNullOrEmpty(s1) Then
+ If String.IsNullOrEmpty(s1) Then ' FN
+ End If
+ End If
+ End Sub
+
+ Public Sub Comparisons(ByVal i As Integer, ByVal j As Integer)
+ If i < j Then
+ If j < i Then ' FN
+ End If
+ If j <= i Then ' FN
+ End If
+ If j = i Then ' FN
+ End If
+ If j <> i Then ' FN
+ End If
+ End If
+ End Sub
+
+ Private Sub ValueEquals(ByVal i As Integer, ByVal j As Integer)
+ If i = j Then
+ If Equals(i, j) Then ' FN
+ End If
+ If i.Equals(j) Then ' FN
+ End If
+ End If
+ End Sub
+
+ Private Sub DefaultExpression(ByVal o As Object)
+ If Nothing Is Nothing Then ' Noncompliant
+ End If
+
+ Dim nullableInt As Integer? = Nothing
+ If nullableInt Is Nothing Then ' Noncompliant
+ End If
+
+ If Nothing Is Nothing Then ' Noncompliant
+ End If
+
+ If Nothing IsNot Nothing Then ' Noncompliant
+ End If
+
+ If Nothing IsNot Nothing Then ' Noncompliant
+ End If
+ End Sub
+
+ Private Sub Cast()
+ Dim i = 5
+ Dim o = CObj(i)
+ If o Is Nothing Then ' Noncompliant
+ End If
+
+ Dim x = CType(o, ConditionEvaluatesToConstant) ' This would throw and invalid cast exception
+ If x Is Nothing Then ' Noncompliant
+ End If
+
+ End Sub
+
+ Public Async Function NotNullAfterAccess(ByVal o As Object, ByVal arr As Integer(,), ByVal coll As IEnumerable(Of Integer), ByVal task As Task) As Task
+ Console.WriteLine(o.ToString())
+ If o Is Nothing Then ' Noncompliant
+ End If
+
+
+ Console.WriteLine(arr(42, 42))
+ If arr Is Nothing Then ' Noncompliant
+ End If
+
+
+ For Each item In coll
+ Next
+ If coll Is Nothing Then ' Noncompliant
+ End If
+
+
+ Await task
+ If task Is Nothing Then ' FN
+ End If
+
+ End Function
+
+ Public Sub EqualsTest32(ByVal o As Object)
+ Dim o2 = o
+ If o Is o2 Then ' FN
+ End If
+ If Object.ReferenceEquals(o, o2) Then ' FN
+ End If
+ If o.Equals(o2) Then ' FN
+ End If
+ If Equals(o2, o) Then ' FN
+ End If
+
+
+ Dim i = 1
+ Dim j = i
+ If i = j Then ' Noncompliant
+ End If
+
+ If i.Equals(j) Then ' FN
+ End If
+
+ If Equals(i, j) Then ' FN
+ End If
+ End Sub
+
+ Private Async Function Test_Await_Constraint(ByVal t As Task(Of String)) As Task
+ If t IsNot Nothing Then
+ Dim o = Await t
+ If Equals(o, Nothing) Then ' Compliant, might be null
+ End If
+ End If
+ End Function
+
+ Public Sub Assert(ByVal condition As Boolean, ByVal o1 As Object)
+ Debug.Assert(condition)
+
+ If condition Then ' Noncompliant
+ End If
+
+ Trace.Assert(condition) ' Compliant
+
+ If o1 IsNot Nothing Then
+ Debug.Assert(o1 Is Nothing, "Some message", "More details", 1, 2, 3) ' Compliant
+ End If
+ End Sub
+
+ Public Sub Assert(ByVal o1 As Object)
+ Debug.Assert(o1 IsNot Nothing)
+ Debug.Assert(o1 Is Nothing)
+ End Sub
+
+ Private Sub ComparisonTransitivity(ByVal a As Integer, ByVal b As Integer, ByVal c As Integer)
+ If a = b AndAlso b < c Then
+ If a >= c Then ' FN
+ End If
+
+ End If
+ If a = b AndAlso b <= c Then
+ If a > c Then ' FN
+ End If
+
+ End If
+ If a > b AndAlso b > c Then
+ If a <= c Then ' FN
+ End If
+
+ End If
+ If a > b AndAlso b >= c Then
+ If a <= c Then ' FN
+ End If
+
+ End If
+ If a >= b AndAlso b >= c Then
+ If a < c Then ' FN
+ End If
+
+ End If
+ If a >= b AndAlso c <= b Then
+ If a < c Then ' FN
+ End If
+
+ End If
+ If a >= b AndAlso c >= b Then
+ If a < c Then
+ End If
+ End If
+ End Sub
+
+ Friend Class Comp
+ Public Shared Operator <(ByVal a As Comp, ByVal b As Comp) As Boolean
+ Return True
+ End Operator
+ Public Shared Operator >(ByVal a As Comp, ByVal b As Comp) As Boolean
+ Return True
+ End Operator
+ Public Shared Operator >=(ByVal a As Comp, ByVal b As Comp) As Boolean
+ Return True
+ End Operator
+ Public Shared Operator <=(ByVal a As Comp, ByVal b As Comp) As Boolean
+ Return True
+ End Operator
+ End Class
+
+ Private Sub RefEqTransitivity(ByVal a As Comp, ByVal b As Comp, ByVal c As Comp)
+ If a Is b AndAlso b Is c Then
+ If a IsNot c Then ' FN
+ End If
+ End If
+
+ If a.Equals(b) AndAlso b Is c Then
+ If a IsNot c Then
+ End If
+ If a Is c Then
+ End If
+ If a.Equals(c) Then ' FN
+ End If
+ If Not a.Equals(c) Then ' FN
+ End If
+ End If
+
+ If a > b AndAlso b Is c Then
+ If a <= c Then ' FN
+ End If
+ End If
+ End Sub
+
+ Private Sub ValueEqTransitivity(ByVal a As Comp, ByVal b As Comp, ByVal c As Comp)
+ If a Is b AndAlso b.Equals(c) Then
+ If a.Equals(c) Then ' FN
+ End If
+ End If
+
+ If a.Equals(b) AndAlso b.Equals(c) Then
+ If a IsNot c Then
+ End If
+ If a Is c Then
+ End If
+ If a.Equals(c) Then ' FN
+ End If
+ If Not a.Equals(c) Then ' FN
+ End If
+ End If
+
+ If a > b AndAlso b.Equals(c) Then
+ If a > c Then ' FN
+ End If
+ If a <= c Then ' FN
+ End If
+ End If
+
+ If Not a.Equals(b) AndAlso b.Equals(c) Then
+ If a.Equals(c) Then ' FN
+ End If
+ If a Is c Then ' FN
+ End If
+ End If
+
+ If a IsNot b AndAlso b.Equals(c) Then
+ If a.Equals(c) Then
+ End If
+ If a Is c Then
+ End If
+ End If
+ End Sub
+
+ Private Sub NeqEqTransitivity(ByVal a As Object, ByVal b As Object, ByVal c As Object)
+ If a Is c AndAlso a IsNot b Then
+ If b Is c Then ' FN
+ End If
+
+ If b.Equals(c) Then
+ End If
+ End If
+
+ If a Is c AndAlso Not a.Equals(b) Then
+ If b Is c Then ' FN
+ End If
+
+ If b.Equals(c) Then ' FN
+ End If ' FN
+
+ End If
+ End Sub
+
+ Public Sub LiftedOperator()
+ Dim i As Integer? = Nothing
+ Dim j As Integer? = 5
+
+ If i < j Then ' Noncompliant
+ End If
+
+ If i <= j Then ' Noncompliant
+ End If
+
+ If i > j Then ' Noncompliant
+ End If
+
+ If i >= j Then ' Noncompliant
+ End If
+
+ If i > 0 Then ' Noncompliant
+ End If
+
+ If i >= 0 Then ' Noncompliant
+ End If
+
+ If i < 0 Then ' Noncompliant
+ End If
+
+ If i <= 0 Then ' Noncompliant
+ End If
+
+ If j > Nothing Then ' Noncompliant
+ End If
+
+ If j >= Nothing Then ' Noncompliant
+ End If
+
+ If j < Nothing Then ' Noncompliant
+ End If
+
+ If j <= Nothing Then ' Noncompliant
+ End If
+ End Sub
+
+ Friend Class Singleton
+ Private Shared syncRoot As Object = New Object()
+
+ Private Shared instanceField As Singleton
+
+ Public Shared ReadOnly Property Instance As Singleton
+ Get
+ If instanceField Is Nothing Then
+ SyncLock syncRoot
+ If instanceField Is Nothing Then ' Noncompliant FP
+ instanceField = New Singleton()
+ End If
+ End SyncLock
+ End If
+ Return instanceField
+ End Get
+ End Property
+ End Class
+
+ Friend Structure MyStructWithNoOperator
+ Public Shared Sub M(ByVal a As MyStructWithNoOperator)
+ If a Is Nothing Then ' Noncompliant, also a compiler error
+ ' Error@-1 [BC30020]
+ End If
+ End Sub
+ End Structure
+
+ Public Class NullableCases
+ Private Sub Case1()
+ Dim b1 As Boolean? = True
+ If b1 = True Then ' Noncompliant
+ End If
+ End Sub
+
+ Private Sub Case2(ByVal i As Boolean?)
+ If i Is Nothing Then
+
+ End If
+ If i = True Then
+
+ End If
+ If i = False Then
+
+ End If
+
+ i = Nothing
+ If i Is Nothing Then ' Noncompliant
+
+ End If
+ If i = True Then ' Noncompliant
+
+ End If
+ If i = False Then ' Noncompliant
+
+ End If
+
+ i = True
+ If i Is Nothing Then ' Noncompliant
+
+ End If
+ If i = True Then ' Noncompliant
+
+ End If
+ If i = False Then ' Noncompliant
+
+ End If
+
+ i = False
+ If i Is Nothing Then ' Noncompliant
+
+ End If
+ If i = True Then ' Noncompliant
+
+ End If
+ If i = False Then ' Noncompliant
+
+ End If
+
+ Dim b2 As Boolean? = True
+ If b2 = False Then ' Noncompliant
+ End If
+
+ Dim b3 As Boolean? = True
+ If b3 Is Nothing Then ' Noncompliant
+ End If
+
+ Dim b4 As Boolean? = Nothing
+ If b4 = True Then ' Noncompliant
+ End If
+
+ Dim b5 As Boolean? = Nothing
+ If b5 = False Then ' Noncompliant
+ End If
+
+
+ Dim b6 As Boolean? = Nothing
+ If b6 Is Nothing Then ' Noncompliant
+ End If
+ Dim b7 As Boolean? = True
+ If b7 = True Then ' Noncompliant
+ End If
+ Dim b8 As Boolean? = False
+ If b8 = False Then ' Noncompliant
+ End If
+
+ End Sub
+
+ Private Sub Case3(ByVal b As Boolean?)
+ If b Is Nothing Then
+ If Nothing Is b Then ' Noncompliant
+ b.ToString()
+ End If
+ Else
+ If b IsNot Nothing Then ' Noncompliant
+ b.ToString()
+ End If
+ End If
+ End Sub
+
+ Private Sub Case4(ByVal b As Boolean?)
+ If b = True Then
+ If True = b Then ' Noncompliant
+ b.ToString()
+ End If
+ End If
+ End Sub
+
+ Private Sub Case5(ByVal b As Boolean?)
+ If b = True Then
+ ElseIf b = False Then
+ Else
+ End If
+ End Sub
+
+ Private Sub Case6(ByVal b As Boolean?)
+ If b Is Nothing Then
+ ElseIf b = True Then
+ Else
+ End If
+ End Sub
+
+ Private Sub Case7(ByVal b As Boolean?)
+ If b Is Nothing Then
+ If If(b, False) Then ' Noncompliant
+
+ End If
+ End If
+ End Sub
+
+ Private Sub Case8(ByVal b As Boolean?)
+ If b IsNot Nothing Then
+ If b.HasValue Then ' Noncompliant
+ End If
+ End If
+ End Sub
+
+ Private Sub Case9(ByVal b As Boolean?)
+ If b = True Then
+ Dim x = b.Value
+ If x = True Then ' Noncompliant
+ End If
+ End If
+ End Sub
+
+ Private Sub Case10(ByVal i As Integer?)
+ If i Is Nothing Then
+ If i.HasValue Then ' Noncompliant
+ End If
+ End If
+ End Sub
+
+ ' https://github.com/SonarSource/sonar-dotnet/issues/4755
+ Public Sub IfElseIfElseFlow_FromCast(ByVal value As Object)
+ Dim b = CType(value, Boolean?)
+ If b = True Then
+ Console.WriteLine("true")
+ ElseIf b = False Then ' Compliant
+ Console.WriteLine("false")
+ Else
+ Console.WriteLine("null")
+ End If
+ End Sub
+
+ Public Sub IfElseIfElseFlow_DirectValue(ByVal b As Boolean?)
+ If b = True Then
+ Console.WriteLine("true")
+ ElseIf b = False Then
+ Console.WriteLine("false")
+ Else
+ Console.WriteLine("null")
+ End If
+ End Sub
+
+ Public Sub IfElseIfElseFlow_KnownNull()
+ Dim b As Boolean? = Nothing
+ If b = True Then ' Noncompliant
+ Console.WriteLine("true") ' Secondary
+ ElseIf b = False Then ' Noncompliant
+ Console.WriteLine("false") ' Secondary
+ Else
+ Console.WriteLine("null")
+ End If
+ End Sub
+ End Class
+
+ Public Class ConstantExpressionsAreExcluded
+ Const T As Boolean = True
+ Const F As Boolean = False
+
+ Private Sub LocalConstants()
+ Const t = True
+ If t Then ' Noncompliant
+ Console.WriteLine()
+ End If
+ Const f = False
+ If f Then ' Noncompliant
+ Console.WriteLine() ' Secondary
+ End If
+ End Sub
+ Private Sub Constants()
+ If T Then ' Compliant it's a constant
+ Console.WriteLine()
+ End If
+ If F Then ' Compliant it's a constant
+ Console.WriteLine()
+ End If
+ End Sub
+ Private Sub WhileTrue()
+ While T ' Compliant it's a constant
+ Console.WriteLine()
+ End While
+ End Sub
+ Private Sub WhileFalse()
+ Do
+ Console.WriteLine()
+ Loop While F ' Compliant it's a constant
+ End Sub
+ Private Sub Condition()
+ Dim x = If(T, 1, 2) ' Compliant, T is constant
+ End Sub
+ End Class
+
+ End Class
+
+ Public Class GuardedTests
+ Public Sub Guarded(ByVal s1 As String)
+ Guard1(s1)
+
+ If Equals(s1, Nothing) Then ' Noncompliant, always flse
+ ' this branch is never executed
+ Else
+ End If
+ End Sub
+
+ Public Sub Guard1(Of T As Class)(
+ ByVal value As T)
+ End Sub
+
+
+ Public NotInheritable Class ValidatedNotNullAttribute
+ Inherits Attribute
+ End Class
+ End Class
+
+ Public Class CatchFinally
+ Public Sub ObjectsShouldNotBeDisposedMoreThanOnce()
+ Dim stream As Stream = Nothing
+ Try
+ stream = File.Open("file", FileMode.Open)
+ Using reader = New StreamReader(stream)
+ ' read the file here
+
+ ' StreamReader will dispose the stream automatically; set stream to null
+ ' to prevent it from disposing twice (the recommended pattern for S3966)
+ stream = Nothing
+ End Using
+
+ Finally
+ If stream IsNot Nothing Then
+ stream.Dispose()
+ End If
+ End Try
+ End Sub
+
+ Public Sub FalseNegatives()
+ ' We cannot detect the case in ObjectsShouldNotBeDisposedMoreThanOnce method above
+ ' and to avoid False Positives we do not report in catch or finally
+ Dim o As Object = Nothing
+ Try
+ Console.WriteLine("Could throw")
+ Catch
+ If o IsNot Nothing Then ' Noncompliant
+ End If
+ If o Is Nothing Then ' Noncompliant
+ End If
+
+ Finally
+ If o IsNot Nothing Then ' Noncompliant
+ End If
+ If o Is Nothing Then ' Noncompliant
+ End If
+ End Try
+ End Sub
+ End Class
+
+ Friend Class UsingStatement
+ Public Sub Method()
+ Dim isTrue = True
+ If isTrue Then ' Noncompliant
+ End If
+ Using reader = New StreamReader("")
+ If isTrue Then ' Noncompliant
+ End If
+ End Using
+ If isTrue Then ' Noncompliant
+ End If
+ End Sub
+ End Class
+
+ Friend Class AsyncAwait
+ Private _foo1 As Object
+ Private Async Function Foo(ByVal t As Task) As Task
+ Dim o As Object = Nothing
+ _foo1 = o
+ Await t ' awaiting clears the constraints
+ If _foo1 IsNot Nothing Then ' Compliant S2583
+ End If
+ If _foo1 Is Nothing Then ' Compliant S2589
+ End If
+ If o IsNot Nothing Then ' Noncompliant
+ End If
+ If o Is Nothing Then ' Noncompliant
+ End If
+ End Function
+ End Class
+
+ Public Class StaticMethods
+ Private _foo1 As Object
+ ' https://github.com/SonarSource/sonar-dotnet/issues/947
+ Private Sub CallToMonitorWaitShouldResetFieldConstraints()
+ Dim o As Object = Nothing
+ _foo1 = o
+ Threading.Monitor.Wait(o) ' This is a multi-threaded application, the fields could change
+ If _foo1 IsNot Nothing Then ' Noncompliant FP
+ End If
+ If _foo1 Is Nothing Then ' Noncompliant FP
+ End If
+ If o IsNot Nothing Then ' Noncompliant
+ End If
+ If o Is Nothing Then ' Noncompliant
+ End If
+ End Sub
+
+ Private Sub CallToStaticMethodsShouldResetFieldConstraints()
+ Dim o As Object = Nothing
+ _foo1 = o
+ Console.WriteLine() ' This particular method has no side effects
+ If _foo1 IsNot Nothing Then ' Noncompliant
+ End If
+ If _foo1 Is Nothing Then ' Noncompliant
+ End If
+ If o IsNot Nothing Then ' Noncompliant
+ End If
+ If o Is Nothing Then ' Noncompliant
+ End If
+ End Sub
+ End Class
+
+
+ Public Class TestNullCoalescing
+ Public Sub CompliantMethod(ByVal input As Boolean?)
+ If If(input, False) Then ' Compliant
+ Console.WriteLine("input is true")
+ Else
+ Console.WriteLine("input is false")
+ End If
+ End Sub
+
+ Public Sub CompliantMethod1(ByVal input As Boolean?)
+ While If(input, False) ' Compliant
+ Console.WriteLine("input is true")
+ End While
+ End Sub
+
+ Public Sub CompliantMethod2(ByVal input As Boolean?, ByVal input1 As Boolean)
+ While If(input, False) AndAlso input1 ' Compliant
+ Console.WriteLine("input is true")
+ End While
+ End Sub
+
+ Public Sub CompliantMethod3(ByVal input As Boolean?, ByVal input1 As Boolean)
+
+ If If(If(input, False), input1, False) Then ' Compliant
+ Console.WriteLine("input is true")
+ End If
+ End Sub
+
+ Public Sub NonCompliantMethod()
+ Dim input As Boolean? = True
+ If If(input, False) Then ' Noncompliant
+ Console.WriteLine("input is true")
+ Else
+ Console.WriteLine("input is false") ' Secondary
+ End If
+ End Sub
+
+ Public Sub NonCompliantMethod1()
+ Dim input As Boolean? = True
+ While If(input, False) ' Noncompliant
+ Console.WriteLine("input is true")
+ End While
+ End Sub
+
+ Public Sub NonCompliantMethod2(ByVal input As Boolean?)
+ While If(input, False) OrElse True ' Compliant
+ Console.WriteLine("input is true")
+ End While
+ End Sub
+
+ Public Sub NonCompliantMethod3(ByVal input As Boolean?, ByVal input1 As Boolean)
+ If If(If(input, False), False, False) Then ' Compliant
+ Console.WriteLine("input is true")
+ End If
+ End Sub
+ End Class
+
+ Friend Class Program
+ Public Shared Function CompliantMethod4(ByVal parameter As String) As String
+ Dim useParameter = If(parameter, "non-empty")
+ If Equals(useParameter, Nothing) OrElse Equals(useParameter, "") Then Return "non-empty" ' Noncompliant
+ ' we don't know if this going to be excuted or not
+
+ Return "empty"
+ End Function
+
+ Public Shared Function Method1347(ByVal parameter As String) As String
+ Dim useParameter = If(parameter, "non-empty")
+ If Not String.IsNullOrEmpty(useParameter) Then
+ Return "non-empty"
+ Else
+ End If
+ Return "empty"
+ End Function
+ End Class
+
+ Friend Class Repro2442
+ Public Sub Method(ByVal unknown As Boolean)
+ Dim f = False
+ Dim t = True
+ If t Then ' Noncompliant
+ Else
+
+ End If
+
+ If f Then ' Noncompliant
+ Else
+
+ End If
+
+ If unknown OrElse t Then ' Noncompliant
+ Else
+
+ End If
+
+ If unknown AndAlso f Then ' Noncompliant
+ Else
+
+ End If
+
+ If unknown AndAlso t Then ' Noncompliant
+ Else
+
+ End If
+
+ If unknown OrElse f Then ' Noncompliant
+ Else
+
+ End If
+
+ If unknown AndAlso t Then ' Noncompliant
+ Else
+
+ End If
+ End Sub
+
+ '''
+ ''' A certain combination of condition wrongly considers the else code as dead.
+ '''
+ Private Shared Sub FalsePositive()
+ FalsePositive2_Sub(True, False, False)
+ FalsePositive2_Sub(True, False, True)
+
+ FalsePositive2_Sub(True, True, True)
+ FalsePositive2_Sub(True, True, False)
+
+ FalsePositive2_Sub(False, False, False)
+ FalsePositive2_Sub(False, False, True)
+
+ FalsePositive2_Sub(False, True, True)
+ FalsePositive2_Sub(False, True, False)
+
+ ' Outcome.
+ Console.WriteLine(If(_test1 AndAlso _test2 AndAlso _test3 AndAlso _test4, "Went through each test condition", "Missed at least one test condition"))
+ End Sub
+
+ Private Shared _test1 As Boolean = False
+ Private Shared _test2 As Boolean = False
+ Private Shared _test3 As Boolean = False
+ Private Shared _test4 As Boolean = False
+
+ Private Shared Sub FalsePositive2_Sub(ByVal testCondition1 As Boolean, ByVal testCondition2 As Boolean, ByVal testCondition3 As Boolean)
+ Dim condition1 = testCondition1
+ Dim condition2 = testCondition2
+ Dim condition3 = condition2 AndAlso testCondition3
+
+ If condition2 AndAlso condition3 AndAlso condition1 Then
+ _test1 = True
+ ElseIf Not condition2 AndAlso Not condition1 Then
+ _test2 = True
+ ElseIf condition2 AndAlso condition1 AndAlso Not condition3 Then ' Noncompliant
+ _test3 = True
+ Else
+ _test4 = True
+ End If
+ End Sub
+ End Class
+
+ Public Class RefArgTest
+ Public Sub Method(ByRef s As String, ByVal x As Integer)
+ End Sub
+ Public Sub Method1(ByVal infixes As String)
+ If Not Equals(infixes, Nothing) Then
+ Method(infixes, infixes.Length)
+ If Equals(infixes, Nothing) Then ' Noncompliant FP: ref
+ Return
+ End If
+ End If
+ End Sub
+
+ Public Sub Method2(ByVal infixes As String)
+ If Not Equals(infixes, Nothing) Then
+ Method(infixes, infixes.Length)
+ If Not Equals(infixes, Nothing) Then ' Noncompliant FP: ref
+ Return
+ End If
+ End If
+ End Sub
+
+ Public Sub Method3(ByVal infixes As String)
+ If Equals(infixes, Nothing) Then
+ Method(infixes, infixes.Length)
+ If Equals(infixes, Nothing) Then ' Noncompliant FP: ref
+ Return
+ End If
+ End If
+ End Sub
+
+ Public Sub Method4(ByVal infixes As String)
+ If Equals(infixes, Nothing) Then
+ Method(infixes, infixes.Length)
+ If Not Equals(infixes, Nothing) Then ' Noncompliant FP: ref
+ Return
+ End If
+ End If
+ End Sub
+
+ End Class
+
+ Friend Class ReproForEachFP
+ Private Shared Function Repro2348(ByVal list As List(Of Integer)) As Boolean
+ Dim containspositive = False
+ Dim containsnegative = False
+
+ For Each value In list
+ If value > 0 Then
+ containspositive = True
+ ElseIf value < 0 Then
+ containsnegative = True
+ End If
+ Next
+
+ Return containspositive AndAlso Not containsnegative ' Compliant
+ End Function
+
+ Private Shared Sub Repro1187_1()
+ Dim do1 = False
+ Dim do2 = False
+ Dim items = New Integer() {1, 2, 3}
+ For Each item In items
+ Select Case item
+ Case 1
+ do1 = True
+ Case 2
+ do2 = True
+ End Select
+ Next
+
+ If do1 AndAlso do2 Then ' Noncompliant: This repro is badly written. This is a TP. You can find the FP below.
+ Throw New InvalidOperationException() ' Secondary
+ End If
+ End Sub
+
+ Private Shared Sub Repro1187_1_Fixed(ByVal items As Integer())
+ Dim do1 = False
+ Dim do2 = False
+ For Each item In items
+ Select Case item
+ Case 1
+ do1 = True
+ Case 2
+ do2 = True
+ End Select
+ Next
+
+ If do1 AndAlso do2 Then ' Noncompliant FP
+ Throw New InvalidOperationException() ' Secondary FP
+ End If
+ End Sub
+
+ Private Shared Sub Repro1187_2(ByVal elementGroup As List(Of Integer))
+ Dim startDoingSomething = False
+ Dim a = 0
+
+ For Each element In elementGroup
+ If Not startDoingSomething Then ' Compliant
+ If element > 3 Then
+ startDoingSomething = True
+ End If
+ Else
+ a += 1
+ End If
+ Next
+ End Sub
+
+ Private Shared Function Repro1160(ByVal files As String()) As Boolean
+ Dim anyPathRooted = False
+ Dim allPathsRooted = True
+ For Each file In files
+ If Path.IsPathRooted(file) Then
+ anyPathRooted = True
+ Else
+ allPathsRooted = False
+ End If
+ Next
+ If anyPathRooted AndAlso Not allPathsRooted Then ' Noncompliant FP
+ Throw New InvalidOperationException("Paths must be all rooted or all unrooted") ' Secondary FP
+ End If
+ Return allPathsRooted
+ End Function
+
+ Private Shared Function ForEachLoop(ByVal items As Integer()) As Boolean
+ Dim bool1 = False
+ Dim bool2 = False
+
+ For Each item In items
+ If item > 0 Then
+ bool1 = True
+ ElseIf item < 0 Then
+ bool2 = True
+ End If
+ Next
+
+ If bool1 AndAlso bool2 Then ' Noncompliant FP
+ Throw New InvalidOperationException() ' Secondary FP
+ End If
+
+ Return bool1 AndAlso Not bool2 ' Compliant
+ End Function
+
+ Private Shared Function ForEachLoop2(ByVal items As Integer()) As Boolean
+ Dim bool1 = False
+ Dim bool2 = False
+
+BeforeLoop:
+
+ For Each item1 In items
+ For Each item2 In items
+ For Each item3 In items
+ For Each item4 In items
+ If item1 > 0 Then
+ bool1 = True
+ ElseIf item2 < 0 Then
+ bool2 = True
+ End If
+ Next
+ Next
+ Next
+ Next
+
+ If bool1 AndAlso bool2 Then ' Noncompliant FP FIX
+ GoTo BeforeLoop
+ End If
+ Return False
+ End Function
+
+ Private Shared Function LoopIterationLimitation(ByVal items As Integer()) As Boolean
+ Dim bool1 = False
+ Dim bool2 = False
+ Dim bool3 = False
+
+ For Each item1 In items
+ If bool2 Then ' Noncompliant - FP because symbolic execution stops at the third iteration of loop
+ bool3 = True ' Secondary FP
+ End If
+ If bool1 Then
+ bool2 = True
+ End If
+ If item1 > 1 Then
+ bool1 = True
+ End If
+
+ Next
+ Return bool3
+ End Function
+ End Class
+
+ Public Class GeneratorFunctions
+ Private generate As Boolean
+
+ Public Sub [Stop]()
+ generate = False
+ End Sub
+
+ Public Iterator Function Repro_1295() As IEnumerable(Of Integer)
+ generate = True
+ While generate ' Noncompliant FP: 'generate' field can potentially be changed inside the loop where this generator is used
+ Yield 0
+ End While
+ End Function
+
+ Public Iterator Function FalseNegative() As IEnumerable(Of Integer)
+ Dim myVariable = True
+ While myVariable ' Noncompliant: myVariable will never change after initialization
+ Yield 0
+ End While
+ End Function
+ End Class
+
+ Public Class StringComparision
+ Public Sub Method(ByVal parameterString As String)
+ Dim emptyString1 = ""
+ Dim emptyString2 = ""
+ Dim nullString1 As String = Nothing
+ Dim nullString2 As String = Nothing
+ Dim fullStringa1 = "a"
+ Dim fullStringa2 = "a"
+ Dim fullStringb = "b"
+ Dim whiteSpaceString1 = " "
+ Dim whiteSpaceString2 = " "
+ Dim doubleWhiteSpaceString1 = " "
+ Dim doubleWhiteSpaceString2 = " "
+
+ If Equals(emptyString1, emptyString2) Then ' FN
+
+ End If
+ If Equals(nullString1, nullString2) Then ' Noncompliant
+
+ End If
+
+ If Equals(fullStringa1, fullStringa2) Then
+
+ End If
+
+ If Equals(fullStringa1, fullStringb) Then
+
+ End If
+
+ If Equals(parameterString, emptyString1) Then
+
+ End If
+
+ If Equals(parameterString, nullString1) Then
+
+ End If
+
+ If Equals(emptyString1, nullString1) Then ' Noncompliant
+
+ End If
+
+ If Equals(emptyString1, fullStringa1) Then ' FN
+
+ End If
+
+ If Equals(nullString1, fullStringa1) Then ' Noncompliant
+
+ End If
+
+ If Equals(fullStringa1, "") Then ' FN
+
+ End If
+
+ If Equals(fullStringa1, Nothing) Then ' Noncompliant
+
+ End If
+
+ If Equals(whiteSpaceString1, whiteSpaceString2) Then ' FN
+
+ End If
+
+ If Equals(whiteSpaceString1, " ") Then ' FN
+
+ End If
+
+ If Equals(whiteSpaceString1, emptyString1) Then ' FN
+
+ End If
+
+ If Equals(whiteSpaceString1, nullString1) Then ' Noncompliant
+
+ End If
+
+ If Equals(whiteSpaceString1, fullStringa1) Then ' FN
+
+ End If
+
+ If Equals(whiteSpaceString1, parameterString) Then
+
+ End If
+
+ If Equals(doubleWhiteSpaceString1, doubleWhiteSpaceString2) Then ' FN
+
+ End If
+
+ If Equals(doubleWhiteSpaceString1, emptyString1) Then ' FN
+
+ End If
+
+ If Equals(doubleWhiteSpaceString1, nullString1) Then ' Noncompliant
+
+ End If
+
+ If Equals(doubleWhiteSpaceString1, fullStringa1) Then ' FN
+
+ End If
+
+ If Equals(doubleWhiteSpaceString1, parameterString) Then
+
+ End If
+
+ End Sub
+ End Class
+
+ Public Class NullOrEmpty
+ Public Sub Method1(ByVal s As String)
+ Dim s1 As String = Nothing
+ Dim s2 = ""
+ Dim s3 = "a"
+ If String.IsNullOrEmpty(s1) Then ' Noncompliant
+ End If
+ If String.IsNullOrEmpty(s2) Then ' FN
+ End If
+
+ If String.IsNullOrEmpty(s) Then
+ End If
+
+ If String.IsNullOrEmpty(s3) Then ' FN
+ End If
+ End Sub
+
+ Public Sub Method2(ByVal s As String)
+
+ If String.IsNullOrEmpty(s) Then
+ End If
+
+ s = ""
+ If String.IsNullOrEmpty(s) Then ' FN
+ End If
+
+ s = Nothing
+ If String.IsNullOrEmpty(s) Then ' Noncompliant
+ End If
+
+ s = "a"
+ If String.IsNullOrEmpty(s) Then ' FN
+ End If
+ End Sub
+
+ Public Sub Method3(ByVal s1 As String)
+ If String.IsNullOrEmpty(s1) Then
+ s1.ToString()
+ Else
+ If Equals(s1, Nothing) Then ' Noncompliant
+ s1.ToString() ' Secondary
+ End If
+ End If
+
+ End Sub
+
+ Public Sub Method4(ByVal s1 As String)
+ If Not String.IsNullOrEmpty(s1) Then
+ If Equals(s1, Nothing) Then ' Noncompliant
+ s1.ToString() ' Secondary
+ End If
+ Else
+ s1.ToString()
+ End If
+
+ End Sub
+
+ Public Sub Method5(ByVal s1 As String)
+ If Not String.IsNullOrEmpty(s1) Then
+ If Equals(s1, Nothing) Then ' Noncompliant
+ s1.ToString() ' Secondary
+ End If
+ Else
+ s1.ToString()
+ End If
+
+ End Sub
+
+ Public Sub Method6(ByVal s1 As String)
+ If String.IsNullOrEmpty(s1) OrElse Equals(s1, "a") Then
+ s1.ToString()
+ Else
+ If Equals(s1, Nothing) Then ' Noncompliant
+ s1.ToString() ' Secondary
+ End If
+ End If
+
+ End Sub
+
+ Public Sub Method7(ByVal s1 As String)
+ If String.IsNullOrEmpty(s1) AndAlso Equals(s1, "a") Then ' FN
+ s1.ToString()
+ Else
+ If Equals(s1, Nothing) Then
+ s1.ToString()
+ End If
+ End If
+
+ End Sub
+
+
+ Public Function Method8(ByVal message As String) As String
+ If Equals(message, Nothing) Then
+ Throw New ArgumentNullException($"{NameOf(message)} shouldn't be null!")
+ End If
+
+ If String.IsNullOrEmpty(message) Then
+ Throw New ArgumentNullException($"{NameOf(message)} shouldn't be empty!")
+ End If
+
+ Return String.Empty
+ End Function
+
+ Private Sub NullCoalesce_Useless(ByVal a As String, ByVal b As String, ByVal c As String, ByVal d As String)
+ Dim isNull As String = Nothing
+ Dim notNull = ""
+ Dim notEmpty = "value"
+ Dim ret As String
+
+ ret = If(b, a)
+ ret = If(b, notNull)
+ ret = If(c, notEmpty)
+ ret = If(d, "N/A")
+
+ 'Left operand: Values notNull and notEmpty are known to be not-null
+ ret = If(notNull, a) ' Noncompliant
+ ' Secondary@-1
+ ret = If(notNull, a) ' Noncompliant
+ ' Secondary@-1
+ ret = "Lorem " & If(notNull, a) & " ipsum" ' Noncompliant
+ ' Secondary@-1
+ ret = If(notNull, "N/A") ' Noncompliant
+ ' Secondary@-1
+ ret = If(notEmpty, "N/A") ' Noncompliant
+ ' Secondary@-1
+
+ 'Left operand: isNull is known to be null
+ ret = If(Nothing, a) ' Noncompliant
+ ret = If(isNull, a) ' NoncompliantP
+ ret = "Lorem " & If(isNull, a) & " ipsum" ' Noncompliant
+
+ 'Right operand: isNull is known to be null, therefore ?? is useless
+ ret = If(a, Nothing) ' FN: NOOP
+ ret = If(a, isNull) ' FN: NOOP
+ ' ~~~~~~
+
+ 'Combo/Fatality
+ ret = If(notNull, isNull)
+ ' ^^^^^^^ Noncompliant {{Change this expression which always evaluates to the same result. Some code paths are unreachable.}}
+ ' ^^^^^^ Secondary@-1
+ ret = If(isNull, Nothing) ' Noncompliant {{Change this expression which always evaluates to the same result.}}
+ ' ^^^^^^
+ ret = If("Value", a)
+ ' ^^^^^^^ Noncompliant {{Change this expression which always evaluates to the same result. Some code paths are unreachable.}}
+ ' ^ Secondary@-1
+ End Sub
+
+ Private Function CoalesceCount(Of T)(ByVal arg As IList(Of T)) As Integer
+ arg = If(arg, New List(Of T)())
+ Return arg.Count
+ End Function
+
+ Public Class CoalesceProperty
+ Private messageField As Object
+
+ Public ReadOnly Property Message As Object
+ Get
+ Return CSharpImpl.__Assign(messageField, If(messageField, New Object()))
+ End Get
+ End Property
+
+ Private Class CSharpImpl
+
+ Shared Function __Assign(Of T)(ByRef target As T, value As T) As T
+ target = value
+ Return value
+ End Function
+ End Class
+ End Class
+ End Class
+
+ Public Class NullOrWhiteSpace
+ Public Sub Method1(ByVal s As String)
+ Dim s1 As String = Nothing
+ Dim s2 = ""
+ Dim s3 = If(s, "")
+ Dim s4 = " "
+
+ If String.IsNullOrWhiteSpace(s1) Then ' Noncompliant
+ End If
+
+
+ If String.IsNullOrWhiteSpace(s2) Then ' FN
+ If Equals(s2, "a") Then ' FN
+
+ End If
+ End If
+
+ If String.IsNullOrWhiteSpace(s3) Then
+
+ End If
+
+ If String.IsNullOrWhiteSpace(s4) Then ' FN
+
+ End If
+
+ If Not String.IsNullOrWhiteSpace(s4) Then ' FN
+
+ End If
+
+ If Not String.IsNullOrWhiteSpace(s) Then
+ If Equals(s, "") Then ' FN
+
+ End If
+
+ If Equals(s, " ") Then ' FN
+
+ End If
+ End If
+
+ End Sub
+ End Class
+
+End Namespace
From 31279fc25efc28f07eb3eddbca5cd7638d9cc8d1 Mon Sep 17 00:00:00 2001
From: mary-georgiou-sonarsource
Date: Wed, 9 Aug 2023 11:21:18 +0200
Subject: [PATCH 03/20] Ignore this commit - rspec update so tests work - rspec
is draft
---
analyzers/rspec/vbnet/S2583.html | 56 +++++++++++++++++++
analyzers/rspec/vbnet/S2583.json | 33 +++++++++++
analyzers/rspec/vbnet/S2589.html | 59 ++++++++++++++++++++
analyzers/rspec/vbnet/S2589.json | 32 +++++++++++
analyzers/rspec/vbnet/Sonar_way_profile.json | 2 +
5 files changed, 182 insertions(+)
create mode 100644 analyzers/rspec/vbnet/S2583.html
create mode 100644 analyzers/rspec/vbnet/S2583.json
create mode 100644 analyzers/rspec/vbnet/S2589.html
create mode 100644 analyzers/rspec/vbnet/S2589.json
diff --git a/analyzers/rspec/vbnet/S2583.html b/analyzers/rspec/vbnet/S2583.html
new file mode 100644
index 00000000000..e3ac10fbce1
--- /dev/null
+++ b/analyzers/rspec/vbnet/S2583.html
@@ -0,0 +1,56 @@
+Why is this an issue?
+Conditional expressions which are always true
or false
can lead to unreachable code.
+In the case below, the call of Dispose()
never happens.
+
+var a = false;
+if (a)
+{
+ Dispose(); // Never reached
+}
+
+Exceptions
+This rule will not raise an issue in either of these cases:
+
+In these cases, it is obvious the code is as intended.
+How to fix it
+The conditions should be reviewed to decide whether:
+
+ - to update the condition or
+ - to remove the condition.
+
+Code examples
+Noncompliant code example
+
+' TODO
+
+Compliant solution
+
+' TODO
+
+Resources
+
+Documentation
+
+
diff --git a/analyzers/rspec/vbnet/S2583.json b/analyzers/rspec/vbnet/S2583.json
new file mode 100644
index 00000000000..c0cf516a4cc
--- /dev/null
+++ b/analyzers/rspec/vbnet/S2583.json
@@ -0,0 +1,33 @@
+{
+ "title": "Conditionally executed code should be reachable",
+ "type": "BUG",
+ "code": {
+ "impacts": {
+ "RELIABILITY": "MEDIUM"
+ },
+ "attribute": "LOGICAL"
+ },
+ "status": "ready",
+ "remediation": {
+ "func": "Constant\/Issue",
+ "constantCost": "15min"
+ },
+ "tags": [
+ "cwe",
+ "unused",
+ "suspicious",
+ "pitfall"
+ ],
+ "defaultSeverity": "Major",
+ "ruleSpecification": "RSPEC-2583",
+ "sqKey": "S2583",
+ "scope": "All",
+ "securityStandards": {
+ "CWE": [
+ 489,
+ 571,
+ 570
+ ]
+ },
+ "quickfix": "targeted"
+}
diff --git a/analyzers/rspec/vbnet/S2589.html b/analyzers/rspec/vbnet/S2589.html
new file mode 100644
index 00000000000..20919778e85
--- /dev/null
+++ b/analyzers/rspec/vbnet/S2589.html
@@ -0,0 +1,59 @@
+Why is this an issue?
+An operand of a boolean expression that never changes the result of the expression might not match the programmer’s intent and can lead to
+unexpected behavior and potential bugs.
+
+var a = true;
+if (a)
+{
+ DoSomething();
+}
+
+This also applies to the null
+coalescing operator when one of the operands always evaluates to null
.
+
+string d = null;
+var v1 = d ?? "value";
+
+Exceptions
+This rule will not raise an issue in either of these cases:
+
+In these cases, it is obvious the code is as intended.
+How to fix it
+The conditions should be reviewed to decide whether:
+
+ - to update the unnecessary operand
+ - to remove the unnecessary operand
+
+Code examples
+Noncompliant code example
+
+' To be updated
+
+Compliant solution
+
+' To be updated
+----
+
+Resources
+Documentation
+
+
diff --git a/analyzers/rspec/vbnet/S2589.json b/analyzers/rspec/vbnet/S2589.json
new file mode 100644
index 00000000000..3b655f4974f
--- /dev/null
+++ b/analyzers/rspec/vbnet/S2589.json
@@ -0,0 +1,32 @@
+{
+ "title": "Boolean expressions should not be gratuitous",
+ "type": "CODE_SMELL",
+ "code": {
+ "impacts": {
+ "MAINTAINABILITY": "MEDIUM"
+ },
+ "attribute": "LOGICAL"
+ },
+ "status": "ready",
+ "remediation": {
+ "func": "Constant\/Issue",
+ "constantCost": "10min"
+ },
+ "tags": [
+ "cwe",
+ "suspicious",
+ "redundant"
+ ],
+ "defaultSeverity": "Major",
+ "ruleSpecification": "RSPEC-2589",
+ "sqKey": "S2589",
+ "scope": "All",
+ "securityStandards": {
+ "CWE": [
+ 489,
+ 571,
+ 570
+ ]
+ },
+ "quickfix": "unknown"
+}
diff --git a/analyzers/rspec/vbnet/Sonar_way_profile.json b/analyzers/rspec/vbnet/Sonar_way_profile.json
index b31d79ea262..c8c73e8f87f 100644
--- a/analyzers/rspec/vbnet/Sonar_way_profile.json
+++ b/analyzers/rspec/vbnet/Sonar_way_profile.json
@@ -68,6 +68,8 @@
"S2387",
"S2437",
"S2551",
+ "S2583",
+ "S2589",
"S2612",
"S2692",
"S2737",
From 5d07f9b025dab7df438758f95745ecbac974aba8 Mon Sep 17 00:00:00 2001
From: mary-georgiou-sonarsource
Date: Thu, 10 Aug 2023 09:32:26 +0200
Subject: [PATCH 04/20] Change class name in UTs to be clearer
---
.../Roslyn/ConditionEvaluatesToConstant.CSharp9.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.CSharp9.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.CSharp9.cs
index 3f9e4b3c9ec..42cce4b0c0c 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.CSharp9.cs
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.CSharp9.cs
@@ -3,7 +3,7 @@
namespace Tests.Diagnostics
{
- public class CSharp8
+ public class Patterns
{
void IsPattern()
{
From b7fa219a6e5cde1dc5d0da1a26bdbb5449ee5cf1 Mon Sep 17 00:00:00 2001
From: mary-georgiou-sonarsource
Date: Thu, 10 Aug 2023 09:41:40 +0200
Subject: [PATCH 05/20] Fix after rebase
---
.../Roslyn/ConditionEvaluatesToConstant.cs | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs b/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
index 54c9fbd7b25..96d6770827e 100644
--- a/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
+++ b/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
@@ -29,13 +29,6 @@ public class ConditionEvaluatesToConstant : ConditionEvaluatesToConstantBase
protected override DiagnosticDescriptor Rule2589 => S2589;
public override bool ShouldExecute() => true;
- protected override bool IsConditionalAccessExpression(SyntaxNode syntax) =>
- syntax.Parent is ConditionalAccessExpressionSyntax conditional && conditional.Expression == syntax;
-
- protected override bool IsForLoopIncrementor(SyntaxNode syntax) => false; // Is is possible to have a boolean in a for loop in vb.net?
- protected override bool IsLeftCoalesceExpression(SyntaxNode syntax) =>
- syntax.Parent is BinaryConditionalExpressionSyntax { } binary
- && binary.FirstExpression == syntax;
- protected override bool IsUsing(SyntaxNode syntax) =>
- syntax.IsKind(SyntaxKind.VariableDeclarator) && syntax.Parent.IsKind(SyntaxKind.UsingStatement);
+ protected override bool IsInsideUsingDeclaration(SyntaxNode node) =>
+ node.IsKind(SyntaxKind.VariableDeclarator) && node.Parent.IsKind(SyntaxKind.UsingStatement);
}
From 29904d82ab7352226b46a335b4603c95017f64d4 Mon Sep 17 00:00:00 2001
From: mary-georgiou-sonarsource
Date: Thu, 10 Aug 2023 10:32:26 +0200
Subject: [PATCH 06/20] mark UTs with issue location and remove repros already
existing in C# uts
---
.../ConditionEvaluatesToConstant.VB14.vb | 21 +-
.../Roslyn/ConditionEvaluatesToConstant.vb | 252 ------------------
2 files changed, 12 insertions(+), 261 deletions(-)
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb
index d7d673f8474..4f852e6a4ba 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb
@@ -3,13 +3,15 @@
Private Sub ConditionalAccessNullPropagation(ByVal o As Object)
If o Is Nothing Then
- If Equals(o?.ToString(), Nothing) Then ' Noncompliant
- ' Secondary@-1
- ' Noncompliant@-2
+ If Equals(o?.ToString(), Nothing) Then
+ ' ^ Noncompliant
+ ' ^^^^^^^^^^^ Secondary@-1
+ ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
End If
- If o?.GetHashCode() Is Nothing Then '' Noncompliant
- ' Secondary@-1
- ' Noncompliant@-2
+ If o?.GetHashCode() Is Nothing Then
+ ' ^ Noncompliant
+ ' ^^^^^^^^^^^^^^ Secondary@-1
+ ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
End If
End If
End Sub
@@ -27,9 +29,10 @@
Dim m = New MyClassWithEnum()
Console.WriteLine(m.myEnum)
m = Nothing
- If m?.myEnum = MyEnum.One Then ' Noncompliant
- ' Secondary@-1
- ' Noncompliant@-2
+ If m?.myEnum = MyEnum.One Then
+ ' ^ Noncompliant
+ ' ^^^^^^^ Secondary@-1
+ ' ^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
End If
End Sub
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
index abdd7d8ea57..49bfeed6c9d 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
@@ -1421,88 +1421,6 @@ Namespace Tests.Diagnostics
End Function
End Class
- Friend Class Repro2442
- Public Sub Method(ByVal unknown As Boolean)
- Dim f = False
- Dim t = True
- If t Then ' Noncompliant
- Else
-
- End If
-
- If f Then ' Noncompliant
- Else
-
- End If
-
- If unknown OrElse t Then ' Noncompliant
- Else
-
- End If
-
- If unknown AndAlso f Then ' Noncompliant
- Else
-
- End If
-
- If unknown AndAlso t Then ' Noncompliant
- Else
-
- End If
-
- If unknown OrElse f Then ' Noncompliant
- Else
-
- End If
-
- If unknown AndAlso t Then ' Noncompliant
- Else
-
- End If
- End Sub
-
- '''
- ''' A certain combination of condition wrongly considers the else code as dead.
- '''
- Private Shared Sub FalsePositive()
- FalsePositive2_Sub(True, False, False)
- FalsePositive2_Sub(True, False, True)
-
- FalsePositive2_Sub(True, True, True)
- FalsePositive2_Sub(True, True, False)
-
- FalsePositive2_Sub(False, False, False)
- FalsePositive2_Sub(False, False, True)
-
- FalsePositive2_Sub(False, True, True)
- FalsePositive2_Sub(False, True, False)
-
- ' Outcome.
- Console.WriteLine(If(_test1 AndAlso _test2 AndAlso _test3 AndAlso _test4, "Went through each test condition", "Missed at least one test condition"))
- End Sub
-
- Private Shared _test1 As Boolean = False
- Private Shared _test2 As Boolean = False
- Private Shared _test3 As Boolean = False
- Private Shared _test4 As Boolean = False
-
- Private Shared Sub FalsePositive2_Sub(ByVal testCondition1 As Boolean, ByVal testCondition2 As Boolean, ByVal testCondition3 As Boolean)
- Dim condition1 = testCondition1
- Dim condition2 = testCondition2
- Dim condition3 = condition2 AndAlso testCondition3
-
- If condition2 AndAlso condition3 AndAlso condition1 Then
- _test1 = True
- ElseIf Not condition2 AndAlso Not condition1 Then
- _test2 = True
- ElseIf condition2 AndAlso condition1 AndAlso Not condition3 Then ' Noncompliant
- _test3 = True
- Else
- _test4 = True
- End If
- End Sub
- End Class
-
Public Class RefArgTest
Public Sub Method(ByRef s As String, ByVal x As Integer)
End Sub
@@ -1544,176 +1462,6 @@ Namespace Tests.Diagnostics
End Class
- Friend Class ReproForEachFP
- Private Shared Function Repro2348(ByVal list As List(Of Integer)) As Boolean
- Dim containspositive = False
- Dim containsnegative = False
-
- For Each value In list
- If value > 0 Then
- containspositive = True
- ElseIf value < 0 Then
- containsnegative = True
- End If
- Next
-
- Return containspositive AndAlso Not containsnegative ' Compliant
- End Function
-
- Private Shared Sub Repro1187_1()
- Dim do1 = False
- Dim do2 = False
- Dim items = New Integer() {1, 2, 3}
- For Each item In items
- Select Case item
- Case 1
- do1 = True
- Case 2
- do2 = True
- End Select
- Next
-
- If do1 AndAlso do2 Then ' Noncompliant: This repro is badly written. This is a TP. You can find the FP below.
- Throw New InvalidOperationException() ' Secondary
- End If
- End Sub
-
- Private Shared Sub Repro1187_1_Fixed(ByVal items As Integer())
- Dim do1 = False
- Dim do2 = False
- For Each item In items
- Select Case item
- Case 1
- do1 = True
- Case 2
- do2 = True
- End Select
- Next
-
- If do1 AndAlso do2 Then ' Noncompliant FP
- Throw New InvalidOperationException() ' Secondary FP
- End If
- End Sub
-
- Private Shared Sub Repro1187_2(ByVal elementGroup As List(Of Integer))
- Dim startDoingSomething = False
- Dim a = 0
-
- For Each element In elementGroup
- If Not startDoingSomething Then ' Compliant
- If element > 3 Then
- startDoingSomething = True
- End If
- Else
- a += 1
- End If
- Next
- End Sub
-
- Private Shared Function Repro1160(ByVal files As String()) As Boolean
- Dim anyPathRooted = False
- Dim allPathsRooted = True
- For Each file In files
- If Path.IsPathRooted(file) Then
- anyPathRooted = True
- Else
- allPathsRooted = False
- End If
- Next
- If anyPathRooted AndAlso Not allPathsRooted Then ' Noncompliant FP
- Throw New InvalidOperationException("Paths must be all rooted or all unrooted") ' Secondary FP
- End If
- Return allPathsRooted
- End Function
-
- Private Shared Function ForEachLoop(ByVal items As Integer()) As Boolean
- Dim bool1 = False
- Dim bool2 = False
-
- For Each item In items
- If item > 0 Then
- bool1 = True
- ElseIf item < 0 Then
- bool2 = True
- End If
- Next
-
- If bool1 AndAlso bool2 Then ' Noncompliant FP
- Throw New InvalidOperationException() ' Secondary FP
- End If
-
- Return bool1 AndAlso Not bool2 ' Compliant
- End Function
-
- Private Shared Function ForEachLoop2(ByVal items As Integer()) As Boolean
- Dim bool1 = False
- Dim bool2 = False
-
-BeforeLoop:
-
- For Each item1 In items
- For Each item2 In items
- For Each item3 In items
- For Each item4 In items
- If item1 > 0 Then
- bool1 = True
- ElseIf item2 < 0 Then
- bool2 = True
- End If
- Next
- Next
- Next
- Next
-
- If bool1 AndAlso bool2 Then ' Noncompliant FP FIX
- GoTo BeforeLoop
- End If
- Return False
- End Function
-
- Private Shared Function LoopIterationLimitation(ByVal items As Integer()) As Boolean
- Dim bool1 = False
- Dim bool2 = False
- Dim bool3 = False
-
- For Each item1 In items
- If bool2 Then ' Noncompliant - FP because symbolic execution stops at the third iteration of loop
- bool3 = True ' Secondary FP
- End If
- If bool1 Then
- bool2 = True
- End If
- If item1 > 1 Then
- bool1 = True
- End If
-
- Next
- Return bool3
- End Function
- End Class
-
- Public Class GeneratorFunctions
- Private generate As Boolean
-
- Public Sub [Stop]()
- generate = False
- End Sub
-
- Public Iterator Function Repro_1295() As IEnumerable(Of Integer)
- generate = True
- While generate ' Noncompliant FP: 'generate' field can potentially be changed inside the loop where this generator is used
- Yield 0
- End While
- End Function
-
- Public Iterator Function FalseNegative() As IEnumerable(Of Integer)
- Dim myVariable = True
- While myVariable ' Noncompliant: myVariable will never change after initialization
- Yield 0
- End While
- End Function
- End Class
-
Public Class StringComparision
Public Sub Method(ByVal parameterString As String)
Dim emptyString1 = ""
From ac8ca0d1fe96c74c67f2675e6f40bd72db56a7f5 Mon Sep 17 00:00:00 2001
From: mary-georgiou-sonarsource
Date: Thu, 10 Aug 2023 11:42:42 +0200
Subject: [PATCH 07/20] Add shouldexecute, tests for shouldExecute + small
fixes
---
.../Roslyn/ConditionEvaluatesToConstant.cs | 36 +++++-
.../ConditionEvaluatesToConstant.VB14.vb | 105 +++++++++++++++++-
.../Roslyn/ConditionEvaluatesToConstant.vb | 19 +---
3 files changed, 145 insertions(+), 15 deletions(-)
diff --git a/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs b/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
index 96d6770827e..15823297bd0 100644
--- a/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
+++ b/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
@@ -18,6 +18,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+using StyleCop.Analyzers.Lightup;
+
namespace SonarAnalyzer.SymbolicExecution.Roslyn.RuleChecks.VisualBasic;
public class ConditionEvaluatesToConstant : ConditionEvaluatesToConstantBase
@@ -28,7 +30,39 @@ public class ConditionEvaluatesToConstant : ConditionEvaluatesToConstantBase
protected override DiagnosticDescriptor Rule2583 => S2583;
protected override DiagnosticDescriptor Rule2589 => S2589;
- public override bool ShouldExecute() => true;
+ public override bool ShouldExecute()
+ {
+ var walker = new SyntaxKindWalker();
+ walker.SafeVisit(Node);
+ return walker.ContainsCondition;
+ }
+
+ private sealed class SyntaxKindWalker : SafeVisualBasicSyntaxWalker
+ {
+ public bool ContainsCondition { get; private set; }
+ public override void Visit(SyntaxNode node)
+ {
+ if (!ContainsCondition)
+ {
+ ContainsCondition = node.IsAnyKind(
+ SyntaxKind.AndAlsoExpression,
+ SyntaxKind.AndExpression,
+ SyntaxKind.BinaryConditionalExpression,
+ SyntaxKind.ConditionalAccessExpression,
+ SyntaxKind.DoWhileStatement,
+ SyntaxKind.DoUntilStatement,
+ SyntaxKind.SelectStatement,
+ SyntaxKind.SimpleDoStatement,
+ SyntaxKind.TernaryConditionalExpression,
+ SyntaxKind.IfStatement,
+ SyntaxKind.OrExpression,
+ SyntaxKind.OrElseExpression,
+ SyntaxKind.WhileStatement);
+
+ base.Visit(node);
+ }
+ }
+ }
protected override bool IsInsideUsingDeclaration(SyntaxNode node) =>
node.IsKind(SyntaxKind.VariableDeclarator) && node.Parent.IsKind(SyntaxKind.UsingStatement);
}
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb
index 4f852e6a4ba..7a806c5c756 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb
@@ -1,4 +1,6 @@
-Namespace Tests.Diagnostics
+Imports System
+
+Namespace Tests.Diagnostics
Public Class VB14
Private Sub ConditionalAccessNullPropagation(ByVal o As Object)
@@ -205,4 +207,105 @@
End Sub
End Class
End Class
+
+ Class ShouldExecute
+
+ Public Sub AndAlsoExpression()
+ Dim c1 = True
+ If c1 AndAlso c1 Then ' Noncompliant
+ ' Noncompliant@-1
+ Console.WriteLine("Always True")
+ End If
+ End Sub
+
+ Public Sub AndExpression()
+ Dim c1 = True
+ If c1 And c1 Then ' Noncompliant
+ Console.WriteLine("Always True")
+ End If
+ End Sub
+
+ Public Sub TernaryConditionalExpression()
+ Dim c1 = True
+ Dim x = If(c1, c1, c1) ' Noncompliant
+ ' Secondary@-1
+ End Sub
+
+ Public Shared Sub ConditionalAccessExpression()
+ Dim sObj = Nothing
+ Dim x = sObj?.str?.Length > 2 ' Noncompliant
+ ' Secondary@-1
+ End Sub
+
+ Public Sub DoLoopUntilStatement()
+ Dim c1 = false
+ Do
+ Console.WriteLine("")
+ Loop Until c1 ' Noncompliant
+ End Sub
+
+ Public Sub DoLoopWhileStatement()
+ Dim c1 = True
+ Do
+ Console.WriteLine("")
+ Loop While c1 ' Noncompliant
+ End Sub
+
+ Public Sub DoUntilStatement()
+ Dim c1 = False
+ Do Until c1 ' Noncompliant
+ Console.WriteLine("")
+ Loop
+ End Sub
+
+ Public Sub DoWhileStatement()
+ Dim c1 = True
+ Do While c1 ' Noncompliant
+ Console.WriteLine("")
+ Loop
+ End Sub
+
+ Public Sub IfStatement()
+ Dim c1 = True
+ If c1 ' Noncompliant
+ Console.WriteLine("")
+ End If
+ End Sub
+
+ Public Sub OrAlsoExpression()
+ Dim c1 = True
+ If c1 OrElse False Then ' Noncompliant
+ ' Secondary@-1
+ Console.WriteLine("Always True")
+ End If
+ End Sub
+
+ Public Sub OrExpression()
+ Dim c1 = True
+ If c1 Or False Then ' Noncompliant
+ Console.WriteLine("Always True")
+ End If
+ End Sub
+
+ Public Sub WhileStatement()
+ Dim c1 = True
+ While c1 ' Noncompliant
+ Console.WriteLine("")
+ End While
+ End Sub
+
+ Public Sub SelectStatement()
+ Dim i = 10
+ Dim b = True
+ Select Case i
+ Case 1 ' Noncompliant
+ b = False ' Secondary
+ End Select
+ End Sub
+
+ End Class
+
End Namespace
+
+
+
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
index 49bfeed6c9d..de13a2ef348 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
@@ -254,7 +254,7 @@ Namespace Tests.Diagnostics
End While
End Sub
- Public Sub Method_Switch()
+ Public Sub Method_Select()
Dim i = 10
Dim b = True
Select Case i
@@ -267,7 +267,7 @@ Namespace Tests.Diagnostics
End If
End Sub
- Public Sub Method_Switch_Learn(ByVal cond As Boolean)
+ Public Sub Method_Select_Learn(ByVal cond As Boolean)
Select Case cond
Case True
If cond Then ' Noncompliant
@@ -1427,7 +1427,7 @@ Namespace Tests.Diagnostics
Public Sub Method1(ByVal infixes As String)
If Not Equals(infixes, Nothing) Then
Method(infixes, infixes.Length)
- If Equals(infixes, Nothing) Then ' Noncompliant FP: ref
+ If Equals(infixes, Nothing) Then ' Noncompliant FP: ref
Return
End If
End If
@@ -1445,7 +1445,7 @@ Namespace Tests.Diagnostics
Public Sub Method3(ByVal infixes As String)
If Equals(infixes, Nothing) Then
Method(infixes, infixes.Length)
- If Equals(infixes, Nothing) Then ' Noncompliant FP: ref
+ If Equals(infixes, Nothing) Then ' Noncompliant FP: ref
Return
End If
End If
@@ -1515,7 +1515,7 @@ Namespace Tests.Diagnostics
End If
- If Equals(fullStringa1, Nothing) Then ' Noncompliant
+ If Equals(fullStringa1, Nothing) Then ' Noncompliant
End If
@@ -1723,17 +1723,10 @@ Namespace Tests.Diagnostics
Public ReadOnly Property Message As Object
Get
- Return CSharpImpl.__Assign(messageField, If(messageField, New Object()))
+ Return If(messageField Is Nothing, New Object(), messageField)
End Get
End Property
- Private Class CSharpImpl
-
- Shared Function __Assign(Of T)(ByRef target As T, value As T) As T
- target = value
- Return value
- End Function
- End Class
End Class
End Class
From a88295c0d36ab0161e7c1a193e03adc1b59c024f Mon Sep 17 00:00:00 2001
From: mary-georgiou-sonarsource
Date: Thu, 10 Aug 2023 14:08:31 +0200
Subject: [PATCH 08/20] Revert "Reworked secondary locations"
This reverts commit 4137efaa629d837a0d36e609c45473d81a021e28.
---
.../Roslyn/ConditionEvaluatesToConstant.cs | 17 ++++-
.../ConditionEvaluatesToConstantBase.cs | 67 +++++++++----------
.../Roslyn/SymbolicRuleCheck.cs | 7 +-
.../ConditionEvaluatesToConstant.CSharp8.cs | 15 ++---
.../Roslyn/ConditionEvaluatesToConstant.cs | 15 ++---
5 files changed, 60 insertions(+), 61 deletions(-)
diff --git a/analyzers/src/SonarAnalyzer.CSharp/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs b/analyzers/src/SonarAnalyzer.CSharp/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
index b0ebbf868f6..9ccf666951c 100644
--- a/analyzers/src/SonarAnalyzer.CSharp/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
+++ b/analyzers/src/SonarAnalyzer.CSharp/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
@@ -59,7 +59,18 @@ public override void Visit(SyntaxNode node)
}
}
- protected override bool IsInsideUsingDeclaration(SyntaxNode node) =>
- (node.IsKind(SyntaxKind.VariableDeclaration) && node.Parent.IsKind(SyntaxKind.UsingStatement))
- || (node is LocalDeclarationStatementSyntax local && local.UsingKeyword().IsKind(SyntaxKind.UsingKeyword));
+ protected override bool IsLeftCoalesceExpression(SyntaxNode syntax) =>
+ syntax.Parent is BinaryExpressionSyntax { } binary
+ && binary.OperatorToken.IsKind(SyntaxKind.QuestionQuestionToken)
+ && binary.Left == syntax;
+
+ protected override bool IsConditionalAccessExpression(SyntaxNode syntax) =>
+ syntax.Parent is ConditionalAccessExpressionSyntax conditional && conditional.Expression == syntax;
+
+ protected override bool IsForLoopIncrementor(SyntaxNode syntax) =>
+ syntax.Parent is ForStatementSyntax forStatement && forStatement.Incrementors.Contains(syntax);
+
+ protected override bool IsUsing(SyntaxNode syntax) =>
+ (syntax.IsKind(SyntaxKind.VariableDeclaration) && syntax.Parent.IsKind(SyntaxKind.UsingStatement))
+ || (syntax is LocalDeclarationStatementSyntax local && local.UsingKeyword().IsKind(SyntaxKind.UsingKeyword));
}
diff --git a/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/RuleChecks/ConditionEvaluatesToConstantBase.cs b/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/RuleChecks/ConditionEvaluatesToConstantBase.cs
index fd6b6220be3..df3b3f0918b 100644
--- a/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/RuleChecks/ConditionEvaluatesToConstantBase.cs
+++ b/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/RuleChecks/ConditionEvaluatesToConstantBase.cs
@@ -38,9 +38,12 @@ public abstract class ConditionEvaluatesToConstantBase : SymbolicRuleCheck
private readonly Dictionary trueOperations = new();
private readonly Dictionary falseOperations = new();
- private readonly List reached = new();
+ private readonly HashSet reached = new();
- protected abstract bool IsInsideUsingDeclaration(SyntaxNode node);
+ protected abstract bool IsLeftCoalesceExpression(SyntaxNode syntax);
+ protected abstract bool IsConditionalAccessExpression(SyntaxNode syntax);
+ protected abstract bool IsForLoopIncrementor(SyntaxNode syntax);
+ protected abstract bool IsUsing(SyntaxNode syntax);
public override ProgramState[] PreProcess(SymbolicContext context)
{
@@ -52,7 +55,7 @@ public override ProgramState ConditionEvaluated(SymbolicContext context)
{
var operation = context.Operation.Instance;
if (operation.Kind is not OperationKindEx.Literal
- && !operation.Syntax.Ancestors().Any(IsInsideUsingDeclaration)
+ && !operation.Syntax.Ancestors().Any(IsUsing)
&& operation.TrackedSymbol(context.State) is not IFieldSymbol { IsConst: true }
&& !IsDiscardPattern(operation))
{
@@ -90,54 +93,53 @@ public override void ExecutionCompleted()
private void ReportIssue(IOperation operation, BasicBlock block, bool conditionValue)
{
var issueMessage = operation.Kind == OperationKindEx.IsNull ? MessageNull : string.Format(MessageBool, conditionValue);
- var syntax = ToBranchValueCondition(operation.Syntax);
- var secondaryLocations = SecondaryLocations(block, conditionValue, syntax);
+ var secondaryLocations = SecondaryLocations(block, conditionValue);
if (secondaryLocations.Any())
{
- ReportIssue(Rule2583, syntax, secondaryLocations, issueMessage, S2583MessageSuffix);
+ ReportIssue(Rule2583, operation, secondaryLocations, issueMessage, S2583MessageSuffix);
}
else
{
- ReportIssue(Rule2589, syntax, null, issueMessage, string.Empty);
+ ReportIssue(Rule2589, operation, null, issueMessage, string.Empty);
}
}
- private List SecondaryLocations(BasicBlock block, bool conditionValue, SyntaxNode conditionSyntax)
+ private List SecondaryLocations(BasicBlock block, bool conditionValue)
{
List locations = new();
- var unreachable = UnreachableOperations(block, conditionValue).ToHashSet();
- var currentStart = conditionSyntax.Span.End;
- var reachedNodes = reached.Select(x => x.Syntax).Where(x => x.SpanStart > conditionSyntax.Span.End).OrderBy(x => x.SpanStart);
-
- foreach (var reachedNode in reachedNodes)
+ IOperation currentStart = null;
+ IOperation currentEnd = null;
+ var unreachable = UnreachableOperations(block, conditionValue).Where(x => !IsIgnoredLocation(x.Syntax)).ToHashSet();
+ foreach (var operation in unreachable.Concat(reached).OrderBy(x => x.Syntax.SpanStart))
{
- if (AddLocation(reachedNode.SpanStart))
+ if (unreachable.Contains(operation))
+ {
+ currentStart ??= operation;
+ currentEnd = operation;
+ }
+ else
{
- currentStart = reachedNode.Span.End;
+ AddCurrent();
}
}
- AddLocation(int.MaxValue);
+ AddCurrent();
return locations;
- bool AddLocation(int end)
+ void AddCurrent()
{
- var nodes = unreachable.Where(x => x.SpanStart > currentStart && x.Span.End < end);
- if (nodes.Any())
+ if (currentStart is not null)
{
- var first = nodes.OrderBy(x => x.SpanStart).First();
- var last = nodes.OrderBy(x => x.Span.End).Last();
- locations.Add(first.CreateLocation(last));
- return true;
+ locations.Add(currentStart.Syntax.CreateLocation(currentEnd.Syntax));
+ currentStart = null;
}
- return false;
}
}
- private IEnumerable UnreachableOperations(BasicBlock block, bool conditionValue)
+ private IEnumerable UnreachableOperations(BasicBlock block, bool conditionValue)
{
if (block.SuccessorBlocks.Distinct().Count() != 2)
{
- return Enumerable.Empty();
+ return Enumerable.Empty();
}
HashSet reachable = new() { block };
HashSet unreachable = new();
@@ -145,11 +147,7 @@ private IEnumerable UnreachableOperations(BasicBlock block, bool con
var conditionalIsRechable = (block.ConditionKind == ControlFlowConditionKind.WhenTrue) == conditionValue;
Traverse(conditionalIsRechable ? block.ConditionalSuccessor : block.FallThroughSuccessor, reachable, new List());
Traverse(conditionalIsRechable ? block.FallThroughSuccessor : block.ConditionalSuccessor, unreachable, reachable);
- return unreachable
- .SelectMany(x => x.OperationsAndBranchValue)
- .Except(reached)
- .SelectMany(x => x.DescendantsAndSelf().Select(x => x.Syntax))
- .ToList();
+ return unreachable.SelectMany(x => x.OperationsAndBranchValue).Except(reached);
static void Traverse(ControlFlowBranch branch, HashSet result, ICollection excluded)
{
@@ -170,7 +168,8 @@ static void Traverse(ControlFlowBranch branch, HashSet result, IColl
}
}
- // For SwitchExpressionArms like `true => 5` we are only interested in the left part (`true`).
- private static SyntaxNode ToBranchValueCondition(SyntaxNode syntax) =>
- syntax.IsKind(SyntaxKindEx.SwitchExpressionArm) ? ((SwitchExpressionArmSyntaxWrapper)syntax).Pattern : syntax;
+ private bool IsIgnoredLocation(SyntaxNode x) =>
+ IsForLoopIncrementor(x)
+ || IsConditionalAccessExpression(x)
+ || IsLeftCoalesceExpression(x);
}
diff --git a/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/SymbolicRuleCheck.cs b/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/SymbolicRuleCheck.cs
index b867c9bbcc5..f13eb966204 100644
--- a/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/SymbolicRuleCheck.cs
+++ b/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/SymbolicRuleCheck.cs
@@ -62,12 +62,9 @@ protected void ReportIssue(IOperation operation, IEnumerable additiona
ReportIssue(Rule, operation, additionalLocations, messageArgs);
}
- protected void ReportIssue(DiagnosticDescriptor rule, IOperation operation, IEnumerable additionalLocations, params object[] messageArgs) =>
- ReportIssue(rule, operation.Syntax, additionalLocations, messageArgs);
-
- protected void ReportIssue(DiagnosticDescriptor rule, SyntaxNode syntax, IEnumerable additionalLocations, params object[] messageArgs)
+ protected void ReportIssue(DiagnosticDescriptor rule, IOperation operation, IEnumerable additionalLocations, params object[] messageArgs)
{
- var location = syntax.GetLocation();
+ var location = operation.Syntax.GetLocation();
if (reportedDiagnostics.Add(location))
{
context.ReportIssue(Diagnostic.Create(rule, location, additionalLocations, messageArgs));
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.CSharp8.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.CSharp8.cs
index b5cf878241b..86d8a9b665c 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.CSharp8.cs
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.CSharp8.cs
@@ -23,11 +23,10 @@ public class CSharp8
int SwitchExpression()
{
var a = false;
- return a switch
+ return a switch // Secondary FP
{
- true => 0,
- // ^^^^ Noncompliant
- // ^ Secondary@-1
+ true => 0, // Noncompliant: true branch is always false
+ // Secondary@-1
false => 1 // Noncompliant: false branch is always true
};
}
@@ -235,9 +234,8 @@ void NullCoalesceAssignment_Useless(string a, string b, string c, string d)
//Left operand: Values notNull, notEmpty and ret are known to be not-null
ret = notNull;
- ret ??= a;
- // ^^^ Noncompliant
- // ^ Secondary@-1
+ ret ??= a; // Noncompliant
+ // Secondary@-1
ret = notNull;
ret = "Lorem " + (ret ??= a) + " ipsum"; // Noncompliant
@@ -257,6 +255,7 @@ void NullCoalesceAssignment_Useless(string a, string b, string c, string d)
ret = null;
ret = "Lorem " + (ret ??= a) + " ipsum"; // Noncompliant
+ // Secondary@-1
//Right operand: isNull is known to be null, therefore ?? is useless
ret = a;
@@ -461,7 +460,7 @@ void IfStatement()
void LogicalAndExpression()
{
- bool a = false;
+ bool a = true;
var b = a && true; // Noncompliant
// Secondary@-1
}
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
index 57c96418abd..5f1b73b610f 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
@@ -64,10 +64,9 @@ public void NotExecutedLoops(object o1, object o2, object o3)
// ^^
for (int i = 0; c3; i++) // Noncompliant {{Change this condition so that it does not always evaluate to 'False'. Some code paths are unreachable.}}
- // Secondary@-1 ^33#239
+ // ^^
{
- if (o3 != null)
- // secondary location starts at incrementor and ends at the end of the above line
+ if (o3 != null) // Secondary
break;
}
}
@@ -177,13 +176,6 @@ public void Foo7(bool a, bool b)
}
}
- public void Foo8(bool a, bool b)
- {
- a = true;
- _ = a && b;
- // ^ Noncompliant
- }
-
void Pointer(int* a) // Error [CS0214]
{
if (a != null) // Error [CS0214]
@@ -1925,7 +1917,7 @@ public static void NonCompliant6()
S sObj = null;
if (sObj?.str?.Length > 2)
// ^^^^ Noncompliant
- // ^^^^^^^^^^^^ Secondary@-1
+ // ^^^^^^^ Secondary@-1
// ^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
{
Console.WriteLine("a"); // Secondary
@@ -2800,6 +2792,7 @@ void NullCoalesce_Useless(string a, string b, string c, string d)
ret = null ?? a; // Noncompliant
ret = isNull ?? a; // Noncompliant
ret = ((isNull)) ?? a; // Noncompliant
+ // Secondary@-1 FP
ret = "Lorem " + (isNull ?? a) + " ipsum"; // Noncompliant
//Right operand: isNull is known to be null, therefore ?? is useless
From 1198475137b027a74081e6eae3c7f770a5e3fcc1 Mon Sep 17 00:00:00 2001
From: mary-georgiou-sonarsource
Date: Thu, 10 Aug 2023 14:12:42 +0200
Subject: [PATCH 09/20] revert secondary locations changes
---
.../Roslyn/ConditionEvaluatesToConstant.cs | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs b/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
index 15823297bd0..71bd7bde289 100644
--- a/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
+++ b/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
@@ -63,6 +63,15 @@ public override void Visit(SyntaxNode node)
}
}
}
- protected override bool IsInsideUsingDeclaration(SyntaxNode node) =>
- node.IsKind(SyntaxKind.VariableDeclarator) && node.Parent.IsKind(SyntaxKind.UsingStatement);
+ protected override bool IsConditionalAccessExpression(SyntaxNode syntax) =>
+ syntax.Parent is ConditionalAccessExpressionSyntax conditional && conditional.Expression == syntax;
+
+ protected override bool IsForLoopIncrementor(SyntaxNode syntax) => false; // Is is possible to have a boolean in a for loop in vb.net?
+
+ protected override bool IsLeftCoalesceExpression(SyntaxNode syntax) =>
+ syntax.Parent is BinaryConditionalExpressionSyntax { } binary
+ && binary.FirstExpression == syntax;
+
+ protected override bool IsUsing(SyntaxNode syntax) =>
+ syntax.IsKind(SyntaxKind.VariableDeclarator) && syntax.Parent.IsKind(SyntaxKind.UsingStatement);
}
From 38574921659dc724c81f80a4ed74cbee6ccfab3b Mon Sep 17 00:00:00 2001
From: mary-georgiou-sonarsource
Date: Thu, 10 Aug 2023 14:15:58 +0200
Subject: [PATCH 10/20] nitpicks
---
.../Roslyn/ConditionEvaluatesToConstant.cs | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs b/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
index 71bd7bde289..f98c7970963 100644
--- a/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
+++ b/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
@@ -51,10 +51,10 @@ public override void Visit(SyntaxNode node)
SyntaxKind.ConditionalAccessExpression,
SyntaxKind.DoWhileStatement,
SyntaxKind.DoUntilStatement,
+ SyntaxKind.IfStatement,
SyntaxKind.SelectStatement,
SyntaxKind.SimpleDoStatement,
SyntaxKind.TernaryConditionalExpression,
- SyntaxKind.IfStatement,
SyntaxKind.OrExpression,
SyntaxKind.OrElseExpression,
SyntaxKind.WhileStatement);
@@ -66,7 +66,10 @@ public override void Visit(SyntaxNode node)
protected override bool IsConditionalAccessExpression(SyntaxNode syntax) =>
syntax.Parent is ConditionalAccessExpressionSyntax conditional && conditional.Expression == syntax;
- protected override bool IsForLoopIncrementor(SyntaxNode syntax) => false; // Is is possible to have a boolean in a for loop in vb.net?
+ // For loop in VB.NET does dont have conditions in for loops.
+ // see https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/for-each-next-statement and
+ // https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/for-next-statement
+ protected override bool IsForLoopIncrementor(SyntaxNode syntax) => false;
protected override bool IsLeftCoalesceExpression(SyntaxNode syntax) =>
syntax.Parent is BinaryConditionalExpressionSyntax { } binary
From 6195d0e71ed086b5cb10392fe0b0e8a1f53a2937 Mon Sep 17 00:00:00 2001
From: mary-georgiou-sonarsource
Date: Thu, 10 Aug 2023 15:13:43 +0200
Subject: [PATCH 11/20] fix UTs
---
.../PackagingTests/RuleTypeMappingVB.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/PackagingTests/RuleTypeMappingVB.cs b/analyzers/tests/SonarAnalyzer.UnitTest/PackagingTests/RuleTypeMappingVB.cs
index 053882cb24d..f465745e4f8 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/PackagingTests/RuleTypeMappingVB.cs
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/PackagingTests/RuleTypeMappingVB.cs
@@ -2507,13 +2507,13 @@ internal static class RuleTypeMappingVB
// ["S2580"],
// ["S2581"],
// ["S2582"],
- // ["S2583"],
+ ["S2583"] = "BUG",
// ["S2584"],
// ["S2585"],
// ["S2586"],
// ["S2587"],
// ["S2588"],
- // ["S2589"],
+ ["S2589"] = "CODE_SMELL",
// ["S2590"],
// ["S2591"],
// ["S2592"],
From 1bc0abf82d82290d14147b0fcdd966a3d6bbae3a Mon Sep 17 00:00:00 2001
From: mary-georgiou-sonarsource
Date: Thu, 10 Aug 2023 15:22:37 +0200
Subject: [PATCH 12/20] update ITs
---
...AB-AF12-4012-B945-284C2448DC81}-S2589.json | 17 ++
...5E-C6AE-4D2D-A9DD-B6EFD19A4279}-S2583.json | 28 ++
...5E-C6AE-4D2D-A9DD-B6EFD19A4279}-S2589.json | 95 +++++++
...C2-EB9C-4090-B9A9-B703DF00CCEF}-S2589.json | 30 +++
...61-E2C2-4982-9536-63AEF0A98AAA}-S2589.json | 17 ++
...0E-DD76-4F4D-8250-8598140F828B}-S2583.json | 37 +++
...0E-DD76-4F4D-8250-8598140F828B}-S2589.json | 43 +++
...31-1F7B-4637-9B3A-806988DE50CF}-S2583.json | 244 ++++++++++++++++++
...31-1F7B-4637-9B3A-806988DE50CF}-S2589.json | 43 +++
9 files changed, 554 insertions(+)
create mode 100644 analyzers/its/expected/Ember-MM/Ember Media Manager-{9B57D3AB-AF12-4012-B945-284C2448DC81}-S2589.json
create mode 100644 analyzers/its/expected/Ember-MM/EmberAPI-{208AA35E-C6AE-4D2D-A9DD-B6EFD19A4279}-S2583.json
create mode 100644 analyzers/its/expected/Ember-MM/EmberAPI-{208AA35E-C6AE-4D2D-A9DD-B6EFD19A4279}-S2589.json
create mode 100644 analyzers/its/expected/Ember-MM/generic.EmberCore.MovieExporter-{B0BDF9C2-EB9C-4090-B9A9-B703DF00CCEF}-S2589.json
create mode 100644 analyzers/its/expected/Ember-MM/generic.EmberCore.XBMC-{6FE33C61-E2C2-4982-9536-63AEF0A98AAA}-S2589.json
create mode 100644 analyzers/its/expected/Ember-MM/scraper.EmberCore-{EF6A550E-DD76-4F4D-8250-8598140F828B}-S2583.json
create mode 100644 analyzers/its/expected/Ember-MM/scraper.EmberCore-{EF6A550E-DD76-4F4D-8250-8598140F828B}-S2589.json
create mode 100644 analyzers/its/expected/Ember-MM/scraper.EmberCore.XML-{E567C031-1F7B-4637-9B3A-806988DE50CF}-S2583.json
create mode 100644 analyzers/its/expected/Ember-MM/scraper.EmberCore.XML-{E567C031-1F7B-4637-9B3A-806988DE50CF}-S2589.json
diff --git a/analyzers/its/expected/Ember-MM/Ember Media Manager-{9B57D3AB-AF12-4012-B945-284C2448DC81}-S2589.json b/analyzers/its/expected/Ember-MM/Ember Media Manager-{9B57D3AB-AF12-4012-B945-284C2448DC81}-S2589.json
new file mode 100644
index 00000000000..a774e83fffb
--- /dev/null
+++ b/analyzers/its/expected/Ember-MM/Ember Media Manager-{9B57D3AB-AF12-4012-B945-284C2448DC81}-S2589.json
@@ -0,0 +1,17 @@
+{
+"issues": [
+{
+"id": "S2589",
+"message": "Change this condition so that it does not always evaluate to 'True'.",
+"location": {
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Ember%20Media%20Manager/dlgSettings.vb#L105",
+"region": {
+"startLine": 105,
+"startColumn": 12,
+"endLine": 105,
+"endColumn": 26
+}
+}
+}
+]
+}
diff --git a/analyzers/its/expected/Ember-MM/EmberAPI-{208AA35E-C6AE-4D2D-A9DD-B6EFD19A4279}-S2583.json b/analyzers/its/expected/Ember-MM/EmberAPI-{208AA35E-C6AE-4D2D-A9DD-B6EFD19A4279}-S2583.json
new file mode 100644
index 00000000000..9c21c355d2f
--- /dev/null
+++ b/analyzers/its/expected/Ember-MM/EmberAPI-{208AA35E-C6AE-4D2D-A9DD-B6EFD19A4279}-S2583.json
@@ -0,0 +1,28 @@
+{
+"issues": [
+{
+"id": "S2583",
+"message": "Change this condition so that it does not always evaluate to 'False'. Some code paths are unreachable.",
+"location": [
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/EmberAPI/clsAPILocalization.vb#L242",
+"region": {
+"startLine": 242,
+"startColumn": 32,
+"endLine": 242,
+"endColumn": 48
+}
+},
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/EmberAPI/clsAPILocalization.vb#L245",
+"region": {
+"startLine": 245,
+"startColumn": 29,
+"endLine": 245,
+"endColumn": 130
+}
+}
+]
+}
+]
+}
diff --git a/analyzers/its/expected/Ember-MM/EmberAPI-{208AA35E-C6AE-4D2D-A9DD-B6EFD19A4279}-S2589.json b/analyzers/its/expected/Ember-MM/EmberAPI-{208AA35E-C6AE-4D2D-A9DD-B6EFD19A4279}-S2589.json
new file mode 100644
index 00000000000..2a6b873d11e
--- /dev/null
+++ b/analyzers/its/expected/Ember-MM/EmberAPI-{208AA35E-C6AE-4D2D-A9DD-B6EFD19A4279}-S2589.json
@@ -0,0 +1,95 @@
+{
+"issues": [
+{
+"id": "S2589",
+"message": "Change this condition so that it does not always evaluate to 'False'.",
+"location": {
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/EmberAPI/clsAPIHTTP.vb#L275",
+"region": {
+"startLine": 275,
+"startColumn": 66,
+"endLine": 275,
+"endColumn": 76
+}
+}
+},
+{
+"id": "S2589",
+"message": "Change this condition so that it does not always evaluate to 'False'.",
+"location": {
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/EmberAPI/clsAPIHTTP.vb#L308",
+"region": {
+"startLine": 308,
+"startColumn": 20,
+"endLine": 308,
+"endColumn": 30
+}
+}
+},
+{
+"id": "S2589",
+"message": "Change this condition so that it does not always evaluate to 'False'.",
+"location": {
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/EmberAPI/clsAPIHTTP.vb#L311",
+"region": {
+"startLine": 311,
+"startColumn": 24,
+"endLine": 311,
+"endColumn": 34
+}
+}
+},
+{
+"id": "S2589",
+"message": "Change this condition so that it does not always evaluate to 'False'.",
+"location": {
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/EmberAPI/clsAPIHTTP.vb#L314",
+"region": {
+"startLine": 314,
+"startColumn": 28,
+"endLine": 314,
+"endColumn": 38
+}
+}
+},
+{
+"id": "S2589",
+"message": "Change this condition so that it does not always evaluate to 'False'.",
+"location": {
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/EmberAPI/clsAPINFO.vb#L461",
+"region": {
+"startLine": 461,
+"startColumn": 32,
+"endLine": 461,
+"endColumn": 49
+}
+}
+},
+{
+"id": "S2589",
+"message": "Change this condition so that it does not always evaluate to 'True'.",
+"location": {
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/EmberAPI/clsAPINFO.vb#L706",
+"region": {
+"startLine": 706,
+"startColumn": 24,
+"endLine": 706,
+"endColumn": 34
+}
+}
+},
+{
+"id": "S2589",
+"message": "Change this condition so that it does not always evaluate to 'True'.",
+"location": {
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/EmberAPI/clsAPINFO.vb#L978",
+"region": {
+"startLine": 978,
+"startColumn": 20,
+"endLine": 978,
+"endColumn": 30
+}
+}
+}
+]
+}
diff --git a/analyzers/its/expected/Ember-MM/generic.EmberCore.MovieExporter-{B0BDF9C2-EB9C-4090-B9A9-B703DF00CCEF}-S2589.json b/analyzers/its/expected/Ember-MM/generic.EmberCore.MovieExporter-{B0BDF9C2-EB9C-4090-B9A9-B703DF00CCEF}-S2589.json
new file mode 100644
index 00000000000..d9469e1ef36
--- /dev/null
+++ b/analyzers/its/expected/Ember-MM/generic.EmberCore.MovieExporter-{B0BDF9C2-EB9C-4090-B9A9-B703DF00CCEF}-S2589.json
@@ -0,0 +1,30 @@
+{
+"issues": [
+{
+"id": "S2589",
+"message": "Change this condition so that it does not always evaluate to 'False'.",
+"location": {
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/generic.EmberCore.MovieExport/dlgExportMovies.vb#L367",
+"region": {
+"startLine": 367,
+"startColumn": 24,
+"endLine": 367,
+"endColumn": 31
+}
+}
+},
+{
+"id": "S2589",
+"message": "Change this condition so that it does not always evaluate to 'False'.",
+"location": {
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/generic.EmberCore.MovieExport/dlgExportMovies.vb#L754",
+"region": {
+"startLine": 754,
+"startColumn": 20,
+"endLine": 754,
+"endColumn": 39
+}
+}
+}
+]
+}
diff --git a/analyzers/its/expected/Ember-MM/generic.EmberCore.XBMC-{6FE33C61-E2C2-4982-9536-63AEF0A98AAA}-S2589.json b/analyzers/its/expected/Ember-MM/generic.EmberCore.XBMC-{6FE33C61-E2C2-4982-9536-63AEF0A98AAA}-S2589.json
new file mode 100644
index 00000000000..7b517d64098
--- /dev/null
+++ b/analyzers/its/expected/Ember-MM/generic.EmberCore.XBMC-{6FE33C61-E2C2-4982-9536-63AEF0A98AAA}-S2589.json
@@ -0,0 +1,17 @@
+{
+"issues": [
+{
+"id": "S2589",
+"message": "Change this condition so that it does not always evaluate to 'True'.",
+"location": {
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/generic.EmberCore.XBMC/Module.XBMCxCom.vb#L404",
+"region": {
+"startLine": 404,
+"startColumn": 30,
+"endLine": 404,
+"endColumn": 40
+}
+}
+}
+]
+}
diff --git a/analyzers/its/expected/Ember-MM/scraper.EmberCore-{EF6A550E-DD76-4F4D-8250-8598140F828B}-S2583.json b/analyzers/its/expected/Ember-MM/scraper.EmberCore-{EF6A550E-DD76-4F4D-8250-8598140F828B}-S2583.json
new file mode 100644
index 00000000000..2a8e8ed6d74
--- /dev/null
+++ b/analyzers/its/expected/Ember-MM/scraper.EmberCore-{EF6A550E-DD76-4F4D-8250-8598140F828B}-S2583.json
@@ -0,0 +1,37 @@
+{
+"issues": [
+{
+"id": "S2583",
+"message": "Change this condition so that it does not always evaluate to 'False'. Some code paths are unreachable.",
+"location": [
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore/TVScraper/dlgTVImageSelect.vb#L989",
+"region": {
+"startLine": 989,
+"startColumn": 16,
+"endLine": 989,
+"endColumn": 31
+}
+},
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore/TVScraper/dlgTVImageSelect.vb#L989",
+"region": {
+"startLine": 989,
+"startColumn": 43,
+"endLine": 989,
+"endColumn": 56
+}
+},
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore/TVScraper/dlgTVImageSelect.vb#L992",
+"region": {
+"startLine": 992,
+"startColumn": 13,
+"endLine": 992,
+"endColumn": 58
+}
+}
+]
+}
+]
+}
diff --git a/analyzers/its/expected/Ember-MM/scraper.EmberCore-{EF6A550E-DD76-4F4D-8250-8598140F828B}-S2589.json b/analyzers/its/expected/Ember-MM/scraper.EmberCore-{EF6A550E-DD76-4F4D-8250-8598140F828B}-S2589.json
new file mode 100644
index 00000000000..11353f2e979
--- /dev/null
+++ b/analyzers/its/expected/Ember-MM/scraper.EmberCore-{EF6A550E-DD76-4F4D-8250-8598140F828B}-S2589.json
@@ -0,0 +1,43 @@
+{
+"issues": [
+{
+"id": "S2589",
+"message": "Change this condition so that it does not always evaluate to 'False'.",
+"location": {
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore/TVScraper/clsScrapeTVDB.vb#L674",
+"region": {
+"startLine": 674,
+"startColumn": 44,
+"endLine": 674,
+"endColumn": 68
+}
+}
+},
+{
+"id": "S2589",
+"message": "Change this condition so that it does not always evaluate to 'False'.",
+"location": {
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore/TVScraper/clsScrapeTVDB.vb#L694",
+"region": {
+"startLine": 694,
+"startColumn": 40,
+"endLine": 694,
+"endColumn": 64
+}
+}
+},
+{
+"id": "S2589",
+"message": "Change this condition so that it does not always evaluate to 'False'.",
+"location": {
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore/TVScraper/clsScrapeTVDB.vb#L715",
+"region": {
+"startLine": 715,
+"startColumn": 48,
+"endLine": 715,
+"endColumn": 72
+}
+}
+}
+]
+}
diff --git a/analyzers/its/expected/Ember-MM/scraper.EmberCore.XML-{E567C031-1F7B-4637-9B3A-806988DE50CF}-S2583.json b/analyzers/its/expected/Ember-MM/scraper.EmberCore.XML-{E567C031-1F7B-4637-9B3A-806988DE50CF}-S2583.json
new file mode 100644
index 00000000000..bf9c75c30b8
--- /dev/null
+++ b/analyzers/its/expected/Ember-MM/scraper.EmberCore.XML-{E567C031-1F7B-4637-9B3A-806988DE50CF}-S2583.json
@@ -0,0 +1,244 @@
+{
+"issues": [
+{
+"id": "S2583",
+"message": "Change this condition so that it does not always evaluate to 'True'. Some code paths are unreachable.",
+"location": [
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/frmXMLSettingsHolder.vb#L44",
+"region": {
+"startLine": 44,
+"startColumn": 15,
+"endLine": 44,
+"endColumn": 28
+}
+},
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/frmXMLSettingsHolder.vb#L48-L51",
+"region": {
+"startLine": 48,
+"startColumn": 9,
+"endLine": 51,
+"endColumn": 35
+}
+}
+]
+},
+{
+"id": "S2583",
+"message": "Change this condition so that it does not always evaluate to 'False'. Some code paths are unreachable.",
+"location": [
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/MediaTags/AlbumTag.vb#L380",
+"region": {
+"startLine": 380,
+"startColumn": 20,
+"endLine": 380,
+"endColumn": 33
+}
+},
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/MediaTags/AlbumTag.vb#L381-L384",
+"region": {
+"startLine": 381,
+"startColumn": 24,
+"endLine": 384,
+"endColumn": 33
+}
+}
+]
+},
+{
+"id": "S2583",
+"message": "Change this condition so that it does not always evaluate to 'False'. Some code paths are unreachable.",
+"location": [
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/MediaTags/PersonInfo.vb#L221",
+"region": {
+"startLine": 221,
+"startColumn": 20,
+"endLine": 221,
+"endColumn": 33
+}
+},
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/MediaTags/PersonInfo.vb#L222-L225",
+"region": {
+"startLine": 222,
+"startColumn": 24,
+"endLine": 225,
+"endColumn": 34
+}
+}
+]
+},
+{
+"id": "S2583",
+"message": "Change this condition so that it does not always evaluate to 'False'. Some code paths are unreachable.",
+"location": [
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/ScraperLib/ScrapeResultsEntity.vb#L398",
+"region": {
+"startLine": 398,
+"startColumn": 20,
+"endLine": 398,
+"endColumn": 33
+}
+},
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/ScraperLib/ScrapeResultsEntity.vb#L399-L402",
+"region": {
+"startLine": 399,
+"startColumn": 24,
+"endLine": 402,
+"endColumn": 33
+}
+}
+]
+},
+{
+"id": "S2583",
+"message": "Change this condition so that it does not always evaluate to 'False'. Some code paths are unreachable.",
+"location": [
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/ScraperLib/ScrapeResultsEntity.vb#L414",
+"region": {
+"startLine": 414,
+"startColumn": 20,
+"endLine": 414,
+"endColumn": 33
+}
+},
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/ScraperLib/ScrapeResultsEntity.vb#L415-L418",
+"region": {
+"startLine": 415,
+"startColumn": 24,
+"endLine": 418,
+"endColumn": 33
+}
+}
+]
+},
+{
+"id": "S2583",
+"message": "Change this condition so that it does not always evaluate to 'False'. Some code paths are unreachable.",
+"location": [
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/ScraperLib/ScrapeResultsEntity.vb#L430",
+"region": {
+"startLine": 430,
+"startColumn": 20,
+"endLine": 430,
+"endColumn": 33
+}
+},
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/ScraperLib/ScrapeResultsEntity.vb#L431-L434",
+"region": {
+"startLine": 431,
+"startColumn": 24,
+"endLine": 434,
+"endColumn": 33
+}
+}
+]
+},
+{
+"id": "S2583",
+"message": "Change this condition so that it does not always evaluate to 'False'. Some code paths are unreachable.",
+"location": [
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/ScraperLib/ScrapeResultsEntity.vb#L446",
+"region": {
+"startLine": 446,
+"startColumn": 20,
+"endLine": 446,
+"endColumn": 33
+}
+},
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/ScraperLib/ScrapeResultsEntity.vb#L447-L450",
+"region": {
+"startLine": 447,
+"startColumn": 24,
+"endLine": 450,
+"endColumn": 33
+}
+}
+]
+},
+{
+"id": "S2583",
+"message": "Change this condition so that it does not always evaluate to 'False'. Some code paths are unreachable.",
+"location": [
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/ScraperLib/ScrapeResultsEntity.vb#L462",
+"region": {
+"startLine": 462,
+"startColumn": 20,
+"endLine": 462,
+"endColumn": 33
+}
+},
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/ScraperLib/ScrapeResultsEntity.vb#L463-L466",
+"region": {
+"startLine": 463,
+"startColumn": 24,
+"endLine": 466,
+"endColumn": 33
+}
+}
+]
+},
+{
+"id": "S2583",
+"message": "Change this condition so that it does not always evaluate to 'False'. Some code paths are unreachable.",
+"location": [
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/ScraperLib/ScraperEvaluation.vb#L101",
+"region": {
+"startLine": 101,
+"startColumn": 20,
+"endLine": 101,
+"endColumn": 33
+}
+},
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/ScraperLib/ScraperEvaluation.vb#L102-L105",
+"region": {
+"startLine": 102,
+"startColumn": 24,
+"endLine": 105,
+"endColumn": 33
+}
+}
+]
+},
+{
+"id": "S2583",
+"message": "Change this condition so that it does not always evaluate to 'False'. Some code paths are unreachable.",
+"location": [
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/ScraperXML/ScraperInfo.vb#L190",
+"region": {
+"startLine": 190,
+"startColumn": 20,
+"endLine": 190,
+"endColumn": 33
+}
+},
+{
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/ScraperXML/ScraperInfo.vb#L191-L194",
+"region": {
+"startLine": 191,
+"startColumn": 24,
+"endLine": 194,
+"endColumn": 33
+}
+}
+]
+}
+]
+}
diff --git a/analyzers/its/expected/Ember-MM/scraper.EmberCore.XML-{E567C031-1F7B-4637-9B3A-806988DE50CF}-S2589.json b/analyzers/its/expected/Ember-MM/scraper.EmberCore.XML-{E567C031-1F7B-4637-9B3A-806988DE50CF}-S2589.json
new file mode 100644
index 00000000000..afdb05225cb
--- /dev/null
+++ b/analyzers/its/expected/Ember-MM/scraper.EmberCore.XML-{E567C031-1F7B-4637-9B3A-806988DE50CF}-S2589.json
@@ -0,0 +1,43 @@
+{
+"issues": [
+{
+"id": "S2589",
+"message": "Change this condition so that it does not always evaluate to 'False'.",
+"location": {
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/ScraperLib/ScrapeResultsEntity.vb#L344",
+"region": {
+"startLine": 344,
+"startColumn": 24,
+"endLine": 344,
+"endColumn": 40
+}
+}
+},
+{
+"id": "S2589",
+"message": "Change this condition so that it does not always evaluate to 'False'.",
+"location": {
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/ScraperLib/ScrapeResultsEntity.vb#L348",
+"region": {
+"startLine": 348,
+"startColumn": 24,
+"endLine": 348,
+"endColumn": 37
+}
+}
+},
+{
+"id": "S2589",
+"message": "Change this condition so that it does not always evaluate to 'False'.",
+"location": {
+"uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/sources/Ember-MM/Addons/scraper.EmberCore.XML/XMLScraper/ScraperLib/ScrapeResultsEntity.vb#L372",
+"region": {
+"startLine": 372,
+"startColumn": 24,
+"endLine": 372,
+"endColumn": 41
+}
+}
+}
+]
+}
From 0b67aa5e468e3b770a4d870b2184a93aab25635f Mon Sep 17 00:00:00 2001
From: mary-georgiou-sonarsource
Date: Thu, 10 Aug 2023 17:06:40 +0200
Subject: [PATCH 13/20] remove usused using
---
.../SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs | 2 --
1 file changed, 2 deletions(-)
diff --git a/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs b/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
index f98c7970963..9614c8ff0f6 100644
--- a/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
+++ b/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
@@ -18,8 +18,6 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-using StyleCop.Analyzers.Lightup;
-
namespace SonarAnalyzer.SymbolicExecution.Roslyn.RuleChecks.VisualBasic;
public class ConditionEvaluatesToConstant : ConditionEvaluatesToConstantBase
From a749c8e19aaf98de8b560b1d4e1470e555963968 Mon Sep 17 00:00:00 2001
From: mary-georgiou-sonarsource
Date: Thu, 10 Aug 2023 17:58:08 +0200
Subject: [PATCH 14/20] Apply issue locations
---
.../Roslyn/ConditionEvaluatesToConstant.cs | 2 -
.../ConditionEvaluatesToConstant.VB14.vb | 92 +++++++++----------
.../Roslyn/ConditionEvaluatesToConstant.cs | 8 +-
.../Roslyn/ConditionEvaluatesToConstant.vb | 21 +----
4 files changed, 49 insertions(+), 74 deletions(-)
diff --git a/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs b/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
index 9614c8ff0f6..1e9dae0e0c8 100644
--- a/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
+++ b/analyzers/src/SonarAnalyzer.VisualBasic/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
@@ -44,7 +44,6 @@ public override void Visit(SyntaxNode node)
{
ContainsCondition = node.IsAnyKind(
SyntaxKind.AndAlsoExpression,
- SyntaxKind.AndExpression,
SyntaxKind.BinaryConditionalExpression,
SyntaxKind.ConditionalAccessExpression,
SyntaxKind.DoWhileStatement,
@@ -53,7 +52,6 @@ public override void Visit(SyntaxNode node)
SyntaxKind.SelectStatement,
SyntaxKind.SimpleDoStatement,
SyntaxKind.TernaryConditionalExpression,
- SyntaxKind.OrExpression,
SyntaxKind.OrElseExpression,
SyntaxKind.WhileStatement);
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb
index 7a806c5c756..a331328af6a 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb
@@ -63,16 +63,16 @@ Namespace Tests.Diagnostics
Public Class Result
Public Property Succeed As Boolean
- Public Shared Function Test() As Result
- If Date.Now.Day = 17 Then ' swap value here to test both cases if needed
+ Public Shared Function Test(ByVal cond As Boolean) As Result
+ If cond Then
Return New Result()
End If
Return Nothing
End Function
End Class
- Public Shared Sub Compliant1()
- Dim result = TestNullConditional.Result.Test()
+ Public Shared Sub Compliant1(ByVal cond As Boolean)
+ Dim result = TestNullConditional.Result.Test(cond)
If result Is Nothing OrElse Not result.Succeed Then
Console.WriteLine("shorted")
@@ -91,10 +91,11 @@ Namespace Tests.Diagnostics
Public Shared Sub NonCompliant1()
Dim result As Result = Nothing
- If result?.Succeed IsNot Nothing Then ' Noncompliant
- ' Secondary@-1
- ' Noncompliant@-2
- Console.WriteLine("shorted") ' Secondary
+ If result?.Succeed IsNot Nothing Then
+ ' ^^^^^^ Noncompliant
+ ' ^^^^^^^^ Secondary@-1
+ ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
+ Console.WriteLine("shorted") ' Secondary
If result IsNot Nothing Then
Console.WriteLine("other")
End If
@@ -103,10 +104,11 @@ Namespace Tests.Diagnostics
Public Shared Sub NonCompliant2()
Dim result As Result = New Result()
- If result?.Succeed IsNot Nothing Then ' Noncompliant
- ' Noncompliant@-1
+ If result?.Succeed IsNot Nothing Then
+ ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant
+ ' ^^^^^^ Noncompliant@-1
Console.WriteLine("shorted")
- While result IsNot Nothing ' Noncompliant
+ While result IsNot Nothing ' Noncompliant
Console.WriteLine("other")
End While
End If
@@ -118,24 +120,27 @@ Namespace Tests.Diagnostics
Public Shared Sub Compliant2()
Dim aObj As A = Nothing
- If If(aObj?.booleanVal, False) Then ' Noncompliant
- ' Secondary@-1
- ' Noncompliant@-2
+ If If(aObj?.booleanVal, False) Then
+ ' ^^^^ Noncompliant
+ ' ^^^^^^^^^^^ Secondary@-1
+ ' ^^^^^^^^^^^^^^^^ Noncompliant@-2
Console.WriteLine("a")
End If
End Sub
Public Shared Sub NonCompliant3()
Dim aObj As A = Nothing
- If aObj?.booleanVal Is Nothing Then ' Noncompliant
- ' Secondary@-1
- ' Noncompliant@-2
+ If aObj?.booleanVal Is Nothing Then
+ ' ^^^^ Noncompliant
+ ' ^^^^^^^^^^^ Secondary@-1
+ ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
Console.WriteLine("a")
End If
- If aObj?.booleanVal IsNot Nothing Then ' Noncompliant
- ' Secondary@-1
- ' Noncompliant@-2
+ If aObj?.booleanVal IsNot Nothing Then
+ ' ^^^^ Noncompliant
+ ' ^^^^^^^^^^^ Secondary@-1
+ ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
Console.WriteLine("a") ' Secondary
End If
End Sub
@@ -179,10 +184,11 @@ Namespace Tests.Diagnostics
Public Shared Sub NonCompliant5()
Dim a As A = Nothing
- While If(a?.booleanVal Is Nothing, True, False) ' Noncompliant
- ' Secondary@-1
- ' Noncompliant@-2
- ' Secondary@-3
+ While If(a?.booleanVal Is Nothing, True, False)
+ ' ^ Noncompliant
+ ' ^^^^^^^^^^^ Secondary@-1
+ ' ^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
+ ' ^^^^^ Secondary@-3
Console.WriteLine("Compliant")
End While
End Sub
@@ -199,9 +205,10 @@ Namespace Tests.Diagnostics
Public Shared Sub NonCompliant6()
Dim sObj As S = Nothing
- If sObj?.str?.Length > 2 Then ' Noncompliant
- ' Secondary@-1
- ' Noncompliant@-2
+ If sObj?.str?.Length > 2 Then
+ ' ^^^^ Noncompliant
+ ' ^^^^^^^ Secondary@-1
+ ' ^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
Console.WriteLine("a") ' Secondary
End If
End Sub
@@ -212,17 +219,8 @@ Namespace Tests.Diagnostics
Public Sub AndAlsoExpression()
Dim c1 = True
- If c1 AndAlso c1 Then ' Noncompliant
- ' Noncompliant@-1
- Console.WriteLine("Always True")
- End If
- End Sub
-
- Public Sub AndExpression()
- Dim c1 = True
- If c1 And c1 Then ' Noncompliant
- Console.WriteLine("Always True")
- End If
+ Dim a = c1 AndAlso c1 ' Noncompliant
+ ' Secondary@-1
End Sub
Public Sub TernaryConditionalExpression()
@@ -233,8 +231,9 @@ Namespace Tests.Diagnostics
Public Shared Sub ConditionalAccessExpression()
Dim sObj = Nothing
- Dim x = sObj?.str?.Length > 2 ' Noncompliant
- ' Secondary@-1
+ Dim x = sObj?.str?.Length > 2
+ ' ^^^^ Noncompliant
+ ' ^^^^^^^ Secondary@-1
End Sub
Public Sub DoLoopUntilStatement()
@@ -274,17 +273,8 @@ Namespace Tests.Diagnostics
Public Sub OrAlsoExpression()
Dim c1 = True
- If c1 OrElse False Then ' Noncompliant
- ' Secondary@-1
- Console.WriteLine("Always True")
- End If
- End Sub
-
- Public Sub OrExpression()
- Dim c1 = True
- If c1 Or False Then ' Noncompliant
- Console.WriteLine("Always True")
- End If
+ Dim a = c1 OrElse False ' Noncompliant
+ ' Secondary@-1
End Sub
Public Sub WhileStatement()
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
index 5f1b73b610f..e1e556f1290 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
@@ -1739,9 +1739,9 @@ public class Result
{
public bool Succeed { get; set; }
- public static Result Test()
+ public static Result Test(bool cond)
{
- if (DateTime.Now.Day == 17) // swap value here to test both cases if needed
+ if (cond)
{
return new Result();
}
@@ -1749,9 +1749,9 @@ public static Result Test()
}
}
- public static void Compliant1()
+ public static void Compliant1(bool cond)
{
- var result = Result.Test();
+ var result = Result.Test(cond);
if (result == null || !result.Succeed)
{
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
index de13a2ef348..1a1164fa923 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
@@ -160,7 +160,7 @@ Namespace Tests.Diagnostics
Console.WriteLine()
Else
' secondary location covers all unreachable code blocks:
- Console.WriteLine(1) ' Secondary ??????
+ Console.WriteLine(1) ' Secondary ^17#108
While b
Console.WriteLine(2)
End While ' the secondary location ends at the end of the above line
@@ -205,7 +205,7 @@ Namespace Tests.Diagnostics
b = False
End Sub
- Public Sub Method5(ByVal cond As Boolean)
+ Public Sub Method3(ByVal cond As Boolean)
While cond
Console.WriteLine()
End While
@@ -218,7 +218,7 @@ Namespace Tests.Diagnostics
Console.WriteLine() ' Secondary
End Sub
- Public Sub Method6(ByVal cond As Boolean)
+ Public Sub Method4(ByVal cond As Boolean)
Dim i = 10
While i < 20
i = i + 1
@@ -232,7 +232,7 @@ Namespace Tests.Diagnostics
Console.WriteLine() ' Secondary
End Sub
- Public Sub Method7()
+ Public Sub Method5()
While True ' Compliant
Console.WriteLine()
End While
@@ -240,19 +240,6 @@ Namespace Tests.Diagnostics
Console.WriteLine()
End Sub
- Public Sub Method8(n)
- For Each item In New Integer()() {New Integer() {1, 2, 3}}
- For Each i In item
- Console.WriteLine()
- Next
- Next
- End Sub
-
- Public Sub Method9_For(ByVal cond As Boolean)
- While True ' Not reporting on this
-
- End While
- End Sub
Public Sub Method_Select()
Dim i = 10
From 45da0ec3de3997557dcc7890363f6baa29a9d14f Mon Sep 17 00:00:00 2001
From: mary-georgiou-sonarsource
Date: Thu, 10 Aug 2023 18:09:26 +0200
Subject: [PATCH 15/20] Update compound assignment UTs in both vb and c#
---
.../Roslyn/ConditionEvaluatesToConstant.cs | 13 +++++++++++--
.../Roslyn/ConditionEvaluatesToConstant.vb | 11 +++++++++++
2 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
index e1e556f1290..114b8227a7b 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
@@ -579,8 +579,17 @@ public void BooleanBinary(bool a, bool b)
a ^= true;
if (a) { } // FN: engine doesn't learn BoolConstraints from binary operators
- a ^= true;
- if (a) { } // FN: engine doesn't learn BoolConstraints from binary operators
+ a = a & true;
+ if (a) // FN
+ { }
+
+ a = a | true;
+ if (a) // Noncompliant
+ { }
+
+ a = a^ true;
+ if (a) // Noncompliant
+ { }
}
public void IsAsExpression(object o)
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
index 1a1164fa923..eb73896ea91 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
@@ -447,6 +447,17 @@ Namespace Tests.Diagnostics
End If
End Sub
+ Public Sub CompoundAssignment(ByVal a As Boolean, ByVal b As Boolean)
+ ' https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/operators/assignment-operators
+ a &=True
+ If a Then ' FN
+ End If
+
+ a ^=True
+ If a Then ' FN
+ End If
+ End Sub
+
Public Sub IsAsExpression(ByVal o As Object)
If TypeOf o Is String Then
From 296bbb21876df780449e9aba6964e6900b9e3378 Mon Sep 17 00:00:00 2001
From: mary-georgiou-sonarsource
Date: Thu, 10 Aug 2023 18:19:05 +0200
Subject: [PATCH 16/20] Formatting etc
---
.../Roslyn/ConditionEvaluatesToConstant.cs | 6 +--
.../Roslyn/ConditionEvaluatesToConstant.vb | 44 +++++++++----------
2 files changed, 23 insertions(+), 27 deletions(-)
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
index 114b8227a7b..ffb8f7cbc4f 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
@@ -1637,8 +1637,6 @@ public void Rethrow(bool condition)
public void FalseNegatives()
{
- // We cannot detect the case in ObjectsShouldNotBeDisposedMoreThanOnce method above
- // and to avoid False Positives we do not report in catch or finally
object o = null;
try
{
@@ -1679,8 +1677,8 @@ async Task Foo(Task t)
object o = null;
_foo1 = o;
await t; // awaiting clears the constraints
- if (_foo1 != null) { } // Compliant S2583
- if (_foo1 == null) { } // Compliant S2589
+ if (_foo1 != null) { } // FN
+ if (_foo1 == null) { } // FN
if (o != null) { } // Noncompliant
if (o == null) { } // Noncompliant
}
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
index eb73896ea91..de4c59282ac 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
@@ -654,7 +654,7 @@ Namespace Tests.Diagnostics
End If
If String.IsNullOrWhiteSpace(s) Then ' Noncompliant
End If
- If Not Equals(String.IsInterned(s), Nothing) Then ' FN FIX
+ If Not Equals(String.IsInterned(s), Nothing) Then
End If
s = ""
If String.IsNullOrEmpty(s) Then ' FN
@@ -996,7 +996,7 @@ Namespace Tests.Diagnostics
Friend Structure MyStructWithNoOperator
Public Shared Sub M(ByVal a As MyStructWithNoOperator)
If a Is Nothing Then ' Noncompliant, also a compiler error
- ' Error@-1 [BC30020]
+ ' Error@-1 [BC30020]
End If
End Sub
End Structure
@@ -1190,7 +1190,7 @@ Namespace Tests.Diagnostics
End If
Const f = False
If f Then ' Noncompliant
- Console.WriteLine() ' Secondary
+ Console.WriteLine() ' Secondary
End If
End Sub
Private Sub Constants()
@@ -1259,8 +1259,6 @@ Namespace Tests.Diagnostics
End Sub
Public Sub FalseNegatives()
- ' We cannot detect the case in ObjectsShouldNotBeDisposedMoreThanOnce method above
- ' and to avoid False Positives we do not report in catch or finally
Dim o As Object = Nothing
Try
Console.WriteLine("Could throw")
@@ -1299,9 +1297,9 @@ Namespace Tests.Diagnostics
Dim o As Object = Nothing
_foo1 = o
Await t ' awaiting clears the constraints
- If _foo1 IsNot Nothing Then ' Compliant S2583
+ If _foo1 IsNot Nothing Then ' FN
End If
- If _foo1 Is Nothing Then ' Compliant S2589
+ If _foo1 Is Nothing Then ' FN
End If
If o IsNot Nothing Then ' Noncompliant
End If
@@ -1604,7 +1602,7 @@ Namespace Tests.Diagnostics
s1.ToString()
Else
If Equals(s1, Nothing) Then ' Noncompliant
- s1.ToString() ' Secondary
+ s1.ToString() ' Secondary
End If
End If
@@ -1613,7 +1611,7 @@ Namespace Tests.Diagnostics
Public Sub Method4(ByVal s1 As String)
If Not String.IsNullOrEmpty(s1) Then
If Equals(s1, Nothing) Then ' Noncompliant
- s1.ToString() ' Secondary
+ s1.ToString() ' Secondary
End If
Else
s1.ToString()
@@ -1624,7 +1622,7 @@ Namespace Tests.Diagnostics
Public Sub Method5(ByVal s1 As String)
If Not String.IsNullOrEmpty(s1) Then
If Equals(s1, Nothing) Then ' Noncompliant
- s1.ToString() ' Secondary
+ s1.ToString() ' Secondary
End If
Else
s1.ToString()
@@ -1637,7 +1635,7 @@ Namespace Tests.Diagnostics
s1.ToString()
Else
If Equals(s1, Nothing) Then ' Noncompliant
- s1.ToString() ' Secondary
+ s1.ToString() ' Secondary
End If
End If
@@ -1680,19 +1678,19 @@ Namespace Tests.Diagnostics
'Left operand: Values notNull and notEmpty are known to be not-null
ret = If(notNull, a) ' Noncompliant
- ' Secondary@-1
+ ' Secondary@-1
ret = If(notNull, a) ' Noncompliant
- ' Secondary@-1
+ ' Secondary@-1
ret = "Lorem " & If(notNull, a) & " ipsum" ' Noncompliant
- ' Secondary@-1
+ ' Secondary@-1
ret = If(notNull, "N/A") ' Noncompliant
- ' Secondary@-1
+ ' Secondary@-1
ret = If(notEmpty, "N/A") ' Noncompliant
- ' Secondary@-1
+ ' Secondary@-1
'Left operand: isNull is known to be null
ret = If(Nothing, a) ' Noncompliant
- ret = If(isNull, a) ' NoncompliantP
+ ret = If(isNull, a) ' Noncompliant
ret = "Lorem " & If(isNull, a) & " ipsum" ' Noncompliant
'Right operand: isNull is known to be null, therefore ?? is useless
@@ -1739,8 +1737,8 @@ Namespace Tests.Diagnostics
End If
- If String.IsNullOrWhiteSpace(s2) Then ' FN
- If Equals(s2, "a") Then ' FN
+ If String.IsNullOrWhiteSpace(s2) Then ' FN
+ If Equals(s2, "a") Then ' FN
End If
End If
@@ -1749,20 +1747,20 @@ Namespace Tests.Diagnostics
End If
- If String.IsNullOrWhiteSpace(s4) Then ' FN
+ If String.IsNullOrWhiteSpace(s4) Then ' FN
End If
- If Not String.IsNullOrWhiteSpace(s4) Then ' FN
+ If Not String.IsNullOrWhiteSpace(s4) Then ' FN
End If
If Not String.IsNullOrWhiteSpace(s) Then
- If Equals(s, "") Then ' FN
+ If Equals(s, "") Then ' FN
End If
- If Equals(s, " ") Then ' FN
+ If Equals(s, " ") Then ' FN
End If
End If
From a91a60dcd27414f245f835dfb3f1df45bcbba952 Mon Sep 17 00:00:00 2001
From: mary-georgiou-sonarsource
Date: Fri, 11 Aug 2023 07:32:49 +0200
Subject: [PATCH 17/20] nitpicks
---
.../ConditionEvaluatesToConstant.VB14.vb | 10 +-
.../Roslyn/ConditionEvaluatesToConstant.vb | 217 +++++++++---------
2 files changed, 108 insertions(+), 119 deletions(-)
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb
index a331328af6a..5a378e46fd7 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb
@@ -95,7 +95,7 @@ Namespace Tests.Diagnostics
' ^^^^^^ Noncompliant
' ^^^^^^^^ Secondary@-1
' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
- Console.WriteLine("shorted") ' Secondary
+ Console.WriteLine("shorted") ' Secondary
If result IsNot Nothing Then
Console.WriteLine("other")
End If
@@ -108,7 +108,7 @@ Namespace Tests.Diagnostics
' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant
' ^^^^^^ Noncompliant@-1
Console.WriteLine("shorted")
- While result IsNot Nothing ' Noncompliant
+ While result IsNot Nothing ' Noncompliant
Console.WriteLine("other")
End While
End If
@@ -141,7 +141,7 @@ Namespace Tests.Diagnostics
' ^^^^ Noncompliant
' ^^^^^^^^^^^ Secondary@-1
' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
- Console.WriteLine("a") ' Secondary
+ Console.WriteLine("a") ' Secondary
End If
End Sub
@@ -209,7 +209,7 @@ Namespace Tests.Diagnostics
' ^^^^ Noncompliant
' ^^^^^^^ Secondary@-1
' ^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
- Console.WriteLine("a") ' Secondary
+ Console.WriteLine("a") ' Secondary
End If
End Sub
End Class
@@ -266,7 +266,7 @@ Namespace Tests.Diagnostics
Public Sub IfStatement()
Dim c1 = True
- If c1 ' Noncompliant
+ If c1 ' Noncompliant
Console.WriteLine("")
End If
End Sub
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
index de4c59282ac..0f2f4db1bf0 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
@@ -57,7 +57,7 @@ Namespace Tests.Diagnostics
Do
If o2 IsNot Nothing Then Exit Do
- Loop While c2 ' Noncompliant {{Change this condition so that it does not always evaluate to 'False'.}}
+ Loop While c2 ' Noncompliant {{Change this condition so that it does not always evaluate to 'False'.}}
' ^^
End Sub
@@ -86,7 +86,7 @@ Namespace Tests.Diagnostics
Dim x = t OrElse a OrElse b ' Compliant t is const
- If t = True Then ' Noncompliant
+ If t = True Then ' Noncompliant
Console.WriteLine("")
End If
@@ -102,7 +102,7 @@ Namespace Tests.Diagnostics
Public Sub Foo2(ByVal a As Boolean, ByVal b As Boolean)
Dim l = True
Dim x = l OrElse a OrElse b
- ' ^ Noncompliant
+ ' ^ Noncompliant
' ^^^^^^^^^^ Secondary@-1
End Sub
@@ -270,7 +270,7 @@ Namespace Tests.Diagnostics
If b Then ' Noncompliant
Console.WriteLine()
Else
- Console.WriteLine() ' Secondary
+ Console.WriteLine() ' Secondary
End If
End Sub)
Return True
@@ -393,7 +393,7 @@ Namespace Tests.Diagnostics
Dim b = a
If Not a Then
- If b Then ' FN: requires relation support
+ If b Then ' FN: requires relation support
End If
End If
@@ -416,7 +416,7 @@ Namespace Tests.Diagnostics
End If
If Not (a Or b) Then
- If a Then ' FN: engine doesn't learn BoolConstraints from binary operators
+ If a Then ' FN: engine doesn't learn BoolConstraints from binary operators
End If
End If
@@ -516,18 +516,18 @@ Namespace Tests.Diagnostics
Public Sub EqRelations(ByVal a As Boolean, ByVal b As Boolean)
If a = b Then
- If b = a Then ' FN: requires relation support
+ If b = a Then ' FN: requires relation support
End If
- If b = Not a Then ' FN: requires relation support
+ If b = Not a Then ' FN: requires relation support
End If
- If Not b = Not Not a Then ' FN: requires relation support
+ If Not b = Not Not a Then ' FN: requires relation support
End If
- If Not a = b Then ' FN: requires relation support
+ If Not a = b Then ' FN: requires relation support
End If
Else
- If b <> a Then ' FN: requires relation support
+ If b <> a Then ' FN: requires relation support
End If
- If b <> Not a Then ' FN: requires relation support
+ If b <> Not a Then ' FN: requires relation support
End If
If Not b <> Not Not a Then ' FN: requires relation support
End If
@@ -535,7 +535,7 @@ Namespace Tests.Diagnostics
End If
If a <> b Then
- If b = a Then ' FN: requires relation support
+ If b = a Then ' FN: requires relation support
End If
Else
If b <> a Then ' FN: requires relation support
@@ -555,14 +555,14 @@ Namespace Tests.Diagnostics
End If
If Equals(a, b) Then ' FN
End If
- If a.Equals(b) Then ' FN
+ If a.Equals(b) Then ' FN
End If
End If
If Me Is a Then
If Equals(a) Then ' FN
End If
- If Equals(a) Then ' FN
+ If Equals(a) Then ' FN
End If
End If
End Sub
@@ -606,9 +606,9 @@ Namespace Tests.Diagnostics
End If ' FN
a = Nothing
- If Object.ReferenceEquals(Nothing, a) Then ' Noncompliant
+ If Object.ReferenceEquals(Nothing, a) Then ' Noncompliant
End If
- If Object.ReferenceEquals(a, a) Then ' Noncompliant
+ If Object.ReferenceEquals(a, a) Then ' Noncompliant
End If
If Object.ReferenceEquals(Nothing, New Object()) Then ' Noncompliant
@@ -650,27 +650,27 @@ Namespace Tests.Diagnostics
Public Sub StringEmpty(ByVal s1 As String)
Dim s As String = Nothing
- If String.IsNullOrEmpty(s) Then ' Noncompliant
+ If String.IsNullOrEmpty(s) Then ' Noncompliant
End If
If String.IsNullOrWhiteSpace(s) Then ' Noncompliant
End If
If Not Equals(String.IsInterned(s), Nothing) Then
End If
s = ""
- If String.IsNullOrEmpty(s) Then ' FN
+ If String.IsNullOrEmpty(s) Then ' FN
End If
If String.IsNullOrWhiteSpace(s) Then ' FN
End If
- If String.IsNullOrEmpty(s1) Then ' Compliant, we don't know anything about the argument
+ If String.IsNullOrEmpty(s1) Then ' Compliant, we don't know anything about the argument
End If
If String.IsNullOrWhiteSpace(s1) Then ' Compliant
End If
If String.IsNullOrEmpty(s1) Then
- If String.IsNullOrEmpty(s1) Then ' FN
+ If String.IsNullOrEmpty(s1) Then ' FN
End If
End If
End Sub
@@ -681,7 +681,7 @@ Namespace Tests.Diagnostics
End If
If j <= i Then ' FN
End If
- If j = i Then ' FN
+ If j = i Then ' FN
End If
If j <> i Then ' FN
End If
@@ -692,26 +692,26 @@ Namespace Tests.Diagnostics
If i = j Then
If Equals(i, j) Then ' FN
End If
- If i.Equals(j) Then ' FN
+ If i.Equals(j) Then ' FN
End If
End If
End Sub
Private Sub DefaultExpression(ByVal o As Object)
- If Nothing Is Nothing Then ' Noncompliant
+ If Nothing Is Nothing Then ' Noncompliant
End If
Dim nullableInt As Integer? = Nothing
If nullableInt Is Nothing Then ' Noncompliant
End If
- If Nothing Is Nothing Then ' Noncompliant
+ If Nothing Is Nothing Then ' Noncompliant
End If
- If Nothing IsNot Nothing Then ' Noncompliant
+ If Nothing IsNot Nothing Then ' Noncompliant
End If
- If Nothing IsNot Nothing Then ' Noncompliant
+ If Nothing IsNot Nothing Then ' Noncompliant
End If
End Sub
@@ -767,7 +767,7 @@ Namespace Tests.Diagnostics
If i = j Then ' Noncompliant
End If
- If i.Equals(j) Then ' FN
+ If i.Equals(j) Then ' FN
End If
If Equals(i, j) Then ' FN
@@ -785,7 +785,7 @@ Namespace Tests.Diagnostics
Public Sub Assert(ByVal condition As Boolean, ByVal o1 As Object)
Debug.Assert(condition)
- If condition Then ' Noncompliant
+ If condition Then ' Noncompliant
End If
Trace.Assert(condition) ' Compliant
@@ -807,7 +807,7 @@ Namespace Tests.Diagnostics
End If
If a = b AndAlso b <= c Then
- If a > c Then ' FN
+ If a > c Then ' FN
End If
End If
@@ -822,12 +822,12 @@ Namespace Tests.Diagnostics
End If
If a >= b AndAlso b >= c Then
- If a < c Then ' FN
+ If a < c Then ' FN
End If
End If
If a >= b AndAlso c <= b Then
- If a < c Then ' FN
+ If a < c Then ' FN
End If
End If
@@ -854,7 +854,7 @@ Namespace Tests.Diagnostics
Private Sub RefEqTransitivity(ByVal a As Comp, ByVal b As Comp, ByVal c As Comp)
If a Is b AndAlso b Is c Then
- If a IsNot c Then ' FN
+ If a IsNot c Then ' FN
End If
End If
@@ -863,21 +863,21 @@ Namespace Tests.Diagnostics
End If
If a Is c Then
End If
- If a.Equals(c) Then ' FN
+ If a.Equals(c) Then ' FN
End If
If Not a.Equals(c) Then ' FN
End If
End If
If a > b AndAlso b Is c Then
- If a <= c Then ' FN
+ If a <= c Then ' FN
End If
End If
End Sub
Private Sub ValueEqTransitivity(ByVal a As Comp, ByVal b As Comp, ByVal c As Comp)
If a Is b AndAlso b.Equals(c) Then
- If a.Equals(c) Then ' FN
+ If a.Equals(c) Then ' FN
End If
End If
@@ -886,14 +886,14 @@ Namespace Tests.Diagnostics
End If
If a Is c Then
End If
- If a.Equals(c) Then ' FN
+ If a.Equals(c) Then ' FN
End If
If Not a.Equals(c) Then ' FN
End If
End If
If a > b AndAlso b.Equals(c) Then
- If a > c Then ' FN
+ If a > c Then ' FN
End If
If a <= c Then ' FN
End If
@@ -902,7 +902,7 @@ Namespace Tests.Diagnostics
If Not a.Equals(b) AndAlso b.Equals(c) Then
If a.Equals(c) Then ' FN
End If
- If a Is c Then ' FN
+ If a Is c Then ' FN
End If
End If
@@ -928,7 +928,7 @@ Namespace Tests.Diagnostics
End If
If b.Equals(c) Then ' FN
- End If ' FN
+ End If
End If
End Sub
@@ -937,28 +937,28 @@ Namespace Tests.Diagnostics
Dim i As Integer? = Nothing
Dim j As Integer? = 5
- If i < j Then ' Noncompliant
+ If i < j Then ' Noncompliant
End If
- If i <= j Then ' Noncompliant
+ If i <= j Then ' Noncompliant
End If
- If i > j Then ' Noncompliant
+ If i > j Then ' Noncompliant
End If
- If i >= j Then ' Noncompliant
+ If i >= j Then ' Noncompliant
End If
- If i > 0 Then ' Noncompliant
+ If i > 0 Then ' Noncompliant
End If
- If i >= 0 Then ' Noncompliant
+ If i >= 0 Then ' Noncompliant
End If
- If i < 0 Then ' Noncompliant
+ If i < 0 Then ' Noncompliant
End If
- If i <= 0 Then ' Noncompliant
+ If i <= 0 Then ' Noncompliant
End If
If j > Nothing Then ' Noncompliant
@@ -1004,7 +1004,7 @@ Namespace Tests.Diagnostics
Public Class NullableCases
Private Sub Case1()
Dim b1 As Boolean? = True
- If b1 = True Then ' Noncompliant
+ If b1 = True Then ' Noncompliant
End If
End Sub
@@ -1020,70 +1020,70 @@ Namespace Tests.Diagnostics
End If
i = Nothing
- If i Is Nothing Then ' Noncompliant
+ If i Is Nothing Then ' Noncompliant
End If
- If i = True Then ' Noncompliant
+ If i = True Then ' Noncompliant
End If
- If i = False Then ' Noncompliant
+ If i = False Then ' Noncompliant
End If
i = True
- If i Is Nothing Then ' Noncompliant
+ If i Is Nothing Then ' Noncompliant
End If
- If i = True Then ' Noncompliant
+ If i = True Then ' Noncompliant
End If
- If i = False Then ' Noncompliant
+ If i = False Then ' Noncompliant
End If
i = False
- If i Is Nothing Then ' Noncompliant
+ If i Is Nothing Then ' Noncompliant
End If
- If i = True Then ' Noncompliant
+ If i = True Then ' Noncompliant
End If
- If i = False Then ' Noncompliant
+ If i = False Then ' Noncompliant
End If
Dim b2 As Boolean? = True
- If b2 = False Then ' Noncompliant
+ If b2 = False Then ' Noncompliant
End If
Dim b3 As Boolean? = True
- If b3 Is Nothing Then ' Noncompliant
+ If b3 Is Nothing Then ' Noncompliant
End If
Dim b4 As Boolean? = Nothing
- If b4 = True Then ' Noncompliant
+ If b4 = True Then ' Noncompliant
End If
Dim b5 As Boolean? = Nothing
- If b5 = False Then ' Noncompliant
+ If b5 = False Then ' Noncompliant
End If
Dim b6 As Boolean? = Nothing
- If b6 Is Nothing Then ' Noncompliant
+ If b6 Is Nothing Then ' Noncompliant
End If
Dim b7 As Boolean? = True
- If b7 = True Then ' Noncompliant
+ If b7 = True Then ' Noncompliant
End If
Dim b8 As Boolean? = False
- If b8 = False Then ' Noncompliant
+ If b8 = False Then ' Noncompliant
End If
End Sub
Private Sub Case3(ByVal b As Boolean?)
If b Is Nothing Then
- If Nothing Is b Then ' Noncompliant
+ If Nothing Is b Then ' Noncompliant
b.ToString()
End If
Else
@@ -1095,7 +1095,7 @@ Namespace Tests.Diagnostics
Private Sub Case4(ByVal b As Boolean?)
If b = True Then
- If True = b Then ' Noncompliant
+ If True = b Then ' Noncompliant
b.ToString()
End If
End If
@@ -1117,7 +1117,7 @@ Namespace Tests.Diagnostics
Private Sub Case7(ByVal b As Boolean?)
If b Is Nothing Then
- If If(b, False) Then ' Noncompliant
+ If If(b, False) Then ' Noncompliant
End If
End If
@@ -1125,7 +1125,7 @@ Namespace Tests.Diagnostics
Private Sub Case8(ByVal b As Boolean?)
If b IsNot Nothing Then
- If b.HasValue Then ' Noncompliant
+ If b.HasValue Then ' Noncompliant
End If
End If
End Sub
@@ -1133,30 +1133,18 @@ Namespace Tests.Diagnostics
Private Sub Case9(ByVal b As Boolean?)
If b = True Then
Dim x = b.Value
- If x = True Then ' Noncompliant
+ If x = True Then ' Noncompliant
End If
End If
End Sub
Private Sub Case10(ByVal i As Integer?)
If i Is Nothing Then
- If i.HasValue Then ' Noncompliant
+ If i.HasValue Then ' Noncompliant
End If
End If
End Sub
- ' https://github.com/SonarSource/sonar-dotnet/issues/4755
- Public Sub IfElseIfElseFlow_FromCast(ByVal value As Object)
- Dim b = CType(value, Boolean?)
- If b = True Then
- Console.WriteLine("true")
- ElseIf b = False Then ' Compliant
- Console.WriteLine("false")
- Else
- Console.WriteLine("null")
- End If
- End Sub
-
Public Sub IfElseIfElseFlow_DirectValue(ByVal b As Boolean?)
If b = True Then
Console.WriteLine("true")
@@ -1193,16 +1181,17 @@ Namespace Tests.Diagnostics
Console.WriteLine() ' Secondary
End If
End Sub
+
Private Sub Constants()
- If T Then ' Compliant it's a constant
+ If T Then ' Compliant it's a constant
Console.WriteLine()
End If
- If F Then ' Compliant it's a constant
+ If F Then ' Compliant it's a constant
Console.WriteLine()
End If
End Sub
Private Sub WhileTrue()
- While T ' Compliant it's a constant
+ While T ' Compliant it's a constant
Console.WriteLine()
End While
End Sub
@@ -1212,7 +1201,7 @@ Namespace Tests.Diagnostics
Loop While F ' Compliant it's a constant
End Sub
Private Sub Condition()
- Dim x = If(T, 1, 2) ' Compliant, T is constant
+ Dim x = If(T, 1, 2) ' Compliant, T is constant
End Sub
End Class
@@ -1222,8 +1211,8 @@ Namespace Tests.Diagnostics
Public Sub Guarded(ByVal s1 As String)
Guard1(s1)
- If Equals(s1, Nothing) Then ' Noncompliant, always flse
- ' this branch is never executed
+ If Equals(s1, Nothing) Then ' Noncompliant, always false
+ ' this branch is never executed
Else
End If
End Sub
@@ -1265,13 +1254,13 @@ Namespace Tests.Diagnostics
Catch
If o IsNot Nothing Then ' Noncompliant
End If
- If o Is Nothing Then ' Noncompliant
+ If o Is Nothing Then ' Noncompliant
End If
Finally
If o IsNot Nothing Then ' Noncompliant
End If
- If o Is Nothing Then ' Noncompliant
+ If o Is Nothing Then ' Noncompliant
End If
End Try
End Sub
@@ -1343,7 +1332,7 @@ Namespace Tests.Diagnostics
Public Class TestNullCoalescing
Public Sub CompliantMethod(ByVal input As Boolean?)
- If If(input, False) Then ' Compliant
+ If If(input, False) Then ' Compliant
Console.WriteLine("input is true")
Else
Console.WriteLine("input is false")
@@ -1351,20 +1340,20 @@ Namespace Tests.Diagnostics
End Sub
Public Sub CompliantMethod1(ByVal input As Boolean?)
- While If(input, False) ' Compliant
+ While If(input, False) ' Compliant
Console.WriteLine("input is true")
End While
End Sub
Public Sub CompliantMethod2(ByVal input As Boolean?, ByVal input1 As Boolean)
- While If(input, False) AndAlso input1 ' Compliant
+ While If(input, False) AndAlso input1 ' Compliant
Console.WriteLine("input is true")
End While
End Sub
Public Sub CompliantMethod3(ByVal input As Boolean?, ByVal input1 As Boolean)
- If If(If(input, False), input1, False) Then ' Compliant
+ If If(If(input, False), input1, False) Then ' Compliant
Console.WriteLine("input is true")
End If
End Sub
@@ -1374,19 +1363,19 @@ Namespace Tests.Diagnostics
If If(input, False) Then ' Noncompliant
Console.WriteLine("input is true")
Else
- Console.WriteLine("input is false") ' Secondary
+ Console.WriteLine("input is false") ' Secondary
End If
End Sub
Public Sub NonCompliantMethod1()
Dim input As Boolean? = True
- While If(input, False) ' Noncompliant
+ While If(input, False) ' Noncompliant
Console.WriteLine("input is true")
End While
End Sub
Public Sub NonCompliantMethod2(ByVal input As Boolean?)
- While If(input, False) OrElse True ' Compliant
+ While If(input, False) OrElse True ' Compliant
Console.WriteLine("input is true")
End While
End Sub
@@ -1665,44 +1654,44 @@ Namespace Tests.Diagnostics
Return String.Empty
End Function
- Private Sub NullCoalesce_Useless(ByVal a As String, ByVal b As String, ByVal c As String, ByVal d As String)
- Dim isNull As String = Nothing
- Dim notNull = ""
+ Private Sub BinaryConditional_Useless(ByVal a As String, ByVal b As String, ByVal c As String, ByVal d As String)
+ Dim isNothing As String = Nothing
+ Dim isNotNothing = ""
Dim notEmpty = "value"
Dim ret As String
ret = If(b, a)
- ret = If(b, notNull)
+ ret = If(b, isNotNothing)
ret = If(c, notEmpty)
ret = If(d, "N/A")
- 'Left operand: Values notNull and notEmpty are known to be not-null
- ret = If(notNull, a) ' Noncompliant
+ 'Left operand: Values notNull and notEmpty are known to be not Nothing
+ ret = If(isNotNothing, a) ' Noncompliant
' Secondary@-1
- ret = If(notNull, a) ' Noncompliant
+ ret = If(isNotNothing, a) ' Noncompliant
' Secondary@-1
- ret = "Lorem " & If(notNull, a) & " ipsum" ' Noncompliant
+ ret = "Lorem " & If(isNotNothing, a) & " ipsum" ' Noncompliant
' Secondary@-1
- ret = If(notNull, "N/A") ' Noncompliant
+ ret = If(isNotNothing, "N/A") ' Noncompliant
' Secondary@-1
ret = If(notEmpty, "N/A") ' Noncompliant
' Secondary@-1
'Left operand: isNull is known to be null
ret = If(Nothing, a) ' Noncompliant
- ret = If(isNull, a) ' Noncompliant
- ret = "Lorem " & If(isNull, a) & " ipsum" ' Noncompliant
+ ret = If(isNothing, a) ' Noncompliant
+ ret = "Lorem " & If(isNothing, a) & " ipsum" ' Noncompliant
- 'Right operand: isNull is known to be null, therefore ?? is useless
+ 'Right operand: isNull is known to be null, therefore binary conditional expression is not needed
ret = If(a, Nothing) ' FN: NOOP
- ret = If(a, isNull) ' FN: NOOP
+ ret = If(a, isNothing) ' FN: NOOP
' ~~~~~~
'Combo/Fatality
- ret = If(notNull, isNull)
+ ret = If(isNotNothing, isNothing)
' ^^^^^^^ Noncompliant {{Change this expression which always evaluates to the same result. Some code paths are unreachable.}}
' ^^^^^^ Secondary@-1
- ret = If(isNull, Nothing) ' Noncompliant {{Change this expression which always evaluates to the same result.}}
+ ret = If(isNothing, Nothing) ' Noncompliant {{Change this expression which always evaluates to the same result.}}
' ^^^^^^
ret = If("Value", a)
' ^^^^^^^ Noncompliant {{Change this expression which always evaluates to the same result. Some code paths are unreachable.}}
@@ -1733,7 +1722,7 @@ Namespace Tests.Diagnostics
Dim s3 = If(s, "")
Dim s4 = " "
- If String.IsNullOrWhiteSpace(s1) Then ' Noncompliant
+ If String.IsNullOrWhiteSpace(s1) Then ' Noncompliant
End If
From 8d6368a20c718f07e5d2b5fccebc7169d690794e Mon Sep 17 00:00:00 2001
From: mary-georgiou-sonarsource
Date: Fri, 11 Aug 2023 07:38:39 +0200
Subject: [PATCH 18/20] more nitpicks - remore namespaces
---
.../ConditionEvaluatesToConstant.VB14.vb | 504 ++-
.../Roslyn/ConditionEvaluatesToConstant.vb | 2735 ++++++++---------
2 files changed, 1611 insertions(+), 1628 deletions(-)
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb
index 5a378e46fd7..4e73382d096 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.VB14.vb
@@ -1,301 +1,293 @@
-Imports System
-
-Namespace Tests.Diagnostics
- Public Class VB14
-
- Private Sub ConditionalAccessNullPropagation(ByVal o As Object)
- If o Is Nothing Then
- If Equals(o?.ToString(), Nothing) Then
- ' ^ Noncompliant
- ' ^^^^^^^^^^^ Secondary@-1
- ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
- End If
- If o?.GetHashCode() Is Nothing Then
- ' ^ Noncompliant
- ' ^^^^^^^^^^^^^^ Secondary@-1
- ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
- End If
+Public Class VB14
+
+ Private Sub ConditionalAccessNullPropagation(ByVal o As Object)
+ If o Is Nothing Then
+ If Equals(o?.ToString(), Nothing) Then
+ ' ^ Noncompliant
+ ' ^^^^^^^^^^^ Secondary@-1
+ ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
End If
- End Sub
-
- Friend Enum MyEnum
- One
- Two
- End Enum
-
- Friend Class MyClassWithEnum
- Public myEnum As MyEnum
- End Class
-
- Public Sub EnumMemberAccess()
- Dim m = New MyClassWithEnum()
- Console.WriteLine(m.myEnum)
- m = Nothing
- If m?.myEnum = MyEnum.One Then
+ If o?.GetHashCode() Is Nothing Then
' ^ Noncompliant
- ' ^^^^^^^ Secondary@-1
- ' ^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
+ ' ^^^^^^^^^^^^^^ Secondary@-1
+ ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
End If
- End Sub
-
- Friend Class FooContainer
- Public Property Foo As Boolean
- End Class
-
- Friend Class TestNullConditional
- Private Sub First(ByVal fooContainer As FooContainer, ByVal bar As Boolean)
- If fooContainer?.Foo = False OrElse bar Then
- Console.WriteLine(If(bar, "1", "2"))
- Else
- Console.WriteLine(If(fooContainer IsNot Nothing, "3", "4"))
- End If
- End Sub
-
- Private Sub Second(ByVal fooContainer As FooContainer)
- If fooContainer?.Foo <> True Then
- Console.WriteLine("3")
- If fooContainer IsNot Nothing Then
- Console.WriteLine("4")
- End If
- End If
- End Sub
-
- Public Class Result
- Public Property Succeed As Boolean
-
- Public Shared Function Test(ByVal cond As Boolean) As Result
- If cond Then
- Return New Result()
- End If
- Return Nothing
- End Function
- End Class
-
- Public Shared Sub Compliant1(ByVal cond As Boolean)
- Dim result = TestNullConditional.Result.Test(cond)
-
- If result Is Nothing OrElse Not result.Succeed Then
- Console.WriteLine("shorted")
- If result IsNot Nothing Then
- Console.WriteLine("other")
- End If
- End If
+ End If
+ End Sub
- If result?.Succeed <> True Then
- Console.WriteLine("shorted")
- If result IsNot Nothing Then
- Console.WriteLine("other")
- End If
- End If
- End Sub
-
- Public Shared Sub NonCompliant1()
- Dim result As Result = Nothing
- If result?.Succeed IsNot Nothing Then
- ' ^^^^^^ Noncompliant
- ' ^^^^^^^^ Secondary@-1
- ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
- Console.WriteLine("shorted") ' Secondary
- If result IsNot Nothing Then
- Console.WriteLine("other")
- End If
- End If
- End Sub
-
- Public Shared Sub NonCompliant2()
- Dim result As Result = New Result()
- If result?.Succeed IsNot Nothing Then
- ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant
- ' ^^^^^^ Noncompliant@-1
- Console.WriteLine("shorted")
- While result IsNot Nothing ' Noncompliant
- Console.WriteLine("other")
- End While
- End If
- End Sub
-
- Public Class A
- Public Property booleanVal As Boolean
- End Class
-
- Public Shared Sub Compliant2()
- Dim aObj As A = Nothing
- If If(aObj?.booleanVal, False) Then
- ' ^^^^ Noncompliant
- ' ^^^^^^^^^^^ Secondary@-1
- ' ^^^^^^^^^^^^^^^^ Noncompliant@-2
- Console.WriteLine("a")
- End If
- End Sub
-
- Public Shared Sub NonCompliant3()
- Dim aObj As A = Nothing
- If aObj?.booleanVal Is Nothing Then
- ' ^^^^ Noncompliant
- ' ^^^^^^^^^^^ Secondary@-1
- ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
- Console.WriteLine("a")
- End If
+ Friend Enum MyEnum
+ One
+ Two
+ End Enum
- If aObj?.booleanVal IsNot Nothing Then
- ' ^^^^ Noncompliant
- ' ^^^^^^^^^^^ Secondary@-1
- ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
- Console.WriteLine("a") ' Secondary
- End If
- End Sub
+ Friend Class MyClassWithEnum
+ Public myEnum As MyEnum
+ End Class
- Public Shared Sub Compliant3(ByVal a As A)
+ Public Sub EnumMemberAccess()
+ Dim m = New MyClassWithEnum()
+ Console.WriteLine(m.myEnum)
+ m = Nothing
+ If m?.myEnum = MyEnum.One Then
+ ' ^ Noncompliant
+ ' ^^^^^^^ Secondary@-1
+ ' ^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
+ End If
+ End Sub
+
+ Friend Class FooContainer
+ Public Property Foo As Boolean
+ End Class
- If a?.booleanVal = True Then
- Console.WriteLine("Compliant")
- Return
- End If
+ Friend Class TestNullConditional
+ Private Sub First(ByVal fooContainer As FooContainer, ByVal bar As Boolean)
+ If fooContainer?.Foo = False OrElse bar Then
+ Console.WriteLine(If(bar, "1", "2"))
+ Else
+ Console.WriteLine(If(fooContainer IsNot Nothing, "3", "4"))
+ End If
+ End Sub
- If a IsNot Nothing Then ' Compliant
+ Private Sub Second(ByVal fooContainer As FooContainer)
+ If fooContainer?.Foo <> True Then
+ Console.WriteLine("3")
+ If fooContainer IsNot Nothing Then
+ Console.WriteLine("4")
End If
- End Sub
+ End If
+ End Sub
- Public Shared Sub NonCompliant4(ByVal a As A)
+ Public Class Result
+ Public Property Succeed As Boolean
- If a?.booleanVal Is Nothing Then
- Console.WriteLine("Compliant")
- Return
+ Public Shared Function Test(ByVal cond As Boolean) As Result
+ If cond Then
+ Return New Result()
End If
+ Return Nothing
+ End Function
+ End Class
- If a IsNot Nothing Then ' Noncompliant
+ Public Shared Sub Compliant1(ByVal cond As Boolean)
+ Dim result = TestNullConditional.Result.Test(cond)
+
+ If result Is Nothing OrElse Not result.Succeed Then
+ Console.WriteLine("shorted")
+ If result IsNot Nothing Then
+ Console.WriteLine("other")
End If
- End Sub
+ End If
- Public Shared Sub Compliant4(ByVal a As A)
- If a?.booleanVal Is Nothing Then
- Console.WriteLine("Compliant")
+ If result?.Succeed <> True Then
+ Console.WriteLine("shorted")
+ If result IsNot Nothing Then
+ Console.WriteLine("other")
End If
+ End If
+ End Sub
- If a IsNot Nothing Then ' Compliant
+ Public Shared Sub NonCompliant1()
+ Dim result As Result = Nothing
+ If result?.Succeed IsNot Nothing Then
+ ' ^^^^^^ Noncompliant
+ ' ^^^^^^^^ Secondary@-1
+ ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
+ Console.WriteLine("shorted") ' Secondary
+ If result IsNot Nothing Then
+ Console.WriteLine("other")
End If
- End Sub
+ End If
+ End Sub
- Public Shared Sub Compliant5(ByVal a As A)
- While If(a?.booleanVal Is Nothing, True, False) ' Compliant
- Console.WriteLine("Compliant")
- End While
- End Sub
-
- Public Shared Sub NonCompliant5()
- Dim a As A = Nothing
- While If(a?.booleanVal Is Nothing, True, False)
- ' ^ Noncompliant
- ' ^^^^^^^^^^^ Secondary@-1
- ' ^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
- ' ^^^^^ Secondary@-3
- Console.WriteLine("Compliant")
+ Public Shared Sub NonCompliant2()
+ Dim result As Result = New Result()
+ If result?.Succeed IsNot Nothing Then
+ ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant
+ ' ^^^^^^ Noncompliant@-1
+ Console.WriteLine("shorted")
+ While result IsNot Nothing ' Noncompliant
+ Console.WriteLine("other")
End While
- End Sub
-
- Public Class S
- Public str As String = Nothing
- End Class
+ End If
+ End Sub
- Public Shared Sub Compliant6(ByVal sObj As S)
- If sObj?.str?.Length > 2 Then
- Console.WriteLine("a")
- End If
- End Sub
-
- Public Shared Sub NonCompliant6()
- Dim sObj As S = Nothing
- If sObj?.str?.Length > 2 Then
- ' ^^^^ Noncompliant
- ' ^^^^^^^ Secondary@-1
- ' ^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
- Console.WriteLine("a") ' Secondary
- End If
- End Sub
+ Public Class A
+ Public Property booleanVal As Boolean
End Class
- End Class
- Class ShouldExecute
-
- Public Sub AndAlsoExpression()
- Dim c1 = True
- Dim a = c1 AndAlso c1 ' Noncompliant
- ' Secondary@-1
+ Public Shared Sub Compliant2()
+ Dim aObj As A = Nothing
+ If If(aObj?.booleanVal, False) Then
+ ' ^^^^ Noncompliant
+ ' ^^^^^^^^^^^ Secondary@-1
+ ' ^^^^^^^^^^^^^^^^ Noncompliant@-2
+ Console.WriteLine("a")
+ End If
End Sub
- Public Sub TernaryConditionalExpression()
- Dim c1 = True
- Dim x = If(c1, c1, c1) ' Noncompliant
- ' Secondary@-1
- End Sub
+ Public Shared Sub NonCompliant3()
+ Dim aObj As A = Nothing
+ If aObj?.booleanVal Is Nothing Then
+ ' ^^^^ Noncompliant
+ ' ^^^^^^^^^^^ Secondary@-1
+ ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
+ Console.WriteLine("a")
+ End If
- Public Shared Sub ConditionalAccessExpression()
- Dim sObj = Nothing
- Dim x = sObj?.str?.Length > 2
- ' ^^^^ Noncompliant
- ' ^^^^^^^ Secondary@-1
+ If aObj?.booleanVal IsNot Nothing Then
+ ' ^^^^ Noncompliant
+ ' ^^^^^^^^^^^ Secondary@-1
+ ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
+ Console.WriteLine("a") ' Secondary
+ End If
End Sub
- Public Sub DoLoopUntilStatement()
- Dim c1 = false
- Do
- Console.WriteLine("")
- Loop Until c1 ' Noncompliant
- End Sub
+ Public Shared Sub Compliant3(ByVal a As A)
- Public Sub DoLoopWhileStatement()
- Dim c1 = True
- Do
- Console.WriteLine("")
- Loop While c1 ' Noncompliant
- End Sub
+ If a?.booleanVal = True Then
+ Console.WriteLine("Compliant")
+ Return
+ End If
- Public Sub DoUntilStatement()
- Dim c1 = False
- Do Until c1 ' Noncompliant
- Console.WriteLine("")
- Loop
+ If a IsNot Nothing Then ' Compliant
+ End If
End Sub
- Public Sub DoWhileStatement()
- Dim c1 = True
- Do While c1 ' Noncompliant
- Console.WriteLine("")
- Loop
- End Sub
+ Public Shared Sub NonCompliant4(ByVal a As A)
- Public Sub IfStatement()
- Dim c1 = True
- If c1 ' Noncompliant
- Console.WriteLine("")
+ If a?.booleanVal Is Nothing Then
+ Console.WriteLine("Compliant")
+ Return
+ End If
+
+ If a IsNot Nothing Then ' Noncompliant
End If
End Sub
- Public Sub OrAlsoExpression()
- Dim c1 = True
- Dim a = c1 OrElse False ' Noncompliant
- ' Secondary@-1
+ Public Shared Sub Compliant4(ByVal a As A)
+ If a?.booleanVal Is Nothing Then
+ Console.WriteLine("Compliant")
+ End If
+
+ If a IsNot Nothing Then ' Compliant
+ End If
End Sub
- Public Sub WhileStatement()
- Dim c1 = True
- While c1 ' Noncompliant
- Console.WriteLine("")
+ Public Shared Sub Compliant5(ByVal a As A)
+ While If(a?.booleanVal Is Nothing, True, False) ' Compliant
+ Console.WriteLine("Compliant")
End While
End Sub
- Public Sub SelectStatement()
- Dim i = 10
- Dim b = True
- Select Case i
- Case 1 ' Noncompliant
- b = False ' Secondary
- End Select
+ Public Shared Sub NonCompliant5()
+ Dim a As A = Nothing
+ While If(a?.booleanVal Is Nothing, True, False)
+ ' ^ Noncompliant
+ ' ^^^^^^^^^^^ Secondary@-1
+ ' ^^^^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
+ ' ^^^^^ Secondary@-3
+ Console.WriteLine("Compliant")
+ End While
End Sub
- End Class
-
-End Namespace
-
+ Public Class S
+ Public str As String = Nothing
+ End Class
+ Public Shared Sub Compliant6(ByVal sObj As S)
+ If sObj?.str?.Length > 2 Then
+ Console.WriteLine("a")
+ End If
+ End Sub
+ Public Shared Sub NonCompliant6()
+ Dim sObj As S = Nothing
+ If sObj?.str?.Length > 2 Then
+ ' ^^^^ Noncompliant
+ ' ^^^^^^^ Secondary@-1
+ ' ^^^^^^^^^^^^^^^^^^^^^ Noncompliant@-2
+ Console.WriteLine("a") ' Secondary
+ End If
+ End Sub
+ End Class
+End Class
+
+Class ShouldExecute
+
+ Public Sub AndAlsoExpression()
+ Dim c1 = True
+ Dim a = c1 AndAlso c1 ' Noncompliant
+ ' Secondary@-1
+ End Sub
+
+ Public Sub TernaryConditionalExpression()
+ Dim c1 = True
+ Dim x = If(c1, c1, c1) ' Noncompliant
+ ' Secondary@-1
+ End Sub
+
+ Public Shared Sub ConditionalAccessExpression()
+ Dim sObj = Nothing
+ Dim x = sObj?.str?.Length > 2
+ ' ^^^^ Noncompliant
+ ' ^^^^^^^ Secondary@-1
+ End Sub
+
+ Public Sub DoLoopUntilStatement()
+ Dim c1 = false
+ Do
+ Console.WriteLine("")
+ Loop Until c1 ' Noncompliant
+ End Sub
+
+ Public Sub DoLoopWhileStatement()
+ Dim c1 = True
+ Do
+ Console.WriteLine("")
+ Loop While c1 ' Noncompliant
+ End Sub
+
+ Public Sub DoUntilStatement()
+ Dim c1 = False
+ Do Until c1 ' Noncompliant
+ Console.WriteLine("")
+ Loop
+ End Sub
+
+ Public Sub DoWhileStatement()
+ Dim c1 = True
+ Do While c1 ' Noncompliant
+ Console.WriteLine("")
+ Loop
+ End Sub
+
+ Public Sub IfStatement()
+ Dim c1 = True
+ If c1 ' Noncompliant
+ Console.WriteLine("")
+ End If
+ End Sub
+
+ Public Sub OrAlsoExpression()
+ Dim c1 = True
+ Dim a = c1 OrElse False ' Noncompliant
+ ' Secondary@-1
+ End Sub
+
+ Public Sub WhileStatement()
+ Dim c1 = True
+ While c1 ' Noncompliant
+ Console.WriteLine("")
+ End While
+ End Sub
+
+ Public Sub SelectStatement()
+ Dim i = 10
+ Dim b = True
+ Select Case i
+ Case 1 ' Noncompliant
+ b = False ' Secondary
+ End Select
+ End Sub
+
+End Class
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
index 0f2f4db1bf0..7980a1008f5 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
@@ -1,1760 +1,1751 @@
-Imports System
-Imports System.Collections.Generic
-Imports System.Diagnostics
-Imports System.Threading.Tasks
-Imports System.IO
-Imports System.Linq
-Imports Microsoft.Extensions.Primitives
+Imports System.IO
Imports System.Runtime.InteropServices
-Namespace Tests.Diagnostics
- Public Class ConditionEvaluatesToConstant
- Private Const t As Boolean = True
- Private Const f As Boolean = False
-
- Public Sub LoopsWithBreak(ByVal o1 As Object, ByVal o2 As Object, ByVal o3 As Object)
- Dim c1, c2 As Boolean
- c1 = c2 = True
- While c1 ' Noncompliant
- If o1 IsNot Nothing Then Exit While ' Secondary
- End While
-
- Do
- If o2 IsNot Nothing Then Exit Do
- Loop While c2 ' Noncompliant
-
- End Sub
-
- Public Sub IfStatement()
- Dim c1 = True
- If c1 Then ' Noncompliant
- Console.WriteLine("Always True")
- End If
- End Sub
-
- Private Sub UsingStatement()
- Using writer As TextWriter = Nothing
- If writer IsNot Nothing Then ' Noncompliant
- Console.WriteLine("Hello world") ' Secondary
- End If
- End Using
- End Sub
-
- Public Sub DoesNotRaiseForConst()
- If t Then ' Compliant - no issue is raised for const fields.
- Console.WriteLine("Do stuff")
- End If
- End Sub
-
- Public Sub NotExecutedLoops(ByVal o1 As Object, ByVal o2 As Object, ByVal o3 As Object)
- Dim c1, c2, c3 As Boolean
- c1 = c2 = c3 = False
-
- While c1 ' Noncompliant {{Change this condition so that it does not always evaluate to 'False'. Some code paths are unreachable.}}
- If o1 IsNot Nothing Then Exit While ' Secondary
- End While
-
- Do
- If o2 IsNot Nothing Then Exit Do
+Public Class ConditionEvaluatesToConstant
+ Private Const t As Boolean = True
+ Private Const f As Boolean = False
+
+ Public Sub LoopsWithBreak(ByVal o1 As Object, ByVal o2 As Object, ByVal o3 As Object)
+ Dim c1, c2 As Boolean
+ c1 = c2 = True
+ While c1 ' Noncompliant
+ If o1 IsNot Nothing Then Exit While ' Secondary
+ End While
+
+ Do
+ If o2 IsNot Nothing Then Exit Do
+ Loop While c2 ' Noncompliant
+
+ End Sub
+
+ Public Sub IfStatement()
+ Dim c1 = True
+ If c1 Then ' Noncompliant
+ Console.WriteLine("Always True")
+ End If
+ End Sub
+
+ Private Sub UsingStatement()
+ Using writer As TextWriter = Nothing
+ If writer IsNot Nothing Then ' Noncompliant
+ Console.WriteLine("Hello world") ' Secondary
+ End If
+ End Using
+ End Sub
+
+ Public Sub DoesNotRaiseForConst()
+ If t Then ' Compliant - no issue is raised for const fields.
+ Console.WriteLine("Do stuff")
+ End If
+ End Sub
+
+ Public Sub NotExecutedLoops(ByVal o1 As Object, ByVal o2 As Object, ByVal o3 As Object)
+ Dim c1, c2, c3 As Boolean
+ c1 = c2 = c3 = False
+
+ While c1 ' Noncompliant {{Change this condition so that it does not always evaluate to 'False'. Some code paths are unreachable.}}
+ If o1 IsNot Nothing Then Exit While ' Secondary
+ End While
+
+ Do
+ If o2 IsNot Nothing Then Exit Do
+
+ Loop While c2 ' Noncompliant {{Change this condition so that it does not always evaluate to 'False'.}}
+ ' ^^
+ End Sub
+
+ Public Sub BreakInLoop(ByVal o As Object)
+ Dim c = True
+ While c ' Noncompliant
+ If o IsNot Nothing Then Exit While
+ End While
+ End Sub
+
+ Public Sub ReturnInLoop(ByVal o As Object)
+ Dim c = True
+ While c ' Noncompliant
+ If o IsNot Nothing Then Return
+ End While
+ End Sub
+
+ Public Sub ThrowInLoop(ByVal o As Object)
+ Dim c = True
+ While c ' Noncompliant
+ If o IsNot Nothing Then Throw New Exception()
+ End While
+ End Sub
+
+ Public Sub ConstField(ByVal a As Boolean, ByVal b As Boolean)
+
+ Dim x = t OrElse a OrElse b ' Compliant t is const
+
+ If t = True Then ' Noncompliant
+ Console.WriteLine("")
+ End If
+
+ End Sub
+
+ Public Sub Foo1(ByVal a As Boolean, ByVal b As Boolean)
+ Dim l = True
+ Dim x = l OrElse a OrElse b
+ ' ^ Noncompliant
+ ' ^^^^^^^^^^ Secondary@-1
+ End Sub
+
+ Public Sub Foo2(ByVal a As Boolean, ByVal b As Boolean)
+ Dim l = True
+ Dim x = l OrElse a OrElse b
+ ' ^ Noncompliant
+ ' ^^^^^^^^^^ Secondary@-1
+
+ End Sub
+
+ Public Sub Foo3(ByVal a As Boolean, ByVal b As Boolean)
+ Dim l = True
+ Dim x = l OrElse a OrElse b
+ ' ^ Noncompliant
+ ' ^^^^^^^^^^ Secondary@-1
+ End Sub
+
+ Public Sub Foo4(ByVal a As Boolean, ByVal b As Boolean)
+ Dim l = True
+ Dim m = False
+ Dim x = m OrElse l OrElse a OrElse b
+ ' ^ Noncompliant
+ ' ^ Noncompliant@-1
+ ' ^^^^^^^^^^ Secondary@-2
+
+ End Sub
+
+ Public Sub Foo5(ByVal a As Boolean, ByVal b As Boolean)
+ Dim l = True
+ Dim m = False
+ Dim x = m AndAlso l OrElse a OrElse b
+ ' ^ Noncompliant
+ ' ^ Secondary@-1
+ End Sub
+
+ Public Sub Foo6(ByVal a As Boolean, ByVal b As Boolean)
+ Dim l = True
+ Dim x = If(l OrElse a, a, b)
+ ' ^ Noncompliant
+ ' ^ Secondary@-1
+ ' ^ Secondary@-2
+ End Sub
+
+ Public Sub Foo7(ByVal a As Boolean, ByVal b As Boolean)
+ Dim l = True
+ If If(l OrElse a, a, b) OrElse b Then
+ ' ^ Noncompliant
+ ' ^ Secondary@-1
+ ' ^ Secondary@-2
+ End If
+ End Sub
+
+ Private Sub TestNameof(ByVal s As String)
+ If Equals(Nothing, NameOf(Method1)) Then ' FN FIX
+ End If
+ End Sub
+
+ Public Sub Method1()
+ Dim b = True
+ If b Then ' Noncompliant
+ Console.WriteLine()
+ Else
+ ' secondary location covers all unreachable code blocks:
+ Console.WriteLine(1) ' Secondary ^13#103
+ While b
+ Console.WriteLine(2)
+ End While ' the secondary location ends at the end of the above line
+ End If
+
+ Console.WriteLine()
+ End Sub
+
+ Public Sub Method2()
+ Dim b = True
+ If b Then ' Noncompliant
+ Console.WriteLine()
+ End If
- Loop While c2 ' Noncompliant {{Change this condition so that it does not always evaluate to 'False'.}}
- ' ^^
- End Sub
+ If Not b Then ' Noncompliant
+ Console.WriteLine() ' Secondary
+ End If
- Public Sub BreakInLoop(ByVal o As Object)
- Dim c = True
- While c ' Noncompliant
- If o IsNot Nothing Then Exit While
- End While
- End Sub
+ Console.WriteLine()
+ End Sub
- Public Sub ReturnInLoop(ByVal o As Object)
- Dim c = True
- While c ' Noncompliant
- If o IsNot Nothing Then Return
- End While
- End Sub
+ Public Sub Method2Literals()
+ If True Then ' Compliant
+ Console.WriteLine()
+ End If
- Public Sub ThrowInLoop(ByVal o As Object)
- Dim c = True
- While c ' Noncompliant
- If o IsNot Nothing Then Throw New Exception()
- End While
- End Sub
+ If False Then ' Compliant
+ Console.WriteLine()
+ End If
- Public Sub ConstField(ByVal a As Boolean, ByVal b As Boolean)
+ Console.WriteLine()
+ End Sub
- Dim x = t OrElse a OrElse b ' Compliant t is const
+ Public Sub Method3()
+ Dim b As Boolean
+ TryGet(b)
+ If b Then
+ End If
+ End Sub
- If t = True Then ' Noncompliant
- Console.WriteLine("")
- End If
+ Private Sub TryGet( ByRef b As Boolean)
+ b = False
+ End Sub
- End Sub
+ Public Sub Method3(ByVal cond As Boolean)
+ While cond
+ Console.WriteLine()
+ End While
- Public Sub Foo1(ByVal a As Boolean, ByVal b As Boolean)
- Dim l = True
- Dim x = l OrElse a OrElse b
- ' ^ Noncompliant
- ' ^^^^^^^^^^ Secondary@-1
- End Sub
+ Dim b = True
+ While b ' Noncompliant
+ Console.WriteLine()
+ End While
- Public Sub Foo2(ByVal a As Boolean, ByVal b As Boolean)
- Dim l = True
- Dim x = l OrElse a OrElse b
- ' ^ Noncompliant
- ' ^^^^^^^^^^ Secondary@-1
+ Console.WriteLine() ' Secondary
+ End Sub
- End Sub
+ Public Sub Method4(ByVal cond As Boolean)
+ Dim i = 10
+ While i < 20
+ i = i + 1
+ End While
- Public Sub Foo3(ByVal a As Boolean, ByVal b As Boolean)
- Dim l = True
- Dim x = l OrElse a OrElse b
- ' ^ Noncompliant
- ' ^^^^^^^^^^ Secondary@-1
- End Sub
+ Dim b = True
+ While b ' Noncompliant
+ Console.WriteLine()
+ End While
- Public Sub Foo4(ByVal a As Boolean, ByVal b As Boolean)
- Dim l = True
- Dim m = False
- Dim x = m OrElse l OrElse a OrElse b
- ' ^ Noncompliant
- ' ^ Noncompliant@-1
- ' ^^^^^^^^^^ Secondary@-2
+ Console.WriteLine() ' Secondary
+ End Sub
- End Sub
+ Public Sub Method5()
+ While True ' Compliant
+ Console.WriteLine()
+ End While
- Public Sub Foo5(ByVal a As Boolean, ByVal b As Boolean)
- Dim l = True
- Dim m = False
- Dim x = m AndAlso l OrElse a OrElse b
- ' ^ Noncompliant
- ' ^ Secondary@-1
- End Sub
+ Console.WriteLine()
+ End Sub
- Public Sub Foo6(ByVal a As Boolean, ByVal b As Boolean)
- Dim l = True
- Dim x = If(l OrElse a, a, b)
- ' ^ Noncompliant
- ' ^ Secondary@-1
- ' ^ Secondary@-2
- End Sub
- Public Sub Foo7(ByVal a As Boolean, ByVal b As Boolean)
- Dim l = True
- If If(l OrElse a, a, b) OrElse b Then
- ' ^ Noncompliant
- ' ^ Secondary@-1
- ' ^ Secondary@-2
- End If
- End Sub
+ Public Sub Method_Select()
+ Dim i = 10
+ Dim b = True
+ Select Case i
+ Case 1 ' Noncompliant
+ b = False ' Secondary
+ End Select
- Private Sub TestNameof(ByVal s As String)
- If Equals(Nothing, NameOf(Method1)) Then ' FN FIX
- End If
- End Sub
+ If b Then ' Noncompliant
+ Else
+ End If
+ End Sub
- Public Sub Method1()
- Dim b = True
- If b Then ' Noncompliant
+ Public Sub Method_Select_Learn(ByVal cond As Boolean)
+ Select Case cond
+ Case True
+ If cond Then ' Noncompliant
+ Console.WriteLine()
+ End If
+ End Select
+ End Sub
+
+ Public Property Property1 As Boolean
+ Get
+ Dim a = New Action(Sub()
+ Dim b = True
+ If b Then ' Noncompliant
+ Console.WriteLine()
+ Else
+ Console.WriteLine() ' Secondary
+ End If
+ End Sub)
+ Return True
+ End Get
+ Set(ByVal value As Boolean)
+ value = True
+ If value Then ' Noncompliant
Console.WriteLine()
Else
- ' secondary location covers all unreachable code blocks:
- Console.WriteLine(1) ' Secondary ^17#108
- While b
- Console.WriteLine(2)
- End While ' the secondary location ends at the end of the above line
+ Console.WriteLine() ' Secondary
End If
+ End Set
+ End Property
- Console.WriteLine()
- End Sub
+ Public Shared ReadOnly Property Prop As Boolean
+ Get
+ Return Prop
+ End Get
+ End Property
- Public Sub Method2()
- Dim b = True
- If b Then ' Noncompliant
- Console.WriteLine()
- End If
+ Public Sub Method_Complex()
+ Dim guard1 = True
+ Dim guard2 = True
+ Dim guard3 = True
- If Not b Then ' Noncompliant
- Console.WriteLine() ' Secondary
+ While GetCondition()
+ If guard1 Then
+ guard1 = False
+ Else
+ If guard2 Then ' Noncompliant FP: loop is only analyzed twice
+ guard2 = False
+ Else
+ guard3 = False ' Secondary FP
+ End If
End If
+ End While
+ If guard3 Then ' Noncompliant FP: loop is only analyzed twice
Console.WriteLine()
- End Sub
+ End If
+ End Sub
- Public Sub Method2Literals()
- If True Then ' Compliant
- Console.WriteLine()
- End If
+ Public Sub Method_Complex_2()
+ Dim x = False
+ Dim y = False
- If False Then ' Compliant
- Console.WriteLine()
- End If
+ While GetCondition()
+ While GetCondition()
+ If x Then
+ If y Then ' Noncompliant FP: loop is only analyzed twice
+ End If
+ End If
+ y = True
+ End While
+ x = True
+ End While
+ End Sub
+ Private Shared Function GetObject() As Object
+ Return Nothing
+ End Function
+ Public Sub M()
- Console.WriteLine()
- End Sub
+ Dim o1 = GetObject()
+ Dim o2 As Object = Nothing
- Public Sub Method3()
- Dim b As Boolean
- TryGet(b)
- If b Then
+ If o1 IsNot Nothing Then
+ If Not Equals(o1.ToString(), Nothing) Then
+ o2 = New Object()
End If
- End Sub
+ End If
- Private Sub TryGet( ByRef b As Boolean)
- b = False
- End Sub
+ If o2 Is Nothing Then
+ End If
- Public Sub Method3(ByVal cond As Boolean)
- While cond
- Console.WriteLine()
- End While
+ End Sub
- Dim b = True
- While b ' Noncompliant
- Console.WriteLine()
- End While
+ Public Sub NullableStructs()
+ Dim i As Integer? = Nothing
- Console.WriteLine() ' Secondary
- End Sub
+ If i Is Nothing Then ' Noncompliant, always true
+ Console.WriteLine(i)
+ End If
- Public Sub Method4(ByVal cond As Boolean)
- Dim i = 10
- While i < 20
- i = i + 1
- End While
+ i = New Integer?()
+ If i Is Nothing Then ' Noncompliant
+ End If
- Dim b = True
- While b ' Noncompliant
- Console.WriteLine()
- End While
+ Dim ii = ""
+ If ii Is Nothing Then ' Noncompliant, always false
+ Console.WriteLine(ii) ' Secondary
+ End If
+ End Sub
- Console.WriteLine() ' Secondary
- End Sub
+ Private Shared Function GetCondition() As Boolean
+ Return True
+ End Function
- Public Sub Method5()
- While True ' Compliant
- Console.WriteLine()
- End While
+ Public Sub Lambda(ByVal condition As Boolean)
- Console.WriteLine()
- End Sub
+ Dim fail = False
+ Dim a As Action = New Action(Sub() fail = condition)
+ a()
+ If fail Then ' Noncompliant FP
+ End If
+ End Sub
- Public Sub Method_Select()
- Dim i = 10
- Dim b = True
- Select Case i
- Case 1 ' Noncompliant
- b = False ' Secondary
- End Select
+ Public Sub Constraint(ByVal cond As Boolean)
+ Dim a = cond
+ Dim b = a
+ If a Then
+ If b Then ' FN: requires relation support
- If b Then ' Noncompliant
- Else
End If
- End Sub
-
- Public Sub Method_Select_Learn(ByVal cond As Boolean)
- Select Case cond
- Case True
- If cond Then ' Noncompliant
- Console.WriteLine()
- End If
- End Select
- End Sub
+ End If
+ End Sub
- Public Property Property1 As Boolean
- Get
- Dim a = New Action(Sub()
- Dim b = True
- If b Then ' Noncompliant
- Console.WriteLine()
- Else
- Console.WriteLine() ' Secondary
- End If
- End Sub)
- Return True
- End Get
- Set(ByVal value As Boolean)
- value = True
- If value Then ' Noncompliant
- Console.WriteLine()
- Else
- Console.WriteLine() ' Secondary
- End If
- End Set
- End Property
+ Public Sub Stack(ByVal cond As Boolean)
+ Dim a = cond
+ Dim b = a
- Public Shared ReadOnly Property Prop As Boolean
- Get
- Return Prop
- End Get
- End Property
-
- Public Sub Method_Complex()
- Dim guard1 = True
- Dim guard2 = True
- Dim guard3 = True
-
- While GetCondition()
- If guard1 Then
- guard1 = False
- Else
- If guard2 Then ' Noncompliant FP: loop is only analyzed twice
- guard2 = False
- Else
- guard3 = False ' Secondary FP
- End If
- End If
- End While
-
- If guard3 Then ' Noncompliant FP: loop is only analyzed twice
- Console.WriteLine()
+ If Not a Then
+ If b Then ' FN: requires relation support
End If
- End Sub
+ End If
- Public Sub Method_Complex_2()
- Dim x = False
- Dim y = False
+ Dim fail = False
+ Dim ac As Action = New Action(Sub() fail = cond)
- While GetCondition()
- While GetCondition()
- If x Then
- If y Then ' Noncompliant FP: loop is only analyzed twice
- End If
- End If
- y = True
- End While
- x = True
- End While
- End Sub
- Private Shared Function GetObject() As Object
- Return Nothing
- End Function
- Public Sub M()
+ ac()
- Dim o1 = GetObject()
- Dim o2 As Object = Nothing
+ If Not fail Then ' Noncompliant FP
+ End If
+ End Sub
- If o1 IsNot Nothing Then
- If Not Equals(o1.ToString(), Nothing) Then
- o2 = New Object()
- End If
+ Public Sub BooleanBinary(ByVal a As Boolean, ByVal b As Boolean)
+ If a And Not b Then
+ If a Then ' FN: engine doesn't learn BoolConstraints from binary operators
End If
-
- If o2 Is Nothing Then
+ If b Then ' FN: engine doesn't learn BoolConstraints from binary operators
End If
- End Sub
-
- Public Sub NullableStructs()
- Dim i As Integer? = Nothing
+ End If
- If i Is Nothing Then ' Noncompliant, always true
- Console.WriteLine(i)
+ If Not (a Or b) Then
+ If a Then ' FN: engine doesn't learn BoolConstraints from binary operators
End If
- i = New Integer?()
- If i Is Nothing Then ' Noncompliant
- End If
+ End If
- Dim ii = ""
- If ii Is Nothing Then ' Noncompliant, always false
- Console.WriteLine(ii) ' Secondary
+ If a Xor b Then
+ If Not a Xor Not b Then ' FN: engine doesn't learn BoolConstraints from binary operators
End If
- End Sub
+ End If
- Private Shared Function GetCondition() As Boolean
- Return True
- End Function
+ a = False
+ If a And b Then ' Noncompliant
+ End If
- Public Sub Lambda(ByVal condition As Boolean)
+ a = a Or True
+ If a Then ' Noncompliant
+ End If
- Dim fail = False
- Dim a As Action = New Action(Sub() fail = condition)
- a()
+ a = a Or True
+ If a Then ' Noncompliant
+ End If
- If fail Then ' Noncompliant FP
- End If
- End Sub
+ a = a Xor True
+ If a Then ' Noncompliant
+ End If
- Public Sub Constraint(ByVal cond As Boolean)
- Dim a = cond
- Dim b = a
- If a Then
- If b Then ' FN: requires relation support
+ a = a Xor True
+ If a Then ' Noncompliant
+ End If
+ End Sub
- End If
- End If
- End Sub
+ Public Sub CompoundAssignment(ByVal a As Boolean, ByVal b As Boolean)
+ ' https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/operators/assignment-operators
+ a &=True
+ If a Then ' FN
+ End If
- Public Sub Stack(ByVal cond As Boolean)
- Dim a = cond
- Dim b = a
+ a ^=True
+ If a Then ' FN
+ End If
+ End Sub
- If Not a Then
- If b Then ' FN: requires relation support
- End If
- End If
+ Public Sub IsAsExpression(ByVal o As Object)
- Dim fail = False
- Dim ac As Action = New Action(Sub() fail = cond)
+ If TypeOf o Is String Then
+ End If
- ac()
+ Dim oo As Object = TryCast(o, String)
+ If oo Is Nothing Then
+ End If
- If Not fail Then ' Noncompliant FP
- End If
- End Sub
+ o = Nothing
+ If TypeOf o Is Object Then ' Noncompliant
+ End If
- Public Sub BooleanBinary(ByVal a As Boolean, ByVal b As Boolean)
- If a And Not b Then
- If a Then ' FN: engine doesn't learn BoolConstraints from binary operators
- End If
- If b Then ' FN: engine doesn't learn BoolConstraints from binary operators
- End If
+ oo = TryCast(o, Object)
+ If oo Is Nothing Then ' Noncompliant
+ End If
+ End Sub
+ Public Overloads Sub Equals(ByVal b As Boolean)
+ Dim a = True
+ If a = b Then
+ If b Then ' Noncompliant
End If
-
- If Not (a Or b) Then
- If a Then ' FN: engine doesn't learn BoolConstraints from binary operators
- End If
-
+ Else
+ If b Then ' Noncompliant
End If
+ End If
- If a Xor b Then
- If Not a Xor Not b Then ' FN: engine doesn't learn BoolConstraints from binary operators
- End If
+ If Not a = b Then
+ If b Then ' Noncompliant
End If
-
- a = False
- If a And b Then ' Noncompliant
+ Else
+ If b Then ' Noncompliant
End If
+ End If
+ End Sub
- a = a Or True
- If a Then ' Noncompliant
+ Public Sub NotEquals(ByVal b As Boolean)
+ Dim a = True
+ If a <> b Then
+ If b Then ' Noncompliant
End If
-
- a = a Or True
- If a Then ' Noncompliant
+ Else
+ If b Then ' Noncompliant
End If
+ End If
- a = a Xor True
- If a Then ' Noncompliant
+ If Not a <> b Then
+ If b Then ' Noncompliant
End If
-
- a = a Xor True
- If a Then ' Noncompliant
+ Else
+ If b Then ' Noncompliant
End If
- End Sub
+ End If
+ End Sub
- Public Sub CompoundAssignment(ByVal a As Boolean, ByVal b As Boolean)
- ' https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/operators/assignment-operators
- a &=True
- If a Then ' FN
+ Public Sub EqRelations(ByVal a As Boolean, ByVal b As Boolean)
+ If a = b Then
+ If b = a Then ' FN: requires relation support
End If
-
- a ^=True
- If a Then ' FN
+ If b = Not a Then ' FN: requires relation support
End If
- End Sub
-
- Public Sub IsAsExpression(ByVal o As Object)
-
- If TypeOf o Is String Then
+ If Not b = Not Not a Then ' FN: requires relation support
End If
-
- Dim oo As Object = TryCast(o, String)
- If oo Is Nothing Then
+ If Not a = b Then ' FN: requires relation support
End If
-
- o = Nothing
- If TypeOf o Is Object Then ' Noncompliant
+ Else
+ If b <> a Then ' FN: requires relation support
End If
-
- oo = TryCast(o, Object)
- If oo Is Nothing Then ' Noncompliant
+ If b <> Not a Then ' FN: requires relation support
End If
- End Sub
-
- Public Overloads Sub Equals(ByVal b As Boolean)
- Dim a = True
- If a = b Then
- If b Then ' Noncompliant
- End If
- Else
- If b Then ' Noncompliant
- End If
- End If
-
- If Not a = b Then
- If b Then ' Noncompliant
- End If
- Else
- If b Then ' Noncompliant
- End If
+ If Not b <> Not Not a Then ' FN: requires relation support
End If
- End Sub
- Public Sub NotEquals(ByVal b As Boolean)
- Dim a = True
- If a <> b Then
- If b Then ' Noncompliant
- End If
- Else
- If b Then ' Noncompliant
- End If
- End If
+ End If
- If Not a <> b Then
- If b Then ' Noncompliant
- End If
- Else
- If b Then ' Noncompliant
- End If
+ If a <> b Then
+ If b = a Then ' FN: requires relation support
End If
- End Sub
-
- Public Sub EqRelations(ByVal a As Boolean, ByVal b As Boolean)
- If a = b Then
- If b = a Then ' FN: requires relation support
- End If
- If b = Not a Then ' FN: requires relation support
- End If
- If Not b = Not Not a Then ' FN: requires relation support
- End If
- If Not a = b Then ' FN: requires relation support
- End If
- Else
- If b <> a Then ' FN: requires relation support
- End If
- If b <> Not a Then ' FN: requires relation support
- End If
- If Not b <> Not Not a Then ' FN: requires relation support
- End If
-
+ Else
+ If b <> a Then ' FN: requires relation support
End If
+ End If
+ End Sub
- If a <> b Then
- If b = a Then ' FN: requires relation support
- End If
- Else
- If b <> a Then ' FN: requires relation support
- End If
- End If
- End Sub
+ Private Shared Sub BackPropagation(ByVal a As Object, ByVal b As Object)
+ If a Is b AndAlso b Is Nothing Then
+ a.ToString()
+ End If
+ End Sub
- Private Shared Sub BackPropagation(ByVal a As Object, ByVal b As Object)
- If a Is b AndAlso b Is Nothing Then
- a.ToString()
+ Public Sub RefEqualsImpliesValueEquals(ByVal a As Object, ByVal b As Object)
+ If Object.ReferenceEquals(a, b) Then
+ If Equals(a, b) Then ' FN
End If
- End Sub
-
- Public Sub RefEqualsImpliesValueEquals(ByVal a As Object, ByVal b As Object)
- If Object.ReferenceEquals(a, b) Then
- If Equals(a, b) Then ' FN
- End If
- If Equals(a, b) Then ' FN
- End If
- If a.Equals(b) Then ' FN
- End If
+ If Equals(a, b) Then ' FN
End If
-
- If Me Is a Then
- If Equals(a) Then ' FN
- End If
- If Equals(a) Then ' FN
- End If
+ If a.Equals(b) Then ' FN
End If
- End Sub
+ End If
- Public Sub ValueEqualsDoesNotImplyRefEquals(ByVal a As Object, ByVal b As Object)
- If Equals(a, b) Then ' 'a' could override Equals, so this is not a ref equality check
- If a Is b Then
- End If ' Compliant
+ If Me Is a Then
+ If Equals(a) Then ' FN
End If
- End Sub
-
- Public Sub ReferenceEqualsMethodCalls(ByVal a As Object, ByVal b As Object)
- If Object.ReferenceEquals(a, b) Then
- If a Is b Then
- End If ' FN
+ If Equals(a) Then ' FN
End If
+ End If
+ End Sub
+ Public Sub ValueEqualsDoesNotImplyRefEquals(ByVal a As Object, ByVal b As Object)
+ If Equals(a, b) Then ' 'a' could override Equals, so this is not a ref equality check
If a Is b Then
- If Object.ReferenceEquals(a, b) Then
- End If ' FN
- End If
- End Sub
-
- Public Sub ReferenceEqualsMethodCallWithOpOverload(ByVal a As ConditionEvaluatesToConstant, ByVal b As ConditionEvaluatesToConstant)
- If Object.ReferenceEquals(a, b) Then
- If a Is b Then ' FN
- End If
- End If
+ End If ' Compliant
+ End If
+ End Sub
+ Public Sub ReferenceEqualsMethodCalls(ByVal a As Object, ByVal b As Object)
+ If Object.ReferenceEquals(a, b) Then
If a Is b Then
- If Object.ReferenceEquals(a, b) Then ' Compliant, == is doing a value comparison above. FIX
- End If
- End If
- End Sub
+ End If ' FN
+ End If
- Public Sub ReferenceEquals(ByVal a As Object, ByVal b As Object)
+ If a Is b Then
If Object.ReferenceEquals(a, b) Then
- End If
-
- If Object.ReferenceEquals(a, a) Then
End If ' FN
+ End If
+ End Sub
- a = Nothing
- If Object.ReferenceEquals(Nothing, a) Then ' Noncompliant
- End If
- If Object.ReferenceEquals(a, a) Then ' Noncompliant
+ Public Sub ReferenceEqualsMethodCallWithOpOverload(ByVal a As ConditionEvaluatesToConstant, ByVal b As ConditionEvaluatesToConstant)
+ If Object.ReferenceEquals(a, b) Then
+ If a Is b Then ' FN
End If
+ End If
- If Object.ReferenceEquals(Nothing, New Object()) Then ' Noncompliant
+ If a Is b Then
+ If Object.ReferenceEquals(a, b) Then ' Compliant, == is doing a value comparison above. FIX
End If
+ End If
+ End Sub
- ' Because of boxing:
- Dim i = 10
- If Object.ReferenceEquals(i, i) Then ' FN
- End If
+ Public Sub ReferenceEquals(ByVal a As Object, ByVal b As Object)
+ If Object.ReferenceEquals(a, b) Then
+ End If
- Dim ii As Integer? = Nothing
- Dim jj As Integer? = Nothing
- If Object.ReferenceEquals(ii, jj) Then ' Noncompliant
- End If
+ If Object.ReferenceEquals(a, a) Then
+ End If ' FN
- jj = 10
- If Object.ReferenceEquals(ii, jj) Then ' Noncompliant
- End If
- End Sub
+ a = Nothing
+ If Object.ReferenceEquals(Nothing, a) Then ' Noncompliant
+ End If
+ If Object.ReferenceEquals(a, a) Then ' Noncompliant
+ End If
- Public Sub ReferenceEqualsBool()
- Dim a, b As Boolean
- a = b = True
- If Object.ReferenceEquals(a, b) Then ' FN
- End If
- End Sub
+ If Object.ReferenceEquals(Nothing, New Object()) Then ' Noncompliant
+ End If
- Public Overrides Function Equals(ByVal obj As Object) As Boolean
- Return MyBase.Equals(obj)
- End Function
+ ' Because of boxing:
+ Dim i = 10
+ If Object.ReferenceEquals(i, i) Then ' FN
+ End If
- Public Shared Operator =(ByVal a As ConditionEvaluatesToConstant, ByVal b As ConditionEvaluatesToConstant) As Boolean
- Return False
- End Operator
+ Dim ii As Integer? = Nothing
+ Dim jj As Integer? = Nothing
+ If Object.ReferenceEquals(ii, jj) Then ' Noncompliant
+ End If
- Public Shared Operator <>(ByVal a As ConditionEvaluatesToConstant, ByVal b As ConditionEvaluatesToConstant) As Boolean
- Return False
- End Operator
+ jj = 10
+ If Object.ReferenceEquals(ii, jj) Then ' Noncompliant
+ End If
+ End Sub
- Public Sub StringEmpty(ByVal s1 As String)
- Dim s As String = Nothing
- If String.IsNullOrEmpty(s) Then ' Noncompliant
- End If
- If String.IsNullOrWhiteSpace(s) Then ' Noncompliant
- End If
- If Not Equals(String.IsInterned(s), Nothing) Then
- End If
- s = ""
- If String.IsNullOrEmpty(s) Then ' FN
- End If
-
- If String.IsNullOrWhiteSpace(s) Then ' FN
- End If
+ Public Sub ReferenceEqualsBool()
+ Dim a, b As Boolean
+ a = b = True
+ If Object.ReferenceEquals(a, b) Then ' FN
+ End If
+ End Sub
- If String.IsNullOrEmpty(s1) Then ' Compliant, we don't know anything about the argument
- End If
+ Public Overrides Function Equals(ByVal obj As Object) As Boolean
+ Return MyBase.Equals(obj)
+ End Function
- If String.IsNullOrWhiteSpace(s1) Then ' Compliant
- End If
+ Public Shared Operator =(ByVal a As ConditionEvaluatesToConstant, ByVal b As ConditionEvaluatesToConstant) As Boolean
+ Return False
+ End Operator
- If String.IsNullOrEmpty(s1) Then
- If String.IsNullOrEmpty(s1) Then ' FN
- End If
- End If
- End Sub
-
- Public Sub Comparisons(ByVal i As Integer, ByVal j As Integer)
- If i < j Then
- If j < i Then ' FN
- End If
- If j <= i Then ' FN
- End If
- If j = i Then ' FN
- End If
- If j <> i Then ' FN
- End If
- End If
- End Sub
-
- Private Sub ValueEquals(ByVal i As Integer, ByVal j As Integer)
- If i = j Then
- If Equals(i, j) Then ' FN
- End If
- If i.Equals(j) Then ' FN
- End If
- End If
- End Sub
+ Public Shared Operator <>(ByVal a As ConditionEvaluatesToConstant, ByVal b As ConditionEvaluatesToConstant) As Boolean
+ Return False
+ End Operator
- Private Sub DefaultExpression(ByVal o As Object)
- If Nothing Is Nothing Then ' Noncompliant
- End If
+ Public Sub StringEmpty(ByVal s1 As String)
+ Dim s As String = Nothing
+ If String.IsNullOrEmpty(s) Then ' Noncompliant
+ End If
+ If String.IsNullOrWhiteSpace(s) Then ' Noncompliant
+ End If
+ If Not Equals(String.IsInterned(s), Nothing) Then
+ End If
+ s = ""
+ If String.IsNullOrEmpty(s) Then ' FN
+ End If
- Dim nullableInt As Integer? = Nothing
- If nullableInt Is Nothing Then ' Noncompliant
- End If
+ If String.IsNullOrWhiteSpace(s) Then ' FN
+ End If
- If Nothing Is Nothing Then ' Noncompliant
- End If
+ If String.IsNullOrEmpty(s1) Then ' Compliant, we don't know anything about the argument
+ End If
- If Nothing IsNot Nothing Then ' Noncompliant
- End If
+ If String.IsNullOrWhiteSpace(s1) Then ' Compliant
+ End If
- If Nothing IsNot Nothing Then ' Noncompliant
+ If String.IsNullOrEmpty(s1) Then
+ If String.IsNullOrEmpty(s1) Then ' FN
End If
- End Sub
+ End If
+ End Sub
- Private Sub Cast()
- Dim i = 5
- Dim o = CObj(i)
- If o Is Nothing Then ' Noncompliant
+ Public Sub Comparisons(ByVal i As Integer, ByVal j As Integer)
+ If i < j Then
+ If j < i Then ' FN
End If
-
- Dim x = CType(o, ConditionEvaluatesToConstant) ' This would throw and invalid cast exception
- If x Is Nothing Then ' Noncompliant
+ If j <= i Then ' FN
End If
-
- End Sub
-
- Public Async Function NotNullAfterAccess(ByVal o As Object, ByVal arr As Integer(,), ByVal coll As IEnumerable(Of Integer), ByVal task As Task) As Task
- Console.WriteLine(o.ToString())
- If o Is Nothing Then ' Noncompliant
+ If j = i Then ' FN
End If
-
-
- Console.WriteLine(arr(42, 42))
- If arr Is Nothing Then ' Noncompliant
+ If j <> i Then ' FN
End If
+ End If
+ End Sub
-
- For Each item In coll
- Next
- If coll Is Nothing Then ' Noncompliant
+ Private Sub ValueEquals(ByVal i As Integer, ByVal j As Integer)
+ If i = j Then
+ If Equals(i, j) Then ' FN
End If
-
-
- Await task
- If task Is Nothing Then ' FN
+ If i.Equals(j) Then ' FN
End If
+ End If
+ End Sub
- End Function
+ Private Sub DefaultExpression(ByVal o As Object)
+ If Nothing Is Nothing Then ' Noncompliant
+ End If
- Public Sub EqualsTest32(ByVal o As Object)
- Dim o2 = o
- If o Is o2 Then ' FN
- End If
- If Object.ReferenceEquals(o, o2) Then ' FN
- End If
- If o.Equals(o2) Then ' FN
- End If
- If Equals(o2, o) Then ' FN
- End If
+ Dim nullableInt As Integer? = Nothing
+ If nullableInt Is Nothing Then ' Noncompliant
+ End If
+ If Nothing Is Nothing Then ' Noncompliant
+ End If
- Dim i = 1
- Dim j = i
- If i = j Then ' Noncompliant
- End If
+ If Nothing IsNot Nothing Then ' Noncompliant
+ End If
- If i.Equals(j) Then ' FN
- End If
+ If Nothing IsNot Nothing Then ' Noncompliant
+ End If
+ End Sub
- If Equals(i, j) Then ' FN
- End If
- End Sub
+ Private Sub Cast()
+ Dim i = 5
+ Dim o = CObj(i)
+ If o Is Nothing Then ' Noncompliant
+ End If
- Private Async Function Test_Await_Constraint(ByVal t As Task(Of String)) As Task
- If t IsNot Nothing Then
- Dim o = Await t
- If Equals(o, Nothing) Then ' Compliant, might be null
- End If
- End If
- End Function
+ Dim x = CType(o, ConditionEvaluatesToConstant) ' This would throw and invalid cast exception
+ If x Is Nothing Then ' Noncompliant
+ End If
- Public Sub Assert(ByVal condition As Boolean, ByVal o1 As Object)
- Debug.Assert(condition)
+ End Sub
- If condition Then ' Noncompliant
- End If
+ Public Async Function NotNullAfterAccess(ByVal o As Object, ByVal arr As Integer(,), ByVal coll As IEnumerable(Of Integer), ByVal task As Task) As Task
+ Console.WriteLine(o.ToString())
+ If o Is Nothing Then ' Noncompliant
+ End If
- Trace.Assert(condition) ' Compliant
- If o1 IsNot Nothing Then
- Debug.Assert(o1 Is Nothing, "Some message", "More details", 1, 2, 3) ' Compliant
- End If
- End Sub
+ Console.WriteLine(arr(42, 42))
+ If arr Is Nothing Then ' Noncompliant
+ End If
- Public Sub Assert(ByVal o1 As Object)
- Debug.Assert(o1 IsNot Nothing)
- Debug.Assert(o1 Is Nothing)
- End Sub
- Private Sub ComparisonTransitivity(ByVal a As Integer, ByVal b As Integer, ByVal c As Integer)
- If a = b AndAlso b < c Then
- If a >= c Then ' FN
- End If
-
- End If
- If a = b AndAlso b <= c Then
- If a > c Then ' FN
- End If
+ For Each item In coll
+ Next
+ If coll Is Nothing Then ' Noncompliant
+ End If
- End If
- If a > b AndAlso b > c Then
- If a <= c Then ' FN
- End If
- End If
- If a > b AndAlso b >= c Then
- If a <= c Then ' FN
- End If
+ Await task
+ If task Is Nothing Then ' FN
+ End If
- End If
- If a >= b AndAlso b >= c Then
- If a < c Then ' FN
- End If
+ End Function
- End If
- If a >= b AndAlso c <= b Then
- If a < c Then ' FN
- End If
+ Public Sub EqualsTest32(ByVal o As Object)
+ Dim o2 = o
+ If o Is o2 Then ' FN
+ End If
+ If Object.ReferenceEquals(o, o2) Then ' FN
+ End If
+ If o.Equals(o2) Then ' FN
+ End If
+ If Equals(o2, o) Then ' FN
+ End If
- End If
- If a >= b AndAlso c >= b Then
- If a < c Then
- End If
- End If
- End Sub
- Friend Class Comp
- Public Shared Operator <(ByVal a As Comp, ByVal b As Comp) As Boolean
- Return True
- End Operator
- Public Shared Operator >(ByVal a As Comp, ByVal b As Comp) As Boolean
- Return True
- End Operator
- Public Shared Operator >=(ByVal a As Comp, ByVal b As Comp) As Boolean
- Return True
- End Operator
- Public Shared Operator <=(ByVal a As Comp, ByVal b As Comp) As Boolean
- Return True
- End Operator
- End Class
-
- Private Sub RefEqTransitivity(ByVal a As Comp, ByVal b As Comp, ByVal c As Comp)
- If a Is b AndAlso b Is c Then
- If a IsNot c Then ' FN
- End If
- End If
+ Dim i = 1
+ Dim j = i
+ If i = j Then ' Noncompliant
+ End If
- If a.Equals(b) AndAlso b Is c Then
- If a IsNot c Then
- End If
- If a Is c Then
- End If
- If a.Equals(c) Then ' FN
- End If
- If Not a.Equals(c) Then ' FN
- End If
- End If
+ If i.Equals(j) Then ' FN
+ End If
- If a > b AndAlso b Is c Then
- If a <= c Then ' FN
- End If
- End If
- End Sub
+ If Equals(i, j) Then ' FN
+ End If
+ End Sub
- Private Sub ValueEqTransitivity(ByVal a As Comp, ByVal b As Comp, ByVal c As Comp)
- If a Is b AndAlso b.Equals(c) Then
- If a.Equals(c) Then ' FN
- End If
+ Private Async Function Test_Await_Constraint(ByVal t As Task(Of String)) As Task
+ If t IsNot Nothing Then
+ Dim o = Await t
+ If Equals(o, Nothing) Then ' Compliant, might be null
End If
+ End If
+ End Function
- If a.Equals(b) AndAlso b.Equals(c) Then
- If a IsNot c Then
- End If
- If a Is c Then
- End If
- If a.Equals(c) Then ' FN
- End If
- If Not a.Equals(c) Then ' FN
- End If
- End If
+ Public Sub Assert(ByVal condition As Boolean, ByVal o1 As Object)
+ Debug.Assert(condition)
- If a > b AndAlso b.Equals(c) Then
- If a > c Then ' FN
- End If
- If a <= c Then ' FN
- End If
- End If
+ If condition Then ' Noncompliant
+ End If
- If Not a.Equals(b) AndAlso b.Equals(c) Then
- If a.Equals(c) Then ' FN
- End If
- If a Is c Then ' FN
- End If
- End If
+ Trace.Assert(condition) ' Compliant
- If a IsNot b AndAlso b.Equals(c) Then
- If a.Equals(c) Then
- End If
- If a Is c Then
- End If
- End If
- End Sub
+ If o1 IsNot Nothing Then
+ Debug.Assert(o1 Is Nothing, "Some message", "More details", 1, 2, 3) ' Compliant
+ End If
+ End Sub
- Private Sub NeqEqTransitivity(ByVal a As Object, ByVal b As Object, ByVal c As Object)
- If a Is c AndAlso a IsNot b Then
- If b Is c Then ' FN
- End If
+ Public Sub Assert(ByVal o1 As Object)
+ Debug.Assert(o1 IsNot Nothing)
+ Debug.Assert(o1 Is Nothing)
+ End Sub
- If b.Equals(c) Then
- End If
+ Private Sub ComparisonTransitivity(ByVal a As Integer, ByVal b As Integer, ByVal c As Integer)
+ If a = b AndAlso b < c Then
+ If a >= c Then ' FN
End If
- If a Is c AndAlso Not a.Equals(b) Then
- If b Is c Then ' FN
- End If
+ End If
+ If a = b AndAlso b <= c Then
+ If a > c Then ' FN
+ End If
- If b.Equals(c) Then ' FN
- End If
+ End If
+ If a > b AndAlso b > c Then
+ If a <= c Then ' FN
+ End If
+ End If
+ If a > b AndAlso b >= c Then
+ If a <= c Then ' FN
End If
- End Sub
- Public Sub LiftedOperator()
- Dim i As Integer? = Nothing
- Dim j As Integer? = 5
+ End If
+ If a >= b AndAlso b >= c Then
+ If a < c Then ' FN
+ End If
- If i < j Then ' Noncompliant
+ End If
+ If a >= b AndAlso c <= b Then
+ If a < c Then ' FN
End If
- If i <= j Then ' Noncompliant
+ End If
+ If a >= b AndAlso c >= b Then
+ If a < c Then
End If
+ End If
+ End Sub
+
+ Friend Class Comp
+ Public Shared Operator <(ByVal a As Comp, ByVal b As Comp) As Boolean
+ Return True
+ End Operator
+ Public Shared Operator >(ByVal a As Comp, ByVal b As Comp) As Boolean
+ Return True
+ End Operator
+ Public Shared Operator >=(ByVal a As Comp, ByVal b As Comp) As Boolean
+ Return True
+ End Operator
+ Public Shared Operator <=(ByVal a As Comp, ByVal b As Comp) As Boolean
+ Return True
+ End Operator
+ End Class
- If i > j Then ' Noncompliant
+ Private Sub RefEqTransitivity(ByVal a As Comp, ByVal b As Comp, ByVal c As Comp)
+ If a Is b AndAlso b Is c Then
+ If a IsNot c Then ' FN
End If
+ End If
- If i >= j Then ' Noncompliant
+ If a.Equals(b) AndAlso b Is c Then
+ If a IsNot c Then
+ End If
+ If a Is c Then
+ End If
+ If a.Equals(c) Then ' FN
+ End If
+ If Not a.Equals(c) Then ' FN
End If
+ End If
- If i > 0 Then ' Noncompliant
+ If a > b AndAlso b Is c Then
+ If a <= c Then ' FN
End If
+ End If
+ End Sub
- If i >= 0 Then ' Noncompliant
+ Private Sub ValueEqTransitivity(ByVal a As Comp, ByVal b As Comp, ByVal c As Comp)
+ If a Is b AndAlso b.Equals(c) Then
+ If a.Equals(c) Then ' FN
End If
+ End If
- If i < 0 Then ' Noncompliant
+ If a.Equals(b) AndAlso b.Equals(c) Then
+ If a IsNot c Then
End If
+ If a Is c Then
+ End If
+ If a.Equals(c) Then ' FN
+ End If
+ If Not a.Equals(c) Then ' FN
+ End If
+ End If
- If i <= 0 Then ' Noncompliant
+ If a > b AndAlso b.Equals(c) Then
+ If a > c Then ' FN
+ End If
+ If a <= c Then ' FN
End If
+ End If
- If j > Nothing Then ' Noncompliant
+ If Not a.Equals(b) AndAlso b.Equals(c) Then
+ If a.Equals(c) Then ' FN
End If
+ If a Is c Then ' FN
+ End If
+ End If
- If j >= Nothing Then ' Noncompliant
+ If a IsNot b AndAlso b.Equals(c) Then
+ If a.Equals(c) Then
+ End If
+ If a Is c Then
End If
+ End If
+ End Sub
- If j < Nothing Then ' Noncompliant
+ Private Sub NeqEqTransitivity(ByVal a As Object, ByVal b As Object, ByVal c As Object)
+ If a Is c AndAlso a IsNot b Then
+ If b Is c Then ' FN
End If
- If j <= Nothing Then ' Noncompliant
+ If b.Equals(c) Then
End If
- End Sub
+ End If
- Friend Class Singleton
- Private Shared syncRoot As Object = New Object()
+ If a Is c AndAlso Not a.Equals(b) Then
+ If b Is c Then ' FN
+ End If
- Private Shared instanceField As Singleton
+ If b.Equals(c) Then ' FN
+ End If
- Public Shared ReadOnly Property Instance As Singleton
- Get
- If instanceField Is Nothing Then
- SyncLock syncRoot
- If instanceField Is Nothing Then ' Noncompliant FP
- instanceField = New Singleton()
- End If
- End SyncLock
- End If
- Return instanceField
- End Get
- End Property
- End Class
-
- Friend Structure MyStructWithNoOperator
- Public Shared Sub M(ByVal a As MyStructWithNoOperator)
- If a Is Nothing Then ' Noncompliant, also a compiler error
- ' Error@-1 [BC30020]
- End If
- End Sub
- End Structure
+ End If
+ End Sub
- Public Class NullableCases
- Private Sub Case1()
- Dim b1 As Boolean? = True
- If b1 = True Then ' Noncompliant
- End If
- End Sub
+ Public Sub LiftedOperator()
+ Dim i As Integer? = Nothing
+ Dim j As Integer? = 5
- Private Sub Case2(ByVal i As Boolean?)
- If i Is Nothing Then
+ If i < j Then ' Noncompliant
+ End If
- End If
- If i = True Then
+ If i <= j Then ' Noncompliant
+ End If
- End If
- If i = False Then
+ If i > j Then ' Noncompliant
+ End If
- End If
+ If i >= j Then ' Noncompliant
+ End If
- i = Nothing
- If i Is Nothing Then ' Noncompliant
+ If i > 0 Then ' Noncompliant
+ End If
- End If
- If i = True Then ' Noncompliant
+ If i >= 0 Then ' Noncompliant
+ End If
- End If
- If i = False Then ' Noncompliant
+ If i < 0 Then ' Noncompliant
+ End If
- End If
+ If i <= 0 Then ' Noncompliant
+ End If
- i = True
- If i Is Nothing Then ' Noncompliant
+ If j > Nothing Then ' Noncompliant
+ End If
- End If
- If i = True Then ' Noncompliant
+ If j >= Nothing Then ' Noncompliant
+ End If
- End If
- If i = False Then ' Noncompliant
+ If j < Nothing Then ' Noncompliant
+ End If
- End If
+ If j <= Nothing Then ' Noncompliant
+ End If
+ End Sub
- i = False
- If i Is Nothing Then ' Noncompliant
+ Friend Class Singleton
+ Private Shared syncRoot As Object = New Object()
- End If
- If i = True Then ' Noncompliant
+ Private Shared instanceField As Singleton
+ Public Shared ReadOnly Property Instance As Singleton
+ Get
+ If instanceField Is Nothing Then
+ SyncLock syncRoot
+ If instanceField Is Nothing Then ' Noncompliant FP
+ instanceField = New Singleton()
+ End If
+ End SyncLock
End If
- If i = False Then ' Noncompliant
+ Return instanceField
+ End Get
+ End Property
+ End Class
- End If
+ Friend Structure MyStructWithNoOperator
+ Public Shared Sub M(ByVal a As MyStructWithNoOperator)
+ If a Is Nothing Then ' Noncompliant, also a compiler error
+ ' Error@-1 [BC30020]
+ End If
+ End Sub
+ End Structure
- Dim b2 As Boolean? = True
- If b2 = False Then ' Noncompliant
- End If
+ Public Class NullableCases
+ Private Sub Case1()
+ Dim b1 As Boolean? = True
+ If b1 = True Then ' Noncompliant
+ End If
+ End Sub
- Dim b3 As Boolean? = True
- If b3 Is Nothing Then ' Noncompliant
- End If
+ Private Sub Case2(ByVal i As Boolean?)
+ If i Is Nothing Then
- Dim b4 As Boolean? = Nothing
- If b4 = True Then ' Noncompliant
- End If
+ End If
+ If i = True Then
- Dim b5 As Boolean? = Nothing
- If b5 = False Then ' Noncompliant
- End If
+ End If
+ If i = False Then
+ End If
- Dim b6 As Boolean? = Nothing
- If b6 Is Nothing Then ' Noncompliant
- End If
- Dim b7 As Boolean? = True
- If b7 = True Then ' Noncompliant
- End If
- Dim b8 As Boolean? = False
- If b8 = False Then ' Noncompliant
- End If
+ i = Nothing
+ If i Is Nothing Then ' Noncompliant
- End Sub
+ End If
+ If i = True Then ' Noncompliant
- Private Sub Case3(ByVal b As Boolean?)
- If b Is Nothing Then
- If Nothing Is b Then ' Noncompliant
- b.ToString()
- End If
- Else
- If b IsNot Nothing Then ' Noncompliant
- b.ToString()
- End If
- End If
- End Sub
+ End If
+ If i = False Then ' Noncompliant
- Private Sub Case4(ByVal b As Boolean?)
- If b = True Then
- If True = b Then ' Noncompliant
- b.ToString()
- End If
- End If
- End Sub
+ End If
- Private Sub Case5(ByVal b As Boolean?)
- If b = True Then
- ElseIf b = False Then
- Else
- End If
- End Sub
+ i = True
+ If i Is Nothing Then ' Noncompliant
- Private Sub Case6(ByVal b As Boolean?)
- If b Is Nothing Then
- ElseIf b = True Then
- Else
- End If
- End Sub
+ End If
+ If i = True Then ' Noncompliant
- Private Sub Case7(ByVal b As Boolean?)
- If b Is Nothing Then
- If If(b, False) Then ' Noncompliant
+ End If
+ If i = False Then ' Noncompliant
- End If
- End If
- End Sub
+ End If
- Private Sub Case8(ByVal b As Boolean?)
- If b IsNot Nothing Then
- If b.HasValue Then ' Noncompliant
- End If
- End If
- End Sub
+ i = False
+ If i Is Nothing Then ' Noncompliant
- Private Sub Case9(ByVal b As Boolean?)
- If b = True Then
- Dim x = b.Value
- If x = True Then ' Noncompliant
- End If
- End If
- End Sub
+ End If
+ If i = True Then ' Noncompliant
- Private Sub Case10(ByVal i As Integer?)
- If i Is Nothing Then
- If i.HasValue Then ' Noncompliant
- End If
- End If
- End Sub
+ End If
+ If i = False Then ' Noncompliant
- Public Sub IfElseIfElseFlow_DirectValue(ByVal b As Boolean?)
- If b = True Then
- Console.WriteLine("true")
- ElseIf b = False Then
- Console.WriteLine("false")
- Else
- Console.WriteLine("null")
- End If
- End Sub
-
- Public Sub IfElseIfElseFlow_KnownNull()
- Dim b As Boolean? = Nothing
- If b = True Then ' Noncompliant
- Console.WriteLine("true") ' Secondary
- ElseIf b = False Then ' Noncompliant
- Console.WriteLine("false") ' Secondary
- Else
- Console.WriteLine("null")
- End If
- End Sub
- End Class
+ End If
- Public Class ConstantExpressionsAreExcluded
- Const T As Boolean = True
- Const F As Boolean = False
+ Dim b2 As Boolean? = True
+ If b2 = False Then ' Noncompliant
+ End If
- Private Sub LocalConstants()
- Const t = True
- If t Then ' Noncompliant
- Console.WriteLine()
- End If
- Const f = False
- If f Then ' Noncompliant
- Console.WriteLine() ' Secondary
- End If
- End Sub
+ Dim b3 As Boolean? = True
+ If b3 Is Nothing Then ' Noncompliant
+ End If
- Private Sub Constants()
- If T Then ' Compliant it's a constant
- Console.WriteLine()
- End If
- If F Then ' Compliant it's a constant
- Console.WriteLine()
- End If
- End Sub
- Private Sub WhileTrue()
- While T ' Compliant it's a constant
- Console.WriteLine()
- End While
- End Sub
- Private Sub WhileFalse()
- Do
- Console.WriteLine()
- Loop While F ' Compliant it's a constant
- End Sub
- Private Sub Condition()
- Dim x = If(T, 1, 2) ' Compliant, T is constant
- End Sub
- End Class
+ Dim b4 As Boolean? = Nothing
+ If b4 = True Then ' Noncompliant
+ End If
- End Class
+ Dim b5 As Boolean? = Nothing
+ If b5 = False Then ' Noncompliant
+ End If
- Public Class GuardedTests
- Public Sub Guarded(ByVal s1 As String)
- Guard1(s1)
- If Equals(s1, Nothing) Then ' Noncompliant, always false
- ' this branch is never executed
- Else
+ Dim b6 As Boolean? = Nothing
+ If b6 Is Nothing Then ' Noncompliant
+ End If
+ Dim b7 As Boolean? = True
+ If b7 = True Then ' Noncompliant
+ End If
+ Dim b8 As Boolean? = False
+ If b8 = False Then ' Noncompliant
End If
- End Sub
- Public Sub Guard1(Of T As Class)(
- ByVal value As T)
End Sub
-
- Public NotInheritable Class ValidatedNotNullAttribute
- Inherits Attribute
- End Class
- End Class
-
- Public Class CatchFinally
- Public Sub ObjectsShouldNotBeDisposedMoreThanOnce()
- Dim stream As Stream = Nothing
- Try
- stream = File.Open("file", FileMode.Open)
- Using reader = New StreamReader(stream)
- ' read the file here
-
- ' StreamReader will dispose the stream automatically; set stream to null
- ' to prevent it from disposing twice (the recommended pattern for S3966)
- stream = Nothing
- End Using
-
- Finally
- If stream IsNot Nothing Then
- stream.Dispose()
+ Private Sub Case3(ByVal b As Boolean?)
+ If b Is Nothing Then
+ If Nothing Is b Then ' Noncompliant
+ b.ToString()
+ End If
+ Else
+ If b IsNot Nothing Then ' Noncompliant
+ b.ToString()
End If
- End Try
+ End If
End Sub
- Public Sub FalseNegatives()
- Dim o As Object = Nothing
- Try
- Console.WriteLine("Could throw")
- Catch
- If o IsNot Nothing Then ' Noncompliant
- End If
- If o Is Nothing Then ' Noncompliant
+ Private Sub Case4(ByVal b As Boolean?)
+ If b = True Then
+ If True = b Then ' Noncompliant
+ b.ToString()
End If
+ End If
+ End Sub
- Finally
- If o IsNot Nothing Then ' Noncompliant
- End If
- If o Is Nothing Then ' Noncompliant
- End If
- End Try
+ Private Sub Case5(ByVal b As Boolean?)
+ If b = True Then
+ ElseIf b = False Then
+ Else
+ End If
End Sub
- End Class
- Friend Class UsingStatement
- Public Sub Method()
- Dim isTrue = True
- If isTrue Then ' Noncompliant
+ Private Sub Case6(ByVal b As Boolean?)
+ If b Is Nothing Then
+ ElseIf b = True Then
+ Else
End If
- Using reader = New StreamReader("")
- If isTrue Then ' Noncompliant
+ End Sub
+
+ Private Sub Case7(ByVal b As Boolean?)
+ If b Is Nothing Then
+ If If(b, False) Then ' Noncompliant
+
End If
- End Using
- If isTrue Then ' Noncompliant
End If
End Sub
- End Class
- Friend Class AsyncAwait
- Private _foo1 As Object
- Private Async Function Foo(ByVal t As Task) As Task
- Dim o As Object = Nothing
- _foo1 = o
- Await t ' awaiting clears the constraints
- If _foo1 IsNot Nothing Then ' FN
- End If
- If _foo1 Is Nothing Then ' FN
- End If
- If o IsNot Nothing Then ' Noncompliant
- End If
- If o Is Nothing Then ' Noncompliant
+ Private Sub Case8(ByVal b As Boolean?)
+ If b IsNot Nothing Then
+ If b.HasValue Then ' Noncompliant
+ End If
End If
- End Function
- End Class
+ End Sub
- Public Class StaticMethods
- Private _foo1 As Object
- ' https://github.com/SonarSource/sonar-dotnet/issues/947
- Private Sub CallToMonitorWaitShouldResetFieldConstraints()
- Dim o As Object = Nothing
- _foo1 = o
- Threading.Monitor.Wait(o) ' This is a multi-threaded application, the fields could change
- If _foo1 IsNot Nothing Then ' Noncompliant FP
- End If
- If _foo1 Is Nothing Then ' Noncompliant FP
- End If
- If o IsNot Nothing Then ' Noncompliant
- End If
- If o Is Nothing Then ' Noncompliant
+ Private Sub Case9(ByVal b As Boolean?)
+ If b = True Then
+ Dim x = b.Value
+ If x = True Then ' Noncompliant
+ End If
End If
End Sub
- Private Sub CallToStaticMethodsShouldResetFieldConstraints()
- Dim o As Object = Nothing
- _foo1 = o
- Console.WriteLine() ' This particular method has no side effects
- If _foo1 IsNot Nothing Then ' Noncompliant
- End If
- If _foo1 Is Nothing Then ' Noncompliant
- End If
- If o IsNot Nothing Then ' Noncompliant
- End If
- If o Is Nothing Then ' Noncompliant
+ Private Sub Case10(ByVal i As Integer?)
+ If i Is Nothing Then
+ If i.HasValue Then ' Noncompliant
+ End If
End If
End Sub
- End Class
-
- Public Class TestNullCoalescing
- Public Sub CompliantMethod(ByVal input As Boolean?)
- If If(input, False) Then ' Compliant
- Console.WriteLine("input is true")
+ Public Sub IfElseIfElseFlow_DirectValue(ByVal b As Boolean?)
+ If b = True Then
+ Console.WriteLine("true")
+ ElseIf b = False Then
+ Console.WriteLine("false")
Else
- Console.WriteLine("input is false")
+ Console.WriteLine("null")
End If
End Sub
- Public Sub CompliantMethod1(ByVal input As Boolean?)
- While If(input, False) ' Compliant
- Console.WriteLine("input is true")
- End While
- End Sub
-
- Public Sub CompliantMethod2(ByVal input As Boolean?, ByVal input1 As Boolean)
- While If(input, False) AndAlso input1 ' Compliant
- Console.WriteLine("input is true")
- End While
+ Public Sub IfElseIfElseFlow_KnownNull()
+ Dim b As Boolean? = Nothing
+ If b = True Then ' Noncompliant
+ Console.WriteLine("true") ' Secondary
+ ElseIf b = False Then ' Noncompliant
+ Console.WriteLine("false") ' Secondary
+ Else
+ Console.WriteLine("null")
+ End If
End Sub
+ End Class
- Public Sub CompliantMethod3(ByVal input As Boolean?, ByVal input1 As Boolean)
+ Public Class ConstantExpressionsAreExcluded
+ Const T As Boolean = True
+ Const F As Boolean = False
- If If(If(input, False), input1, False) Then ' Compliant
- Console.WriteLine("input is true")
+ Private Sub LocalConstants()
+ Const t = True
+ If t Then ' Noncompliant
+ Console.WriteLine()
+ End If
+ Const f = False
+ If f Then ' Noncompliant
+ Console.WriteLine() ' Secondary
End If
End Sub
- Public Sub NonCompliantMethod()
- Dim input As Boolean? = True
- If If(input, False) Then ' Noncompliant
- Console.WriteLine("input is true")
- Else
- Console.WriteLine("input is false") ' Secondary
+ Private Sub Constants()
+ If T Then ' Compliant it's a constant
+ Console.WriteLine()
+ End If
+ If F Then ' Compliant it's a constant
+ Console.WriteLine()
End If
End Sub
-
- Public Sub NonCompliantMethod1()
- Dim input As Boolean? = True
- While If(input, False) ' Noncompliant
- Console.WriteLine("input is true")
+ Private Sub WhileTrue()
+ While T ' Compliant it's a constant
+ Console.WriteLine()
End While
End Sub
-
- Public Sub NonCompliantMethod2(ByVal input As Boolean?)
- While If(input, False) OrElse True ' Compliant
- Console.WriteLine("input is true")
- End While
+ Private Sub WhileFalse()
+ Do
+ Console.WriteLine()
+ Loop While F ' Compliant it's a constant
End Sub
-
- Public Sub NonCompliantMethod3(ByVal input As Boolean?, ByVal input1 As Boolean)
- If If(If(input, False), False, False) Then ' Compliant
- Console.WriteLine("input is true")
- End If
+ Private Sub Condition()
+ Dim x = If(T, 1, 2) ' Compliant, T is constant
End Sub
End Class
- Friend Class Program
- Public Shared Function CompliantMethod4(ByVal parameter As String) As String
- Dim useParameter = If(parameter, "non-empty")
- If Equals(useParameter, Nothing) OrElse Equals(useParameter, "") Then Return "non-empty" ' Noncompliant
- ' we don't know if this going to be excuted or not
+End Class
- Return "empty"
- End Function
+Public Class GuardedTests
+ Public Sub Guarded(ByVal s1 As String)
+ Guard1(s1)
- Public Shared Function Method1347(ByVal parameter As String) As String
- Dim useParameter = If(parameter, "non-empty")
- If Not String.IsNullOrEmpty(useParameter) Then
- Return "non-empty"
- Else
- End If
- Return "empty"
- End Function
+ If Equals(s1, Nothing) Then ' Noncompliant, always false
+ ' this branch is never executed
+ Else
+ End If
+ End Sub
+
+ Public Sub Guard1(Of T As Class)(
+ ByVal value As T)
+ End Sub
+
+
+ Public NotInheritable Class ValidatedNotNullAttribute
+ Inherits Attribute
End Class
+End Class
+
+Public Class CatchFinally
+ Public Sub ObjectsShouldNotBeDisposedMoreThanOnce()
+ Dim stream As Stream = Nothing
+ Try
+ stream = File.Open("file", FileMode.Open)
+ Using reader = New StreamReader(stream)
+ ' read the file here
+
+ ' StreamReader will dispose the stream automatically; set stream to null
+ ' to prevent it from disposing twice (the recommended pattern for S3966)
+ stream = Nothing
+ End Using
- Public Class RefArgTest
- Public Sub Method(ByRef s As String, ByVal x As Integer)
- End Sub
- Public Sub Method1(ByVal infixes As String)
- If Not Equals(infixes, Nothing) Then
- Method(infixes, infixes.Length)
- If Equals(infixes, Nothing) Then ' Noncompliant FP: ref
- Return
- End If
+ Finally
+ If stream IsNot Nothing Then
+ stream.Dispose()
+ End If
+ End Try
+ End Sub
+
+ Public Sub FalseNegatives()
+ Dim o As Object = Nothing
+ Try
+ Console.WriteLine("Could throw")
+ Catch
+ If o IsNot Nothing Then ' Noncompliant
+ End If
+ If o Is Nothing Then ' Noncompliant
+ End If
+
+ Finally
+ If o IsNot Nothing Then ' Noncompliant
+ End If
+ If o Is Nothing Then ' Noncompliant
+ End If
+ End Try
+ End Sub
+End Class
+
+Friend Class UsingStatement
+ Public Sub Method()
+ Dim isTrue = True
+ If isTrue Then ' Noncompliant
+ End If
+ Using reader = New StreamReader("")
+ If isTrue Then ' Noncompliant
+ End If
+ End Using
+ If isTrue Then ' Noncompliant
+ End If
+ End Sub
+End Class
+
+Friend Class AsyncAwait
+ Private _foo1 As Object
+ Private Async Function Foo(ByVal t As Task) As Task
+ Dim o As Object = Nothing
+ _foo1 = o
+ Await t ' awaiting clears the constraints
+ If _foo1 IsNot Nothing Then ' FN
+ End If
+ If _foo1 Is Nothing Then ' FN
+ End If
+ If o IsNot Nothing Then ' Noncompliant
+ End If
+ If o Is Nothing Then ' Noncompliant
+ End If
+ End Function
+End Class
+
+Public Class StaticMethods
+ Private _foo1 As Object
+ ' https://github.com/SonarSource/sonar-dotnet/issues/947
+ Private Sub CallToMonitorWaitShouldResetFieldConstraints()
+ Dim o As Object = Nothing
+ _foo1 = o
+ Threading.Monitor.Wait(o) ' This is a multi-threaded application, the fields could change
+ If _foo1 IsNot Nothing Then ' Noncompliant FP
+ End If
+ If _foo1 Is Nothing Then ' Noncompliant FP
+ End If
+ If o IsNot Nothing Then ' Noncompliant
+ End If
+ If o Is Nothing Then ' Noncompliant
+ End If
+ End Sub
+
+ Private Sub CallToStaticMethodsShouldResetFieldConstraints()
+ Dim o As Object = Nothing
+ _foo1 = o
+ Console.WriteLine() ' This particular method has no side effects
+ If _foo1 IsNot Nothing Then ' Noncompliant
+ End If
+ If _foo1 Is Nothing Then ' Noncompliant
+ End If
+ If o IsNot Nothing Then ' Noncompliant
+ End If
+ If o Is Nothing Then ' Noncompliant
+ End If
+ End Sub
+End Class
+
+
+Public Class TestNullCoalescing
+ Public Sub CompliantMethod(ByVal input As Boolean?)
+ If If(input, False) Then ' Compliant
+ Console.WriteLine("input is true")
+ Else
+ Console.WriteLine("input is false")
+ End If
+ End Sub
+
+ Public Sub CompliantMethod1(ByVal input As Boolean?)
+ While If(input, False) ' Compliant
+ Console.WriteLine("input is true")
+ End While
+ End Sub
+
+ Public Sub CompliantMethod2(ByVal input As Boolean?, ByVal input1 As Boolean)
+ While If(input, False) AndAlso input1 ' Compliant
+ Console.WriteLine("input is true")
+ End While
+ End Sub
+
+ Public Sub CompliantMethod3(ByVal input As Boolean?, ByVal input1 As Boolean)
+
+ If If(If(input, False), input1, False) Then ' Compliant
+ Console.WriteLine("input is true")
+ End If
+ End Sub
+
+ Public Sub NonCompliantMethod()
+ Dim input As Boolean? = True
+ If If(input, False) Then ' Noncompliant
+ Console.WriteLine("input is true")
+ Else
+ Console.WriteLine("input is false") ' Secondary
+ End If
+ End Sub
+
+ Public Sub NonCompliantMethod1()
+ Dim input As Boolean? = True
+ While If(input, False) ' Noncompliant
+ Console.WriteLine("input is true")
+ End While
+ End Sub
+
+ Public Sub NonCompliantMethod2(ByVal input As Boolean?)
+ While If(input, False) OrElse True ' Compliant
+ Console.WriteLine("input is true")
+ End While
+ End Sub
+
+ Public Sub NonCompliantMethod3(ByVal input As Boolean?, ByVal input1 As Boolean)
+ If If(If(input, False), False, False) Then ' Compliant
+ Console.WriteLine("input is true")
+ End If
+ End Sub
+End Class
+
+Friend Class Program
+ Public Shared Function CompliantMethod4(ByVal parameter As String) As String
+ Dim useParameter = If(parameter, "non-empty")
+ If Equals(useParameter, Nothing) OrElse Equals(useParameter, "") Then Return "non-empty" ' Noncompliant
+ ' we don't know if this going to be excuted or not
+
+ Return "empty"
+ End Function
+
+ Public Shared Function Method1347(ByVal parameter As String) As String
+ Dim useParameter = If(parameter, "non-empty")
+ If Not String.IsNullOrEmpty(useParameter) Then
+ Return "non-empty"
+ Else
+ End If
+ Return "empty"
+ End Function
+End Class
+
+Public Class RefArgTest
+ Public Sub Method(ByRef s As String, ByVal x As Integer)
+ End Sub
+ Public Sub Method1(ByVal infixes As String)
+ If Not Equals(infixes, Nothing) Then
+ Method(infixes, infixes.Length)
+ If Equals(infixes, Nothing) Then ' Noncompliant FP: ref
+ Return
End If
- End Sub
+ End If
+ End Sub
- Public Sub Method2(ByVal infixes As String)
- If Not Equals(infixes, Nothing) Then
- Method(infixes, infixes.Length)
- If Not Equals(infixes, Nothing) Then ' Noncompliant FP: ref
- Return
- End If
+ Public Sub Method2(ByVal infixes As String)
+ If Not Equals(infixes, Nothing) Then
+ Method(infixes, infixes.Length)
+ If Not Equals(infixes, Nothing) Then ' Noncompliant FP: ref
+ Return
End If
- End Sub
+ End If
+ End Sub
- Public Sub Method3(ByVal infixes As String)
- If Equals(infixes, Nothing) Then
- Method(infixes, infixes.Length)
- If Equals(infixes, Nothing) Then ' Noncompliant FP: ref
- Return
- End If
+ Public Sub Method3(ByVal infixes As String)
+ If Equals(infixes, Nothing) Then
+ Method(infixes, infixes.Length)
+ If Equals(infixes, Nothing) Then ' Noncompliant FP: ref
+ Return
End If
- End Sub
+ End If
+ End Sub
- Public Sub Method4(ByVal infixes As String)
- If Equals(infixes, Nothing) Then
- Method(infixes, infixes.Length)
- If Not Equals(infixes, Nothing) Then ' Noncompliant FP: ref
- Return
- End If
+ Public Sub Method4(ByVal infixes As String)
+ If Equals(infixes, Nothing) Then
+ Method(infixes, infixes.Length)
+ If Not Equals(infixes, Nothing) Then ' Noncompliant FP: ref
+ Return
End If
- End Sub
+ End If
+ End Sub
- End Class
+End Class
- Public Class StringComparision
- Public Sub Method(ByVal parameterString As String)
- Dim emptyString1 = ""
- Dim emptyString2 = ""
- Dim nullString1 As String = Nothing
- Dim nullString2 As String = Nothing
- Dim fullStringa1 = "a"
- Dim fullStringa2 = "a"
- Dim fullStringb = "b"
- Dim whiteSpaceString1 = " "
- Dim whiteSpaceString2 = " "
- Dim doubleWhiteSpaceString1 = " "
- Dim doubleWhiteSpaceString2 = " "
+Public Class StringComparision
+ Public Sub Method(ByVal parameterString As String)
+ Dim emptyString1 = ""
+ Dim emptyString2 = ""
+ Dim nullString1 As String = Nothing
+ Dim nullString2 As String = Nothing
+ Dim fullStringa1 = "a"
+ Dim fullStringa2 = "a"
+ Dim fullStringb = "b"
+ Dim whiteSpaceString1 = " "
+ Dim whiteSpaceString2 = " "
+ Dim doubleWhiteSpaceString1 = " "
+ Dim doubleWhiteSpaceString2 = " "
- If Equals(emptyString1, emptyString2) Then ' FN
+ If Equals(emptyString1, emptyString2) Then ' FN
- End If
- If Equals(nullString1, nullString2) Then ' Noncompliant
+ End If
+ If Equals(nullString1, nullString2) Then ' Noncompliant
- End If
+ End If
- If Equals(fullStringa1, fullStringa2) Then
+ If Equals(fullStringa1, fullStringa2) Then
- End If
+ End If
- If Equals(fullStringa1, fullStringb) Then
+ If Equals(fullStringa1, fullStringb) Then
- End If
+ End If
- If Equals(parameterString, emptyString1) Then
+ If Equals(parameterString, emptyString1) Then
- End If
+ End If
- If Equals(parameterString, nullString1) Then
+ If Equals(parameterString, nullString1) Then
- End If
+ End If
- If Equals(emptyString1, nullString1) Then ' Noncompliant
+ If Equals(emptyString1, nullString1) Then ' Noncompliant
- End If
+ End If
- If Equals(emptyString1, fullStringa1) Then ' FN
+ If Equals(emptyString1, fullStringa1) Then ' FN
- End If
+ End If
- If Equals(nullString1, fullStringa1) Then ' Noncompliant
+ If Equals(nullString1, fullStringa1) Then ' Noncompliant
- End If
+ End If
- If Equals(fullStringa1, "") Then ' FN
+ If Equals(fullStringa1, "") Then ' FN
- End If
+ End If
- If Equals(fullStringa1, Nothing) Then ' Noncompliant
+ If Equals(fullStringa1, Nothing) Then ' Noncompliant
- End If
+ End If
- If Equals(whiteSpaceString1, whiteSpaceString2) Then ' FN
+ If Equals(whiteSpaceString1, whiteSpaceString2) Then ' FN
- End If
+ End If
- If Equals(whiteSpaceString1, " ") Then ' FN
+ If Equals(whiteSpaceString1, " ") Then ' FN
- End If
+ End If
- If Equals(whiteSpaceString1, emptyString1) Then ' FN
+ If Equals(whiteSpaceString1, emptyString1) Then ' FN
- End If
+ End If
- If Equals(whiteSpaceString1, nullString1) Then ' Noncompliant
+ If Equals(whiteSpaceString1, nullString1) Then ' Noncompliant
- End If
+ End If
- If Equals(whiteSpaceString1, fullStringa1) Then ' FN
+ If Equals(whiteSpaceString1, fullStringa1) Then ' FN
- End If
+ End If
- If Equals(whiteSpaceString1, parameterString) Then
+ If Equals(whiteSpaceString1, parameterString) Then
- End If
+ End If
- If Equals(doubleWhiteSpaceString1, doubleWhiteSpaceString2) Then ' FN
+ If Equals(doubleWhiteSpaceString1, doubleWhiteSpaceString2) Then ' FN
- End If
+ End If
- If Equals(doubleWhiteSpaceString1, emptyString1) Then ' FN
+ If Equals(doubleWhiteSpaceString1, emptyString1) Then ' FN
- End If
+ End If
- If Equals(doubleWhiteSpaceString1, nullString1) Then ' Noncompliant
+ If Equals(doubleWhiteSpaceString1, nullString1) Then ' Noncompliant
- End If
+ End If
- If Equals(doubleWhiteSpaceString1, fullStringa1) Then ' FN
+ If Equals(doubleWhiteSpaceString1, fullStringa1) Then ' FN
- End If
+ End If
- If Equals(doubleWhiteSpaceString1, parameterString) Then
+ If Equals(doubleWhiteSpaceString1, parameterString) Then
- End If
+ End If
- End Sub
- End Class
+ End Sub
+End Class
- Public Class NullOrEmpty
- Public Sub Method1(ByVal s As String)
- Dim s1 As String = Nothing
- Dim s2 = ""
- Dim s3 = "a"
- If String.IsNullOrEmpty(s1) Then ' Noncompliant
- End If
- If String.IsNullOrEmpty(s2) Then ' FN
- End If
+Public Class NullOrEmpty
+ Public Sub Method1(ByVal s As String)
+ Dim s1 As String = Nothing
+ Dim s2 = ""
+ Dim s3 = "a"
+ If String.IsNullOrEmpty(s1) Then ' Noncompliant
+ End If
+ If String.IsNullOrEmpty(s2) Then ' FN
+ End If
- If String.IsNullOrEmpty(s) Then
- End If
+ If String.IsNullOrEmpty(s) Then
+ End If
- If String.IsNullOrEmpty(s3) Then ' FN
- End If
- End Sub
+ If String.IsNullOrEmpty(s3) Then ' FN
+ End If
+ End Sub
- Public Sub Method2(ByVal s As String)
+ Public Sub Method2(ByVal s As String)
- If String.IsNullOrEmpty(s) Then
- End If
+ If String.IsNullOrEmpty(s) Then
+ End If
- s = ""
- If String.IsNullOrEmpty(s) Then ' FN
- End If
+ s = ""
+ If String.IsNullOrEmpty(s) Then ' FN
+ End If
- s = Nothing
- If String.IsNullOrEmpty(s) Then ' Noncompliant
- End If
+ s = Nothing
+ If String.IsNullOrEmpty(s) Then ' Noncompliant
+ End If
- s = "a"
- If String.IsNullOrEmpty(s) Then ' FN
- End If
- End Sub
+ s = "a"
+ If String.IsNullOrEmpty(s) Then ' FN
+ End If
+ End Sub
- Public Sub Method3(ByVal s1 As String)
- If String.IsNullOrEmpty(s1) Then
- s1.ToString()
- Else
- If Equals(s1, Nothing) Then ' Noncompliant
- s1.ToString() ' Secondary
- End If
+ Public Sub Method3(ByVal s1 As String)
+ If String.IsNullOrEmpty(s1) Then
+ s1.ToString()
+ Else
+ If Equals(s1, Nothing) Then ' Noncompliant
+ s1.ToString() ' Secondary
End If
+ End If
- End Sub
+ End Sub
- Public Sub Method4(ByVal s1 As String)
- If Not String.IsNullOrEmpty(s1) Then
- If Equals(s1, Nothing) Then ' Noncompliant
- s1.ToString() ' Secondary
- End If
- Else
- s1.ToString()
+ Public Sub Method4(ByVal s1 As String)
+ If Not String.IsNullOrEmpty(s1) Then
+ If Equals(s1, Nothing) Then ' Noncompliant
+ s1.ToString() ' Secondary
End If
+ Else
+ s1.ToString()
+ End If
- End Sub
+ End Sub
- Public Sub Method5(ByVal s1 As String)
- If Not String.IsNullOrEmpty(s1) Then
- If Equals(s1, Nothing) Then ' Noncompliant
- s1.ToString() ' Secondary
- End If
- Else
- s1.ToString()
+ Public Sub Method5(ByVal s1 As String)
+ If Not String.IsNullOrEmpty(s1) Then
+ If Equals(s1, Nothing) Then ' Noncompliant
+ s1.ToString() ' Secondary
End If
+ Else
+ s1.ToString()
+ End If
- End Sub
+ End Sub
- Public Sub Method6(ByVal s1 As String)
- If String.IsNullOrEmpty(s1) OrElse Equals(s1, "a") Then
- s1.ToString()
- Else
- If Equals(s1, Nothing) Then ' Noncompliant
- s1.ToString() ' Secondary
- End If
+ Public Sub Method6(ByVal s1 As String)
+ If String.IsNullOrEmpty(s1) OrElse Equals(s1, "a") Then
+ s1.ToString()
+ Else
+ If Equals(s1, Nothing) Then ' Noncompliant
+ s1.ToString() ' Secondary
End If
+ End If
- End Sub
+ End Sub
- Public Sub Method7(ByVal s1 As String)
- If String.IsNullOrEmpty(s1) AndAlso Equals(s1, "a") Then ' FN
+ Public Sub Method7(ByVal s1 As String)
+ If String.IsNullOrEmpty(s1) AndAlso Equals(s1, "a") Then ' FN
+ s1.ToString()
+ Else
+ If Equals(s1, Nothing) Then
s1.ToString()
- Else
- If Equals(s1, Nothing) Then
- s1.ToString()
- End If
End If
+ End If
+
+ End Sub
+
+
+ Public Function Method8(ByVal message As String) As String
+ If Equals(message, Nothing) Then
+ Throw New ArgumentNullException($"{NameOf(message)} shouldn't be null!")
+ End If
+
+ If String.IsNullOrEmpty(message) Then
+ Throw New ArgumentNullException($"{NameOf(message)} shouldn't be empty!")
+ End If
+
+ Return String.Empty
+ End Function
+
+ Private Sub BinaryConditional_Useless(ByVal a As String, ByVal b As String, ByVal c As String, ByVal d As String)
+ Dim isNothing As String = Nothing
+ Dim isNotNothing = ""
+ Dim notEmpty = "value"
+ Dim ret As String
+
+ ret = If(b, a)
+ ret = If(b, isNotNothing)
+ ret = If(c, notEmpty)
+ ret = If(d, "N/A")
+
+ 'Left operand: Values notNull and notEmpty are known to be not Nothing
+ ret = If(isNotNothing, a) ' Noncompliant
+ ' Secondary@-1
+ ret = If(isNotNothing, a) ' Noncompliant
+ ' Secondary@-1
+ ret = "Lorem " & If(isNotNothing, a) & " ipsum" ' Noncompliant
+ ' Secondary@-1
+ ret = If(isNotNothing, "N/A") ' Noncompliant
+ ' Secondary@-1
+ ret = If(notEmpty, "N/A") ' Noncompliant
+ ' Secondary@-1
+
+ 'Left operand: isNull is known to be null
+ ret = If(Nothing, a) ' Noncompliant
+ ret = If(isNothing, a) ' Noncompliant
+ ret = "Lorem " & If(isNothing, a) & " ipsum" ' Noncompliant
+
+ 'Right operand: isNull is known to be null, therefore binary conditional expression is not needed
+ ret = If(a, Nothing) ' FN: NOOP
+ ret = If(a, isNothing) ' FN: NOOP
+ ' ~~~~~~~~~
+
+ 'Combo/Fatality
+ ret = If(isNotNothing, isNothing)
+ ' ^^^^^^^^^^^^ Noncompliant {{Change this expression which always evaluates to the same result. Some code paths are unreachable.}}
+ ' ^^^^^^^^^ Secondary@-1
+ ret = If(isNothing, Nothing) ' Noncompliant {{Change this expression which always evaluates to the same result.}}
+ ' ^^^^^^^^^
+ ret = If("Value", a)
+ ' ^^^^^^^ Noncompliant {{Change this expression which always evaluates to the same result. Some code paths are unreachable.}}
+ ' ^ Secondary@-1
+ End Sub
+
+ Private Function CoalesceCount(Of T)(ByVal arg As IList(Of T)) As Integer
+ arg = If(arg, New List(Of T)())
+ Return arg.Count
+ End Function
+
+ Public Class CoalesceProperty
+ Private messageField As Object
+
+ Public ReadOnly Property Message As Object
+ Get
+ Return If(messageField Is Nothing, New Object(), messageField)
+ End Get
+ End Property
- End Sub
-
-
- Public Function Method8(ByVal message As String) As String
- If Equals(message, Nothing) Then
- Throw New ArgumentNullException($"{NameOf(message)} shouldn't be null!")
- End If
-
- If String.IsNullOrEmpty(message) Then
- Throw New ArgumentNullException($"{NameOf(message)} shouldn't be empty!")
- End If
-
- Return String.Empty
- End Function
-
- Private Sub BinaryConditional_Useless(ByVal a As String, ByVal b As String, ByVal c As String, ByVal d As String)
- Dim isNothing As String = Nothing
- Dim isNotNothing = ""
- Dim notEmpty = "value"
- Dim ret As String
-
- ret = If(b, a)
- ret = If(b, isNotNothing)
- ret = If(c, notEmpty)
- ret = If(d, "N/A")
-
- 'Left operand: Values notNull and notEmpty are known to be not Nothing
- ret = If(isNotNothing, a) ' Noncompliant
- ' Secondary@-1
- ret = If(isNotNothing, a) ' Noncompliant
- ' Secondary@-1
- ret = "Lorem " & If(isNotNothing, a) & " ipsum" ' Noncompliant
- ' Secondary@-1
- ret = If(isNotNothing, "N/A") ' Noncompliant
- ' Secondary@-1
- ret = If(notEmpty, "N/A") ' Noncompliant
- ' Secondary@-1
-
- 'Left operand: isNull is known to be null
- ret = If(Nothing, a) ' Noncompliant
- ret = If(isNothing, a) ' Noncompliant
- ret = "Lorem " & If(isNothing, a) & " ipsum" ' Noncompliant
-
- 'Right operand: isNull is known to be null, therefore binary conditional expression is not needed
- ret = If(a, Nothing) ' FN: NOOP
- ret = If(a, isNothing) ' FN: NOOP
- ' ~~~~~~
-
- 'Combo/Fatality
- ret = If(isNotNothing, isNothing)
- ' ^^^^^^^ Noncompliant {{Change this expression which always evaluates to the same result. Some code paths are unreachable.}}
- ' ^^^^^^ Secondary@-1
- ret = If(isNothing, Nothing) ' Noncompliant {{Change this expression which always evaluates to the same result.}}
- ' ^^^^^^
- ret = If("Value", a)
- ' ^^^^^^^ Noncompliant {{Change this expression which always evaluates to the same result. Some code paths are unreachable.}}
- ' ^ Secondary@-1
- End Sub
-
- Private Function CoalesceCount(Of T)(ByVal arg As IList(Of T)) As Integer
- arg = If(arg, New List(Of T)())
- Return arg.Count
- End Function
-
- Public Class CoalesceProperty
- Private messageField As Object
-
- Public ReadOnly Property Message As Object
- Get
- Return If(messageField Is Nothing, New Object(), messageField)
- End Get
- End Property
-
- End Class
End Class
+End Class
- Public Class NullOrWhiteSpace
- Public Sub Method1(ByVal s As String)
- Dim s1 As String = Nothing
- Dim s2 = ""
- Dim s3 = If(s, "")
- Dim s4 = " "
+Public Class NullOrWhiteSpace
+ Public Sub Method1(ByVal s As String)
+ Dim s1 As String = Nothing
+ Dim s2 = ""
+ Dim s3 = If(s, "")
+ Dim s4 = " "
- If String.IsNullOrWhiteSpace(s1) Then ' Noncompliant
- End If
+ If String.IsNullOrWhiteSpace(s1) Then ' Noncompliant
+ End If
- If String.IsNullOrWhiteSpace(s2) Then ' FN
- If Equals(s2, "a") Then ' FN
+ If String.IsNullOrWhiteSpace(s2) Then ' FN
+ If Equals(s2, "a") Then ' FN
- End If
End If
+ End If
- If String.IsNullOrWhiteSpace(s3) Then
+ If String.IsNullOrWhiteSpace(s3) Then
- End If
+ End If
- If String.IsNullOrWhiteSpace(s4) Then ' FN
+ If String.IsNullOrWhiteSpace(s4) Then ' FN
- End If
+ End If
- If Not String.IsNullOrWhiteSpace(s4) Then ' FN
+ If Not String.IsNullOrWhiteSpace(s4) Then ' FN
- End If
+ End If
- If Not String.IsNullOrWhiteSpace(s) Then
- If Equals(s, "") Then ' FN
+ If Not String.IsNullOrWhiteSpace(s) Then
+ If Equals(s, "") Then ' FN
- End If
+ End If
- If Equals(s, " ") Then ' FN
+ If Equals(s, " ") Then ' FN
- End If
End If
+ End If
- End Sub
- End Class
-
-End Namespace
+ End Sub
+End Class
From b6cb8aff9ec3ef81a0654eab93034eae64bcf23d Mon Sep 17 00:00:00 2001
From: mary-georgiou-sonarsource
Date: Fri, 11 Aug 2023 07:41:01 +0200
Subject: [PATCH 19/20] update rspecs
---
analyzers/rspec/vbnet/S2583.html | 64 +++++++++++++++-------
analyzers/rspec/vbnet/S2589.html | 91 ++++++++++++++++++++++----------
analyzers/rspec/vbnet/S2589.json | 2 +-
3 files changed, 111 insertions(+), 46 deletions(-)
diff --git a/analyzers/rspec/vbnet/S2583.html b/analyzers/rspec/vbnet/S2583.html
index e3ac10fbce1..a389dc4186d 100644
--- a/analyzers/rspec/vbnet/S2583.html
+++ b/analyzers/rspec/vbnet/S2583.html
@@ -3,22 +3,21 @@ Why is this an issue?
href="https://en.wikipedia.org/wiki/Unreachable_code">unreachable code.
In the case below, the call of Dispose()
never happens.
-var a = false;
-if (a)
-{
- Dispose(); // Never reached
-}
+Dim a = False
+
+If a Then
+ Dispose() ' Never reached
+End If
Exceptions
This rule will not raise an issue in either of these cases:
@@ -32,11 +31,39 @@ How to fix it
Code examples
Noncompliant code example
-' TODO
+Public Sub Sample(ByVal b As Boolean)
+ Dim a = False
+ If a Then ' Noncompliant: The true branch is never reached
+ DoSomething() ' Never reached
+ End If
+
+ If Not a OrElse b Then ' Noncompliant: "not a" is always "True" and the false branch is never reached
+ DoSomething()
+ Else
+ DoSomethingElse() ' Never reached
+ End If
+
+ Dim c = "xxx"
+ Dim res = If(c, "value") ' Noncompliant: d is always not Nothing, "value" is never used
+End Sub
Compliant solution
-' TODO
+Public Sub Sample(ByVal b As Boolean)
+ Dim a = False
+ If Foo(a) Then ' Condition was updated
+ DoSomething()
+ End If
+
+ If b Then ' Parts of the condition were removed.
+ DoSomething()
+ Else
+ DoSomethingElse()
+ End If
+
+ Dim c = "xxx"
+ Dim res = c ' "value" was removed
+End Sub
Resources
@@ -47,10 +74,11 @@ Resources
Documentation
diff --git a/analyzers/rspec/vbnet/S2589.html b/analyzers/rspec/vbnet/S2589.html
index 20919778e85..080013796d8 100644
--- a/analyzers/rspec/vbnet/S2589.html
+++ b/analyzers/rspec/vbnet/S2589.html
@@ -2,30 +2,33 @@ Why is this an issue?
An operand of a boolean expression that never changes the result of the expression might not match the programmer’s intent and can lead to
unexpected behavior and potential bugs.
-var a = true;
-if (a)
-{
- DoSomething();
-}
+Dim a = True
+
+If a Then
+ DoSomething()
+End If
-This also applies to the null
-coalescing operator when one of the operands always evaluates to null
.
+This also applies to the null conditional operator
+when one of the operands always evaluates to Nothing
.
-string d = null;
-var v1 = d ?? "value";
+ Dim d As String = Nothing
+ Dim v1 = If(d, "value")
Exceptions
This rule will not raise an issue in either of these cases:
+
+Const debug = False
+'...
+If debug Then
+ ' Print something
+End If
+
+
+ - When the condition is the literal
True
or False
.
In these cases, it is obvious the code is as intended.
How to fix it
@@ -37,23 +40,57 @@ How to fix it
Code examples
Noncompliant code example
-' To be updated
+Public Sub Sample(ByVal b As Boolean, ByVal c As Boolean)
+ Dim a = True
+ If a Then ' Noncompliant: "a" is always "true"
+ DoSomething()
+ End If
+
+ If b AndAlso a Then ' Noncompliant: "a" is always "true"
+ DoSomething()
+ End If
+
+ If c OrElse Not a Then ' Noncompliant: "Not a" is always "false"
+ DoSomething()
+ End If
+
+ Dim d As String = Nothing
+ Dim v1 = If(d, "value") ' Noncompliant: "d" is always Nothing and v1 is always "value".
+ Dim v2 = If(s, d) ' Noncompliant: "d" is always Nothing and v2 is always equal to s.
+End Sub
Compliant solution
-' To be updated
-----
+Public Sub Sample(ByVal b As Boolean, ByVal c As Boolean, ByVal s As String)
+ Dim a = IsAllowed()
+ If a Then ' Compliant
+ DoSomething()
+ End If
+
+ If b AndAlso a Then ' Compliant
+ DoSomething()
+ End If
+
+ If c OrElse Not a Then ' Compliant
+ DoSomething()
+ End If
+
+ Dim d As String = GetStringData()
+ Dim v1 = If(d, "value") ' Compliant
+ Dim v2 = If(s, d) ' Compliant
+End Sub
Resources
Documentation
diff --git a/analyzers/rspec/vbnet/S2589.json b/analyzers/rspec/vbnet/S2589.json
index 3b655f4974f..2ef13c9d15b 100644
--- a/analyzers/rspec/vbnet/S2589.json
+++ b/analyzers/rspec/vbnet/S2589.json
@@ -28,5 +28,5 @@
570
]
},
- "quickfix": "unknown"
+ "quickfix": "targeted"
}
From 325ac72831a97c7b20034bd7bb14da05771aec7f Mon Sep 17 00:00:00 2001
From: mary-georgiou-sonarsource
Date: Fri, 11 Aug 2023 09:11:08 +0200
Subject: [PATCH 20/20] round 2
---
.../Roslyn/ConditionEvaluatesToConstant.cs | 28 +++++---
.../Roslyn/ConditionEvaluatesToConstant.vb | 64 ++++++++++++++-----
2 files changed, 66 insertions(+), 26 deletions(-)
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
index ffb8f7cbc4f..1c9bafa0438 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.cs
@@ -570,17 +570,8 @@ public void BooleanBinary(bool a, bool b)
a = false;
if (a & b) { } // Noncompliant
- a &= true;
- if (a) { } // FN: engine doesn't learn BoolConstraints from binary operators
-
- a |= true;
- if (a) { } // FN: engine doesn't learn BoolConstraints from binary operators
-
- a ^= true;
- if (a) { } // FN: engine doesn't learn BoolConstraints from binary operators
-
a = a & true;
- if (a) // FN
+ if (a) // Noncompliant
{ }
a = a | true;
@@ -592,6 +583,23 @@ public void BooleanBinary(bool a, bool b)
{ }
}
+ public void BooleanBinary_CompoundAssignments(bool a, bool b)
+ {
+ a = false;
+
+ a &= true;
+ if (a)
+ { } // FN: engine doesn't learn BoolConstraints from binary operators
+
+ a |= true;
+ if (a)
+ { } // FN: engine doesn't learn BoolConstraints from binary operators
+
+ a ^= true;
+ if (a)
+ { } // FN: engine doesn't learn BoolConstraints from binary operators
+ }
+
public void IsAsExpression(object o)
{
if (o is string) { }
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
index 7980a1008f5..91a9373366c 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Roslyn/ConditionEvaluatesToConstant.vb
@@ -256,6 +256,38 @@ Public Class ConditionEvaluatesToConstant
End Select
End Sub
+ Public Sub RelationshipWithConstraint(ByVal a As Boolean, ByVal b As Boolean)
+ If a = b AndAlso a Then
+ If b Then ' FN: requires relation support
+ ' ~
+ End If
+ End If
+
+ If a <> b AndAlso a Then
+ If b Then ' FN: requires relation support
+ End If
+ End If
+
+ If a AndAlso b Then
+ If a = b Then ' Noncompliant
+ End If
+ End If
+
+ If a AndAlso b AndAlso a = b Then
+ ' ^^^^^ Noncompliant
+ End if
+
+ a = True
+ b = False
+ If a AndAlso b Then
+ ' ^ Noncompliant
+ ' ^ Noncompliant@-1
+
+
+ End If
+End Sub
+
+
Public Property Property1 As Boolean
Get
Dim a = New Action(Sub()
@@ -670,7 +702,7 @@ Public Class ConditionEvaluatesToConstant
Public Sub Comparisons(ByVal i As Integer, ByVal j As Integer)
If i < j Then
- If j < i Then ' FN
+ If j < i Then ' FN
End If
If j <= i Then ' FN
End If
@@ -691,7 +723,7 @@ Public Class ConditionEvaluatesToConstant
End Sub
Private Sub DefaultExpression(ByVal o As Object)
- If Nothing Is Nothing Then ' Noncompliant
+ If Nothing Is Nothing Then ' Noncompliant
End If
Dim nullableInt As Integer? = Nothing
@@ -722,12 +754,12 @@ Public Class ConditionEvaluatesToConstant
Public Async Function NotNullAfterAccess(ByVal o As Object, ByVal arr As Integer(,), ByVal coll As IEnumerable(Of Integer), ByVal task As Task) As Task
Console.WriteLine(o.ToString())
- If o Is Nothing Then ' Noncompliant
+ If o Is Nothing Then ' Noncompliant
End If
Console.WriteLine(arr(42, 42))
- If arr Is Nothing Then ' Noncompliant
+ If arr Is Nothing Then ' Noncompliant
End If
@@ -930,37 +962,37 @@ Public Class ConditionEvaluatesToConstant
Dim i As Integer? = Nothing
Dim j As Integer? = 5
- If i < j Then ' Noncompliant
+ If i < j Then ' Noncompliant
End If
- If i <= j Then ' Noncompliant
+ If i <= j Then ' Noncompliant
End If
- If i > j Then ' Noncompliant
+ If i > j Then ' Noncompliant
End If
- If i >= j Then ' Noncompliant
+ If i >= j Then ' Noncompliant
End If
- If i > 0 Then ' Noncompliant
+ If i > 0 Then ' Noncompliant
End If
- If i >= 0 Then ' Noncompliant
+ If i >= 0 Then ' Noncompliant
End If
- If i < 0 Then ' Noncompliant
+ If i < 0 Then ' Noncompliant
End If
- If i <= 0 Then ' Noncompliant
+ If i <= 0 Then ' Noncompliant
End If
- If j > Nothing Then ' Noncompliant
+ If j > Nothing Then ' Noncompliant
End If
If j >= Nothing Then ' Noncompliant
End If
- If j < Nothing Then ' Noncompliant
+ If j < Nothing Then ' Noncompliant
End If
If j <= Nothing Then ' Noncompliant
@@ -988,8 +1020,8 @@ Public Class ConditionEvaluatesToConstant
Friend Structure MyStructWithNoOperator
Public Shared Sub M(ByVal a As MyStructWithNoOperator)
- If a Is Nothing Then ' Noncompliant, also a compiler error
- ' Error@-1 [BC30020]
+ If a Is Nothing Then ' Noncompliant, also a compiler error
+ ' Error@-1 [BC30020]
End If
End Sub
End Structure