-
Notifications
You must be signed in to change notification settings - Fork 59
How to debug and troubleshoot my code generator #76
Comments
Notes for above; the generated file is there, the comments are there, but there is no output. But I assure you there is a tree I am building which should be there. Ideally, I should be able to examine the output of the test assembly for the Consequently, I am also chewing on a
Assuming presence of the But basically, somewhere between the given source code, and the compilation result, i.e. Project project;
// Ostensibly, my Generator is invoked during this call:
var diagnostics = project.GetCompilationAsync().Result.GetDiagnostics();
// Do something with the Diagnostics... And/or, ostensibly, additional analytics on the built source tree. Which, I assume would invoke the generator. Short of this approach, would a "simple" |
I'm no expert, but I've had my share of experience with this codebase, allow me to iron out the way this framework/tool works. First, let's go through all of the artifacts this project (
Now, armed with understanding of the CodeGeneration framework structure, we can analyze a typical code generation-involving build process.
To clear up:
I hope this helps somewhat. PS @AArnott having put a bit of effort into writing this down, would you consider using this comment somewhere in wiki or in README, pending additions and modifications you deem necessary? I'm inclined to believe it could help some more people get a clearer picture of how this framework actually works. :) |
In general, I've got an idea how it works, but I wonder if the DotNetCli references could at all be migrated to NuGet style package references? In other words, make the whole code-gen process more seamless. That would certainly help with the dependencies, keeping the whole pipeline flowing. That, or there being first class support for propagating DotNetCli references via NuGet, somehow... |
@mwpowellhtx No, DotNetCliTools are by design non-propagating. They are project-level, development-time only tools, and are useful only during the build of the project in which they are referenced. Other similar tools are EntityFrameworkCore tool, XmlSerializer tool etc. That said, if you're referencing the issue of including the reference to the tool package, then that's a whole other story - for example it could be "done" (more like "hacked" but it'd work) by preparing an MSBuild So if you're planning to distribute your custom generator package, currently it's rather hard. You could hack up a props/targets and include that in your package, but it'll likely cause conflicts if the consumer references more than one code-generating package. That said, this project is not yet quite stable regarding the API and generators based on different |
@amis92 Yes, I understand that. But what I'm suggesting, what I wonder about, is whether the NuGet package reference It would certainly make unit testing a heck of a lot easier, I think. That said concerning Code Gen, per se... Concerning Verifiers efforts, yes, I am breaking up the dependencies a bit to better support at least a compilation-oriented treatment of my generator callbacks. I'd followed a similar approach as you did concerning calling helper For this purpose, I wouldn't need Code Fixes, per se, so to allow some flexibility whether analyzers are required, and so on. In this instance, all I need is the compilation result, diagnostic, etc. Anyway, that's a bit tangential to this, apart from ensuring my integration scaffold is in order. |
Following up here, I am at a point, I have the Short of that, sort of integration tests, I don't know if it is appropriate from a unit test perspective to simply test whatever underlying bits are contributing to the generation of the Assuming that it is, why doesn't it land in the expected generated code documents? |
It seems I can do something like this: var context = new CodeGeneration.Roslyn.TransformationContext(classDecl
, compilation.GetSemanticModel(compilation.SyntaxTrees.First()), compilation, ProjectDirectory);
var members = g.GenerateAsync(context, new DiagnosticProgress(), CancellationToken.None).Result; But this is generating something that clearly is not correct. Does this tell me I must even provide white space elements? The really important bits are there, to be sure; but the white space elements, new lines, etc, are not. Really?
|
Okay, with |
Alright, so at this point, I am fairly confident that everything from the Literally, what is generated is this:
So... Something glue-wise, in between, is not working. |
Ugh, there's also a whole slew of possible combinations for parent syntax declarations that could happen. Such as, namespace MyClasses { } namespace My.Classes { } namespace My { namespace Classes { } } To name a few. Which all has an impact on the syntax that must be digested. I'll have to study that in more depth I think for the actual semantic model, how it breaks down. Resulting syntax elements are something like, Json-ish in pseudo code:
And,
In the last couple of use cases, I might expect "My.Classes" to fall out in the semantic model, however. |
I don't know what's not working for you, but I can assure you that Roslyn.CodeGeneration takes care of inserting results of your Generator into parent syntax correctly. using System;
namespace A
{
namespace B
{
[CustomGenerator]
class ToBeProcessed
{
public string Text { get; }
}
}
} If your generator returns SyntaxList of using System;
namespace A
{
namespace B
{
class Generated { }
}
} That will also cover nested classes - their "parent" classes will be auto-inserted as well. |
I don't know, either; at the moment, I am 99.9% confident the generator itself would provide the correct code, unless, let's say, it wasn't before and was silently failing for some reason. This is plausible considering I had to NormalizeWhitespace after all the important bits had been arranged. At any rate, it's helped me improve a couple of things, and raised my awareness of a couple of potentially nasty corner cases re: namespaces. For the typical, sort of, dot delimited namespace, no worries. But for nested ones, or anything more complicated than that, I shall not worry about it for now. Really, it's just more of a concern verifying not only the compilation under test, but also the generated bits aligning with that compilation. The next steps for me are to investigate the connective tissue in more depth, and there are a half dozen or so that deserve a closer look most likely. |
I'd really like to help you out, but without access to your project I don't think I can. Maybe you could prepare a minimal reproduction on GitHub, or sth. |
@amis92 Well, I'd appreciate it. My project is on Github, for starters. I am in the process of making the transition into Standard/Core. If you are interested you could start there. I am fleshing out my Generator unit tests at the moment. As soon as that is more or less presentable, I will commit that and reconsider the Code Generation integration bits. |
@amis92 I pushed my work thus far into the repo just now. The next bits for me are to review my comprehension of the Code Generation integration. Otherwise, should be ready for you to have a gander at it if you wouldn't mind. |
Afaik the issue was resolved. Closing. |
Just to chime-in (and crosspost from my reply to #186 ) - I'm able to debug and step-through my
|
my code generation attribute inherits from the below
N.B.: that way at build-runtime I can decide to launch the debugger when I need to investigate something - simply by adding the attribute property 'LaunchDebuggerDuringBuild' when required. |
Basically that. Is there some sort of "print line", console output, etc, I could wire into?
I see evidence that the generator is at least trying, literally the
.generated.cs
file is landing in myobj/$(Configuration)
folder. However, what I expect to be generated is not being generated, but I'd at least like to get some feedback as to what is happening.Do you have a Gitter I could post to?
The text was updated successfully, but these errors were encountered: