AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
25.78k stars 2.23k forks source link

Source Generator to emit metadata of currently existing avalonia properties in the code #11301

Open maxkatz6 opened 1 year ago

maxkatz6 commented 1 year ago

Is your feature request related to a problem? Please describe.

Current problem is that all of the metadata used in the Avalonia property creation (Register<Type>(Name, DefaultValue...) - specifically name, default value and more) are not available in the ref assemblies. Why we need this info in ref assemblies? To use it in the Avalonia property analyzers. You can find long list of analyzers that were recently implemented, but were disabled by default as they won't work properly with ref assemblies: https://github.com/AvaloniaUI/Avalonia/blob/master/src/tools/Avalonia.Analyzers/AvaloniaPropertyAnalyzer.cs#L25

Describe the solution you'd like

Generate assembly (type?) attributes for each Avalonia property (including AddOwner properties) with following information:

  1. Property kind - attached/styled/direct
  2. Owner type
  3. Host type
  4. Property type
  5. Property name
  6. Original host type (in case of AddOwner, is it needed?)
  7. If property inherits
  8. ...Anything more?

Describe alternatives you've considered

Generate some embedded resource? Doesn't sound good, but I also don't see any alternatives.

Additional context

We might want to reuse the same attribute in the future to generate Avalonia partial properties, when it gets implemented in C#. In which case this attribute should fully cover current Register methods signature (or at least be extendable enough without big changes).

More related discussions in these PRs: https://github.com/AvaloniaUI/Avalonia/pull/10244 https://github.com/AvaloniaUI/Avalonia/pull/11029

CC @tomenscape @grokys

TomEdwardsEnscape commented 1 year ago

I've made several attempts at this so far. What I've learnt is that generating attributes while the user is typing is too slow. Far too slow. Responsiveness while typing starts to degrade and even after that Intellisense suggestions are delayed. The biggest part of the problem appears to be the need for type symbols, which requires promoting every small change into a new design-time compilation.

The solution I have come up with (but not fully implemented) is to generate just one attribute at compile time, which contains byte array of serialised data about the entire assembly. This can then be read by the analyser when it encounters the compiled assembly and merged into the property model it is currently building.

Generating this is fast because the project is already being compiled, so all the data we need is already parsed and in memory. To reduce file size, the serialised data can be prefixed with a compressed dictionary of symbol names.

maxkatz6 commented 1 year ago

We also need to solve a similar problem for XAML resources. User can define multiple hundreds of resources (like we do in Fluent theme), but this information is not visible in the app metadata. XAML editors, autocompletion, validation tools need to know if a resource with specific name exists or not. See https://github.com/AvaloniaUI/AvaloniaVS/issues/279#issuecomment-1522796799 for more details.

CC @kekekeks @jl0pd if you have any ideas.