Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate S2583/S2589: Scaffold the rule for the new SE #7657

Merged
merged 5 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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.CSharp;

public class ConditionEvaluatesToConstant : ConditionEvaluatesToConstantBase
{
public static readonly DiagnosticDescriptor S2589 = DescriptorFactory.Create(DiagnosticIdCodeSmell, MessageFormat);
public static readonly DiagnosticDescriptor S2583 = DescriptorFactory.Create(DiagnosticIdBug, MessageFormat);
protected override DiagnosticDescriptor Rule => null;
public override bool ShouldExecute() => false;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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;

public abstract class ConditionEvaluatesToConstantBase : SymbolicRuleCheck
{
protected const string DiagnosticIdCodeSmell = "S2589"; // Code smell
protected const string DiagnosticIdBug = "S2583"; // Bug

protected const string MessageFormat = "{0}";
protected const string MessageFormatBool = "Change this condition so that it does not always evaluate to '{0}'.";
protected const string MessageNull = "Change this expression which always evaluates to 'null'.";
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,62 +21,125 @@
using SonarAnalyzer.Rules.CSharp;
using SonarAnalyzer.SymbolicExecution.Sonar.Analyzers;

using ChecksCS = SonarAnalyzer.SymbolicExecution.Roslyn.RuleChecks.CSharp;
using CS = SonarAnalyzer.Rules.CSharp;

namespace SonarAnalyzer.UnitTest.Rules
{
[TestClass]
public class ConditionEvaluatesToConstantTest
{
private readonly VerifierBuilder sonar = new VerifierBuilder<SymbolicExecutionRunner>().WithBasePath(@"SymbolicExecution\Sonar")
private readonly VerifierBuilder sonar = new VerifierBuilder()
.AddAnalyzer(() => new CS.SymbolicExecutionRunner(AnalyzerConfiguration.AlwaysEnabledWithSonarCfg))
.WithBasePath(@"SymbolicExecution\Sonar")
.WithOnlyDiagnostics(ConditionEvaluatesToConstant.S2583, ConditionEvaluatesToConstant.S2589);

private readonly VerifierBuilder roslynCS = new VerifierBuilder()
.AddAnalyzer(() => new CS.SymbolicExecutionRunner(AnalyzerConfiguration.AlwaysEnabled))
.WithBasePath(@"SymbolicExecution\Roslyn")
.WithOnlyDiagnostics(ChecksCS.ConditionEvaluatesToConstant.S2589);

[DataTestMethod]
[DataRow(ProjectType.Product)]
[DataRow(ProjectType.Test)]
public void ConditionEvaluatesToConstant_CS(ProjectType projectType) =>
public void ConditionEvaluatesToConstant_Sonar_CS(ProjectType projectType) =>
sonar.AddPaths("ConditionEvaluatesToConstant.cs")
.AddReferences(NuGetMetadataReference.MicrosoftExtensionsPrimitives("3.1.7").Concat(TestHelper.ProjectTypeReference(projectType)))
.Verify();

[Ignore] // Fixme: Remove after implementation
[DataTestMethod]
[DataRow(ProjectType.Product)]
[DataRow(ProjectType.Test)]
public void ConditionEvaluatesToConstant_Roslyn_CS(ProjectType projectType) =>
roslynCS.AddPaths("ConditionEvaluatesToConstant.cs")
.AddReferences(NuGetMetadataReference.MicrosoftExtensionsPrimitives("3.1.7").Concat(TestHelper.ProjectTypeReference(projectType)))
.Verify();

[TestMethod]
public void ConditionEvaluatesToConstant_FromCSharp7() =>
public void ConditionEvaluatesToConstant_Sonar_CSharp7() =>
sonar.AddPaths("ConditionEvaluatesToConstant.CSharp7.cs")
.WithOptions(ParseOptionsHelper.FromCSharp7)
.Verify();

[Ignore] // Fixme: Remove after implementation
[TestMethod]
public void ConditionEvaluatesToConstant_FromCSharp8() =>
public void ConditionEvaluatesToConstant_Roslyn_CSharp7() =>
roslynCS.AddPaths("ConditionEvaluatesToConstant.CSharp7.cs")
.WithOptions(ParseOptionsHelper.FromCSharp7)
.Verify();

[TestMethod]
public void ConditionEvaluatesToConstant_Sonar_CSharp8() =>
sonar.AddPaths("ConditionEvaluatesToConstant.CSharp8.cs")
.AddReferences(MetadataReferenceFacade.NETStandard21)
.WithOptions(ParseOptionsHelper.FromCSharp8)
.Verify();

[Ignore] // FIXME: Remove after implementation
[TestMethod]
public void ConditionEvaluatesToConstant_Roslyn_CSharp8() =>
roslynCS.AddPaths("ConditionEvaluatesToConstant.CSharp8.cs")
.AddReferences(MetadataReferenceFacade.NETStandard21)
.WithOptions(ParseOptionsHelper.FromCSharp8)
.Verify();

#if NET

[TestMethod]
public void ConditionEvaluatesToConstant_FromCSharp9() =>
public void ConditionEvaluatesToConstant_Sonar_CSharp9() =>
sonar.AddPaths("ConditionEvaluatesToConstant.CSharp9.cs")
.WithOptions(ParseOptionsHelper.FromCSharp9)
.Verify();

[Ignore] // FIXME: Remove after implementation
[TestMethod]
public void ConditionEvaluatesToConstant_FromCSharp9_TopLevelStatements() =>
public void ConditionEvaluatesToConstant_Roslyn_CSharp9() =>
roslynCS.AddPaths("ConditionEvaluatesToConstant.CSharp9.cs")
.WithOptions(ParseOptionsHelper.FromCSharp9)
.Verify();

[TestMethod]
public void ConditionEvaluatesToConstant_Sonar_CSharp9_TopLevelStatements() =>
sonar.AddPaths("ConditionEvaluatesToConstant.CSharp9.TopLevelStatements.cs")
.WithTopLevelStatements()
.Verify();

[Ignore] // FIXME: Remove after implementation
[TestMethod]
public void ConditionEvaluatesToConstant_FromCSharp10() =>
public void ConditionEvaluatesToConstant_Roslyn_CSharp9_TopLevelStatements() =>
roslynCS.AddPaths("ConditionEvaluatesToConstant.CSharp9.TopLevelStatements.cs")
.WithTopLevelStatements()
.Verify();

[TestMethod]
public void ConditionEvaluatesToConstant_Sonar_CSharp10() =>
sonar.AddPaths("ConditionEvaluatesToConstant.CSharp10.cs")
.WithOptions(ParseOptionsHelper.FromCSharp10)
.WithConcurrentAnalysis(false)
.Verify();

[Ignore] // FIXME: Remove after implementation
[TestMethod]
public void ConditionEvaluatesToConstant_FromCSharp11() =>
public void ConditionEvaluatesToConstant_Roslyn_CSharp10() =>
roslynCS.AddPaths("ConditionEvaluatesToConstant.CSharp10.cs")
.WithOptions(ParseOptionsHelper.FromCSharp10)
.WithConcurrentAnalysis(false)
.Verify();

[TestMethod]
public void ConditionEvaluatesToConstant_Sonar_CSharp11() =>
sonar.AddPaths("ConditionEvaluatesToConstant.CSharp11.cs")
.WithOptions(ParseOptionsHelper.FromCSharp11)
.Verify();

[Ignore] // FIXME: Remove after implementation
[TestMethod]
public void ConditionEvaluatesToConstant_Roslyn_CSharp11() =>
roslynCS.AddPaths("ConditionEvaluatesToConstant.CSharp11.cs")
.WithOptions(ParseOptionsHelper.FromCSharp11)
.Verify();

#endif

}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SonarAnalyzer.UnitTest.TestCases;

struct MyStruct
{
public bool x;
public bool y = false;

public MyStruct()
{
x = false;
}
}

class AClass
{
public static void DoSomething()
{
MyStruct myStruct = new();
if (myStruct.x) { } // FN
else if (myStruct.y) { } // FN
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
namespace SonarAnalyzer.UnitTest.TestCases
{
class AClass
{
void DoSomething() { }

void ListPattern()
{
int[] a = new int[] { 1, 2, 3 };
if (a is [1, 2, 3]) // FN
{
DoSomething();
}
}

void ListPattern2()
{
int[] a = new int[] { 1, 2, 3 };
if (a is [1, _, 3]) // FN
{
DoSomething();
}
}

void ListPattern3()
{
int[] a = new int[] { 1, 2, 3 };
if (a is [1, .., 3]) // FN
{
DoSomething();
}
}

void ListPattern4()
{
int[] a = new int[] { 1, 2, 3 };
if (a is [> 0, < 3, < 42]) // FN
{
DoSomething();
}
}
}
}
Loading