dotnet / MobileBlazorBindings

Experimental Mobile Blazor Bindings - Build native and hybrid mobile apps with Blazor
MIT License
1.2k stars 171 forks source link

ComponentWrapperGenerator improvements #309

Open Dreamescaper opened 3 years ago

Dreamescaper commented 3 years ago

I decided to write down my thoughts on improving ComponentWrapperGenerator to make it usable for 3rd party projects as well. This issue is somewhat related to #151 , but the approach is probably different.

  1. Remove runtime execution requirement. Currently generator retrieves actual BindableProperty values from element. We should probably avoid that, if possible. I've tried using Generator for Xamarin Community Toolkit controls, and it simply failed with an exception, that Forms.Init should be invoked beforehand (because of Device.GetNamedSize usage).

  2. Convert it to Roslyn source generator. This tool should be able to run on build, there is probably no need to commit generated files. While it is possible to use it as is as MSBuild task, Source Generators have better VS support, and it would be much easier to customize parametrized assemblies support. Besides, ability to use Roslyn's Syntax classes would probably make code cleaner.

  3. Parametrize input TypesToGenerate are currently taken from file, but we need to parametrize other things as well (e.g. namespace). It can be a json file (C# analyzer additional file in case of Source Generator), probably something like this:

    {
    "rootNamespace": "Microsoft.MobileBlazorBindings.Elements",
    "typesToGenerate": [
        "Xamarin.Forms.ActivityIndicator",
        "Xamarin.Forms.BaseMenuItem",
        "etc"
    ]
    }
  4. Publish as nuget. Project name should be adjusted though, e.g. Microsoft.MobileBlazorBindings.ComponentGenerator

  5. Generate (most) events. It's not straightforward, as we need to have event named correspondingly to properties in order them to be bindable, and XF names do not always match (e.g. IsChecked - CheckedChanged). But I still think that it's possible to handle most of those changes (e.g. trim 'Is' when looking for matching property).

  6. Generate ChildContent handling. (Based on ContentProperty attribute on element)

Eilon commented 3 years ago

This is... very interesting! I haven't played with source generators but they certainly open up some incredible solutions.

Here are my thoughts on this:

  1. So long as it isn't too complicated then I think this would be very cool. It's not like the current component generator is simple per se, but it's written as somewhat "naive" code that is fairly easy to walk through and debug. Certainly some of that naivety could be sacrificed for a superior solution.
  2. Having the files checked in does provide some value because it helps see what has changed either on purpose or by accident. There are certainly other ways to achieve this, but it's a nice "feature" of the current implementation.
  3. If using a source generator is a ton of work then of course it might not be worthwhile. But that's perhaps up to you 😄
Dreamescaper commented 3 years ago

Well, point 1 is certainly a blocker for Source generator conversion - it won't be able to get runtime data. But I think it should be changed anyway, since it's unreliable.

Apart from that - I think it would be more or less direct conversion. Working with Roslyn's ISymbols is not that different than with Reflection's *Info classes.

I would at least split it to multiple files though (maybe simply partial classes). It's not really easy to navigate that file now :)

I'm not sure whether it's possible to commit generated files though... Will check it out.

UPDATE: No, I don't think it's possible to commit files created with Source Generators. However we can simply create a small exe project which will get generated sources and stores them as physical files, if we want to to have them checked in this project (I agree that it will make some things easier, e.g. PR review process).