Skip to content
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
1 change: 1 addition & 0 deletions docs/Rules/MA0042.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public sealed class Sample
The rule does not report a diagnostic for `IDbContextFactory<TContext>.CreateDbContext()`. The `CreateDbContextAsync()` overload was introduced only for specific edge-case scenarios where the factory itself must perform asynchronous initialization, and is not intended as a general-purpose replacement. See [dotnet/efcore#26630](https://github.com/dotnet/efcore/issues/26630) for more details.

The rule does not report a diagnostic for the following SQLite APIs by default:
- `SqliteConnection.Open()`
- `SqliteConnection.CreateCommand()`
- `SqliteCommand.ExecuteNonQuery()`
- `SqliteCommand.ExecuteScalar()`
Expand Down
1 change: 1 addition & 0 deletions docs/Rules/MA0045.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public async Task Sample()
````

This rule shares the same SQLite special-cases as [MA0042](MA0042.md) by default:
- `SqliteConnection.Open()`
- `SqliteConnection.CreateCommand()`
- `SqliteCommand.ExecuteNonQuery()`
- `SqliteCommand.ExecuteScalar()`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,9 @@ private bool HasAsyncEquivalent(IInvocationOperation operation, bool sqliteSpeci
return false;
}

// SqliteConnection.CreateCommand() always returns SqliteCommand.
// SqliteCommand does not override DisposeAsync, so there is no async alternative to require.
// SqliteConnection.Open() and CreateCommand() are synchronous by design in Microsoft.Data.Sqlite.
// SqliteConnection.CreateCommand() always returns SqliteCommand and SqliteCommand does not override
// DisposeAsync, so there is no async alternative to require.
// https://learn.microsoft.com/en-us/dotnet/standard/data/sqlite/async
else if (sqliteSpecialCasesEnabled && IsSqliteSpecialCaseMethod(targetMethod))
{
Expand Down Expand Up @@ -329,6 +330,16 @@ private bool IsSqliteConnectionCreateCommand(IMethodSymbol targetMethod)
targetMethod.ReturnType.IsEqualTo(SqliteCommandSymbol);
}

private bool IsSqliteConnectionOpen(IMethodSymbol targetMethod)
{
if (SqliteConnectionSymbol is null)
return false;

return targetMethod.Name is "Open" &&
targetMethod.ContainingType.IsEqualTo(SqliteConnectionSymbol) &&
targetMethod.Parameters.Length == 0;
}

private bool IsSqliteCommandMethod(IMethodSymbol targetMethod)
{
if (SqliteCommandSymbol is null)
Expand All @@ -340,7 +351,7 @@ private bool IsSqliteCommandMethod(IMethodSymbol targetMethod)

private bool IsSqliteSpecialCaseMethod(IMethodSymbol targetMethod)
{
return IsSqliteConnectionCreateCommand(targetMethod) || IsSqliteCommandMethod(targetMethod);
return IsSqliteConnectionOpen(targetMethod) || IsSqliteConnectionCreateCommand(targetMethod) || IsSqliteCommandMethod(targetMethod);
}

private IMethodSymbol? FindPotentialAsyncEquivalent(IInvocationOperation operation, IMethodSymbol targetMethod, string methodName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2024,6 +2024,28 @@ public async Task A(SqliteConnection connection)
.ValidateAsync();
}

[Fact]
[Trait("Issue", "https://github.com/meziantou/Meziantou.Analyzer/issues/1121")]
public async Task SqliteConnection_Open_NoDiagnostic()
{
await CreateProjectBuilder()
.WithTargetFramework(TargetFramework.Net8_0)
.AddNuGetReference("Microsoft.Data.Sqlite.Core", "8.0.0", "lib/net8.0/")
.WithSourceCode("""
using System.Threading.Tasks;
using Microsoft.Data.Sqlite;

class Test
{
public async Task A(SqliteConnection connection)
{
connection.Open();
}
}
""")
.ValidateAsync();
}

[Fact]
[Trait("Issue", "https://github.com/meziantou/Meziantou.Analyzer/issues/1121")]
public async Task SqliteCommand_ExecuteMethods_NoDiagnostic()
Expand Down Expand Up @@ -2071,6 +2093,29 @@ public async Task A(SqliteConnection connection)
.ValidateAsync();
}

[Fact]
[Trait("Issue", "https://github.com/meziantou/Meziantou.Analyzer/issues/1121")]
public async Task SqliteConnection_Open_OptionDisabled_Diagnostic()
{
await CreateProjectBuilder()
.WithTargetFramework(TargetFramework.Net8_0)
.AddNuGetReference("Microsoft.Data.Sqlite.Core", "8.0.0", "lib/net8.0/")
.AddAnalyzerConfiguration("MA0042.enable_sqlite_special_cases", "false")
.WithSourceCode("""
using System.Threading.Tasks;
using Microsoft.Data.Sqlite;

class Test
{
public async Task A(SqliteConnection connection)
{
[|connection.Open()|];
}
}
""")
.ValidateAsync();
}

[Fact]
[Trait("Issue", "https://github.com/meziantou/Meziantou.Analyzer/issues/1121")]
public async Task SqliteCommand_ExecuteMethods_OptionDisabled_Diagnostic()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,49 @@ private void A(SqliteCommand command)
.ValidateAsync();
}

[Fact]
[Trait("Issue", "https://github.com/meziantou/Meziantou.Analyzer/issues/1121")]
public async Task PrivateNonAsync_SqliteConnection_Open_NoDiagnostic()
{
await CreateProjectBuilder()
.WithTargetFramework(TargetFramework.Net8_0)
.AddNuGetReference("Microsoft.Data.Sqlite.Core", "8.0.0", "lib/net8.0/")
.WithSourceCode("""
using Microsoft.Data.Sqlite;

class Test
{
private void A(SqliteConnection connection)
{
connection.Open();
}
}
""")
.ValidateAsync();
}

[Fact]
[Trait("Issue", "https://github.com/meziantou/Meziantou.Analyzer/issues/1121")]
public async Task PrivateNonAsync_SqliteConnection_Open_OptionDisabled_Diagnostic()
{
await CreateProjectBuilder()
.WithTargetFramework(TargetFramework.Net8_0)
.AddNuGetReference("Microsoft.Data.Sqlite.Core", "8.0.0", "lib/net8.0/")
.AddAnalyzerConfiguration("MA0042.enable_sqlite_special_cases", "false")
.WithSourceCode("""
using Microsoft.Data.Sqlite;

class Test
{
private void A(SqliteConnection connection)
{
[|connection.Open()|];
}
}
""")
.ValidateAsync();
}

[Fact]
[Trait("Issue", "https://github.com/meziantou/Meziantou.Analyzer/issues/1121")]
public async Task PrivateNonAsync_SqliteCommand_ExecuteMethods_OptionDisabled_Diagnostic()
Expand Down
Loading