 Visual Studio already has analyzers, which will allow you to diagnose your code at compile time. But what about source generators, which is a brand new tool which will allow you to both diagnose and add additional code to your original source. So learn more about that on this episode of Visual Studio Toolbox. Hi, everybody. Welcome to Visual Studio Toolbox. I'm your host, Leslie Richardson, and today I'm joined by Chris Shankovich, who is a senior dev on the Rosalind team. And I'm also joined by Philip Carter, who is a senior PM on the Rosalind team. Welcome, guys. Thanks. Thanks for having us. Great. Happy to have you here. So today we're going to be talking about source generators in C-Sharp. So that's really exciting. It's a brand new feature, right? Yeah. So source generators is a new feature that we're currently previewing and hoping to ship in an upcoming release of C-Sharp. And it's a feature that we've talked a little bit about for a long time, and it's been something that people have wanted for a long time. And so we're really happy to be actually finally getting something out to customers and shipping something. We think people are really happy. That's great. So can you give a brief overview as to what source generators are? Yeah, sure. So essentially source generators is, as a feature, lets you run code inside the compiler that can look at user's code and then output new code based on those decisions. So it actually plugs directly into the compiler pipeline and then lets you basically augment the user code that exists with new code based on decisions. And it's not, like, as a feature, it's something that's existed for quite a while in the .NET space, but there's never been a really integrated sort of supported way of doing it. And it means that if you want to build these things yourself, there's a lot of work that you'd have to do up front in terms of the tooling. So you'd actually have to build the tool and then sort of integrate into your build pipeline or run it manually. And then if you wanted to distribute these things, there was no standard way of doing that. So you'd actually have to go to users, ask them to install the tool, ask them to augment their pipeline. And because it was this non-supported thing, it meant that it didn't necessarily work in your CI scenarios or it didn't necessarily work in the IDE. And so really by bringing it inside the compiler, we're aiming to solve that problem of making it really, really easy to use and consume. And so they'll be distributed by NuGet packages. So it really is as simple as just adding a NuGet reference and now all that goodness that you could do is now like available to you out of the box, essentially. That sounds great. And it actually kind of sounds similar to a typical analyzer like a Rosalind analyzer. So what are some of the ways that source generators differ from analyzers? Yeah, so it's very much using the same mechanisms as analyzers. It's just that rather than just saying, highlighting certain pieces of source code or looking and adding diagnostics, it can actually add a new source code in. So you can essentially do things like, and we'll show you some examples of this, but like generating boilerplate code or reading external files and adding new code in. So for scenarios around things like GRPC where you've got these like proto-buff files that you wanna turn into C sharp code, those are the kind of scenarios that generators really enable. So with analyzers and stuff, you're typically inspecting at like compile time, style-based things or other related structures that you're configuring as these are depending on whatever it is that you want to diagnose, right? Yeah. And then with source generators, you're adding files in based off of that inspection. Yeah, so you can actually using the full power of Rosalind. You can actually look at the code and you can understand the code as well as the compiler does, right? So it's not just a simple like, oh, is this string something? You really have semantic understanding of the code. You can say, oh, is this type used by something else? Does this property exist on this type? And so you get that real full power and then from there, you can actually go and generate new experiences on top of that. And that might be consuming the user's type or it might be like, you could imagine a serializer that actually builds all the serialization code at compile time. And so a lot of what generators allows is taking things that experiences that today are done at runtime because they require this introspection of code, right? You have to look at the user's type and know what fields are on it so that you can generate the serialization code. And today you have to do that at runtime and there's no real need to do it at runtime other than that's the only tools that users have had available. And of course, the disadvantage of that is that it makes runtime slower. You have startup costs or those kinds of problems. And so source generators are really moving that to the compile phase so that you can do it once up front and get it all out of the way. So then the startup can be faster and you don't have to rely on those runtime constructs. That is fantastic because I always complain whenever I'm making like a .NET core app about how slow it can be just to start up at times, especially since I do a lot of presentations so it's just like waiting around. So it sounds like source generators can be really useful when improving the performance and the time it takes to start. Yeah, I mean, it's definitely one of the scenarios that we're targeting with the feature. And I think what's interesting is that source generators really has kind of two customers when you think about it because there's the kind of the one that we've been working with now, which is the authors which is actually building them and writing code and writing generators but actually the most common customer of a source generator is gonna be the consumer. And that's part of what we're really trying to do with this feature is make it great for consumers. So like today, we see that not that many people are analyzers, whereas lots and lots of people use them. We really want that to be the case with generators too. And so we're expecting that most of our customers will actually interact through generators that other people have written. But they'll just essentially just by pulling in a package it realizes faster or make their authoring experience simpler. So there's a lot of magic going on behind the hood but actually the ultimate thing is that as a writer you just have to write less code or your code gets faster, right? So that is kind of one of our really big aims for this it's to make it kind of seamless for those consumers of source generators as well. That sounds really great. Oh, sorry, sorry. One thing that I was also gonna mention is there are various, I guess you could call them first party customers at Microsoft to author components that people use, right? For example, ASP.NET Core, Azure Functions and they sort of fit, they have like pieces of what they're doing that fits squarely and where source generators are sort of aiming for us. Like there's an element, for example, an ASP.NET startup where they need to introspect to sort of to build up like a routing table. Like you write in your code, like these are my controllers, this has a get, this is a put, things like that. And that's all with like little attributes and there's pieces of that that could potentially be moved into compile time that folks who are working on that are kind of interested in sort of exploring with source generators to be able to say, oh, well, what if instead of, the first time an app starts up it builds up the routing table. The routing table is built up at publish time when you publish your application. So that's just shaved off of startup costs. And so there's still gonna be other startup time things that are gonna happen that source generators aren't solving, but this is, it's one of those things where like there's a lot of different things for in this area of performance and source generators can sort of act as a solution for one of those things. And so another thing we're interested in is, sort of once this is in a pretty good shape for folks internally to sort of incorporate is sort of seeing like, hey, like how much better could you make some of these really high use components that a lot of users sort of rely on? And like, how could we use that to sort of influence, like additional things that we want to do as source generators in the future? That is fantastic. And especially for teams, I bet that can be super useful. Just somebody can make a source generator and then any of their teammates can use that same generator and get that same consistent diagnostic and experience at compile time. Great. So I'd love to see how this actually works within Visual Studio and just an example of why this could be useful for people. Let me show my screen. Okay, so here I have a, actually have a solution which is gonna show some generators running in real time in Visual Studio and showing some of the things they can do. What we actually have here is a kind of cut down version of a public sample we've published. So if you wanna go see this, you can actually go and grab this today and play with this. It's here in the Roslin SDK repo and it actually has a whole bunch of generators. There's a five or six generators and you can see them running, see how they're implemented and also see them being used in the IDE. So if you wanna play along, you need Visual Studio 16.7, any of the recent previews support this. But what I've got here is just that sample but just taken down to a few examples just so we can look at it today. So the first one we're gonna look at is a sample we call auto notify. So if you've ever written a WPF code or UWP and done an MVDM style of model, then you'll be familiar with a pattern that uses I notify property changed. So it allows the view model to reflect changes back to the UI. But in order to do that, it has quite a lot of boilerplate that you have to write. And so it's a really common case that we've seen customers ask, is there a way that we can do this without some boilerplate code? And especially as we've added newer, more terse syntax to C sharp, the I notify property change doesn't let you keep up with that. You still have to define a property. You have to have a backing field and you have to have a property and call that property. And it's just a lot of code you have to write. A lot of background you need to know about. A lot of boilerplate noise. So we have a generator which basically aims to do that for you. So you can write your class and just keep your business logic and then have the generator just go and do that boilerplate for you. So what we'll start is by writing our new view model. And the first thing you're gonna notice is that I've made this a partial class. And so the thing to know about generators is that they can't change any source code that the users written. They can only add new source code into the compilation. And this is a deliberate design decision we've made. And so it means that to actually have a generator interact your code, you explicitly have to opt in by making yourself partial. And this says I'm gonna write some code in this file and the generator is then gonna add a new file to the compilation that has the rest of the code for this class. So let's add some fields and I'll start with them in private. So let's have a field called text and let's have a field called here and we create an instance of our view model where when we dot into it, we'll see that there's nothing very interesting going wrong, right? Because right now this is just a standard C sharp class. It's got two private fields. So there's nothing we can see on it. So what we wanna do is we wanna have the generator actually go in and go and put all that boilerplate in for us that we'd normally have to do to turn this into a view model. So to do that, all we actually have to do here is tag our fields that we want the generator to react to with this attribute called auto notifier. And now when I come down here and I dot onto the view model, you can see suddenly we've now got this property amount, this property text, and we're doing the property changed handler automatically in the class. And so what's actually happening in the background is as I'm typing, Visual Studio is running this auto notifier generator and it's using Roslyn and it's coming to this class and it's seeing these attributes saying auto notify and that says, oh, okay, this is a class that the user wants me to generate code for. And so it goes and generates a copy of the example view model as a partial class and it's in there that it actually puts the properties text and amount and it implements our notified property changed and it puts all the right change handlers in for you. So suddenly all that boiler plate just goes away and happens automatically. That is fantastic. Yeah. A really simple example, but we're like, well, now why have the user write this when we can automate? Right. So when you use the auto notify keyword, do you, can you only apply it to properties or could you apply it to an entire partial class? Yeah, so right now the generator itself, you have to put them on the fields, but there's kind of the really nice thing about generators is that this isn't prescribed by source generators itself. So it's up to the generator to kind of determine the mechanism that it wants to use. So in this case, right now, you have to put it on the field, but there's nothing to stock you're going in and changing that generator to make it go on the class or you could actually, if you wanted to do it just based by convention, rather than having like explicitly tagging them, you can do that too. So it's actually, it's up to the generator to really decide how it wants to handle that kind of opt-in mechanism. That's terrible. And then in this particular one, there's also a few other things we can do. So this generator has the ability to, for instance, customize the generated code. So I can actually say, oh, I want this property name to be called count. And now when we come down here, as you can imagine, we now get a property called count. So even though our field is amount, we're saying to the generator, hey, we've got this field called amount. We'd like to expose it as a property in the view model, but we want you to call it something else. And so we can kind of do those things. And also because we have this, we said we've got that full semantic introspection, it means that actually, even if as a user, I wanted to implement notified property change myself, I can still do that. And the generator now will see, oh, okay, the user has implemented it, so I won. So it still works, everything still compiles because it can actually go and see how much it needs to do. So it's not completely dumb. It doesn't just say, oh, well, I'm gonna just spit out these properties. I can actually check the content of the user's class and add to it as needed. So it means that like, if you wanted to partially upgrade an existing one, you can do that and then remove things and add things as needed. So this is really one of the common use cases we think we're gonna see people building generators for is these kind of wherever there's boilerplate, wherever there's things that is relatively easy to mechanically generate, you can just do it now in a generator. And it means that when you're looking at the code, you can really see what's actually important in the code versus what's just the boilerplate that's needed to make things work. Yeah, that sounds like it would save a lot of people some time. Do we wanna just kind of briefly look at the auto notify generator itself to sort of see how it's implemented? Yeah, sure. So, I mean, I'm not gonna go too much into how the actual generators go because it's, you know, I mentioned those two kind of customers of like the author and the consumer. So that's very much the consumer experience. And then from the authoring experience at the simplest level, what you do is you have to derive from this interface called I source generator. And it's pretty simple and it basically has two methods on it. There's an initialize method and execute method. And so during initialization, you can kind of set the generator up. You say, in this case, we have this syntax notifications we're registering. So as the compiler discovers syntax in the syntax trees, it will actually call back into your receiver and you can make decisions. And then we have the execute method. And it's as simple as the execute method has this add to source method. So you say, oh, I'd like to add some source to the compilation and you can just add it in. And here actually you can see, we have up here the auto notify attribute that we were adding into the compilation is actually defined here in the generator. And down here it's actually adding it in. So the user source doesn't have that attribute that it's using to look it up. It's just being added by the generator. And then here because we do a whole bunch of lookups so we can look up the attribute symbol that we've added and then we can find the fields that we want to augment and we go through and we basically build up a list of the fields and then we actually just go out and output the, we have this process class method where actually goes and outputs all that boilerplate that we talked about. So it's, you know, and it's obviously there's some complexity to it, but essentially it looks at the user's code, says, oh, okay, show me everywhere that auto notify attribute is. And then it builds up that model and says, okay, this is the source code I'd like you to add to the compilation. It's cool. So with this is making a source generator similar to how you would make an analyzer. So that you use like the same kind of a conventions. Yeah, so source generator is slightly different. The notion of having like the initialized setup is very similar. But the really big difference between source generators and analyzers is that analyzers have a sort of like a push model. So as things get created in the compilation, they will ping the analyzer and say, oh, this new class was made. Oh, this new method was found. Whereas in source generators, you have to actually pull the information from the compilation yourself. So rather than being alerted as things happen, you just say, oh, things are about to happen. Would you like to go and find information out? And that's mainly a performance reason because with an analyzer, as you have to build the compilation anyway. So as that compilation is being built, it's kind of free to say, oh, here's the symbol, here's the thing. But with source generators, we have to essentially break it into two passes of compilation because we have to compile all the user's code that you're gonna introspect. And then once you've added your source code, we then compile it again. But Roslyn has like a lazy model of compilation. So if you don't ask any questions about a user's code, we won't actually compile it. So we only do the compilation ones. So if we wanted to do that kind of push-based symbol model, then we'd have to do all that compilation upfront to push all those symbols for you, only for the generator to say, ah, actually, I'm not interested in these. And then we have to recompile everything again. So it's kind of, that's the reason why it's just where in the pipeline it runs that means there's a slightly different experience with the author. So the other demo we have is using CSV files. So we looked at that example where we were looking at some user code and making decisions and outputting source code based on that. But the other really common scenario we think source training is gonna be used for is essentially consuming things that are not C-Sharp, right? And so you can say, oh, I've got this file that I would like to have some C-Sharp representation. And we mentioned like JSON serializers, GRPC and proto buff files are an obvious candidate for this. And in this example, we have a CSV file. So we're saying, oh, we have the CSV file with some data and we wanna parse it runtime and understand the print values from it. But rather than having to actually go and write code to understand that, we can just parse the file to a generator and say, okay, build me a parser for this at compile time that I can then use. So we've got the CSV file, it's very simple. We just got a couple of headers. We have the make, the model, the year and the engine of some cars. And what we're gonna do is pass that to our CSV generator. And the way we do that is through the additional files mechanism. So if we go look at the generated demo project here, you'll see we're actually parsing this in through additional files. And so generators when they run in the execute method can look at all the source code, but they can also go and ask for these additional files that are passed in. So in this way, the user can say, hey, this isn't source code, but I want a generator to use it to create some source code essentially. And the way the CSV generator works in this demo is we have a namespace called CSV. And then for each file you pass in, it will generate a class. So you can see here we had our cars.csv file and it's generated to the class called cars. And it has a enumerable called all. So it basically, for each row in that CSV file, there'll be an entry in this I enumerable. So what we can do is we can say, okay, so for each car in this enumerable, let's just write out who made it. So we'll say, you'll notice here, once again, we get this strongly typed model. So because we actually passed it to a generator, we're not just doing this ourselves, it actually reads those headers and makes a class that matches it. So as a user now, I can just say, hey, I want to read this CSV file and automatically we have code that can do that for us. That is so simple in comparison to what you usually have to do. Yeah, right, you don't have to write the parses, you don't have to go. Right. It's not very exciting, but there we go, we get two cars that we put in that CSV file coming out. And again, the really great thing is that because this is all happening in real time, I can actually go to that cars.csv file and I can change it. So I can say, oh, what if, you know, perhaps we wanted to not call this year, but made in year. And then when I go back to my CSV generator and we look at that car, we now see that it's called made in year, right? So, and you'll even notice, I didn't even save the CSV file. So actually the IDE is knows what's that it's changed. It's run the generator and it's gone, oh, okay, the header's changed. So now we're going to call it made in year. So it's like very, very short, tight loop between some external data and the representation that makes it rather than like, oh, you change it, then you have to go fix your parser and then change the places that use it. It all just kind of flows through automatically and magically for you as a user. It's scary in a good way. So like, yeah, usually, I mean, you might have like a car's class and then you have to go edit something. If you wanted to go change one of the fields or whatever, and you don't have to do any of that here. Right. And so, especially for things like, and you know, we said GRPC, but there's like a real candidate that we see as being useful or things like Rezex for resource string files. Like there's a lot of these things that we have where you have some representation that is not in code and you want the code, the access, is that to always stay in sync with the data. And so this is where it really brings that power in and just makes it kind of trivial to do those kind of things. Yeah, what I like about this in particular is like, so you know how you said, oh yeah, you got to like create the car class and then change it. Like that's sort of, that's like really annoying dev work sometimes. It's like, okay, well, I'm not actually solving a problem here. I'm just kind of reacting to change in my environment that I just have to deal with. And this is like, oh, well, you know, sure. Maybe you're going to have some, some like proper domain model that involves cars that like, you know, you don't want generated. You want to actually have that be part of your domain, but like chances are like very oftentimes that that's not like the thing that is coming directly from the CSV. Like, you know, today you have to create all these sort of like ephemeral types to represent, you know, the data format that it's getting translated into and then you manipulate the data a little bit and then you turn it into like what you want in your domain to be. And this kind of sort of gets, gets that, you know, ephemeral type stuff. You can just eliminate your concerns about that for the most part, if you have like a really good generator, which is awesome. Yeah. The other place that it really comes into its own is that, you know, we, these kind of data generator programs have existed for a while, right? There are already today things where you can give it say an XML file and it will build the access class for you. But you've got to have that tool installed and more important, you've got to remember to actually run it if you update the XML, right? So you've always got two sources of truth as to what actually is the, the schema essentially. And so, you know, you can edit the XML and then you check it in and your CI runs and it fails because it couldn't actually understand it. Whereas here you're saying, Oh, no, no, there's a single source of truth and that is say the XML file, but the generator then just says, okay, well, all this other stuff that flows from that just happens automatically. So you don't ever get these places where it's out of sync. And so I think that's one of, that was going back to what we talked about it being, you know, built in and kind of part of the compiler. That's when those experiences really shine because you don't ever have to worry about things like that getting out of sync. Nice. So regarding all of that, I mean, there's so much that's going on. This seems like a very powerful new feature. So what are some of the existing limitations to using source generators? Like I know you already mentioned that you can't modify code, which was more of a design decision, but like what are some of the other things that users should consider when using this tool? Yeah, I mean, we set out with a set of fairly strong principles. And actually it's worth showing there's a, we have some documents and I'll go through these in a sec but the top actually lists these. And so really the two, the big main one is we've mentioned before is that they're additive only. And that's that you cannot change the user source code. You can only add new code in. And that's, there's a couple of reasons why we went with that model. One of them is just about understanding what generators are doing, right? Like you don't necessarily want to have them arbitrarily modifying your code. And so you want to say, oh, if a user has written this code then that's the code that should go. But there's also like an ordering interesting problem there that if you have multiple generators, if you can modify code, then how do multiple generators run together? There could be conflict, right? Yeah, right. And so here a lot of the demos were showing that just an individual thing running, but we absolutely envisage projects having multiple generators running within each other. And so like, as soon as you start allowing things to change then you get into very complicated problems. There are obvious cases where a lot of people say, oh, you know, I can't do this without doing an additive without doing an editable version of the generator. And that's actually one of the things we want to point out with this design is that we haven't come across things you can't do yet. We think that the language is flexible enough and we think that we've given you enough tools that additive will allow you to solve a problem. But we are open, you know, this is a preview and we want to hear from customers. So if there really are compelling scenarios that require generators that edit code, we absolutely want to hear them and we absolutely want to evolve the feature going forward to enable any scenarios we don't have. And that's kind of the other constraint here that if feeds into this additive only is that they run unordered. So generators aren't aware of each other. So you can't say, oh, I'm a generator who relies on some other generator. They absolutely run in isolation and you don't know whether there are others. And again, we've seen a few, there are some versions of this in the wild where people have allowed you to sort of say, oh, this one runs, then this one and this one. And for now, we're limiting the design deliberately to say, no, you can't, you know, if you have to do that, then this isn't the feature for you, essentially. They can't prioritize one over the other. No, exactly. They have to run all at the same time. And they all see, essentially, they all see the same input state that they're generating against. But while I got it up, I should point to this. We have this source generators cookbook. And so two of the generators I showed you there, like we said, oh, we think these are common scenarios that people go on to do, like looking at code and generating or looking at external files and generating code. And so that's why we've made this, we call it the cookbook because essentially it's a list of like recipes that you can follow to build generators. So if you're watching this thinking, oh, you know, I really wanna build a generator that looks at a particular kind of file and then generates some code, but how would I get started? This document actually has ideas of how to do that. So we say, oh, look, if you wanted to do this additional file transformation generator, so I wanna transform a non-C-Shark file into an equivalent C-Shark file, then we have this recipe you can follow that we think is kind of a best practice to build a generator that does that. So we're still a little behind on some of our tooling. So some of this you have to go create manually, but the recipes hopefully get you to that, you can start with a generator that actually does something and then adjust it to your needs, rather than just having to start from a completely scratch empty generator file. So you talked a little bit about how consumers are going to be one of your main basis for source generators. And so I'm sure you're working to create a community that feels comfortable sharing all of their different source generators that they come up with as well as downloading them and using them for their own purposes. So what's that community going to look like? Is it gonna be similar to how analyzers are pretty accessible these days, like in GitHub or other avenues? Yeah, exactly. I mean, so the nice thing is that the primary delivery mechanism is NuGet. So it means that actually in terms of publishing a generator, it's as simple as the same with analyzers as creating a package, putting a generator in there and uploading it to NuGet.org. And then anyone can go and grab those generators. But we also think that there's a lot of opportunity for packaging generators alongside existing libraries. So you could imagine if you were a library which does something like here, like a CSV parser, then as well as including just the actual library for doing the parsing, we expect that maybe those authors will ship a generator alongside it in that package. So as users upgrade to the newest versions, they just get those generators for them by default. And then maybe even it's transparent to the user that where before it was happening at runtime, it now happens at compile time or they opt in and say, oh, I'd like this to be a compile time feature. But by having that standard NuGet mechanism, it means that you can just get them even essentially for free along with the libraries that we think we use them. And Phillip mentioned that a bit around some of our first party customers. And in the same way that we ship certain NuGet packages with templates, we absolutely envisage that there will be templates that have generators baked into them. So you could imagine the WPF version which has that auto notify property generator built in. So, oh, as part of the template so that you don't have to go and, oh, I wanna use this, I have to go and install it. It's just there when you do file a new project. And then you can just tag your properties as the ones that you're interested in. Yeah, that sounds really accessible. And yeah, it's great to have that giant community to utilize this very powerful tool. I didn't realize just how much this could do just at first glance. So it's really exciting. Like, I wanna use one of these. Like, I never wanna serialize JSON again. I think the really important thing that I wanna stress is that we're coming towards a V1 release right now. But we very, very much see it as the start of the journey of source generators. This is not the end point. So for us, V1 is about really making that consumer scenario really nice. So as a user who just wants to use a generator, it works in Visual Studio. It's fast, it's stable, it does what it's supposed to do. But we certainly have a lot of plans for making the authoring experience better. It's certainly not the smoothest experience right now. And we absolutely intend to keep moving forward with that and improving that and adding new capabilities to generators. We have a very long list of ideas we're excited to bring. As always, there's prioritization we have to make around what we're gonna do. And so that's one of the reasons we wanna get this out into the hands of people so that authors can come back and say, oh, I'd really like to be able to do X, but I can't, rather than us trying to guess what people might wanna do. We have some ideas and we think we've hit those scenarios, but as we see users building more things, we wanna get that feedback. So come to us on GitHub, file issues, file ideas as you're building these and we really wanna work with the community to keep advancing generators going forward for the future. Cool. So of the ones that you're allowed to share, what are some of the improvements that you're thinking about adding to source generators? So the biggest one is this idea of partial compilation. And that's, we may or may not make this for V1, but right now the execute happens. We have to do all of that generation, even if you don't sort of have the notion of what's changed. It's always this compiler-centric view of the world, where it's like, oh, here's all that source code, do all the generation and carry on. But when you're in the IDE and you're just typing with your keys, obviously most of the time, a lot of things haven't changed. And so we're really came for, especially for authors to get to this partial generation idea where we're like, oh, the user didn't change this entire CSV file, they just changed one column in it. So what you don't need to do all of that generation upfront, you just need to give me what's changed. And also just plugging more into some of the sort of IDE related scenarios. So like right now, obviously when you do like a go to death on something that's like come from a CSV file, right now it'll just, and the current preview is actually, it just says nothing. It's like, I can't find the symbol. We fully expect it to show you at least the generated code, but a really nice experience would be that you go to death and it takes you to the CSV file and generated it. And so it's just kind of enabling those tools in for the authors to actually say to the IDE, oh, not only is this some source code, but here's where I actually generated it from if you wanna go show that to the user and just kind of making it really seamlessly together. So that's kind of where we think we'll be focusing going forward. Yeah, there's some interesting tooling considerations. Like for example, renaming something, like the rename refactoring doesn't really make sense in the scenario for like generated code. So the sort of questions about like, oh, well, what should happen if somebody tries to do that? But then like go to death, that's like an obvious thing that you would wanna see, right? Like, if you're a consumer and say, I don't wanna say for some reason, like you're working with like an alpha version of a package and it's not quite generating things, the way that you would have expected it to, being able to like go to definition to see what the result was, like maybe if there was a way to figure out like what debugging that generation steps, sort of like, you know, sort of how it arrived at what it generated and sort of figuring out like what a good experience for that is, is definitely a really interesting space from a tooling standpoint that there's a lot of, there's a lot of thought going into that right now because now that a lot of the core mechanisms are sort of in place and you know, there's a pretty good experience right now. There's like, okay, well now there's kind of like this whole set of things that people can do inside of Visual Studio and sort of there's like, okay, are there special things we need to do for some things? Do we enable or disable certain things? We need to go and build new things and I think a lot of that's also gonna be driven by user feedback, you know, as we like, you know, we have our own opinions about like, what's the most important thing to make sure works perfect in the IDE, but you know, that's, that could probably be wildly wrong compared to what some majority of people are gonna say once it's, you know, shipped and stable is like a 1.0, so. Cool, can definitely relate to my opinions differing from the rest of the community, so. Well, that's really exciting. So for people who are interested in trying this out in preview, where can they go and how should they get started? You already mentioned the cookbook obviously, which is a great name by the way. Yeah, so like I said, you need a relatively modern preview version of Visual Studio for the IDE integration and that samples repo in the Roslin SDK is probably the easiest way to do because you can just clone that, you can open the source generators.sln and you'll see those generators and you can start typing and playing around with them in real time. So that's probably the easiest way to go and then if you wanna build them, then yeah, the cookbook gives you a set of recipes of how to build new generators, but also a lot of the samples map fairly closely to things that are in the cookbook too. So you can kind of see more involved samples and how those work. That is fantastic. Well, with that, thank you guys so much for coming on the show. This was really cool tool that I hope a lot of people go and try out. I want to try this out. The next time I am working with JSON especially, which is a lot, so. I'm really excited about this one. So with that, happy coding. Let's get started.