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) + } + } }