Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,14 @@ interface DokkaAttribute {
*/
val DokkaClasspathAttribute: Attribute<String> =
Attribute("org.jetbrains.dokka.classpath")

/**
* The usage attribute for Dokka jars.
* We are not using [org.gradle.api.attributes.Usage.JAVA_RUNTIME] because this would create
* two outgoing variants exposing jars and potentially confuse consumers.
*
* See https://github.com/adamko-dev/dokkatoo/issues/165
*/
val DokkaJavaRuntimeUsage = "dokka-java-runtime"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.named
import org.jetbrains.dokka.gradle.dependencies.DokkaAttribute.Companion.DokkaClasspathAttribute
import org.jetbrains.dokka.gradle.dependencies.DokkaAttribute.Companion.DokkaFormatAttribute
import org.jetbrains.dokka.gradle.dependencies.DokkaAttribute.Companion.DokkaJavaRuntimeUsage
import org.jetbrains.dokka.gradle.internal.*

/**
Expand Down Expand Up @@ -51,18 +52,13 @@ class FormatDependenciesManager(
formatName = formatName,
)

init {
project.dependencies {
applyAttributeHacks()
}
}

private fun AttributeContainer.jvmJar() {
attribute(USAGE_ATTRIBUTE, objects.named(AttributeHackPrefix + JAVA_RUNTIME))
attribute(CATEGORY_ATTRIBUTE, objects.named(AttributeHackPrefix + LIBRARY))
attribute(BUNDLING_ATTRIBUTE, objects.named(AttributeHackPrefix + EXTERNAL))
attribute(TARGET_JVM_ENVIRONMENT_ATTRIBUTE, objects.named(AttributeHackPrefix + STANDARD_JVM))
attribute(LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(AttributeHackPrefix + JAR))
attribute(USAGE_ATTRIBUTE, objects.named(DokkaAttribute.DokkaJavaRuntimeUsage))
attribute(LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(JAR))

attribute(CATEGORY_ATTRIBUTE, objects.named(LIBRARY))
attribute(BUNDLING_ATTRIBUTE, objects.named(EXTERNAL))
attribute(TARGET_JVM_ENVIRONMENT_ATTRIBUTE, objects.named(STANDARD_JVM))
}

//region Dokka Generator Plugins
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
package org.jetbrains.dokka.gradle.formats

import org.gradle.api.Action
import org.gradle.api.Named
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.ExternalModuleDependency
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.attributes.AttributeCompatibilityRule
import org.gradle.api.attributes.AttributeContainer
import org.gradle.api.attributes.CompatibilityCheckDetails
import org.gradle.api.attributes.Usage
import org.gradle.api.file.FileSystemOperations
import org.gradle.api.file.ProjectLayout
import org.gradle.api.logging.Logging
Expand All @@ -24,12 +28,15 @@ import org.jetbrains.dokka.gradle.adapters.AndroidAdapter
import org.jetbrains.dokka.gradle.adapters.JavaAdapter
import org.jetbrains.dokka.gradle.adapters.KotlinAdapter
import org.jetbrains.dokka.gradle.dependencies.DependencyContainerNames
import org.jetbrains.dokka.gradle.dependencies.DokkaAttribute
import org.jetbrains.dokka.gradle.dependencies.DokkaAttribute.Companion.DokkaClasspathAttribute
import org.jetbrains.dokka.gradle.dependencies.DokkaAttribute.Companion.DokkaFormatAttribute
import org.jetbrains.dokka.gradle.dependencies.FormatDependenciesManager
import org.jetbrains.dokka.gradle.internal.Attribute
import org.jetbrains.dokka.gradle.internal.InternalDokkaGradlePluginApi
import org.jetbrains.dokka.gradle.internal.PluginFeaturesService.Companion.pluginFeaturesService
import javax.inject.Inject
import kotlin.jvm.java

/**
* Base Gradle Plugin for setting up a Dokka Publication for a specific output format.
Expand Down Expand Up @@ -141,6 +148,44 @@ abstract class DokkaFormatPlugin(
}
//endregion
}

/**
* When using Dokka, a given project exposes 2 "jar" outgoing variants:
* - The traditional one, containing the code of the project.
* - The Dokka one, containing dokka plugins.
*
* This creates a tension:
* - Dokka wants to resolve transitive dependencies of plugins using `java-runtime`
* usage.
* - But by using `java-runtime`, it potentially confuses all other regular consumers
* that are now going to resolve plugins when they really wanted the "traditional" jar file.
*
* To solve this, we use `dokka-java-runtime` for usage and a compatibility
* rule:
* - Dokka consumers are able to resolve plugins transitive dependencies thanks to
* the compatibility rule.
* - Dokka consumers disambiguate the traditional variants by forcing the `org.jetbrains.dokka.classpath`
* attribute on all consumable configurations to a "none" value.
* - Traditional consumers disambiguate the Dokka plugins variants because the
* compatibility rule is one way. If the consumer asks for `java-runtime`, `dokka-java-runtime`
* is not considered compatible.
*
* See https://github.com/adamko-dev/dokkatoo/issues/165
*/
target.dependencies.attributesSchema {
attribute(Usage.USAGE_ATTRIBUTE) {
compatibilityRules.add(DokkaCompatibilityRule::class.java)
}
}
target.configurations.configureEach {
if (isCanBeConsumed) {
attributes {
if (this.contains(Usage.USAGE_ATTRIBUTE) && !this.contains(DokkaClasspathAttribute)) {
attribute(DokkaClasspathAttribute, "none")
}
}
}
}
}
}

