VsixCommunity / ExtensibilityEssentials

A Visual Studio extension pack
Other
59 stars 8 forks source link

Source generators not working in non-SDK style projects #21

Closed SlipperyBrick closed 7 months ago

SlipperyBrick commented 7 months ago

I've used the extensibility essentials 2022 to get started with a template that has a single command so that I can start developing my Visual Studio extension. I've used WPF in my extension and decided to follow MVVM using the community MVVM toolkit and noticed that there is issues where source generators cannot be used properly. For instance, using a property generated by a source generator will give you an error of Property "X" does not exist in the current context.

This seems to be an issue with legacy style projects. I am now looking to get some advise on the best way to convert my legacy project to an SDK-style project and if this is even possible?

My project is available here if anyone is interested and wants some context.

reduckted commented 7 months ago

Using SDK-style projects isn't supported, though it is possible with some limitations such as some designer windows not working.

I've used an SDK-style project here: https://github.com/reduckted/ProjectFilter/blob/master/source/ProjectFilter/ProjectFilter.csproj

Support was supposed to be coming early last year, but was delayed. See this ticket: https://developercommunity.visualstudio.com/t/VSIX-project-with-SDK-style-csproj/1572145

SlipperyBrick commented 7 months ago

Just gave the links you posted a read, I'm new to C#, .NET and Visual Studio extension development. Seems there is still no word on when this feature is coming, although there is official documentation on setting up a project for extension development here but I'm reluctant to start a fresh new project.

I assume this isn't a simple case of just changing a few things in the .csproj to get an SDK-style csproj without breaking everything.

reduckted commented 7 months ago

If you didn't want to change the extension's project file to be SDK-style, another option would be to create a second project that is a class library. That project can be an SDK-style project, and the extension project can reference that project. For example:

SlipperyBrick commented 7 months ago

If you didn't want to change the extension's project file to be SDK-style, another option would be to create a second project that is a class library. That project can be an SDK-style project, and the extension project can reference that project. For example:

  • vwatch is the existing project and is a legacy-style project.
  • vwatch.mvm is the class library that is an SDK-style project.
  • vwatch references vwatch.mvvm.

I'll give this a shot, whilst its not ideal it sounds like a simpler work around. Thanks a ton for your help as well, much appreciated!

SlipperyBrick commented 7 months ago

I have ran into some issues which I'm not sure how to resolve.

I have set up a new project as suggested and had to fiddle with the .NET runtimes and versions as the template I have used from the Extensibility Essentials 2022 targeted .NET Framework 4.8. I've moved my view model and model to the new project and now have it building and running. I'm not sure if there is a user error on my part regarding the MVVM toolkit or whether there is a versioning issue, I had to roll back to 8.0.0 for the MVVM toolkit as .NET Framework 4.8 only supports up to 7.3 for the C# language version (later versions of MVVM toolkit use a higher C# language version and I was getting an error with the source generators for MVVM toolkit when using the latest MVVM toolkit version with .NET Framework 4.8).

My project is available here, the source generators for MVVM toolkit seem to be working (they are generating the expected code for the attributes I am using and I can't see any errors when observing them in the analysers tree view within the solution explorer of Visual Studio). Yet when I run my code and add a new entry to my list in my UI the remove button doesn't change its IsEnabled state based on the value of CanRemove.

My expectations are that CanRemove will update according to the state of IsExecutablesEmpty (which will be notified when the executables collection changes), the data context and bindings are correctly set in my controls as well (I've split out my controls into separate XAML files and aggregate them into my main view ConfigurationWindow.xaml):

ShowConfigurationWindow.cs is the code file which defines the ExecuteAsync method, this method is invoked when the user clicks "VWatch Configuration" from the Tools menu bar at the top of Visual Studio (which is where my extension can be accessed from).

Header.xaml is a control which defines the buttons for adding and removing entries to the ProcessList (this is a list item where the user can add multiple entries that hold a string value that is part of my ExecutableModel). The main view where the controls are used is in the Views folder.

I suspect this is something I am doing wrong, but I'm a bit lost as to what it is. I appreciate this is probably out of the realms of this discussion as well, but any help I would be absolutely grateful for.

SlipperyBrick commented 7 months ago

Closing this issue as I've discovered that changed events for collections are different. Using [ObservableProperty] on a collection will invoke property change event when the collection itself changes and not when calling Add or Remove on the collection.