From b1b2b9a4e7730e70666e522ae6c1692ac0b43bad Mon Sep 17 00:00:00 2001 From: Nebojsa Vuksic Date: Mon, 27 Jul 2026 14:39:05 +0200 Subject: [PATCH] JEWEL-1374 declare Icons API modules as dependencies in published Jewel POMs Jewel Standalone consumers hit `NoClassDefFoundError: com/intellij/platform/icons/IconManager` at IntUiTheme startup because the generated POMs did not declare the Icons API modules (`com.jetbrains.intellij.platform:icons-api` / `-api-rendering` / `-impl`), forcing consumers to wire them by hand. The POM generator's `patchDependencies` had no branch for the `com.jetbrains.intellij.platform` groupId, so the icons dependencies fell into the implicit `else` and were silently dropped. Emit them as `compile` dependencies instead: the icons-api types are part of Jewel's public API (e.g. `Icon(...)` and the `iconKey(...)` DSL in jewel-ui), so `compile` is required for downstream compilation and also mirrors the Gradle `api(project(":jb-icons-*"))` wiring. Because `patchDependencies` receives a module's direct dependencies, this naturally scopes the change to `jewel-ui` (icons-api, icons-api-rendering, icons-impl) and `jewel-int-ui-standalone` (icons-api, icons-impl); other Jewel modules receive the icons transitively. The icons artifacts themselves are already published to Maven Central by the earlier JEWEL-1354 work. Add a regression test in MavenArtifactsBuilderTest that drives the public `mavenArtifacts.patchDependencies` hook for `intellij.platform.jewel.ui` and asserts the icons dependencies survive as `compile` with transitives; it fails without the generator fix. (cherry picked from commit c5b8cdc2a7397a2eb23ad6aef4b1e5daaf3f6527) IJ-MR-215743 GitOrigin-RevId: 84580c1f2537ab357c5cf7fea5e16bf8d6aaa867 --- .../intellij/build/JewelMavenArtifacts.kt | 8 ++++ .../build/MavenArtifactsBuilderTest.kt | 41 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/build/src/org/jetbrains/intellij/build/JewelMavenArtifacts.kt b/build/src/org/jetbrains/intellij/build/JewelMavenArtifacts.kt index 4bcdd34ec983..6abba05e38f0 100644 --- a/build/src/org/jetbrains/intellij/build/JewelMavenArtifacts.kt +++ b/build/src/org/jetbrains/intellij/build/JewelMavenArtifacts.kt @@ -157,6 +157,14 @@ internal object JewelMavenArtifacts { add(dependency.withTransitiveDependencies(DependencyScope.COMPILE)) } } + "com.jetbrains.intellij.platform" -> { + // Publish the Icons API modules (icons-api / icons-api-rendering / icons-impl) as compile + // dependencies, so consumers of the Jewel Standalone artifacts get IconManager on their + // classpath and can both boot IntUiTheme and compile against the public Icon/iconKey APIs. + if (coordinates.artifactId.startsWith("icons-")) { + add(dependency.withTransitiveDependencies(DependencyScope.COMPILE)) + } + } // else -> ignore the dependency, as it comes through transitively, usually from Compose. diff --git a/platform/build-scripts/tests/testSrc/org/jetbrains/intellij/build/MavenArtifactsBuilderTest.kt b/platform/build-scripts/tests/testSrc/org/jetbrains/intellij/build/MavenArtifactsBuilderTest.kt index 9fc172ccf0d7..18a905b93d97 100644 --- a/platform/build-scripts/tests/testSrc/org/jetbrains/intellij/build/MavenArtifactsBuilderTest.kt +++ b/platform/build-scripts/tests/testSrc/org/jetbrains/intellij/build/MavenArtifactsBuilderTest.kt @@ -5,7 +5,10 @@ import kotlinx.coroutines.runBlocking import org.jetbrains.intellij.build.BuildPaths.Companion.COMMUNITY_ROOT import org.jetbrains.intellij.build.BuildPaths.Companion.ULTIMATE_HOME import org.jetbrains.intellij.build.impl.createBuildContext +import org.jetbrains.intellij.build.impl.maven.DependencyScope +import org.jetbrains.intellij.build.impl.maven.MavenArtifactDependency import org.jetbrains.intellij.build.impl.maven.MavenArtifactsBuilder +import org.jetbrains.intellij.build.impl.maven.MavenCoordinates import org.junit.Assert import org.junit.Test @@ -66,4 +69,42 @@ class MavenArtifactsBuilderTest { Assert.assertTrue("Javadocs are not required for $moduleName", isJavadocJarRequired(module)) } } + + /** + * The Icons API modules are part of Jewel's public API surface (e.g. `Icon(...)` and the `iconKey(...)` DSL), + * so the published Jewel POMs must declare them as compile dependencies. Otherwise consumers of the standalone + * artifacts hit `NoClassDefFoundError: com/intellij/platform/icons/IconManager` at `IntUiTheme` startup. + * See JEWEL-1374. + */ + @Test + fun `jewel poms declare icons api dependencies`() { + val context = runBlocking { + createBuildContext( + projectHome = ULTIMATE_HOME, + productProperties = IdeaCommunityProperties(COMMUNITY_ROOT.communityRoot), + setupTracer = false, + ) + } + val jewelUi = context.outputProvider.findRequiredModule("intellij.platform.jewel.ui") + val iconsDependencies = listOf("icons-api", "icons-api-rendering", "icons-impl").map { artifactId -> + MavenArtifactDependency( + coordinates = MavenCoordinates("com.jetbrains.intellij.platform", artifactId, "SNAPSHOT"), + includeTransitiveDeps = false, + excludedDependencies = emptyList(), + scope = null, + ) + } + + val patched = context.productProperties.mavenArtifacts.patchDependencies(jewelUi, iconsDependencies) + + Assert.assertEquals( + "The Icons API dependencies must be kept in the jewel-ui POM", + iconsDependencies.map { it.coordinates.artifactId }, + patched.map { it.coordinates.artifactId }, + ) + for (dependency in patched) { + Assert.assertEquals("${dependency.coordinates} must be a compile dependency", DependencyScope.COMPILE, dependency.scope) + Assert.assertTrue("${dependency.coordinates} must include transitive dependencies", dependency.includeTransitiveDeps) + } + } }