Inject language into JSLiteralExpression inside Vue context
Hi,
I'm developing Intellij plugin and having problems with injecting my mini-language inside JavaScript string literal.
I have LanguageInjector which works fine for js, jsx, tsx, php files, but it doesn't work for Vue files.
In case of Vue file LanguageInjector does not get PsiElement as injection host.
Here is Vue sample:
<template>
<h1>{{ $t('tst2.base.unresolved')}}</h1>
</template>
in given Vue sample I want to treat value of 'tst2.base.unresolved' as expression in my mini-language.
First I've tried to move my LanguageInjector to more general approach with MultiHostInjector. I found that if my multihost injector works before VueInjector, than I'm getting context with type XmlText:
{{ $t('tst2.base.unresolved')}}
If my MutliHOstInjector works after VueInjector (which is reasonable, from my point of view) I don't get PsiElement containing desired injection point at all.
Here is how I understand what should happen in this case.
Vue template is Html-based language, which injects in it's XmlText another language - VueJs. VueJS in turn is JS-dialect. And since VueJS is dialect of JS I would expect that JS-specific extension points would work and I could get desired PsiElement, containing JS string literal in my MultiHostResolver (or in Language injector) as it happens for php, tsx, jsx. But it does not work for Vue.
What am I getting wrong?
Evgeniy
请先登录再写评论。
Hi Evgeniy! Thanks for reaching out to us! The problem you're facing is that you cannot inject into an injection. Basically, there is only one level of injection allowed. Could you please elaborate more on how your min-language is intended to work and maybe we could figure out a different solution?
Hi, Piotr!
Thanks for your response!
I'm developing a plugin for work with i18next - like localization framework, it is similar to properties plugin - localization is stored in separate file (json, js, yaml) and it is referenced by key with very simple syntax - namespace + composite key. Initially I've implemented straightforward approach - try to parse each literal by my own state-machine parser. This worked fine, I've implemented annotator, reference contributor (from source to translation and back), code completion and some quick fix-code generations. This solution however has some drawbacks: first - I have to worry about each language where i18n key may occur. Second - I could not implement key rename refactoring from first attack. So I came to an idea to think of i18n key as a mini-language, so I could inject it in any suitable place of JS (and other languages) code. I hoped that this approach is going to be more concise and general and I could get a lot of features for free:). I've even implemented i18n language based not on my own lexer/parser but standard jflex/bnf code generation. And so I came to this nested languages problem (and many others) and have to refuse this mini-language idea
Evgeniy, as far as I understand your needs, you can try `com.intellij.psi.injection.ReferenceInjector`, which should work for injecting references into various languages host elements and should work within language injections. You can have a look at https://github.com/JetBrains/intellij-plugins/blob/master/vuejs/src/org/jetbrains/vuejs/libraries/vuex/codeInsight/refs/VuexJSLiteralReferenceProvider.kt - `getReferencesByElement()` to see how to inject segment references. `VuexStoreSymbolStringReference` allows to provide code completion and simple customization of unresolved references message (in which case you might not need `LocalInspectionTool` at all). You can even resolve to a `FakePsiElement` with custom `isEquivalentTo` as in https://github.com/JetBrains/intellij-plugins/blob/master/AngularJS/src/org/angular2/entities/Angular2DirectiveSelectorPsiElement.java and you can customize find usage, which is basis for refactoring, as in https://github.com/JetBrains/intellij-plugins/blob/master/AngularJS/src/org/angular2/findUsages/Angular2FindUsagesHandlerFactory.java . If needed refactoring behavior can be further customized, just let me know what problems you face.