0

I'm trying to create an Intellij plugin that does the same thing as a VSCode extension I recently created, Ligatures Limited, which is designed prevent font coding ligatures from fonts like Fira Code from being rendered out-of-context, so that they work for things like operators and punctuation, but don't show up in comments and strings.

I've tried to follow the code in this example: https://github.com/JetBrains/intellij-sdk-docs/tree/master/code_samples/psi_demo

...but when I create code that looks like this

    public void actionPerformed(AnActionEvent anActionEvent) {
        Editor editor = anActionEvent.getData(CommonDataKeys.EDITOR);
        PsiFile psiFile = anActionEvent.getData(CommonDataKeys.PSI_FILE);
        if (editor == null || psiFile == null) return;
        int offset = editor.getCaretModel().getOffset();

        final StringBuilder infoBuilder = new StringBuilder();
        PsiElement element = psiFile.findElementAt(offset);

...with three different file types, I find that only JSON files (of JSON, JavaScript, and TypeScript files) are being recognized by language, and being tokenized as far as my extension is allowed to see. Syntax coloring and other language-specific support are clearly functioning at some level, but not in a way my extension seems to be able to access.

psiFile.language is JSON for JSON, but it's only TEXT for JavaScript, and textmate for TypeScript.

I can see all of the different token types for JSON (JsonObject, JsonStringLiteral, JsonProperty, etc), but JavaScript files come back as one big TEXT token with all of the text of the JavaScript file inside of it, and TypeScript only yields PsiElement(empty token)

Here's my current plugin.xml file:

<idea-plugin>
  <id>com.shetline.ligatures-limited</id>
  <name>Ligatures Limited</name>
  <vendor email="kerry@shetline.com" url="http://github.com/kshetline/ligatures-limited-idea">Kerry Shetline</vendor>

  <description><![CDATA[
    Code ligatures <i>only where you want them</i>, not where you don't
    ]]></description>

  <depends>com.intellij.modules.lang</depends>
  <depends>com.intellij.modules.platform</depends>
  <depends optional="true">JavaScript</depends>

  <applicationListeners>
    <listener class="com.shetline.lligatures.LigaturesLimited" topic="com.intellij.ide.AppLifecycleListener"/>
  </applicationListeners>

  <extensions defaultExtensionNs="com.intellij">
    <applicationService serviceImplementation="com.shetline.lligatures.LigaturesLimited"/>
    <highlightVisitor implementation="com.shetline.lligatures.LigaturesLimited"/>
    <highlightingPassFactory implementation="com.shetline.lligatures.LigaturesLimited"/>
  </extensions>

  <actions>
  </actions>
</idea-plugin>

I'm a bit worried that I might need to explicitly add dependencies for every language I want to parse. But then again, adding <depends optional="true">JavaScript</depends> didn't help me getting any further parsing JavaScript, so maybe that wouldn't help anyway.

Is it a timing thing perhaps, like maybe I'm getting a callback from highlightVisitor before the file has been parsed?

kshetline
  • 12,547
  • 4
  • 37
  • 73
  • 1
    JavaScript and TypeScript are only available in IntelliJ Ultimate, whereas JSON is available in the community edition. My guess is that this is why you have to add JavaScript (and TypeScript) dependencies explicitly, so that you actually depend on the ultimate edition (which you might be able to add as a single dependency instead?) I am not sure if this has anything to do with it, it's just the first thing that comes to mind. – Abby May 12 '20 at 13:29
  • @Abby, I tried adding `com.intellij.modules.ultimate`. That didn't help, but I think you're onto something, because I opened up an old Java project, and Java (supported by the public edition) is recognized and tokenized just fine. – kshetline May 12 '20 at 15:34

1 Answers1

1

I was snagged by something which is automatically done by the wizard that creates starter Intellij plug-in projects.

My default build.gradle.kts file contained this:

intellij {
  version = "2020.1.1"
}

Little did I know that, even though I was running the Ultimate Edition of IDEA, this configuration caused my plugin to launch inside a Community Edition wrapper, which of course had no idea about all of the languages I was trying to handle.

Changing to this:

intellij {
  version = "IU-2019.3.3"
}

...fixed the problem. Ideally I'd like to find a way to programmatically use the current version of my development environment, but this definitely fixes the essential problem I was having.

kshetline
  • 12,547
  • 4
  • 37
  • 73
  • You might find something interesting in [setup DSL](https://github.com/JetBrains/gradle-intellij-plugin#setup-dsl) (but probably not much more than you've found out by now). – Abby May 14 '20 at 14:36