Skip to content

Commit

Permalink
Repro for S2077: Ternary in formatted string (#9623)
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastien-marichal committed Aug 12, 2024
1 parent b9e9573 commit 32d4351
Show file tree
Hide file tree
Showing 10 changed files with 367 additions and 146 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,159 +21,168 @@
using CS = SonarAnalyzer.Rules.CSharp;
using VB = SonarAnalyzer.Rules.VisualBasic;

namespace SonarAnalyzer.Test.Rules
namespace SonarAnalyzer.Test.Rules;

[TestClass]
public class ExecutingSqlQueriesTest
{
[TestClass]
public class ExecutingSqlQueriesTest
{
private readonly VerifierBuilder builderCS = new VerifierBuilder().AddAnalyzer(() => new CS.ExecutingSqlQueries(AnalyzerConfiguration.AlwaysEnabled)).WithBasePath("Hotspots");
private readonly VerifierBuilder builderVB = new VerifierBuilder().AddAnalyzer(() => new VB.ExecutingSqlQueries(AnalyzerConfiguration.AlwaysEnabled)).WithBasePath("Hotspots");
private readonly VerifierBuilder builderCS = new VerifierBuilder().AddAnalyzer(() => new CS.ExecutingSqlQueries(AnalyzerConfiguration.AlwaysEnabled)).WithBasePath("Hotspots");
private readonly VerifierBuilder builderVB = new VerifierBuilder().AddAnalyzer(() => new VB.ExecutingSqlQueries(AnalyzerConfiguration.AlwaysEnabled)).WithBasePath("Hotspots");

[TestMethod]
public void ExecutingSqlQueries_CS_Dapper() =>
builderCS
.AddPaths("ExecutingSqlQueries.Dapper.cs")
.AddReferences(MetadataReferenceFacade.SystemData)
.AddReferences(NuGetMetadataReference.Dapper())
.Verify();

[TestMethod]
public void ExecutingSqlQueries_CS_MySqlData() =>
builderCS
.AddPaths("ExecutingSqlQueries.MySqlData.cs")
.AddReferences(MetadataReferenceFacade.SystemData)
.AddReferences(MetadataReferenceFacade.SystemComponentModelPrimitives)
.AddReferences(NuGetMetadataReference.Dapper("2.1.35"))
.AddReferences(NuGetMetadataReference.MySqlData("9.0.0"))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_CS_EF6() =>
builderCS.AddPaths("ExecutingSqlQueries.EF6.cs")
.AddReferences(NuGetMetadataReference.EntityFramework())
.Verify();

[TestMethod]
public void ExecutingSqlQueries_OrmLite_CS() =>
builderCS
.AddPaths(@"ExecutingSqlQueries.OrmLite.cs")
.AddReferences(MetadataReferenceFacade.SystemData)
.AddReferences(NuGetMetadataReference.ServiceStackOrmLite(Constants.NuGetLatestVersion))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_NHibernate_CS() =>
builderCS
.AddPaths("ExecutingSqlQueries.NHibernate.cs")
.AddReferences(NuGetMetadataReference.NHibernate(Constants.NuGetLatestVersion))
.Verify();

#if NETFRAMEWORK // System.Data.OracleClient.dll is not available on .Net Core

[TestMethod]
public void ExecutingSqlQueries_CS_Net46() =>
builderCS
.AddPaths("ExecutingSqlQueries.Net46.cs")
.AddReferences(GetReferencesNet46(Constants.NuGetLatestVersion))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_VB_Net46() =>
builderVB
.AddPaths("ExecutingSqlQueries.Net46.vb")
.WithOptions(ParseOptionsHelper.FromVisualBasic15)
.AddReferences(GetReferencesNet46(Constants.NuGetLatestVersion))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_MonoSqlLite_Net46_CS() =>
builderCS
.AddPaths("ExecutingSqlQueries.Net46.MonoSqlLite.cs")
.AddReferences(FrameworkMetadataReference.SystemData)
.AddReferences(NuGetMetadataReference.MonoDataSqlite())
.Verify();

[TestMethod]
public void ExecutingSqlQueries_MonoSqlLite_Net46_VB() =>
builderVB
.AddPaths("ExecutingSqlQueries.Net46.MonoSqlLite.vb")
.AddReferences(FrameworkMetadataReference.SystemData)
.AddReferences(NuGetMetadataReference.MonoDataSqlite())
.WithOptions(ParseOptionsHelper.FromVisualBasic14)
.Verify();

internal static IEnumerable<MetadataReference> GetReferencesNet46(string sqlServerCeVersion) =>
MetadataReferenceFacade.NetStandard
.Concat(FrameworkMetadataReference.SystemData)
.Concat(FrameworkMetadataReference.SystemDataOracleClient)
.Concat(NuGetMetadataReference.SystemDataSqlServerCe(sqlServerCeVersion))
.Concat(NuGetMetadataReference.MySqlData("8.0.22"))
.Concat(NuGetMetadataReference.MicrosoftDataSqliteCore())
.Concat(NuGetMetadataReference.SystemDataSQLiteCore());
[TestMethod]
public void ExecutingSqlQueries_CS_Net46() =>
builderCS
.AddPaths("ExecutingSqlQueries.Net46.cs")
.AddReferences(GetReferencesNet46(Constants.NuGetLatestVersion))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_VB_Net46() =>
builderVB
.AddPaths("ExecutingSqlQueries.Net46.vb")
.WithOptions(ParseOptionsHelper.FromVisualBasic15)
.AddReferences(GetReferencesNet46(Constants.NuGetLatestVersion))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_MonoSqlLite_Net46_CS() =>
builderCS
.AddPaths("ExecutingSqlQueries.Net46.MonoSqlLite.cs")
.AddReferences(FrameworkMetadataReference.SystemData)
.AddReferences(NuGetMetadataReference.MonoDataSqlite())
.Verify();

[TestMethod]
public void ExecutingSqlQueries_MonoSqlLite_Net46_VB() =>
builderVB
.AddPaths("ExecutingSqlQueries.Net46.MonoSqlLite.vb")
.AddReferences(FrameworkMetadataReference.SystemData)
.AddReferences(NuGetMetadataReference.MonoDataSqlite())
.WithOptions(ParseOptionsHelper.FromVisualBasic14)
.Verify();

internal static IEnumerable<MetadataReference> GetReferencesNet46(string sqlServerCeVersion) =>
MetadataReferenceFacade.NetStandard
.Concat(FrameworkMetadataReference.SystemData)
.Concat(FrameworkMetadataReference.SystemDataOracleClient)
.Concat(NuGetMetadataReference.SystemDataSqlServerCe(sqlServerCeVersion))
.Concat(NuGetMetadataReference.MySqlData("8.0.22"))
.Concat(NuGetMetadataReference.MicrosoftDataSqliteCore())
.Concat(NuGetMetadataReference.SystemDataSQLiteCore());

#else

[TestMethod]
public void ExecutingSqlQueries_CS_EntityFrameworkCore2() =>
builderCS
.AddPaths("ExecutingSqlQueries.EntityFrameworkCore2.cs")
.WithOptions(ParseOptionsHelper.FromCSharp8)
.AddReferences(GetReferencesEntityFrameworkNetCore("2.2.6").Concat(NuGetMetadataReference.SystemComponentModelTypeConverter()))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_CS_EntityFrameworkCore7() =>
builderCS
.AddPaths("ExecutingSqlQueries.EntityFrameworkCoreLatest.cs")
.WithOptions(ParseOptionsHelper.FromCSharp8)
.AddReferences(GetReferencesEntityFrameworkNetCore("7.0.14"))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_CSharp9() =>
builderCS
.AddPaths("ExecutingSqlQueries.CSharp9.cs")
.WithTopLevelStatements()
.AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version).Concat(NuGetMetadataReference.MicrosoftDataSqliteCore()))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_CSharp10() =>
builderCS
.AddPaths("ExecutingSqlQueries.CSharp10.cs")
.WithOptions(ParseOptionsHelper.FromCSharp10)
.WithTopLevelStatements()
.AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version).Concat(NuGetMetadataReference.MicrosoftDataSqliteCore()))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_CSharp11() =>
builderCS
.AddPaths("ExecutingSqlQueries.CSharp11.cs")
.WithOptions(ParseOptionsHelper.FromCSharp11)
.WithTopLevelStatements()
.AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version).Concat(NuGetMetadataReference.MicrosoftDataSqliteCore()))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_CSharp12() =>
builderCS
.AddPaths("ExecutingSqlQueries.CSharp12.cs")
.WithOptions(ParseOptionsHelper.FromCSharp12)
.AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version).Concat(NuGetMetadataReference.MicrosoftDataSqliteCore()))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_VB_EntityFrameworkCore2() =>
builderVB
.AddPaths(@"ExecutingSqlQueries.EntityFrameworkCore2.vb")
.WithOptions(ParseOptionsHelper.FromVisualBasic15)
.AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_VB_EntityFrameworkCore7() =>
builderVB
.AddPaths(@"ExecutingSqlQueries.EntityFrameworkCoreLatest.vb")
.WithOptions(ParseOptionsHelper.FromVisualBasic15)
.AddReferences(GetReferencesEntityFrameworkNetCore("7.0.14"))
.Verify();

