Repository navigation
Public API | Enforce ref/implementation parity using ApiCompat - #4890
Conversation
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
priyankatiwari08
left a comment
There was a problem hiding this comment.
Looks good — no code concerns. CodeQL build currently fails with NU1301 until Microsoft.DotNet.ApiCompat.Task is in the curated feed (as noted in the description).
|
/azp run |
|
Azure Pipelines: Successfully started running 2 pipeline(s). 1 pipeline(s) were filtered out due to trigger conditions. |
cheenamalhotra
left a comment
There was a problem hiding this comment.
Scope: 91395855..3376d0d0 (full PR diff)
What this PR does: Turns on ApiCompat so the implementation assembly is checked against the ref assembly for net462 and net10.0. It also lines up attributes and adds suppressions for type forwards.
Existing feedback
| Source | Item | Status |
|---|---|---|
| @priyankatiwari08 (review) | CodeQL fails with NU1301 until Microsoft.DotNet.ApiCompat.Task is in the curated feed |
Feed blocker, not a code issue |
| Copilot | none | n/a |
New findings
| Priority | Location | Issue |
|---|---|---|
| P2 | Microsoft.Data.SqlClient.csproj:73 |
ApiCompat is skipped when building only one framework (-f net10.0) |
Tests: CI didn't validate this because of the feed blocker. The finding comes from tracing the ApiCompat task targets. I didn't run a local build. The milestone check failure is stale now that 8.0.0-preview1 is set.
cheenamalhotra
left a comment
There was a problem hiding this comment.
@edwardneal there are some build errors that would need your attention. Thanks.
|
Thanks @cheenamalhotra, looks like it's the result of the earlier PR being merged. I've merged main, finished the removal of the type forwarding attributes and confirmed that the build passes locally. |
|
/azp run |
|
Azure Pipelines: Successfully started running 2 pipeline(s). 1 pipeline(s) were filtered out due to trigger conditions. |
|
/azp run |
|
Azure Pipelines: Successfully started running 2 pipeline(s). 1 pipeline(s) were filtered out due to trigger conditions. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4890 +/- ##
==========================================
- Coverage 67.91% 66.62% -1.29%
==========================================
Files 311 305 -6
Lines 45286 68341 +23055
==========================================
+ Hits 30757 45534 +14777
- Misses 14529 22807 +8278
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
/azp run |
|
Azure Pipelines: Successfully started running 2 pipeline(s). 1 pipeline(s) were filtered out due to trigger conditions. |
Description
This PR performs final (non-source-breaking) resync between the ref and the implementation SqlClient assemblies, using ApiCompat between the two assemblies to prevent future drift in most situations.
The curated NuGet feed needs to have the
Microsoft.DotNet.ApiCompat.Taskpackage in it before CI will pass.Build changes
Since we need to have a ref assembly to compare against, I've added a project reference to it from the implementation assembly. This follows the same pattern as the notsupported assembly.
ApiCompat always runs, and runs in its strictest configuration. This forces all types and attributes (besides a few suppressions) to match between the two assemblies, and prevents parameter name changes.
ApiCompat exclusions/suppressions
Most of the attribute exclusions are fairly non-controversial. The attributes generated by Roslyn for async/iterator state machines and for compiler-generated code are ignored, as are the attributes generated to handle nullable reference types.
I've currently chosen to exclude two other groups:
DynamicallyAccessedMembersandTypeForwardedFrom. DynamicallyAccessedMembers is excluded because NativeAOT support isn't fully implemented; this attribute is present on types and parameters which perform UDT handling, and this isn't fully settled on yet. Future NativeAOT work will need to adjust this exclusion.TypeForwardedFrom clashes slightly with #4816. I'd originally excluded the attribute because I saw the ref assemblies as compile-time concerns and the type forwarding as runtime concerns. I'd be just as happy to drop this exclusion and incorporate the type forwarding into the ref assembly.
The mismatched type forwarding also explains the wider set of type suppressions in ApiCompatSuppressions[.netcore].xml.
Changes
Generally speaking, I've aligned the ref assembly with the runtime assembly unless doing so would mean deleting an attribute. There are only a few such situations, but where this has happened I've added it to the implementation assembly. The single exception to both rules is
SqlCommand.ResetCommandTimeout- this attribute has no effect on a Reset method, and the implementation never had it.Reference assembly changes:
ComVisibletoSqlFileStream.CanTimeout,ReadTimeoutandWriteTimeout.StringSyntaxto theSqlJsonconstructor.DesignerCategorytoSqlCommand,SqlCommandBuilder,SqlConnection,SqlDataAdapter.DefaultValueto use the enum name rather than an integer:SqlCommand.CommandType,SqlCommand.UpdatedRowSource.DesignerSerializationVisibilityfromSqlCommand.ResetCommandTimeout- this was not valid on this method. While the ResetX notation can be valid, it doesn't require this attribute.DesignerSerializationVisibilitytoSqlCommand.Parameters,SqlCommand.RetryLogicProvider,SqlConnection.ServerProcessId,SqlConnection.RetryLogicProvider.BrowsabletoSqlCommand.RetryLogicProvider,SqlConnection.ServerProcessId,SqlConnection.RetryLogicProvider. This hides them from a winforms PropertyGrid.DefaultValuefrom conditionally compiled (netfx-only):SqlConnection.ColumnEncryptionKeyCacheTtl,SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled,SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.DefaultValue:SqlParameter.ForceColumnEncryption.TypeConverterand associated non-public converter types:SqlConnectionEncryptOption,SqlConnectionStringBuilder,SqlConnectionStringBuilder.InitialCatalog,SqlConnectionStringBuilder.NetworkLibrary,SqlParameter.Flags:SqlConnectionOverrides.Obsolete:SqlConnectionStringBuilder.ConnectionReset(removed a double-space.)DefaultPropertyto correct name:SqlConnectionStringBuilder.Implementation assembly changes:
DesignerSerializationVisibilityfrom conditionally compiled (netfx-only):SqlException.Errors.DesignerSerializationVisibilitytoSqlParameterCollection.this[].BrowsabletoSqlParameter.OffsetandSqlParameterCollection.this[].DefaultValuetoSqlParameter.IsNullable.EditorBrowsabletoSqlParameter.Offset.Known limitation
This works well for net462 and net10.0, but netstandard2.0 has no implementation assemblies to compare against, and the per-TFM API surface varies. This means that we can't use ApiCompat for that TFM, and can't practically compare between the netstandard2.0 and one of the other builds.
Issues
Contributes to #4826. That'll be ready to close once this is merged and a decision is made on backports.
Testing
Compile-time changes should be validated by CI - the implementation-side changes are limited to attribute metadata.