wmjordan / Codist

A visual studio extension which enhances syntax highlighting, quick info (tooltip), navigation bar, scrollbar, display quality, and brings smart tool bar with code refactoring to code editor.
https://marketplace.visualstudio.com/items?itemName=wmj.Codist
GNU General Public License v3.0
300 stars 26 forks source link

Support Community Toolkit MVVM Attributes #266

Open HeinzKessler opened 1 year ago

HeinzKessler commented 1 year ago

The .Net Community Toolkit is sure to become popular very quickly. Its MVVM toolkit allows for automatic generation of boilerplate code needed for properties, relay commands etc. in WPF.

A WPF "observable property" will look like this:

[ObservableProperty] private bool _myPropertyValue;

The actual property will be auto generated in a second .cs file, and the class has to be a partial class. See here. Therefore the lines above act like a public property.

The only drawback is that there's only a private field left, decorated with the [ObservableProperty] attribute, which will not be formatted as a public property by Codist. Therefore it would be nice if codist could recognize the code generation attributes of the .Net Community Toolkit and offer syntax highlighting accordingly.

wmjordan commented 1 year ago

recognize the code generation attributes of the .Net Community Toolkit and offer syntax highlighting accordingly.

I am afraid this will slow down the syntax highlighter a bit. When highlighting a field, Codist will first recognize that it is a IFieldSymbol, then if this request is supported, it will iterate through all custom attributes and compare them each other and check if it is of type communitytoolkit.mvvm.componentmodel.ObservablePropertyAttribute, by comparing the custom attribute name first, then each namespace part one by one and try to find out the corresponding property and make sure it is public. The current implementation only deal with properties exposed by IFieldSymbol and the new implementation will have to take care for custom attributes. All instances of fields will be checked like that, which is a draw back to performance.

However, on Super Quick Info and the symbol tool tip for those annotated fields, you can read the [ObservableProperty] annotation. If you are not sure about a field, you can just hover your mouse on it and get the information.

HeinzKessler commented 1 year ago

Thanks for this comprehensive explanation. I suppose, 99% of the fields won't have any custom attributes at all, so the performance overhead will mostly come down to the attribute check only. But OK, at least this will remain and will affect performance. Is there an existing way to format such fields "manually", e.g. by using certain prefixes or postfixes in the name, i.e. is there a way to format fields by some kind of regex pattern? Or some other trick to format them manually?

wmjordan commented 1 year ago

is there a way to format fields by some kind of regex pattern? Or some other trick to format them manually?

Yes. Theoretically it is not difficult to implement at all. However, the logic will affect ALL symbols being highlighted. The current workflow to highlight C# symbols:

  1. VS passes some text (typically a line) to the tagger (the class which highlights text)
  2. the tagger calls Roslyn to parse the document (or fetch the semantic model of the already parsed and cached document)
  3. tagger analyzes each token, finds out the syntax node it belongs to, and the possible code symbol
  4. tagger checks the symbol kind (class, struct, field, property, etc.), then the more concrete semantic aspect, for instance, static, virtual, volatile, etc. For each found out semantic aspect, generate a tagged span (the span of the token with the classification tag) and yield return to the tag aggregator.
  5. the consumer of the tag aggregator will use the span and tag to highlight the code.
  6. VS repeats the above steps to highlight other parts of the code

If "regex pattern enabled" highlight is to be implemented, for instance, you may want only private instance fields with a prefix "_m_" to be tagged with "My Style 1", but someone else will prefer that any private static fields start with "__" to be highlighted with "His Style 1", and someone else will prefer that any method named with a suffix "Async" to be highlighted with "Her Style 1", but private method suffixed with "Async" should be "Her Style 2"...

The code logic will become complicated. The current implementation in the step 4 does not have associated concept for compound sematic aspects such as "private static", "sealed override", etc. It once met with a member or type which is "private", it yields a "C#: Private member" tag, and when it later finds that member or type is "static", it yields another "C#: Static member" tag. So, if _private instance fields with a prefix "m" to be tagged with "My Style 1"_ is to be implemented, we have to rewrite the logic of the tagger to compare with compound aspects.

If the "Regex pattern enabled" highlight does not cooperate with the aforementioned sematic aspects, the code logic will be much simpler. However, each token will be examined by the regular expressions, which may be a little slow, I am afraid.