internal static IEnumerable<MetadataReference> GetReferencesEntityFrameworkNetCore(string entityFrameworkVersion) =>
Enumerable.Empty<MetadataReference>()
.Concat(NuGetMetadataReference.MicrosoftEntityFrameworkCore(entityFrameworkVersion))
.Concat(NuGetMetadataReference.MicrosoftEntityFrameworkCoreRelational(entityFrameworkVersion));
[TestMethod]
public void ExecutingSqlQueries_CS_EntityFrameworkCore2() =>
builderCS
.AddPaths("ExecutingSqlQueries.EntityFrameworkCore2.cs")
.WithOptions(ParseOptionsHelper.FromCSharp8)
.AddReferences(GetReferencesEntityFrameworkNetCore("2.2.6").Concat(NuGetMetadataReference.SystemComponentModelTypeConverter()))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_CS_EntityFrameworkCore7() =>
builderCS
.AddPaths("ExecutingSqlQueries.EntityFrameworkCoreLatest.cs")
.WithOptions(ParseOptionsHelper.FromCSharp8)
.AddReferences(GetReferencesEntityFrameworkNetCore("7.0.14"))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_CSharp9() =>
builderCS
.AddPaths("ExecutingSqlQueries.CSharp9.cs")
.WithTopLevelStatements()
.AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version).Concat(NuGetMetadataReference.MicrosoftDataSqliteCore()))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_CSharp10() =>
builderCS
.AddPaths("ExecutingSqlQueries.CSharp10.cs")
.WithOptions(ParseOptionsHelper.FromCSharp10)
.WithTopLevelStatements()
.AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version).Concat(NuGetMetadataReference.MicrosoftDataSqliteCore()))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_CSharp11() =>
builderCS
.AddPaths("ExecutingSqlQueries.CSharp11.cs")
.WithOptions(ParseOptionsHelper.FromCSharp11)
.WithTopLevelStatements()
.AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version).Concat(NuGetMetadataReference.MicrosoftDataSqliteCore()))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_CSharp12() =>
builderCS
.AddPaths("ExecutingSqlQueries.CSharp12.cs")
.WithOptions(ParseOptionsHelper.FromCSharp12)
.AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version).Concat(NuGetMetadataReference.MicrosoftDataSqliteCore()))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_VB_EntityFrameworkCore2() =>
builderVB
.AddPaths(@"ExecutingSqlQueries.EntityFrameworkCore2.vb")
.WithOptions(ParseOptionsHelper.FromVisualBasic15)
.AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_VB_EntityFrameworkCore7() =>
builderVB
.AddPaths(@"ExecutingSqlQueries.EntityFrameworkCoreLatest.vb")
.WithOptions(ParseOptionsHelper.FromVisualBasic15)
.AddReferences(GetReferencesEntityFrameworkNetCore("7.0.14"))
.Verify();

