I think most plugin developers running into issues that agents search for api and usages of plugins and intellij code to "understand" it. But they are mostly in the end starting to decompile files. All models starting to do that some faster then others.
Also depending on the knowledge cut they are trying to find also a way out of outdated apis.
● Format: type\tid\tname\tpath — one plugin per line. Examples:
# Decompile all compatible plugins with vineflower
./gradlew -q printPluginDependencies | grep "^compatible" | cut -f4 | \
xargs -I{} java -jar decompiled/vineflower.jar {} decompiled/
# Just get the ml.llm path
./gradlew -q printPluginDependencies | grep "com.intellij.ml.llm" | cut -f4
# All paths for xargs
./gradlew -q printPluginDependencies | cut -f4
// Helper: parse plugin.xml InputStream → (pluginId, pluginName)
fun parsePluginXml(stream: java.io.InputStream): Pair<String?, String?> {
return try {
val factory = DocumentBuilderFactory.newInstance().also {
it.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false)
it.isValidating = false
}
val doc = factory.newDocumentBuilder().parse(stream)
val id = doc.getElementsByTagName("id").item(0)?.textContent?.trim()
val name = doc.getElementsByTagName("name").item(0)?.textContent?.trim()
id to name
} catch (_: Exception) {
null to null
}
}
// Helper: find plugin.xml in JARs under plugin dir → (pluginId, pluginName)
fun readPluginXmlFromDir(pluginDir: File): Pair<String?, String?> {
val libDir = pluginDir.resolve("lib").takeIf { it.exists() } ?: return null to null
libDir.listFiles { f -> f.extension == "jar" }
?.sortedBy { it.name }
?.forEach { jar ->
try {
JarFile(jar).use { jf ->
val entry = jf.getJarEntry("META-INF/plugin.xml") ?: return@use
val (id, name) = parsePluginXml(jf.getInputStream(entry))
if (id != null) return id to name
}
} catch (_: Exception) {}
}
return null to null
}
// Print all plugin dependencies (bundled + compatible) with ID, name, and path
tasks.register("printPluginDependencies") {
group = "intellij"
description = "Print all bundled and compatible plugins with ID, name, and path"
notCompatibleWithConfigurationCache("Reads plugin directories and resolves configurations at execution time")
doLast {
val extractedAttr = Attribute.of("intellijPlatformExtracted", Boolean::class.javaObjectType)
// type\tid\tname\tpath (tab-separated, pipe with -q flag)
fun printPlugin(type: String, id: String?, name: String?, dir: File) =
println("$type\t${id ?: ""}\t${name ?: ""}\t${dir.absolutePath}")
intellijPlatform.platformPath.resolve("plugins").toFile()
.listFiles()
?.filter { it.isDirectory }
?.mapNotNull { dir -> readPluginXmlFromDir(dir).let { (id, name) -> if (id != null) Triple(id, name, dir) else null } }
?.sortedBy { it.first }
?.forEach { (id, name, dir) -> printPlugin("bundled", id, name, dir) }
configurations.getByName("intellijPlatformPluginDependency")
.incoming
.artifactView { attributes { attribute(extractedAttr, true) } }
.files
.sortedBy { it.name }
.forEach { extractedDir ->
val (id, name) = extractedDir.listFiles()
?.filter { it.isDirectory }
?.firstNotNullOfOrNull { subDir -> readPluginXmlFromDir(subDir).let { (i, n) -> if (i != null) i to n else null } }
?: (null to null)
printPlugin("compatible", id, name, extractedDir)
}
}
}
Describe the need of your request
I think most plugin developers running into issues that agents search for api and usages of plugins and intellij code to "understand" it. But they are mostly in the end starting to decompile files. All models starting to do that some faster then others.
Also depending on the knowledge cut they are trying to find also a way out of outdated apis.
That's why i have added a skill (https://github.com/Haehnchen/idea-php-symfony2-plugin/tree/master/.claude/skills/intellij-plugin-development/references) helping them way faster to use local development context.
Not optimal not directly coupled to the gradle deps, because they "grepping" around.
I noticed you have added
printBundledPluginsprintBundledModules, so am playing with a task for is. Maybe something like this can be integrated.Proposed solution
Alternatives you've considered
No response
Additional context
No response