Expand Down Expand Up @@ -232,3 +277,11 @@ abstract class DokkaFormatPlugin(
private val logger = Logging.getLogger(DokkaFormatPlugin::class.java)
}
}

internal open class DokkaCompatibilityRule : AttributeCompatibilityRule<Usage> {
override fun execute(details: CompatibilityCheckDetails<Usage>): Unit = details.run {
if (consumerValue?.name == DokkaAttribute.DokkaJavaRuntimeUsage && producerValue?.name == Usage.JAVA_RUNTIME) {
compatible()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ class DokkaPluginFunctionalTest : FunSpec({
fun checkVariant(format: String) {
@Suppress("LocalVariableName")
val Format = format.uppercaseFirstChar()

variants shouldContain /* language=text */ """
|--------------------------------------------------
|Variant dokka${Format}ModuleOutputDirectoriesConsumable~internal
Expand All @@ -146,6 +145,7 @@ class DokkaPluginFunctionalTest : FunSpec({
| - :DokkaPluginFunctionalTest:unspecified (default capability)
|Attributes
| - org.gradle.usage = org.jetbrains.dokka
| - org.jetbrains.dokka.classpath = none
| - org.jetbrains.dokka.format = $format
| - org.jetbrains.dokka.module-component = ModuleOutputDirectories
|Artifacts
Expand Down Expand Up @@ -195,11 +195,11 @@ class DokkaPluginFunctionalTest : FunSpec({
|[Internal Dokka Configuration] Dokka Generator runtime classpath for $format - will be used in Dokka Worker. Should contain all transitive dependencies, plugins (and their transitive dependencies), so Dokka Worker can run.
|
|Attributes
| - org.gradle.category = DGP~library
| - org.gradle.dependency.bundling = DGP~external
| - org.gradle.jvm.environment = DGP~standard-jvm
| - org.gradle.libraryelements = DGP~jar
| - org.gradle.usage = DGP~java-runtime
| - org.gradle.category = library
| - org.gradle.dependency.bundling = external
| - org.gradle.jvm.environment = standard-jvm
| - org.gradle.libraryelements = jar
| - org.gradle.usage = dokka-java-runtime
| - org.jetbrains.dokka.classpath = dokka-generator
| - org.jetbrains.dokka.format = $format
|Extended Configurations
Expand All @@ -221,11 +221,11 @@ class DokkaPluginFunctionalTest : FunSpec({
|[Internal Dokka Configuration] Resolves Dokka Plugins classpath for $format. Fetch only the plugins (no transitive dependencies) for use in the Dokka JSON Configuration.
|
|Attributes
| - org.gradle.category = DGP~library
| - org.gradle.dependency.bundling = DGP~external
| - org.gradle.jvm.environment = DGP~standard-jvm
| - org.gradle.libraryelements = DGP~jar
| - org.gradle.usage = DGP~java-runtime
| - org.gradle.category = library
| - org.gradle.dependency.bundling = external
| - org.gradle.jvm.environment = standard-jvm
| - org.gradle.libraryelements = jar
| - org.gradle.usage = dokka-java-runtime
| - org.jetbrains.dokka.classpath = dokka-plugins
| - org.jetbrains.dokka.format = $format
|Extended Configurations
Expand All @@ -236,11 +236,11 @@ class DokkaPluginFunctionalTest : FunSpec({
|[Internal Dokka Configuration] Resolves Dokka Plugins classpath for a $format Publication (consisting of one or more Dokka Modules).
|
|Attributes
| - org.gradle.category = DGP~library
| - org.gradle.dependency.bundling = DGP~external
| - org.gradle.jvm.environment = DGP~standard-jvm
| - org.gradle.libraryelements = DGP~jar
| - org.gradle.usage = DGP~java-runtime
| - org.gradle.category = library
| - org.gradle.dependency.bundling = external
| - org.gradle.jvm.environment = standard-jvm
| - org.gradle.libraryelements = jar
| - org.gradle.usage = dokka-java-runtime
| - org.jetbrains.dokka.classpath = dokka-publication-plugins
| - org.jetbrains.dokka.format = $format
|Extended Configurations
Expand Down
Loading