internal static IEnumerable<MetadataReference> GetReferencesEntityFrameworkNetCore(string entityFrameworkVersion) =>
Enumerable.Empty<MetadataReference>()
.Concat(NuGetMetadataReference.MicrosoftEntityFrameworkCore(entityFrameworkVersion))
.Concat(NuGetMetadataReference.MicrosoftEntityFrameworkCoreRelational(entityFrameworkVersion));

#endif

[TestMethod]
public void ExecutingSqlQueries_CS_Dapper() =>
builderCS
.AddPaths("ExecutingSqlQueries.Dapper.cs")
.AddReferences(MetadataReferenceFacade.SystemData)
.AddReferences(NuGetMetadataReference.Dapper())
.Verify();

[TestMethod]
public void ExecutingSqlQueries_CS_EF6() =>
builderCS.AddPaths("ExecutingSqlQueries.EF6.cs")
.AddReferences(NuGetMetadataReference.EntityFramework())
.Verify();

[TestMethod]
public void ExecutingSqlQueries_OrmLite_CS() =>
builderCS
.AddPaths(@"ExecutingSqlQueries.OrmLite.cs")
.AddReferences(MetadataReferenceFacade.SystemData)
.AddReferences(NuGetMetadataReference.ServiceStackOrmLite(Constants.NuGetLatestVersion))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_NHibernate_CS() =>
builderCS
.AddPaths("ExecutingSqlQueries.NHibernate.cs")
.AddReferences(NuGetMetadataReference.NHibernate(Constants.NuGetLatestVersion))
.Verify();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -210,4 +210,20 @@ public void CommandDefinition_Constructor(string query, string param)
new CommandDefinition(query + param, new { Id = 1 }); // Noncompliant
}
}

