Using Source Generator, instead of GenAPI to produce NotSupported library#4315
Closed
tetolv wants to merge 5 commits into
Closed
Using Source Generator, instead of GenAPI to produce NotSupported library#4315tetolv wants to merge 5 commits into
tetolv wants to merge 5 commits into
Conversation
Contributor
Author
|
@dotnet-policy-service agree |
Member
|
Hi @tetolv Thanks for the contribution, but we'll be removing the NotSupported libraries in future iterations, as they are no longer needed - so we won't be making more changes to it's build system. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This is an attempt to replace GenAPI-based generation of the NotSupported version of the MDS library with Source Generator based one.
Sorry for breaking the rule of not surprising dev team with big unannounced PRs, but at the beginning I wasn't even expected, that something will come out of it. I just saw a comment
in \src\Microsoft.Data.SqlClient\notsupported\Microsoft.Data.SqlClient.csproj and wondered if source generators would really simplify that matter.
Current solution
Current solution is temporary, as it combines both GenAPI-based and SourceGen-based approaches for NotSupported library generation, so that source produced by both tools could be compared to validate, that they are compatible, and nothing is added, lost, or modified, if we switch from GenAPI to Source Generators.
At the heart of SourceGen-based solution is
tools/GenAPI/Microsoft.Data.SqlClient.SourceGenerator/Microsoft.Data.SqlClient.SourceGenerator.csprojproject which containsRefToNotSupportedGeneratorclass, that performs source code rewriting by substituting bodies of all public, or internal methods, constructors, or properties withPlatformNotSupportedExceptionthrowing. This source generator is referenced only insrc/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.csprojvia:build.projis extended with a new targetBuildSqlClientNotSupportedSG, which builds Not Supported library using Source Generators. It does it as following:BuildSqlClientNotSupportedSGdepends onBuildSqlClientRef, which compiles ref library and also performs source rewriting, addingPlatformNotSupportedExceptionthrowing to all methods/constructors/property accessors.\src\Microsoft.Data.SqlClient\notsupported(see, CompilerGeneratedFilesOutputPath parameter above). This is the same project, which uses GenAPI to build unsupported library. As a result with will contain both sources generated by GenAPI and by Source Generator. To prevent duplicate type errors compiling it, a new propertyNotSupportedSGis introduced, which controls, which sources are taken for build:BuildSqlClientNotSupportedSGbuilds notsupported project passing-p:NotSupportedSG=true, which takes source generated sources for compilation.In addition I have added separated target to the
\tools\targets\CompareMdsRefAssemblies.targets, which builds side-by-side both GenAPI-based and SourceGen-based version of notsupported library and compares them usingdotnet apicompatto verify API compatibility.Current results
If we are looking at the differences between .cs files generated by GenAPI and Source Generator, then there appears to be many, but most of them are purely syntactical and does not represent differences in actual APIs:
partialpartialPlatformNotSupportedExceptionDispose()methoddefaultkeyworddefault(System.Threading.CancellationToken)defaultdefaultkeywordpublic SqlRowUpdatedEventArgs(System.Data.DataRow row, System.Data.IDbCommand command, System.Data.StatementType statementType, System.Data.Common.DataTableMapping tableMapping) : base (default(System.Data.DataRow), default(System.Data.IDbCommand), default(System.Data.StatementType), default(System.Data.Common.DataTableMapping)) { throw ... }, when there were nodefaultin ref sourcedefaultis not usedAttributesuffixAttributesuffixHere I attach both sources produced by GenAPI and Source Generator, so that you could compare them in a diff tool:
GenAPI-produced.zip
SourceGen-produced.zip
When binary comparison is performed using
dotnet apicompat, following result is returned (results for all targets net8.0, net9.0, net462, netstandard2.0 are the same):, which correspond to the following method (difference is highlighted):
In general I think, that Source Generators solution produces compatible result in more straightforward and modern way. Also some of the complexity of the current solution is attributed to coexistence with GenAPI, as all the
#if GENAPI_COMPAT ... #endifblocks in[RefToNotsupportedTypeRewriter](https://github.com/dotnet/SqlClient/compare/main...tetolv:SqlClient:not-supported-lib-sg?expand=1#diff-f3fda4d678f3a1e56e9521baf31cfc37412f3a2fab035d1e63261344d95a91a7), only exists to produce code more similar to what GenAPI produces, to make diff reading a little easier. Eventually those hacks could be removed.Other notes
\tools\targets\CompareMdsRefAssemblies.targets, because it already conveniently had other targets I was needed, although it is meant for different specific purpose.Microsoft.Data.SqlClient.SourceGeneratorproject itself is added to the\tools\GenAPI\directory, although it might not be the best place for it.Will be happy to hear any feedback.