Request: minimal language injection example


For instance
-an existing language (JavascriptLanguage)
-a simple target: all String literals in Java code

Such an example would be much appreciated.


12 comments

Hello Taras,

TT> For instance
TT> -an existing language (JavascriptLanguage)
TT> -a simple target: all String literals in Java code
TT> Such an example would be much appreciated.

Taken from GWT Studio plugin:

PsiManager.getInstance(project).registerLanguageInjector(new JsInjector(project));

public class JsInjector implements LanguageInjector {
Project project;

public JsInjector(Project project) {
this.project = project;
}

public void getLanguagesToInject(@NotNull PsiLanguageInjectionHost host,
@NotNull InjectedLanguagePlaces injectionPlacesRegistrar) {
if (host instanceof PsiComment && ((PsiComment)host).getTokenType() ==
JavaTokenType.C_STYLE_COMMENT) {
PsiComment comment = (PsiComment)host;
String text = comment.getText();

if (!text.startsWith("/-{") || !text.endsWith("}-/")) return;

final PsiElement parent = host.getParent();
if (parent != null && parent instanceof PsiMethod) {
PsiMethod method = (PsiMethod)parent;
if (method.getModifierList().hasExplicitModifier("native")) {
@NonNls StringBuilder prefix = new StringBuilder();
prefix.append("function ");
prefix.append(method.getName());
prefix.append(" ( ");
final PsiParameter[] parameters = method.getParameterList().getParameters();
for (int i = 0; i != parameters.length; ++i) {
prefix.append("/*");
prefix.append(parameters+.getType().toString());
prefix.append("*/");
prefix.append(parameters+.getName());
prefix.append(",");
}

prefix.append("/*");
prefix.append("window");
prefix.append("*/");
prefix.append("$wnd");
prefix.append(",");

prefix.append("/*");
prefix.append("Document");
prefix.append("*/");
prefix.append("$doc");

prefix.append(") {");

final Language language = ((LanguageFileType)FileTypeManager.getInstance().getFileTypeByExtension("js")).getLanguage();
String suffix = "}";
injectionPlacesRegistrar.addPlace(language, new TextRange(4, text.length()
- 4), prefix.toString(), suffix);
}
}
}
}
}


--
Dmitry Jemerov
Software Developer
http://www.jetbrains.com/
"Develop with Pleasure!"


0

Hello Dmitry,

I had to make some small modifications to get the example to work in the
current EAP release.
(Most likely due to IDEADEV-9349)

However...after that...it works.

Quite a spectacular sight to see one language embedded inside another, while
both having references, completions, inspections...

Congratulations on this functionality! I can't wait to see how other plugin
developers will use it.

Regards,
Taras


0

Taras Tielkes wrote:

Congratulations on this functionality! I can't wait to see how other
plugin developers will use it.


The 6.0-compatible version of the XPathView/XSLT plugin will make use of the API
(after having used a home-grown, light version in 5.1) and there's also a new,
even more hot plugin coming that enables language injection based on java
annotations and UI configuration - and a lot more (its initial release depends
on IDEADEV-9023 and IDEADEV-8302 being fixed). Stay tuned ;)

Sascha

0

Hello Sascha,

The 6.0-compatible version of the XPathView/XSLT plugin will make use
of the API (after having used a home-grown, light version in 5.1) and
there's also a new, even more hot plugin coming that enables language
injection based on java annotations and UI configuration - and a lot
more (its initial release depends on IDEADEV-9023 and IDEADEV-8302
being fixed). Stay tuned ;)


XPathView/XsltSupport is very good already (on par with commercial XSLT-supporting
editors).

What was the "after having used a home-grown, light" solution used for 5.1?
(I'd explore the source, but it seems later versions do not longer include
it)

The only thing I want to use the Injection API for is to disable the built-in
completion proposals for String literals in some places - not terribly exiting
usage.

Regards,

Taras


0

Taras Tielkes wrote:

XPathView/XsltSupport is very good already (on par with commercial
XSLT-supporting editors).

What was the "after having used a home-grown, light" solution used for 5.1?


Basically the way how XPath expressions are embedded into XML to enable the
features you listed: A tricky way of using highlighters and references. It
wouldn't however, solve your specific completion problem in 5.1.

(I'd explore the source, but it seems later versions do not longer
include it)


Only the latest version, basically because the plugin manager only used to
accept plugins up to 1 MB which this version exceeded.

The only thing I want to use the Injection API for is to disable the
built-in completion proposals for String literals in some places - not
terribly exiting usage.


Well, that's what I figured, but I saw a chance to do some advertising for the
new plugin and maybe to get some JB guy to have (another) look at the mentioned
issues. ;)

Sascha

0

Hello Sascha,

Well, that's what I figured, but I saw a chance to do some advertising
for the new plugin and maybe to get some JB guy to have (another) look
at the mentioned issues. ;)


I'm very interested in IDEA-8561 myself. If I understand correctly, a language
that can be injected into both Java and XML will have a nontrivial unescaping
requirement (apart from forced knowledge about current host language).


0

I need to inject javascript language into xml attribute values, and attribute values should start with "script:" prefix like below:

Why the InjectedLanguagePlaces.addPlace() call requires prefix, suffix (we can exclude script prefix from parsing using correct textRange)?

Is the code below correct?

0

"Alex Orishchenko" <no_mail@jetbrains.com> wrote in message
news:5382888.1168599387774.JavaMail.itn@is.intellij.net...
>I need to inject javascript language into xml attribute values, and
>attribute values should start with "script:" prefix like below:

 <span name="script:user.name"/>
> ]]>

Why the addPlace call requires prefix, suffix (we can exclude script
prefix from parsing using correct textRange)?


To support exotic situations when you want to add something to parsing, for
example treat your xml attribute value as some javascript function body, not
just as javascript file contents.

>

Is the code below correct?

 TextRange range = new TextRange(1 + "script:".length, text.length - 1);
> registar.addPlace(scriptLanguage, range, "script:", "")
> ]]>


Not quite. This way the following text will be fed to the javascript parser:
"script:" /prefix/ + "user.name" /attribute value range/+ "" /suffix/
You might have meant
registar.addPlace(scriptLanguage, range, null, null)
instead.

regards,
--
Alexey Kudravtsev
Software Developer
JetBrains, Inc, http://www.jetbrains.com
"Develop with pleasure!"


0

Hey Dmitry,
What would be missing from my custom language to cause the getLanguagesToInject on my custom language injector to never be called? My custom language is a templating language like JSP and I want to inject HTML in the non-script sections of the file. So I have to do anything special in my PSI objects or something to get these blocks to allow language injection?

Thanks,
Brian

0

I found my answer. My custom PsiElement objects that I wanted to allow language injection into needed to implement PsiLanguageInjectionHost.

0

That's true, but what what PsiLanguageInjectionHost implementation should look like?

0

Please sign in to leave a comment.