1+ package com.github.tempest.framework.views.injection
2+
3+ import com.intellij.lang.Language
4+ import com.intellij.lang.injection.MultiHostInjector
5+ import com.intellij.lang.injection.MultiHostRegistrar
6+ import com.intellij.lang.tree.util.children
7+ import com.intellij.openapi.util.TextRange
8+ import com.intellij.psi.PsiElement
9+ import com.intellij.psi.PsiLanguageInjectionHost
10+ import com.intellij.psi.html.HtmlTag
11+ import com.intellij.psi.impl.source.html.HtmlRawTextImpl
12+ import com.intellij.psi.xml.XmlAttribute
13+ import com.intellij.psi.xml.XmlAttributeValue
14+ import com.intellij.psi.xml.XmlText
15+ import com.intellij.psi.xml.XmlToken
16+
17+ class PHPLanguageInjector : MultiHostInjector {
18+ override fun getLanguagesToInject (
19+ registrar : MultiHostRegistrar ,
20+ element : PsiElement
21+ ) {
22+ when (element) {
23+ is XmlAttributeValue -> {
24+ val attribute = element.parent as ? XmlAttribute ? : return
25+
26+ if (! attribute.name.startsWith(' :' ) || attribute.name.startsWith(" ::" )) return
27+
28+ val injectableHost = element as ? PsiLanguageInjectionHost ? : return
29+
30+ registrar
31+ .startInjecting(Language .findLanguageByID(" PHP" ) ? : return )
32+ .addPlace(" <?=" , " ?>" , injectableHost, TextRange (0 , injectableHost.textLength))
33+ .doneInjecting()
34+ }
35+
36+ is HtmlTag -> {
37+ element.children
38+ .mapNotNull { it as ? HtmlRawTextImpl }
39+ .forEach { child->
40+ injectIntoText(HtmlTextInjectionHostWrapper (child), registrar)
41+ }
42+ }
43+
44+ is XmlText -> {
45+ // println("element: ${element.text}, ${element.javaClass.name} ${element is PsiLanguageInjectionHost}")
46+ val injectableHost = element as ? PsiLanguageInjectionHost ? : return
47+ injectIntoText(injectableHost, registrar)
48+ }
49+ }
50+ }
51+
52+ private fun injectIntoText (
53+ element : PsiLanguageInjectionHost ,
54+ registrar : MultiHostRegistrar
55+ ) {
56+ val children = element.node.children().toList()
57+ .filter { it is XmlToken }
58+ .apply { if (size < 2 ) return }
59+
60+ // println("children: $children")
61+ val openTag = children.firstOrNull()?.psi ? : return
62+ val closeTag = children.lastOrNull()?.psi
63+
64+ // println("openTag: ${openTag.text}, closeTag: ${closeTag?.text}")
65+ if ((openTag.text == " {!!" && closeTag?.text == " !!}" ) || (openTag.text == " {{" && closeTag?.text == " }}" )) {
66+ val language = Language .findLanguageByID(" PHP" ) ? : return
67+
68+ val textRange = TextRange (openTag.textRangeInParent.endOffset, closeTag.startOffsetInParent)
69+ // println("injecting ${language} into $element, $textRange")
70+ registrar.startInjecting(language)
71+ .addPlace(" <?=" , " ?>" , element, textRange)
72+ .doneInjecting()
73+ }
74+ }
75+
76+ override fun elementsToInjectIn () = listOf (
77+ XmlAttributeValue ::class .java,
78+ XmlText ::class .java,
79+ HtmlTag ::class .java,
80+ )
81+ }
0 commit comments