docopt / docopt.net

Port of docopt to .net
https://docopt.github.io/docopt.net/
Other
350 stars 33 forks source link

Replace embedding in source generator with library reference #154

Closed atifaziz closed 2 years ago

atifaziz commented 2 years ago

This PR moves away from having the source generator embed DocoptNet sources into the user's project to instead using a reference to the DocoptNet library.

While embedding source files was originally an attractive option that allowed the source generator to operate independent of the core library and without incurring additional dependencies, it does create a big limitation going forward: the embedded sources will be subject to the limitation of the user's project and choices of C# language features. For example, if the user's project is bound to C# 9 then it means our sources cannot use any features of C# 10 or later; embedding them in such a case will cause the user's project to fail compilation. By switching to a library reference, only the generated code needs to use C# 9 as the lowest common denominator but the DocoptNet library can remain independent of other restrictions.

Another benefit is that there needs to be only one package that needs distribution, which will contain the core library and the source generator. Both will work in tandem. The user's project, however, will end up taking a dependency on the docopt.net package, which wasn't required when embedding the source code. This may not be a huge issue as the majority of consumers of the package are expected to be console applications.

There are two unfortunate drawbacks/complications as a side-effect of the switch. First, some private implementation details and types need to become public, to be accessible to the generated code (these have all been marked explicitly by moving them under the DocoptNet.Internals namespace). Second, the packaging becomes complicated due to a chicken-or-egg problem: DocoptNet.CodeGeneration project needs to depend on DocoptNet project, but the packaging of DocoptNet needs to include the outputs from DocoptNet.CodeGeneration. To break the cycle, the packaging isn't as simple as running dotnet pack anymore. This PR therefore adds the pack.ps1 script, which essentially merges the files from DocoptNet.CodeGeneration.*.nupkg into docopt.net.*.nupkg. Only docopt.net.*.nupkg is published then.

The PR also adds separate integration tests to exercise the use of the source generator via the NuGet package (using a local feed and cache). It ensures that the C# compiler can detect the source generator in the package, load it with its dependencies and use the final output as expected.


PS The packaging could be simplified again by merging the DocoptNet.CodeGeneration project into DocoptNet so there is one library, project and package.