// https://github.com/SonarSource/sonar-dotnet/issues/9602
class Repro_9602
{
public void ConstantQuery(IDbConnection dbConnection, bool onlyEnabled)
{
string query = "SELECT id FROM users";
if(onlyEnabled)
query += " WHERE enabled = 1";
string query2 = $"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"; // Secondary - FP

dbConnection.Query<int>(query); // Compliant
dbConnection.Query<int>(query2); // Noncompliant - FP
dbConnection.Query<int>($"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Noncompliant - FP
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,28 @@ public class Blog
{
public string Url { get; set; }
}

// https://github.com/SonarSource/sonar-dotnet/issues/9602
class Repro_9602
{
public void ConstantQuery(DbContext context, bool onlyEnabled)
{
string query = "SELECT id FROM users";
if(onlyEnabled)
query += " WHERE enabled = 1";
string query2 = $"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"; // Secondary [c1, c2, c3]

context.Database.ExecuteSqlCommand(query); // Compliant
context.Database.ExecuteSqlCommand(query2); // Noncompliant [c1] - FP
context.Database.ExecuteSqlCommand($"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Compliant

context.Database.ExecuteSqlCommandAsync(query); // Compliant
context.Database.ExecuteSqlCommandAsync(query2); // Noncompliant [c2] - FP
context.Database.ExecuteSqlCommandAsync($"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Compliant

context.Query<User>().FromSql(query); // Compliant
context.Query<User>().FromSql(query2); // Noncompliant [c3] - FP
context.Query<User>().FromSql($"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Compliant
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,29 @@ Namespace Tests.Diagnostics

End Class

' https://github.com/SonarSource/sonar-dotnet/issues/9602
Class Repro_9602
Public Sub ConstantQuery(context As DbContext, onlyEnabled As Boolean)
Dim query As String = "SELECT id FROM users"
If onlyEnabled Then
query += " WHERE enabled = 1"
End If
Dim query2 As String = $"SELECT id FROM users {(If(onlyEnabled, "WHERE enabled = 1", ""))}" ' Secondary [c1,c2,c3]

context.Database.ExecuteSqlCommand(query) ' Compliant
context.Database.ExecuteSqlCommand(query2) ' Noncompliant [c1] - FP
context.Database.ExecuteSqlCommand($"SELECT id FROM users {(If(onlyEnabled, "WHERE enabled = 1", ""))}") ' Compliant

context.Database.ExecuteSqlCommandAsync(query) ' Compliant
context.Database.ExecuteSqlCommandAsync(query2) ' Noncompliant [c2] - FP
context.Database.ExecuteSqlCommandAsync($"SELECT id FROM users {(If(onlyEnabled, "WHERE enabled = 1", ""))}") ' Compliant

context.Query(Of User)().FromSql(query) ' Compliant
context.Query(Of User)().FromSql(query2) ' Noncompliant [c3] - FP
context.Query(Of User)().FromSql($"SELECT id FROM users {(If(onlyEnabled, "WHERE enabled = 1", ""))}") ' Compliant
End Sub
End Class

Class User
Private Property Id As String
Private Property Name As String
Expand Down
Loading

0 comments on commit 32d4351

Please sign in to comment.