JavaScriptIntention find parent file of virtual editor
Hi, I'm trying to build a JavaScriptIntention in Javascript template literal, for following javascript code:
import {html, LitElement} from 'lit';
import {customElement} from 'lit/decorators.js';
@customElement('demo-test')
export class DemoTest extends LitElement {
render() {
return html`
<foo-bar>
</foo-bar>
`;
}
}
If I place cursor on ‘foo-bar’ html content. In isAvailable or invoke of com.intellij.lang.javascript.intentions.JavaScriptIntention implementation, I get as parameter an Editor that seems to be something virtual. I don't find a way to get parent Editor.
Same if I use psiElement.getContainingFile() this gives an instance of HtmlFile, with file name only in toString, but no way to get full path of it, or parent file. Content is only html literal content.
Plugin code:
package com.ge.sdc.webgen.intentions.html;
import com.intellij.codeInspection.util.IntentionFamilyName;
import com.intellij.lang.javascript.intentions.JavaScriptIntention;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.xml.XmlElementType;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
public class WebComponentImportIntention extends JavaScriptIntention {
@Override
public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) {
if (element.getNode().getElementType() == XmlElementType.XML_NAME && element.getParent() instanceof XmlTag parent) {
System.out.println("Parent " + parent);
return true;
}
return false;
}
@Override
public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException {
System.out.println(element.getContainingFile()); // not real file: HtmlFile:demo-test.js
System.out.println(element.getContainingFile().getFileDocument().getText()); // <foo-bar> </foo-bar>
}
@Override
public @NotNull @IntentionFamilyName String getFamilyName() {
return "test";
}
}
How can I find parent elements of this virtual things ?
Please sign in to leave a comment.
A bit of clarifications: I'm stuck in Injected HTML file https://www.jetbrains.com/help/idea/using-language-injections.html
And would like to get its parent. getParent() of it returns null
Found this issue https://intellij-support.jetbrains.com/hc/en-us/community/posts/207567045-How-to-get-the-parent-psi-element-outside-of-a-language-injection
But not working, looping on getContext() works 2 on 3 times until it reaches “HtmlFile:foo.js”, the root of injected language content, and next getContext() returns null, I would expect to get something around “JSReturnStatment”
After more tests, it appears that I find parent content with
element.getContainingFile().getContext()
Only in isAvailable method I get expected result. In invoke method this is null.
Am I doing something wrong or using the wrong tool ? I try to add an import intention on HTML tag to add “import ‘./foo.js’" in top of js file.
In fact it seems that is null when putting a debugger break point in invoke, and I get expected value without break point.
Hi Julien,
It's hard to tell why it was showing null in the debugging session. Maybe the execution was suspended at the time when the injection was not in place or for another reason. It's hard to tell. I assume the problem is solved as it works at runtime. If not, please clarify what's more is missing.
Hi thank you for the answer, yes problem is solved. I think it looks like something was suspended during debug session.