Closed mwpowellhtx closed 5 years ago
I'd be interested to know why you want your own build time package.
I think your question is how to reference my buildtime package from yours, such that you don't yourself consume it, but your downstream folks do. Is that it? If so, try this in your csproj:
<PackageReference Include="CodeGeneration.Roslyn.BuildTime" PrivateAssets="none" ExcludeAssets="build" />
That should prevent you from consuming the build authoring that is breaking your build, while (hopefully) still propagating that build authoring to your own consumers.
@AArnott Because I have a set of attributes, analyzers, etc, that I want to bundle in similar fashion... That depends on CodeGeneration.Roslyn.BuildTime
, but which itself does not use it.
@AArnott What is the purpose of the using
and extern
alias bits added in TransformationContext
?
I furnished empty ranges for them and my unit tests seemed to work, though.
Those are for those generators that need to add using
or extern
directives at the top of the generated C# file. Most generators probably don't need to do this, so empty lists are fine.
Of course; if there's something conventional, that's probably a-ok. In my case, I think I am putting those in myself as a matter of course. But it's good to know.
Question is, how do you specify them by convention? I'm not sure my generator ever sees the TransformationContext
, at least not directly, correct?
Sure it does. When your generator is invoked, the TransformationContext
is passed in:
No, my generator implements GenerateAsync
. In turn is passed the context
. I do not actually do the contextualization. In the unit test I do, of course; but not in the production code.
I don't understand. I was answering your question:
I'm not sure my generator ever sees the TransformationContext, at least not directly, correct?
I was showing you how in fact your generator does see the TransformationContext, by virtue of being handed it when the method I quoted is invoked, which you implement.
Actually, these properties from TransformationContext include usings and externs already added to the generated document (by previously invoked generators). I believe the comments are pretty clear:
These are necessary for an example scenario:
Generator A impements ICodeGenerator
but depending on whether the generated code has using System.IO
or not, it'll emit qualified or unqualified references to Path
class. It can check that by accessing the context.CompilationUnitUsings
collection.
Generator B wants to add using System.Linq
at compilation unit level (top-level/document level), as it uses the extension methods from that namespace. So it implements IRichCodeGenerator
and, if the context.CompilationUnitUsings
doesn't contain that using yet, returns result with the using added to RichGenerationResult.Usings
.
Now, if the generator B didn't check the using was already included in generated document, it'd add duplicate using, which is unnecessary and may lead to warnings etc.
@amis92 You don't understand? From the GENERATOR's perspective. TransformationContext
is passed into the generator. I do not actually have any control over that context, but at least at the moment I am implementing ICodeGenerator
only.
My tests are invoking GenerateAsync
, but I don't think I am actually creating any contexts in the actual production code. I just implement the GenerateAsync
method.
@AArnott So the question stands. How do I specify the using
bits, aliases
, etc, for the context? The key is implementing IRichCodeGenerator
instead of or in addition to ICodeGenerator
?
@amis92 Even the so-called "rich" interface does not create any contexts. Nor does it furnish any using bits.
Task<RichGenerationResult> GenerateRichAsync(TransformationContext context, IProgress<Diagnostic> progress, CancellationToken cancellationToken);
You don't create the context, except for unit tests, as intended.
Thus, you don't specify (assign the values) of context's properties, including CompilationUnit -Usings and -Externs.
They are the context in which your generator is invoked. You cannot change it.
If your question is how to add compilation unit usings/externs to the generated document, you need to implement the IRichCodeGenerator
and pass them in the return value. RichGenerationResult
has the following assignable properties:
As an implementation detail, if you're implementing IRichCodeGenerator
, the ICodeGenerator.GenerateAsync
method isn't invoked. It can throw.
:bulb: I see it, thanks for pointing that out. Bit of a rabbit hole to be honest.
@amis92 I was following the RecordGenerator
model concerning BuildTime
. So far the only way I can see is to define my nuspec
. I'm not sure there is a way for me to neatly stitch together the dependencies via the new csproj
furnished method, at least not without incurring actual build-time Code Generation, which is what I don't want. My build-time assembly just needs to be a "do nothing" placeholder for the NuGet build-time packaging, I think.
Thoughts? Is there a way to circumvent and/or overcome the issue?
Honestly, I think that this issue derailed into the issue/discussion about Rich Generation usage. It's hard to stitch together that with the original issue. Maybe rename that one to what it actually was about and open a new one that compiles all the things concerning the package you want to create? It's hard for me to connect the dots right now, since the context spans across several posts at the beginning and the one here.
@amis92 Thoughts? Seems as though the nuspec
approach is the best possible approach, but I was curious if it could be done with more up to date csproj
package generation.
Well, if you're generating a package without any dlls contained, just bundling/aggregating other references, I'd advise using nuspec
, since it's more "appropriate" (it's not a C# project). If you insist on using csproj
(and I can see why, I like it better as well and there's versioning tooling support), @AArnott's first comment should work?
If you want not to package any dlls (e.g. because they don't actually contain anything), I'm pretty sure there's an MSBuild switch to exclude packaging artifacts. In fact, what you're trying to achieve is already done for BuildTime package here:
Closing in favour of #113
Hello, I'd like to generate my own Build Time package, and I think it must include a reference to
CodeGeneration.Roslyn.BuildTime
, right? I'd like to do so using the newCSPROJ
furnished NuGet properties. Basically the project is a do-nothing, placeholder project that does nothing more than make the necessary references.Previously, I was doing this using a
nuspec
file, but I would like to incorporate myBumpAssemblyVersions
in the process.What I am finding is that when I make the reference,
BuildTime
is trying to actually generate some code. Is there a way I can configure it not to do this, because at the moment things are failing. In other words, there is no source, there is nothing to generate. I just need the package reference so that it gets picked up by NuGet when packaging occurs.Thanks!