DEV Community

Cover image for JetBrains IDE Plugin Development: Migrating from Gradle IntelliJ Plugin to IntelliJ Platform Gradle Plugin
alaje
alaje

Posted on

JetBrains IDE Plugin Development: Migrating from Gradle IntelliJ Plugin to IntelliJ Platform Gradle Plugin

The title of this article is not more confusing than suddenly upgrading your IntelliJ IDEA version and discovering all the reds in your plugin project.

Errors in project

More errors in project

Now, I knew something had changed, but I didn’t know exactly what. When I finally discovered the cause, fixing it was just a matter of following the documentation

Step 1: Update the plugins block in your build.gradle file

plugins {
    id("java")
    id("org.jetbrains.kotlin.jvm") version "1.9.21"
    id("org.jetbrains.intellij.platform") version "2.2.1" // [visit here to see latest version](https://github.com/JetBrains/intellij-platform-gradle-plugin/releases)
}
Enter fullscreen mode Exit fullscreen mode

We've replaced id("org.jetbrains.intellij") version "1.16.1" because as of version 2, the IntelliJ plugin now goes by the name IntelliJ Platform Gradle Plugin.

Step 2: Add the migration plugin

Me thinking I was in the clear after step 1:

Smiling gif

Then this happened:

Still errors after first step

When the documentation said that there were significant breaking changes, I should have expected it; I really should have. I carried my sorry self back to the documentation and discovered that the team over at JetBrains was so helpful that they provided another plugin to help us through the migration. How sweet of them! (Sarcasm, for all my folks on the slower side). I mean, I was dreading what was to come now. If they went the mile to provide an entire plugin to help, does it not mean the worst?

So, let’s update the plugins block again with our new plugin:

