Skip to content

Commit b8ef2dd

Browse files
Fix fastutil shadowing (#3476)
* support running CLI tests with K2 * explicitly control dependencies in CLI integration tests --------- Co-authored-by: Ignat Beresnev <[email protected]> (cherry picked from commit 3c989c1)
1 parent fdff1ed commit b8ef2dd

File tree

4 files changed

+113
-32
lines changed

4 files changed

+113
-32
lines changed

dokka-integration-tests/cli/build.gradle.kts

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,50 +15,65 @@ dependencies {
1515
implementation(projects.utilities)
1616
}
1717

18-
/* Create a fat base plugin jar for cli tests */
19-
val basePluginShadow: Configuration by configurations.creating {
18+
val cliPluginsClasspath: Configuration by configurations.creating {
19+
description = "plugins/dependencies required to run CLI with base plugin"
2020
attributes {
21-
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage::class.java, "java-runtime"))
21+
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
2222
}
23+
24+
// we don't fetch transitive dependencies here to be able to control external dependencies explicitly
25+
isTransitive = false
2326
}
2427

25-
val cliConfiguration: Configuration by configurations.creating {
28+
val cliClasspath: Configuration by configurations.creating {
29+
description = "dependency on CLI JAR"
2630
attributes {
27-
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage::class.java, Usage.JAVA_RUNTIME))
28-
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling::class.java, Bundling.SHADOWED))
31+
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
32+
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
2933
}
3034
// we should have single artifact here
3135
isTransitive = false
3236
}
3337

3438
dependencies {
35-
cliConfiguration("org.jetbrains.dokka:runner-cli")
39+
cliClasspath("org.jetbrains.dokka:runner-cli")
40+
41+
cliPluginsClasspath("org.jetbrains.dokka:plugin-base")
42+
// required dependencies of `plugin-base`
43+
cliPluginsClasspath(libs.freemarker)
44+
cliPluginsClasspath(libs.kotlinx.html)
3645

37-
basePluginShadow("org.jetbrains.dokka:plugin-base")
46+
val tryK2 = project.providers
47+
.gradleProperty("org.jetbrains.dokka.experimental.tryK2")
48+
.map(String::toBoolean)
49+
.orNull ?: false
50+
51+
val analysisDependency = when {
52+
tryK2 -> "org.jetbrains.dokka:analysis-kotlin-symbols"
53+
else -> "org.jetbrains.dokka:analysis-kotlin-descriptors"
54+
}
3855

39-
// TODO [beresnev] analysis switcher
40-
basePluginShadow("org.jetbrains.dokka:analysis-kotlin-descriptors") {
56+
cliPluginsClasspath(analysisDependency) {
4157
attributes {
42-
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling::class.java, Bundling.SHADOWED))
58+
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
4359
}
4460
}
4561
}
4662

