-
Notifications
You must be signed in to change notification settings - Fork 37
Description
Hi There
I have a proposal to improve the PoExtractor and would like to get some feedback from you whether you the proposed solution is agreeable with the project and whether you would accept a PR.
Motivation
My team discussed using this tool and we anticipate the limitations regarding name convention and msgctxt to lead to some friction:
- the fact that the member name (
T,S,H) is used to identity usage ofIStringLocalizer- it's brittle. Spelling it differently means localization just stops working, without any errors.
- our coding style says field members need to start with a lower case character. We'd have a choice of:
- ignoring "warnings" in the IDE --> this lessens the values of IDE warnings overall
- each and every time add a
// ReSharper disable once InconsistentNaming requireddirective --> cumbersome.
- deriving the
msgctxtfrom the class theIStringLocalizeris used in creates a few scenarios where the PoExtractor uses a differentmsgctxtthanOrchardCore.Localizationwill use. These can happen by accident. The code will still compile, and we'll only find out once someone reports localizations as missing - creating friction in the process. This can happen accidentally, for example, when you move some code usingIStringLocalizer<T>to another class.- theoretically we could write an Analyzer ourselves to ensure code is conformant with the conventions used in the PoExtractor. However, that would duplicate some of what PoExtractor is doing - so not better to maintain. Furthermore, if we can write an analyzer which can judge conformity (correct name for
IStringLocalizer<T>,Tis correctly chosen), we can most likely also just remove the limitations with similar code. And we think that's worth more.
- theoretically we could write an Analyzer ourselves to ensure code is conformant with the conventions used in the PoExtractor. However, that would duplicate some of what PoExtractor is doing - so not better to maintain. Furthermore, if we can write an analyzer which can judge conformity (correct name for
Solution Idea
What's missing in the current implementation is, instead of just reading the AST, also resolving types.
From some quick research it seems to me that for this we need a roslyn SemanticModel besides the SyntaxTree. And the SemanticModel requires a Compilation.
I've done a very dirty proof of concept:
See here
and here
The result of this is, that the field/property the IStringLocalizer<T> is assigned to can have any name.
The part of generating a different msgctxt depending on the type parameter T is not addressed, but from what I see can be done with the information already made available in this change.
I'm not really experienced with Roslyn, so there's a few questions-marks / risks:
- maybe there's a better way to achieve the same
- haven't tested how it works when the code doesn't compile
- haven't tested whether/how it works when the source references another version of the
Microsoft.Extensions.Localization, which defines theIStringLocalizer<T>interface - maybe a
Compilationdoesn't really mean compiling it... I just don't understand this well enough, yet ;-)
Having said that, I think it's not unlikely that it would only work on compiling (error-free) code (warnings would probably be fine).
If that limitation is fine, maybe the PoExtractor could be simplified by removing explicit support for razor (and even liquid?) templates by opening + building the whole project. My expectation here is that this would deal with generating the classes from .razor files automatically and the tool could then work on any class and not care for whether it's razor/liquid or whatnot.
I would, however, expect this to slow down processing time.
For us, both would be acceptable.
Alternative Solution
Instead of using Roslyn, and analyze source code, one could also analyze the IL with Mono.Cecil. From past experience, I would say, for the problem at hand, Mono.Cecil is simpler to work with than SyntaxTree + SemanticModel but:
- only ever works on compiled code. The current solution does not need a compiled result, it doesn't even need code without errors / compiling code.
- Cecil development seems to be on the backburner, and I'm not sure about continued support/development
- don't know how well this integrates with AoT / native compilation
- consider me biased because I have experience with Mono.CeCil but almost none with Roslyn