plugins {
    ...

    id("org.jetbrains.intellij.platform") version "2.2.1"
    id("org.jetbrains.intellij.platform.migration") version "2.2.1"
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Replace the intelliJ block

We got Unresolved reference: intellij for our intelliJ block is because the intelliJ block has now been replaced with the intellijPlatform block. When we load the new script configuration and then sync our Gradle changes, we now see that the migration plugin is doing its thing already.

Suggestion from migration plugin

It tells us we should do a couple of things instead. How it’s rendered in the pop-up isn’t making the migration plugin’s suggestion as helpful as it is, so I’ve copied it below so that we can make sense of it:

/*
Define the IntelliJ Platform dependency in `dependencies {}` block instead:
repositories {
    mavenCentral()
    intellijPlatform {
        defaultRepositories()
    }
}
dependencies {
    intellijPlatform {
        create(type, version)
    }
}
IntelliJ Platform Extension: https:// plugins. jetbrains. com/ docs/ intellij/ tools-intellij-platform-gradle-plugin-dependencies-extension.
*/
Enter fullscreen mode Exit fullscreen mode

Now we can see what we have to do.

Step 4: Add the intellijPlatform blocks

We must add two types of intellijPlatform blocks, one for the repository and another for the dependencies.

In the repository:

repositories {
    ...

    intellijPlatform{
        defaultRepositories()
    }
}

Enter fullscreen mode Exit fullscreen mode

In the dependencies:

dependencies {
   ...

    intellijPlatform {
        create("IC", "2024.1.1") 
    }
}
Enter fullscreen mode Exit fullscreen mode

The values I passed into the create function are the same values that were previously being set for the version and type in the old intelliJ block:

intellij {
    version.set("2024.1.1")
    type.set("IC") // Target IDE Platform

    ...
}
Enter fullscreen mode Exit fullscreen mode

Step 5: Add plugins and bundledPlugins functions

At this point, I was facing my last red line.

More warnings from migration plugin

After formatting the migration plugin’s suggestion, this is what we have:

/* Using 'plugins: ListProperty<Any>' is an error. 
Define dependencies on plugins or bundled plugins in `dependencies {}` block 
instead: 
repositories { 
    mavenCentral() 
    intellijPlatform { 
        defaultRepositories() 
    } 
} 

dependencies { 
    intellijPlatform { 
        plugins(providers.gradleProperty("platformPlugins").map { 
            it. split(',') 
        }) 
        bundledPlugins(providers.gradleProperty("platformBundledPlugins").map { 
            it. split(',') 
        }) 
    }
} 

Note that bundled plugins are now separated from plugins available in JetBrains 
Marketplace. 
IntelliJ Platform Extension: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-extension.html 
Migration guide: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-migration.html
Enter fullscreen mode Exit fullscreen mode

It’s clear that our intellij.plugins is no longer available, but even though we know what to do, we need to understand why we now have two functions to add.

An IntelliJ IDE comes with bundled plugins, which are plugins out of the box, and then we have plugins that don’t come with an IntelliJ IDE, so if you want to use them, you have to get them from, say, the Marketplace. Before IntelliJ Platform Gradle Plugin, you declared your plugins the same way irrespective of their source, but now you actually have to determine which of your plugins are bundled or not and then use either the plugins function or the bundledPlugins function for them.
The arguments: providers.gradleProperty("platformPlugins").map { it. split(',')} and providers.gradleProperty("platformBundledPlugins").map {it. split(',')} being passed into the functions in the snippet above is simply a way to access your list of plugins from your project’s gradle.properties file and then transform it into an appropriate value. So, unless your plugins are defined in your gradle.properties file, we can ignore that.

I had three plugins in my project:

...
"com.intellij.java",
"org.jetbrains.kotlin",
"Dart:241.15989.9"
...
Enter fullscreen mode Exit fullscreen mode

Already, I knew which ones came with IntelliJ and which ones I had to get from the Marketplace. You can quickly know which is which when testing your IDE plugin in the IDE development instance, because you don’t have to install the bundled plugins for the target IDE. Another way to know this is by running the printBundledPlugins task to see all the bundled plugins for the IDE. Here are some of the ones packed into the IntelliJ IDEA Community Edition:

List of bundled plugins

So now I have:

dependencies {
    implementation(files("libs/svgSalamander-1.1.4.jar"))
    intellijPlatform {
        create("IC", "2024.1.1")
        plugins("Dart:241.15989.9")
        bundledPlugins("com.intellij.java", "org.jetbrains.kotlin")
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 6: Do away with patchPluginXml, publishPlugin and signPlugin tasks

At this point, when building and running my plugin, it works!

Landing screen for dev IDE

But there’s this ugly warning the migration plugin was sharing whenever I ran my plugin:

Ugly warning from migration plugin

And reading through it, I saw it was more advice for the kind of changes I should make for my migration to 2.x, so of course, it made sense to do as instructed:

intellijPlatform {
    pluginConfiguration {

    }
    publishing { 

    }
    signing {

    }
}
Enter fullscreen mode Exit fullscreen mode

The problem was that after I added the above code, the migration plugin didn’t offer any further steps. I didn’tupposed to go into my functions. The IDE's suggestions helped me guess what wentnted either the docs or the migration plugin to tell me exactly what to know what was s where, but I wa do.

Suggestions from IDE

Since the migration plugin wasn’t doing that, I went back to the documentation, but that specific migration documentation page did not provide the answer. It instead redirected me to the IntelliJ Platform Extension page, where I saw this:

intellijPlatform {
  buildSearchableOptions = true
  instrumentCode = true
  projectName = project.name
  sandboxContainer = "..."

  pluginConfiguration {
    // ...
  }
  publishing {
    // ...
  }
  signing {
    // ...
  }
  pluginVerification {
    // ...
  }
}
Enter fullscreen mode Exit fullscreen mode

Before we go on, you should see what my tasks block was looking like:

tasks {
    buildSearchableOptions {
        enabled = false
    }

    // Set the JVM compatibility versions
    withType<JavaCompile> {
        sourceCompatibility = "17"
        targetCompatibility = "17"
    }
    withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
        kotlinOptions.jvmTarget = "17"
    }

    patchPluginXml {
        sinceBuild.set("241")
    }

    signPlugin {
        certificateChain.set(System.getenv("CERTIFICATE_CHAIN"))
        privateKey.set(System.getenv("PRIVATE_KEY"))
        password.set(System.getenv("PRIVATE_KEY_PASSWORD"))
    }

    publishPlugin {
        token.set(System.getenv("PUBLISH_TOKEN"))
    }
}
Enter fullscreen mode Exit fullscreen mode

Unfortunately, on that site’s page, we didn’t have one exact place to see what we had to change into what, so reading through was a must. Finally, we ended up several changes:

  • Move buildSearchableOptions to the intellijPlatform top-level function
  • Remove the patchPluginXml **task and add the sinceBuild with the ideaVersion function
  • Remove the signPlugin task and add the certificateChain , privateKey and password with the signing function instead
  • Remove the publishPlugin **task and add the token with the publishing function
  • Set the sourceCompatibility , targetCompatibility , and kotlinJvmTarget in the verifyPluginProjectConfiguration

The result:

intellijPlatform {
    buildSearchableOptions = false

    pluginConfiguration {
        ideaVersion {
            sinceBuild = "241"
        }
    }
    publishing {
        token = System.getenv("PUBLISH_TOKEN")
    }
    signing {
        certificateChain = System.getenv("CERTIFICATE_CHAIN")
        privateKey = System.getenv("PRIVATE_KEY")
        password = System.getenv("PRIVATE_KEY_PASSWORD")
    }
}

tasks {
    verifyPluginProjectConfiguration {
        sourceCompatibility = "17"
        targetCompatibility = "17"
        kotlinJvmTarget = "17"
    }
}
Enter fullscreen mode Exit fullscreen mode

After doing this, it turns out the ugly warning is still there:

Ugly warning still there after change

But by now, I think it’s just the migration plugin guy acting up.

Step 7: Remove the setupDependencies task (Optional)

Just because I don’t like ignoring warnings, I went a step further to respond to this warning from the migration plugin:

Warning about setupDependencies

The setupDependencies task is no longer required in 2.x, so I removed it per the steps outlined in documentation:

Steps to remove setupDependencies

Removing setupDependencies

Conclusion

The last thing I did was remove the migration plugin, and c’est fini! I successfully migrated my IntelliJ IDE plugin project to the IntelliJ Platform Gradle Plugin (I think 🤔). Overall, I don’t think the migration plugin was helpful much since I still had to rely on the documentation to carry out many of the changes. The experience would have been much better if quick fixes had been incorporated into it. All in all, all’s well that ends well. I hope this helped!

Top comments (0)