47-
val basePluginShadowJar by tasks.register("basePluginShadowJar", ShadowJar::class) {
48-
configurations = listOf(basePluginShadow)
49-
archiveFileName.set("fat-base-plugin-${project.version}.jar")
50-
archiveClassifier.set("")
63+
val cliPluginsShadowJar by tasks.registering(ShadowJar::class) {
64+
archiveFileName.set("cli-plugins-${project.version}.jar")
65+
configurations = listOf(cliPluginsClasspath)
5166

5267
// service files are merged to make sure all Dokka plugins
5368
// from the dependencies are loaded, and not just a single one.
5469
mergeServiceFiles()
5570
}
5671

5772
tasks.integrationTest {
58-
dependsOn(cliConfiguration)
59-
dependsOn(basePluginShadowJar)
73+
dependsOn(cliClasspath)
74+
dependsOn(cliPluginsShadowJar)
6075

6176
inputs.dir(file("projects"))
62-
environment("CLI_JAR_PATH", cliConfiguration.singleFile)
63-
environment("BASE_PLUGIN_JAR_PATH", basePluginShadowJar.archiveFile.get())
77+
environment("CLI_JAR_PATH", cliClasspath.singleFile)
78+
environment("BASE_PLUGIN_JAR_PATH", cliPluginsShadowJar.get().archiveFile.get())
6479
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@file:Suppress("unused")
2+
3+
/**
4+
* A class that lives inside the root package
5+
*
6+
* <[email protected]> - checks markdown parsing of emails and non-trivial cases like #3329, should compile
7+
*/
8+
class RootPackageClass {
9+
val description = "I do live in the root package!"
10+
}

dokka-subprojects/analysis-kotlin-descriptors/build.gradle.kts

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
33
*/
44

5+
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
56
import dokkabuild.overridePublicationArtifactId
67

78
plugins {
@@ -22,7 +23,7 @@ dependencies {
2223
implementation(projects.dokkaSubprojects.analysisKotlinDescriptorsIde)
2324
}
2425

25-
tasks.shadowJar {
26+
tasks.withType<ShadowJar>().configureEach {
2627
// service files are merged to make sure all Dokka plugins
2728
// from the dependencies are loaded, and not just a single one.
2829
mergeServiceFiles()
@@ -34,9 +35,8 @@ tasks.shadowJar {
3435
* KT issue: https://youtrack.jetbrains.com/issue/KT-47150
3536
*
3637
* what is happening here?
37-
* fastutil is removed from shadow-jar completely,
38-
* instead we declare a maven RUNTIME dependency on fastutil;
39-
* this dependency will be fetched by Gradle at build time (as any other dependency from maven-central)
38+
* 1. we create intermediate `shadowDependenciesJar` with dependencies but without fastutil classes in it
39+
* 2. then we create final `shadowJar` with full fastutil from maven and dependencies from `shadowDependenciesJar` instead of original dependencies
4040
*
4141
* why do we need this?
4242
* because `kotlin-compiler` artifact includes unshaded (not-relocated) STRIPPED `fastutil` dependency,
@@ -47,5 +47,34 @@ tasks.shadowJar {
4747
* and so such classes are not replaced afterward by `shadowJar` task - it visits every class once
4848
*
4949
*/
50-
dependencies.shadow(libs.fastutil)
51-
tasks.shadowJar { exclude("it/unimi/dsi/fastutil/**") }
50+
51+
val shadowOverride: Configuration by configurations.creating {
52+
description = "dependencies which we need to replace with original ones because `kotlin-compiler` minimizes them"
53+
attributes {
54+
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
55+
}
56+
}
57+
58+
dependencies {
59+
shadowOverride(libs.fastutil)
60+
}
61+
62+
val shadowDependenciesJar by tasks.registering(ShadowJar::class) {
63+
group = "shadow"
64+
description = "Create a shadow jar from dependencies without fastutil"
65+
66+
archiveClassifier.set("dependencies")
67+
destinationDirectory.set(project.layout.buildDirectory.dir("shadowDependenciesLibs"))
68+
69+
// we need to create JAR with dependencies, but without fastutil,
70+
// so we include `runtimeClasspath` configuration (the same configuration which is used by default `shadowJar` task)
71+
// and include `fastutil` from the result
72+
configurations = listOf(project.configurations.runtimeClasspath.get())
73+
exclude("it/unimi/dsi/fastutil/**")
74+
}
75+
76+
tasks.shadowJar {
77+
// override configurations to remove dependencies handled in `shadowJarDependencies`
78+
configurations = emptyList()
79+
from(shadowOverride, shadowDependenciesJar)
80+
}

dokka-subprojects/analysis-kotlin-symbols/build.gradle.kts

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
33
*/
44

5+
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
56
import dokkabuild.overridePublicationArtifactId
67

78
plugins {
@@ -84,22 +85,20 @@ dependencies {
8485
compileOnly(libs.kotlinx.coroutines.core)
8586
}
8687

87-
tasks.shadowJar {
88+
tasks.withType<ShadowJar>().configureEach {
8889
// service files are merged to make sure all Dokka plugins
8990
// from the dependencies are loaded, and not just a single one.
9091
mergeServiceFiles()
9192
}
9293

93-
9494
/**
9595
* hack for shadow jar and fastutil because of kotlin-compiler
9696
*
9797
* KT issue: https://youtrack.jetbrains.com/issue/KT-47150
9898
*
9999
* what is happening here?
100-
* fastutil is removed from shadow-jar completely,
101-
* instead we declare a maven RUNTIME dependency on fastutil;
102-
* this dependency will be fetched by Gradle at build time (as any other dependency from maven-central)
100+
* 1. we create intermediate `shadowDependenciesJar` with dependencies but without fastutil classes in it
101+
* 2. then we create final `shadowJar` with full fastutil from maven and dependencies from `shadowDependenciesJar` instead of original dependencies
103102
*
104103
* why do we need this?
105104
* because `kotlin-compiler` artifact includes unshaded (not-relocated) STRIPPED `fastutil` dependency,
@@ -110,6 +109,34 @@ tasks.shadowJar {
110109
* and so such classes are not replaced afterward by `shadowJar` task - it visits every class once
111110
*
112111
*/
113-
dependencies.shadow(libs.fastutil)
114-
tasks.shadowJar { exclude("it/unimi/dsi/fastutil/**") }
115112

113+
val shadowOverride: Configuration by configurations.creating {
114+
description = "dependencies which we need to replace with original ones because `kotlin-compiler` minimizes them"
115+
attributes {
116+
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
117+
}
118+
}
119+
120+
dependencies {
121+
shadowOverride(libs.fastutil)
122+
}
123+
124+
val shadowDependenciesJar by tasks.registering(ShadowJar::class) {
125+
group = "shadow"
126+
description = "Create a shadow jar from dependencies without fastutil"
127+
128+
archiveClassifier.set("dependencies")
129+
destinationDirectory.set(project.layout.buildDirectory.dir("shadowDependenciesLibs"))
130+
131+
// we need to create JAR with dependencies, but without fastutil,
132+
// so we include `runtimeClasspath` configuration (the same configuration which is used by default `shadowJar` task)
133+
// and include `fastutil` from the result
134+
configurations = listOf(project.configurations.runtimeClasspath.get())
135+
exclude("it/unimi/dsi/fastutil/**")
136+
}
137+
138+
tasks.shadowJar {
139+
// override configurations to remove dependencies handled in `shadowJarDependencies`
140+
configurations = emptyList()
141+
from(shadowOverride, shadowDependenciesJar)
142+
}

0 commit comments

Comments
 (0)