Skip to content

Instantly share code, notes, and snippets.

@alshain
Last active January 10, 2021 02:46
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save alshain/cdaea3d757643efb469121e8d8c2b601 to your computer and use it in GitHub Desktop.
Save alshain/cdaea3d757643efb469121e8d8c2b601 to your computer and use it in GitHub Desktop.
IntelliJ Plugin Development

IntelliJ Plugin Development Resources

IntelliJ SDK Documentation IntelliJ Open-API and Plugin Development Forum

Gitter channel

https://github.com/JetBrains/gradle-intellij-plugin/

Available IntelliJ releases and version numbers releases (also CLion and AndroidStudio)

    intellij {
        version = "2019.1" // IntelliJ community, because `type` is set to 'IC' by default.
        version = "IU-2019.1 // Ultimate version
        version = "IU-IU-192.5118.30-EAP-SNAPSHOT" // for EAPs
        // alternatively use `type` instead of the prefix
        type = "IC" // or "IU" | "JPS" | "CL" (CLion) | "MPS" | "RD" (Rider)
        setPlugins(
            "DatabaseTools",  // bundled plugin
            "Tomcat",         // bundled plugin
            "java",         // bundled plugin
            "UML",            // bundled plugin
            "jsp",            // bundled plugin
            
            // Syntax for plugins from installable repositories:
            // org.plugin.id:version[@channel]
            // for PyCharm functionality
            // Plugin name is `Pythonid` (extraced from plugin.xml inside one of the plugin's JARs)
            // See here for version numbers: https://plugins.jetbrains.com/plugin/631-python
            "Pythonid:2019.1.191.6183.87", 
            // Kotlin Plugin (see below for EAP)
            "org.jetbrains.kotlin:1.3.21-release-IJ2019.1-2"
            //    See here for current version numbers https://plugins.jetbrains.com/plugin/6954-kotlin
            // Kotlin Plugin EAP
            // Important: You need to specify the EAP channel using `@EAP`
            "org.jetbrains.kotlin:1.3.30-eap-125-IJ2019.1-1@EAP"
            //    See the link above for versions and switch to the EAP tab
        )
        updateSinceUntilBuild = true

        
        tasks.withType<PatchPluginXmlTask> {
            sinceBuild(prop("sinceBuild"))
            untilBuild(prop("untilBuild"))
        }
    }

Classes

  • RunLineMarkerContributor
    • Used to allow running classes/tests via the gutter, Psi-based

RunCoonfigurationImporter RunConfigurationType RunConfigurationProducer

  • JBProtocolCommand (EP) Run custom command via URL (e.g. from browser -> IntelliJ via Toolbox)
    Example

    jetbrains://idea/checkout/git?checkout.repo=git@github.com:dkandalov/live-plugin.git&idea.required.plugins.id=Git4Idea
    
  • RunAnythingProvider Custom extensions to run anything

  • Messages.showInputDialog() etc ask user for input, validate

  • EditorLinePainter (EP) debugger uses this to paint inline debug values and such

  • StatusBarWidget, StatusBarWidgetProvider (EP)

  • MultiHostInjector (EP) To provide custom injections, can also provide custom "context" around fragments based on PSI-computations and such Also check out:

    • ConcatenationAwareInjector (EP)
    • LanguageInjector (EP)

New Stuff in IntelliJ 2019.2

  • ServiceViewContributor<T>
    • T is custom data for service. If they service itself is a ServiceViewContributor: child services
  • ServiceViewDescriptor Controls presentation of item in tree, also has content for right hand side pane
  • ServiceViewProvidingContributor Not sure.... seems override a descriptor's

ServiceViewContributor is not constantly polled about services as it would seem.

Notify IntelliJ that a contributor of a certain type has new services, this will trigger tree-refresh/tool window activation on first service.

project.messageBus.syncPublisher(ServiceEventListener.TOPIC).handle(
    ServiceEventListener.ServiceEvent(MyServiceViewContributor::class.java)
)

Database Interaction

  • DataSource

  • DbPsiFacade, provides access to all DataSources

  • DasTable some model thingy....

    • DbPsiFacade.findElement(dasTable) to find corresponding Psi element (DbElement), is contained inside a virtual file -> can be displayed as editor: data grid
  • OpenDataFileDescriptor open custom Data View

  • GoToRelatedProvider

    • DbViewGotoRelatedProvider
    • DbGrtidGotoRelatedProvider

Get all tables in all data sources

// iterate through all data sources (project and global)
for (DbDataSource dataSource : DbPsiFacade.getInstance(project).getDataSources()) {

  // dataSource.getModel().traverser() will list all the objects

  // com.intellij.database.util.DasUtil is a convenience class for the same task:
  // e.g. iterate through all tables
  for (DasTable table : DasUtil.getTables(datasource)) {
    // to something with tables
  }
}

Open Data View with pre-defined filter

This currently navigates to the "table" table in the "first" data

Attention: If the array of tables is null or empty or contains an incorrect table name, the data view will be displayed but the filter will be ignored silently.

import com.intellij.database.Dbms
import com.intellij.database.editor.OpenDataFileDescriptor
import com.intellij.database.model.DasColumn
import com.intellij.database.psi.DbPsiFacade
import com.intellij.database.psi.DbTable
import com.intellij.database.util.DasUtil
import com.intellij.database.util.DdlBuilder
import com.intellij.openapi.project.Project

val project: Project = null!!

val dbPsiFacade = DbPsiFacade.getInstance(project)
dbPsiFacade.dataSources.map {
    for (table in DasUtil.getTables(it)) {
        val columns = DasUtil.getColumns(table) ?: error("Didn't find columns for table")
        val firstColumn = columns.first()?.let { arrayOf(it.name) } ?: emptyArray()
        val findElement = dbPsiFacade.findElement(table) ?: continue
        val dbTable = findElement as? DbTable ?: continue

        OpenDataFileDescriptor(project, findElement.virtualFile, firstColumn, null) { ddlBuilder: DdlBuilder?, mutableList: MutableList<DasColumn>?, dbms: Dbms? ->
            ddlBuilder!!.space().identifier("ONE").space().keyword("=").space().literal("'hello'")
        }.navigate(true)
        return@map
    }
}
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
// Will configure project with
// - Java
// - Kotlin 1.3.21 support
// - jUnit for testing
// Plugin:
// IntelliJ Ultimate 2019 with Python and jsp plugins
plugins {
id("org.jetbrains.intellij") version "0.4.7"
java
kotlin("jvm") version "1.3.21"
}
group = "com.example.intellij.plugins"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
}
dependencies {
implementation(kotlin("stdlib-jdk8"))
testCompile("junit", "junit", "4.12")
}
// See https://github.com/JetBrains/gradle-intellij-plugin/
intellij {
version = "IU-2019.1"
setPlugins("Pythonid:2019.1.191.6183.87", "jsp")
}
configure<JavaPluginConvention> {
sourceCompatibility = JavaVersion.VERSION_1_8
}
tasks.getByName<org.jetbrains.intellij.tasks.PatchPluginXmlTask>("patchPluginXml") {
changeNotes("""
Add change notes here.<br>
<em>most HTML tags may be used</em>""")
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment