aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsebastian.sellmair <sebastian.sellmair@jetbrains.com>2020-07-18 12:18:59 +0200
committerSebastian Sellmair <34319766+sellmair@users.noreply.github.com>2020-08-14 17:51:11 +0200
commiteae1ce49d18c2978b49166ea502bf2c109a85504 (patch)
tree477f39e33f14c71042f06eecc938d6efaa95e66c
parent6c635551ed3ea0cfe5f04b54a98cb28225061d26 (diff)
downloaddokka-eae1ce49d18c2978b49166ea502bf2c109a85504.tar.gz
dokka-eae1ce49d18c2978b49166ea502bf2c109a85504.tar.bz2
dokka-eae1ce49d18c2978b49166ea502bf2c109a85504.zip
Simplify Dokka Gradle Plugin
-rw-r--r--core/src/main/kotlin/DokkaBootstrapImpl.kt34
-rw-r--r--core/src/main/kotlin/configuration.kt46
-rw-r--r--core/src/main/kotlin/defaultConfiguration.kt25
-rw-r--r--core/src/main/kotlin/utilities/json.kt4
-rw-r--r--core/src/test/kotlin/utilities/DokkaConfigurationJsonTest.kt10
-rw-r--r--gradle/wrapper/gradle-wrapper.properties5
-rw-r--r--integration-tests/build.gradle.kts1
-rw-r--r--integration-tests/gradle/projects/it-basic-groovy/build.gradle13
-rw-r--r--integration-tests/gradle/projects/it-basic/build.gradle.kts8
-rw-r--r--integration-tests/gradle/projects/it-multiplatform-0/build.gradle.kts12
-rw-r--r--integration-tests/gradle/projects/it-multiplatform-0/src/jvmMain/kotlin/it/mpp0/ExpectedClass.kt6
-rw-r--r--integration-tests/gradle/projects/it-multiplatform-0/src/jvmMain/kotlin/it/mpp0/JvmOnlyClass.kt13
-rw-r--r--integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Android0GradleIntegrationTest.kt12
-rw-r--r--integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Multimodule0IntegrationTest.kt7
-rw-r--r--integration-tests/src/main/kotlin/org/jetbrains/dokka/it/AbstractIntegrationTest.kt3
-rw-r--r--kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/AnalysisEnvironment.kt11
-rw-r--r--kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/EnvironmentAndFacade.kt4
-rw-r--r--plugins/base/src/main/kotlin/allModulePage/MultimodulePageCreator.kt7
-rw-r--r--plugins/base/src/main/kotlin/renderers/FileWriter.kt14
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationTransformer.kt6
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/SuppressedDocumentableFilterTransformer.kt2
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/samples/SamplesTransformer.kt10
-rw-r--r--plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt19
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt47
-rw-r--r--plugins/base/src/test/kotlin/expect/AbstractExpectTest.kt2
-rw-r--r--plugins/base/src/test/kotlin/renderers/html/HtmlRenderingOnlyTestBase.kt2
-rw-r--r--plugins/gfm/src/test/kotlin/renderers/gfm/DivergentTest.kt3
-rw-r--r--plugins/gfm/src/test/kotlin/renderers/gfm/GfmRenderingOnlyTestBase.kt4
-rw-r--r--plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocPackageTemplateMapTest.kt3
-rw-r--r--runners/cli/src/main/kotlin/cli/main.kt20
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaParentTask.kt73
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaTask.kt55
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt185
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTask.kt73
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultimoduleTask.kt78
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt315
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt298
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleExternalDocumentationLinkBuilder.kt22
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradlePackageOptionsBuilder.kt36
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt25
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceRootBuilder.kt15
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/KotlinSourceSetGist.kt105
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ReflectDsl.kt72
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/TaskDependencyInternalWithAdditions.kt20
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/automagicTypedProxy.kt (renamed from runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ProxyUtils.kt)9
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/configurationImplementations.kt259
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokka.kt7
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaBootstrapFactory.kt (renamed from runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaBootstrapFactory.kt)11
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaDefaultOutputDirectory.kt (renamed from runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/defaultDokkaOutputDirectory.kt)0
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaSourceSetIDFactory.kt (renamed from runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaSourceSetIDFactory.kt)0
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/gradleConfigurations.kt (renamed from runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaConfigurations.kt)0
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt1
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/sourceSetKotlinGistConfiguration.kt21
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt12
-rw-r--r--runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaParentTaskTest.kt107
-rw-r--r--runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTaskTest.kt60
-rw-r--r--runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationJsonTest.kt51
-rw-r--r--runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationSerializableTest.kt13
-rw-r--r--runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleTaskTest.kt112
-rw-r--r--runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/KotlinDslDokkaTaskConfigurationTest.kt5
-rw-r--r--runners/maven-plugin/src/main/kotlin/DokkaMojo.kt21
-rw-r--r--testApi/src/main/kotlin/testApi/testRunner/TestRunner.kt45
62 files changed, 1272 insertions, 1187 deletions
diff --git a/core/src/main/kotlin/DokkaBootstrapImpl.kt b/core/src/main/kotlin/DokkaBootstrapImpl.kt
index a2efab41..584d8b8c 100644
--- a/core/src/main/kotlin/DokkaBootstrapImpl.kt
+++ b/core/src/main/kotlin/DokkaBootstrapImpl.kt
@@ -70,38 +70,8 @@ class DokkaBootstrapImpl : DokkaBootstrap {
private lateinit var generator: DokkaGenerator
- fun configure(logger: DokkaLogger, configuration: DokkaConfigurationImpl) = with(configuration) {
-
- fun defaultLinks(config: DokkaSourceSetImpl): List<ExternalDocumentationLinkImpl> {
- val links = mutableListOf<ExternalDocumentationLinkImpl>()
- if (!config.noJdkLink) {
- val javadocLink =
- if (config.jdkVersion < 11) "https://docs.oracle.com/javase/${config.jdkVersion}/docs/api/"
- else "https://docs.oracle.com/en/java/javase/${config.jdkVersion}/docs/api/java.base/"
- val packageListLink =
- if (config.jdkVersion < 11) "${javadocLink}/package-list"
- else "https://docs.oracle.com/en/java/javase/${config.jdkVersion}/docs/api/element-list"
- links += DokkaConfiguration.ExternalDocumentationLink
- .Builder(javadocLink, packageListLink)
- .build() as ExternalDocumentationLinkImpl
- }
-
- if (!config.noStdlibLink)
- links += DokkaConfiguration.ExternalDocumentationLink
- .Builder("https://kotlinlang.org/api/latest/jvm/stdlib/")
- .build() as ExternalDocumentationLinkImpl
- return links
- }
-
- val configurationWithLinks = configuration.copy(
- sourceSets = sourceSets.map {
- val links: List<ExternalDocumentationLinkImpl> =
- it.externalDocumentationLinks + defaultLinks(it)
- it.copy(externalDocumentationLinks = links)
- }
- )
-
- generator = DokkaGenerator(configurationWithLinks, logger)
+ fun configure(logger: DokkaLogger, configuration: DokkaConfigurationImpl) {
+ generator = DokkaGenerator(configuration, logger)
}
override fun configure(serializedConfigurationJSON: String, logger: BiConsumer<String, String>) = configure(
diff --git a/core/src/main/kotlin/configuration.kt b/core/src/main/kotlin/configuration.kt
index 91ee4d64..67c55861 100644
--- a/core/src/main/kotlin/configuration.kt
+++ b/core/src/main/kotlin/configuration.kt
@@ -2,16 +2,16 @@
package org.jetbrains.dokka
-import org.jetbrains.dokka.utilities.toJsonString
import org.jetbrains.dokka.utilities.parseJson
+import org.jetbrains.dokka.utilities.toJsonString
import java.io.File
import java.io.Serializable
import java.net.URL
object DokkaDefaults {
- const val outputDir = "./dokka"
+ val outputDir = File("./dokka")
const val format: String = "html"
- val cacheRoot: String? = null
+ val cacheRoot: File? = null
const val offlineMode: Boolean = false
const val failOnWarning: Boolean = false
@@ -51,6 +51,14 @@ enum class Platform(val key: String) {
}
}
+interface DokkaConfigurationBuilder<T : Any> {
+ fun build(): T
+}
+
+fun <T : Any> Iterable<DokkaConfigurationBuilder<T>>.build(): List<T> {
+ return this.map { it.build() }
+}
+
data class DokkaSourceSetID(
val moduleName: String,
val sourceSetName: String
@@ -65,8 +73,8 @@ fun DokkaConfigurationImpl(json: String): DokkaConfigurationImpl = parseJson(jso
fun DokkaConfiguration.toJsonString(): String = toJsonString(this)
interface DokkaConfiguration : Serializable {
- val outputDir: String
- val cacheRoot: String?
+ val outputDir: File
+ val cacheRoot: File?
val offlineMode: Boolean
val failOnWarning: Boolean
val sourceSets: List<DokkaSourceSet>
@@ -78,11 +86,11 @@ interface DokkaConfiguration : Serializable {
val sourceSetID: DokkaSourceSetID
val displayName: String
val moduleDisplayName: String
- val classpath: List<String>
+ val classpath: List<File>
val sourceRoots: List<SourceRoot>
val dependentSourceSets: Set<DokkaSourceSetID>
- val samples: List<String>
- val includes: List<String>
+ val samples: List<File>
+ val includes: List<File>
val includeNonPublic: Boolean
val includeRootPackage: Boolean
val reportUndocumented: Boolean
@@ -96,12 +104,12 @@ interface DokkaConfiguration : Serializable {
val apiVersion: String?
val noStdlibLink: Boolean
val noJdkLink: Boolean
- val suppressedFiles: List<String>
+ val suppressedFiles: List<File>
val analysisPlatform: Platform
}
interface SourceRoot : Serializable {
- val path: String
+ val directory: File
}
interface SourceLinkDefinition : Serializable {
@@ -112,8 +120,8 @@ interface DokkaConfiguration : Serializable {
interface DokkaModuleDescription : Serializable {
val name: String
- val path: String
- val docFile: String
+ val path: File
+ val docFile: File
}
interface PackageOptions : Serializable {
@@ -135,7 +143,7 @@ interface DokkaConfiguration : Serializable {
constructor(root: String, packageList: String? = null) : this(URL(root), packageList?.let { URL(it) })
- fun build(): ExternalDocumentationLink =
+ fun build(): ExternalDocumentationLinkImpl =
if (packageListUrl != null && url != null)
ExternalDocumentationLinkImpl(url!!, packageListUrl!!)
else if (url != null)
@@ -146,4 +154,16 @@ interface DokkaConfiguration : Serializable {
}
}
+fun ExternalDocumentationLink(
+ url: URL? = null,
+ packageListUrl: URL? = null
+): ExternalDocumentationLinkImpl =
+ DokkaConfiguration.ExternalDocumentationLink.Builder(url = url, packageListUrl = packageListUrl).build()
+
+
+fun ExternalDocumentationLink(
+ url: String, packageListUrl: String? = null
+): ExternalDocumentationLinkImpl =
+ DokkaConfiguration.ExternalDocumentationLink.Builder(root = url, packageList = packageListUrl).build()
+
diff --git a/core/src/main/kotlin/defaultConfiguration.kt b/core/src/main/kotlin/defaultConfiguration.kt
index 8e38e8d5..384ce392 100644
--- a/core/src/main/kotlin/defaultConfiguration.kt
+++ b/core/src/main/kotlin/defaultConfiguration.kt
@@ -3,10 +3,12 @@ package org.jetbrains.dokka
import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
import java.io.File
import java.net.URL
+import kotlin.reflect.full.memberProperties
+import kotlin.reflect.full.primaryConstructor
data class DokkaConfigurationImpl(
- override val outputDir: String = DokkaDefaults.outputDir,
- override val cacheRoot: String? = DokkaDefaults.cacheRoot,
+ override val outputDir: File = DokkaDefaults.outputDir,
+ override val cacheRoot: File? = DokkaDefaults.cacheRoot,
override val offlineMode: Boolean = DokkaDefaults.offlineMode,
override val sourceSets: List<DokkaSourceSetImpl> = emptyList(),
override val pluginsClasspath: List<File> = emptyList(),
@@ -15,15 +17,16 @@ data class DokkaConfigurationImpl(
override val failOnWarning: Boolean = DokkaDefaults.failOnWarning
) : DokkaConfiguration
+
data class DokkaSourceSetImpl(
override val moduleDisplayName: String,
override val displayName: String = DokkaDefaults.sourceSetDisplayName,
override val sourceSetID: DokkaSourceSetID,
- override val classpath: List<String> = emptyList(),
+ override val classpath: List<File> = emptyList(),
override val sourceRoots: List<SourceRootImpl>,
override val dependentSourceSets: Set<DokkaSourceSetID> = emptySet(),
- override val samples: List<String> = emptyList(),
- override val includes: List<String> = emptyList(),
+ override val samples: List<File> = emptyList(),
+ override val includes: List<File> = emptyList(),
override val includeNonPublic: Boolean = DokkaDefaults.includeNonPublic,
override val includeRootPackage: Boolean = DokkaDefaults.includeRootPackage,
override val reportUndocumented: Boolean = DokkaDefaults.reportUndocumented,
@@ -37,19 +40,21 @@ data class DokkaSourceSetImpl(
override val apiVersion: String? = null,
override val noStdlibLink: Boolean = DokkaDefaults.noStdlibLink,
override val noJdkLink: Boolean = DokkaDefaults.noJdkLink,
- override val suppressedFiles: List<String> = emptyList(),
+ override val suppressedFiles: List<File> = emptyList(),
override val analysisPlatform: Platform = DokkaDefaults.analysisPlatform
) : DokkaSourceSet
data class DokkaModuleDescriptionImpl(
override val name: String,
- override val path: String,
- override val docFile: String
+ override val path: File,
+ override val docFile: File
) : DokkaConfiguration.DokkaModuleDescription
data class SourceRootImpl(
- override val path: String
-) : DokkaConfiguration.SourceRoot
+ override val directory: File
+) : DokkaConfiguration.SourceRoot {
+ constructor(directoryPath: String) : this(File(directoryPath))
+}
data class SourceLinkDefinitionImpl(
override val path: String,
diff --git a/core/src/main/kotlin/utilities/json.kt b/core/src/main/kotlin/utilities/json.kt
index 9e4677aa..feac2b23 100644
--- a/core/src/main/kotlin/utilities/json.kt
+++ b/core/src/main/kotlin/utilities/json.kt
@@ -56,10 +56,10 @@ private object FileSerializer : StdScalarSerializer<File>(File::class.java) {
private object SourceRootSerializer : StdScalarSerializer<SourceRoot>(SourceRoot::class.java) {
override fun serialize(value: SourceRoot, g: JsonGenerator, provider: SerializerProvider) {
- g.writeString(value.path)
+ g.writeString(value.directory.path)
}
}
private object SourceRootImplDeserializer : StdScalarDeserializer<SourceRootImpl>(SourceRootImpl::class.java) {
- override fun deserialize(p: JsonParser, ctxt: DeserializationContext): SourceRootImpl = SourceRootImpl(p.text)
+ override fun deserialize(p: JsonParser, ctxt: DeserializationContext): SourceRootImpl = SourceRootImpl(File(p.text))
}
diff --git a/core/src/test/kotlin/utilities/DokkaConfigurationJsonTest.kt b/core/src/test/kotlin/utilities/DokkaConfigurationJsonTest.kt
index e954c82c..35755f50 100644
--- a/core/src/test/kotlin/utilities/DokkaConfigurationJsonTest.kt
+++ b/core/src/test/kotlin/utilities/DokkaConfigurationJsonTest.kt
@@ -9,12 +9,12 @@ class DokkaConfigurationJsonTest {
@Test
fun `simple configuration toJsonString then parseJson`() {
val configuration = DokkaConfigurationImpl(
- outputDir = "customOutputDir",
+ outputDir = File("customOutputDir"),
pluginsClasspath = listOf(File("plugins/customPlugin.jar")),
sourceSets = listOf(
DokkaSourceSetImpl(
moduleDisplayName = "customModuleDisplayName",
- sourceRoots = listOf(SourceRootImpl("customSourceRoot")),
+ sourceRoots = listOf(SourceRootImpl(File("customSourceRoot"))),
sourceSetID = DokkaSourceSetID("customModuleName", "customSourceSetName")
)
)
@@ -48,14 +48,14 @@ class DokkaConfigurationJsonTest {
val parsedConfiguration = DokkaConfigurationImpl(json)
assertEquals(
DokkaConfigurationImpl(
- outputDir = "customOutputDir",
+ outputDir = File("customOutputDir"),
pluginsClasspath = listOf(File("plugins/customPlugin.jar")),
sourceSets = listOf(
DokkaSourceSetImpl(
moduleDisplayName = "customModuleDisplayName",
- sourceRoots = listOf(SourceRootImpl("customSourceRoot")),
+ sourceRoots = listOf(SourceRootImpl(File("customSourceRoot"))),
sourceSetID = DokkaSourceSetID("customModuleName", "customSourceSetName"),
- classpath = listOf("classpath/custom1.jar", "classpath/custom2.jar")
+ classpath = listOf(File("classpath/custom1.jar"), File("classpath/custom2.jar"))
)
)
),
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index bb8b2fc2..29271bed 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,6 @@
+#Tue Jul 21 13:56:13 CEST 2020
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip
-zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
diff --git a/integration-tests/build.gradle.kts b/integration-tests/build.gradle.kts
index 86472aa9..aaa8b153 100644
--- a/integration-tests/build.gradle.kts
+++ b/integration-tests/build.gradle.kts
@@ -38,7 +38,6 @@ subprojects {
?: System.getenv("DOKKA_INTEGRATION_TEST_IS_EXHAUSTIVE")?.toBoolean()
?: false.toString()
)
-
}
tasks.check {
diff --git a/integration-tests/gradle/projects/it-basic-groovy/build.gradle b/integration-tests/gradle/projects/it-basic-groovy/build.gradle
index 13a34619..405b55ed 100644
--- a/integration-tests/gradle/projects/it-basic-groovy/build.gradle
+++ b/integration-tests/gradle/projects/it-basic-groovy/build.gradle
@@ -10,28 +10,29 @@ dependencies {
}
dokkaHtml {
- outputDirectory = "$buildDir/dokka/customHtml"
+ outputDirectory = new File(buildDir, "/dokka/customHtml")
pluginsConfiguration.put("pluginA", "configA")
failOnWarning = false
dokkaSourceSets {
customSourceSet {
- sourceRoot { path = "$projectDir/src/main/java" }
- sourceRoot { path = "$projectDir/src/main/kotlin" }
+ sourceRoot { directory = file("src/main/java") }
+ sourceRoot { directory = file("src/main/kotlin") }
displayName = "custom"
reportUndocumented = true
}
}
+
}
dokkaJavadoc {
- outputDirectory = "$buildDir/dokka/customJavadoc"
+ outputDirectory = new File(buildDir, "dokka/customJavadoc")
}
dokkaGfm {
- outputDirectory = "$buildDir/dokka/customGfm"
+ outputDirectory = new File(buildDir, "dokka/customGfm")
}
dokkaJekyll {
- outputDirectory = "$buildDir/dokka/customJekyll"
+ outputDirectory = new File(buildDir, "dokka/customJekyll")
}
diff --git a/integration-tests/gradle/projects/it-basic/build.gradle.kts b/integration-tests/gradle/projects/it-basic/build.gradle.kts
index b3ddde18..45454e29 100644
--- a/integration-tests/gradle/projects/it-basic/build.gradle.kts
+++ b/integration-tests/gradle/projects/it-basic/build.gradle.kts
@@ -14,11 +14,11 @@ dependencies {
tasks.withType<DokkaTask> {
dokkaSourceSets {
configureEach {
- moduleDisplayName = "Basic Project"
- suppressedFiles = listOf("src/main/kotlin/it/suppressedByPath")
+ moduleDisplayName.set("Basic Project")
+ suppressedFiles.from(file("src/main/kotlin/it/suppressedByPath"))
perPackageOption {
- prefix = "it.suppressedByPackage"
- suppress = true
+ prefix.set("it.suppressedByPackage")
+ suppress.set(true)
}
}
}
diff --git a/integration-tests/gradle/projects/it-multiplatform-0/build.gradle.kts b/integration-tests/gradle/projects/it-multiplatform-0/build.gradle.kts
index 52aa9d36..26200399 100644
--- a/integration-tests/gradle/projects/it-multiplatform-0/build.gradle.kts
+++ b/integration-tests/gradle/projects/it-multiplatform-0/build.gradle.kts
@@ -1,5 +1,3 @@
-import org.jetbrains.dokka.gradle.DokkaTask
-
plugins {
kotlin("multiplatform")
id("org.jetbrains.dokka")
@@ -20,13 +18,3 @@ kotlin {
}
}
}
-
-tasks.withType<DokkaTask> {
- dokkaSourceSets {
- create("commonMain")
- create("jvmMain")
- create("linuxMain")
- create("macosMain")
- create("jsMain")
- }
-}
diff --git a/integration-tests/gradle/projects/it-multiplatform-0/src/jvmMain/kotlin/it/mpp0/ExpectedClass.kt b/integration-tests/gradle/projects/it-multiplatform-0/src/jvmMain/kotlin/it/mpp0/ExpectedClass.kt
index 8e7fa96e..6de30de6 100644
--- a/integration-tests/gradle/projects/it-multiplatform-0/src/jvmMain/kotlin/it/mpp0/ExpectedClass.kt
+++ b/integration-tests/gradle/projects/it-multiplatform-0/src/jvmMain/kotlin/it/mpp0/ExpectedClass.kt
@@ -2,4 +2,10 @@ package it.mpp0
actual class ExpectedClass {
actual val platform: String = "jvm"
+
+ /**
+ * This function can only be used by JVM consumers
+ */
+ fun jvmOnlyFunction() = Unit
+
}
diff --git a/integration-tests/gradle/projects/it-multiplatform-0/src/jvmMain/kotlin/it/mpp0/JvmOnlyClass.kt b/integration-tests/gradle/projects/it-multiplatform-0/src/jvmMain/kotlin/it/mpp0/JvmOnlyClass.kt
new file mode 100644
index 00000000..21101a89
--- /dev/null
+++ b/integration-tests/gradle/projects/it-multiplatform-0/src/jvmMain/kotlin/it/mpp0/JvmOnlyClass.kt
@@ -0,0 +1,13 @@
+@file:Suppress("unused")
+
+package it.mpp0
+
+/**
+ * This class can only be used by JVM consumers
+ */
+class JvmOnlyClass {
+ /**
+ * This function can only be used by JVM consumers
+ */
+ fun myJvm() = println("HI")
+}
diff --git a/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Android0GradleIntegrationTest.kt b/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Android0GradleIntegrationTest.kt
index d6dfe451..a657e9c7 100644
--- a/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Android0GradleIntegrationTest.kt
+++ b/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Android0GradleIntegrationTest.kt
@@ -62,12 +62,6 @@ class Android0GradleIntegrationTest(override val versions: BuildVersions) : Abst
"Expected html files in html output directory"
)
- htmlOutputDir.allHtmlFiles().forEach { file ->
- assertContainsNoErrorClass(file)
- assertNoUnresolvedLinks(file)
- assertNoHrefToMissingLocalFileOrDirectory(file)
- }
-
assertTrue(
htmlOutputDir.allHtmlFiles().any { file ->
"https://developer.android.com/reference/android/content/Context.html" in file.readText()
@@ -80,5 +74,11 @@ class Android0GradleIntegrationTest(override val versions: BuildVersions) : Abst
file.readText()
}, "Expected link to developer.android.com/.../androidx/"
)
+
+ htmlOutputDir.allHtmlFiles().forEach { file ->
+ assertContainsNoErrorClass(file)
+ assertNoUnresolvedLinks(file)
+ assertNoHrefToMissingLocalFileOrDirectory(file)
+ }
}
}
diff --git a/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Multimodule0IntegrationTest.kt b/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Multimodule0IntegrationTest.kt
index fc7a6a81..70b5832d 100644
--- a/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Multimodule0IntegrationTest.kt
+++ b/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Multimodule0IntegrationTest.kt
@@ -36,6 +36,13 @@ class Multimodule0IntegrationTest(override val versions: BuildVersions) : Abstra
assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:dokkaHtmlMultimodule")).outcome)
assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:dokkaGfmMultimodule")).outcome)
assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:dokkaJekyllMultimodule")).outcome)
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:moduleB:dokkaHtml")).outcome)
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:moduleC:dokkaHtml")).outcome)
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:moduleB:dokkaGfm")).outcome)
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:moduleC:dokkaGfm")).outcome)
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:moduleB:dokkaJekyll")).outcome)
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:moduleC:dokkaJekyll")).outcome)
+
val outputDir = File(projectDir, "moduleA/build/dokka/htmlMultimodule")
assertTrue(outputDir.isDirectory, "Missing dokka output directory")
diff --git a/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/AbstractIntegrationTest.kt b/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/AbstractIntegrationTest.kt
index c4914652..d21106fa 100644
--- a/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/AbstractIntegrationTest.kt
+++ b/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/AbstractIntegrationTest.kt
@@ -3,10 +3,13 @@ package org.jetbrains.dokka.it
import org.jsoup.Jsoup
import org.junit.Rule
import org.junit.rules.TemporaryFolder
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
import java.io.File
import kotlin.test.assertFalse
import kotlin.test.assertTrue
+@RunWith(JUnit4::class)
abstract class AbstractIntegrationTest {
@get:Rule
diff --git a/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/AnalysisEnvironment.kt b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/AnalysisEnvironment.kt
index 685bfe82..14067f43 100644
--- a/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/AnalysisEnvironment.kt
+++ b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/AnalysisEnvironment.kt
@@ -540,12 +540,11 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl
* Adds list of paths to source roots.
* $list: collection of files to add
*/
- fun addSources(list: List<String>) {
- list.forEach {
- configuration.addKotlinSourceRoot(it)
- val file = File(it)
- if (file.isDirectory || file.extension == ".java") {
- configuration.addJavaSourceRoot(file)
+ fun addSources(sourceDirectories: List<File>) {
+ sourceDirectories.forEach { directory ->
+ configuration.addKotlinSourceRoot(directory.path)
+ if (directory.isDirectory || directory.extension == ".java") {
+ configuration.addJavaSourceRoot(directory)
}
}
}
diff --git a/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/EnvironmentAndFacade.kt b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/EnvironmentAndFacade.kt
index d9a89194..009bc66c 100644
--- a/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/EnvironmentAndFacade.kt
+++ b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/EnvironmentAndFacade.kt
@@ -17,12 +17,12 @@ internal fun createEnvironmentAndFacade(
if (analysisPlatform == Platform.jvm) {
addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre())
}
- sourceSet.classpath.forEach { addClasspath(File(it)) }
+ sourceSet.classpath.forEach(::addClasspath)
addSources(
(sourceSet.sourceRoots + configuration.sourceSets.filter { it.sourceSetID in sourceSet.dependentSourceSets }
.flatMap { it.sourceRoots })
- .map { it.path }
+ .map { it.directory }
)
loadLanguageVersionSettings(sourceSet.languageVersion, sourceSet.apiVersion)
diff --git a/plugins/base/src/main/kotlin/allModulePage/MultimodulePageCreator.kt b/plugins/base/src/main/kotlin/allModulePage/MultimodulePageCreator.kt
index de2242f2..4be84749 100644
--- a/plugins/base/src/main/kotlin/allModulePage/MultimodulePageCreator.kt
+++ b/plugins/base/src/main/kotlin/allModulePage/MultimodulePageCreator.kt
@@ -43,7 +43,7 @@ class MultimodulePageCreator(
header(2, "All modules:")
table(styles = setOf(MultimoduleTable)) {
modules.mapNotNull { module ->
- val paragraph = module.docFile.let(::File).readText().let { parser.parse(it).firstParagraph() }
+ val paragraph = module.docFile.readText().let { parser.parse(it).firstParagraph() }
paragraph?.let {
val dri = DRI(packageName = MULTIMODULE_PACKAGE_PLACEHOLDER, classNames = module.name)
val dci = DCI(setOf(dri), ContentKind.Main)
@@ -68,10 +68,9 @@ class MultimodulePageCreator(
}
private fun throwOnMissingModuleDocFile(module: DokkaConfiguration.DokkaModuleDescription) {
- val docFile = File(module.docFile)
- if (!docFile.exists() || !docFile.isFile) {
+ if (!module.docFile.exists() || !module.docFile.isFile) {
throw DokkaException(
- "Missing documentation file for module ${module.name}: ${docFile.absolutePath}"
+ "Missing documentation file for module ${module.name}: ${module.docFile.absolutePath}"
)
}
}
diff --git a/plugins/base/src/main/kotlin/renderers/FileWriter.kt b/plugins/base/src/main/kotlin/renderers/FileWriter.kt
index 181295c0..cd38f1b9 100644
--- a/plugins/base/src/main/kotlin/renderers/FileWriter.kt
+++ b/plugins/base/src/main/kotlin/renderers/FileWriter.kt
@@ -21,10 +21,10 @@ class FileWriter(val context: DokkaContext): OutputWriter {
createdFiles.add(path)
try {
- val dir = Paths.get(root, path.dropLastWhile { it != '/' }).toFile()
+ val dir = Paths.get(root.absolutePath, path.dropLastWhile { it != '/' }).toFile()
withContext(Dispatchers.IO) {
dir.mkdirsOrFail()
- Files.write(Paths.get(root, "$path$ext"), text.lines())
+ Files.write(Paths.get(root.absolutePath, "$path$ext"), text.lines())
}
} catch (e: Throwable) {
context.logger.error("Failed to write $this. ${e.message}")
@@ -41,7 +41,7 @@ class FileWriter(val context: DokkaContext): OutputWriter {
private suspend fun copyFromDirectory(pathFrom: String, pathTo: String) {
- val dest = Paths.get(root, pathTo).toFile()
+ val dest = Paths.get(root.path, pathTo).toFile()
val uri = javaClass.getResource(pathFrom).toURI()
withContext(Dispatchers.IO) {
File(uri).copyRecursively(dest, true)
@@ -51,7 +51,7 @@ class FileWriter(val context: DokkaContext): OutputWriter {
private suspend fun copyFromJar(pathFrom: String, pathTo: String) {
val rebase = fun(path: String) =
"$pathTo/${path.removePrefix(pathFrom)}"
- val dest = Paths.get(root, pathTo).toFile()
+ val dest = Paths.get(root.path, pathTo).toFile()
dest.mkdirsOrFail()
val uri = javaClass.getResource(pathFrom).toURI()
val fs = getFileSystemForURI(uri)
@@ -60,12 +60,12 @@ class FileWriter(val context: DokkaContext): OutputWriter {
if (Files.isDirectory(file)) {
val dirPath = file.toAbsolutePath().toString()
withContext(Dispatchers.IO) {
- Paths.get(root, rebase(dirPath)).toFile().mkdirsOrFail()
+ Paths.get(root.path, rebase(dirPath)).toFile().mkdirsOrFail()
}
} else {
val filePath = file.toAbsolutePath().toString()
withContext(Dispatchers.IO) {
- Paths.get(root, rebase(filePath)).toFile().writeBytes(
+ Paths.get(root.path, rebase(filePath)).toFile().writeBytes(
this@FileWriter.javaClass.getResourceAsStream(filePath).readBytes()
)
}
@@ -85,4 +85,4 @@ class FileWriter(val context: DokkaContext): OutputWriter {
} catch (e: FileSystemAlreadyExistsException) {
FileSystems.getFileSystem(uri)
}
-} \ No newline at end of file
+}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationTransformer.kt
index 4a98a5e0..71824922 100644
--- a/plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationTransformer.kt
+++ b/plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationTransformer.kt
@@ -22,9 +22,9 @@ internal class ModuleAndPackageDocumentationTransformer(
val modulesAndPackagesDocumentation =
context.configuration.sourceSets
- .map {
- Pair(it.moduleDisplayName, it) to
- it.includes.map { Paths.get(it) }
+ .map { sourceSet ->
+ Pair(sourceSet.moduleDisplayName, sourceSet) to
+ sourceSet.includes.map { it.toPath() }
.also {
it.forEach {
if (Files.notExists(it))
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/SuppressedDocumentableFilterTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/SuppressedDocumentableFilterTransformer.kt
index 79feb832..7febabbb 100644
--- a/plugins/base/src/main/kotlin/transformers/documentables/SuppressedDocumentableFilterTransformer.kt
+++ b/plugins/base/src/main/kotlin/transformers/documentables/SuppressedDocumentableFilterTransformer.kt
@@ -45,7 +45,7 @@ class SuppressedDocumentableFilterTransformer(val context: DokkaContext) : PreMe
if (documentable !is WithExpectActual) return false
val sourceFile = File(source(documentable).path).absoluteFile
return sourceSet(documentable).suppressedFiles.any { suppressedFile ->
- sourceFile.startsWith(File(suppressedFile).absoluteFile)
+ sourceFile.startsWith(suppressedFile.absoluteFile)
}
}
}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/samples/SamplesTransformer.kt b/plugins/base/src/main/kotlin/transformers/pages/samples/SamplesTransformer.kt
index 695ef050..f13e52ab 100644
--- a/plugins/base/src/main/kotlin/transformers/pages/samples/SamplesTransformer.kt
+++ b/plugins/base/src/main/kotlin/transformers/pages/samples/SamplesTransformer.kt
@@ -43,16 +43,16 @@ abstract class SamplesTransformer(val context: DokkaContext) : PageTransformer {
}
}
- private fun setUpAnalysis(context: DokkaContext) = context.configuration.sourceSets.map {
- it to AnalysisEnvironment(DokkaMessageCollector(context.logger), it.analysisPlatform).run {
+ private fun setUpAnalysis(context: DokkaContext) = context.configuration.sourceSets.map { sourceSet ->
+ sourceSet to AnalysisEnvironment(DokkaMessageCollector(context.logger), sourceSet.analysisPlatform).run {
if (analysisPlatform == Platform.jvm) {
addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre())
}
- it.classpath.forEach { addClasspath(File(it)) }
+ sourceSet.classpath.forEach(::addClasspath)
- addSources(it.samples.map { it })
+ addSources(sourceSet.samples.toList())
- loadLanguageVersionSettings(it.languageVersion, it.apiVersion)
+ loadLanguageVersionSettings(sourceSet.languageVersion, sourceSet.apiVersion)
val environment = createCoreEnvironment()
val (facade, _) = createResolutionFacade(environment)
diff --git a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
index c4c6483f..1ac4edf7 100644
--- a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
@@ -95,7 +95,7 @@ private class DokkaDescriptorVisitor(
private fun Collection<DeclarationDescriptor>.filterDescriptorsInSourceSet() = filter {
it.toSourceElement.containingFile.toString().let { path ->
path.isNotBlank() && sourceSet.sourceRoots.any { root ->
- Paths.get(path).startsWith(Paths.get(root.path))
+ Paths.get(path).startsWith(root.directory.toPath())
}
}
}
@@ -356,7 +356,8 @@ private class DokkaDescriptorVisitor(
sources = actual,
visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
generics = descriptor.typeParameters.map { it.toTypeParameter() },
- documentation = descriptor.takeIf { it.kind != CallableMemberDescriptor.Kind.SYNTHESIZED }?.resolveDescriptorData() ?: emptyMap(),
+ documentation = descriptor.takeIf { it.kind != CallableMemberDescriptor.Kind.SYNTHESIZED }
+ ?.resolveDescriptorData() ?: emptyMap(),
modifier = descriptor.modifier().toSourceSetDependent(),
type = descriptor.returnType!!.toBound(),
sourceSets = setOf(sourceSet),
@@ -746,11 +747,19 @@ private class DokkaDescriptorVisitor(
private data class InheritanceLevel(val level: Int, val superclass: DRI?, val interfaces: List<DRI>)
- private data class ClassInfo(val inheritance: List<InheritanceLevel>, val docs: SourceSetDependent<DocumentationNode>){
+ private data class ClassInfo(
+ val inheritance: List<InheritanceLevel>,
+ val docs: SourceSetDependent<DocumentationNode>
+ ) {
val supertypes: List<DriWithKind>
get() = inheritance.firstOrNull { it.level == 0 }?.let {
- listOfNotNull(it.superclass?.let { DriWithKind(it, KotlinClassKindTypes.CLASS) }) + it.interfaces.map { DriWithKind(it, KotlinClassKindTypes.INTERFACE) }
- }.orEmpty()
+ listOfNotNull(it.superclass?.let {
+ DriWithKind(
+ it,
+ KotlinClassKindTypes.CLASS
+ )
+ }) + it.interfaces.map { DriWithKind(it, KotlinClassKindTypes.INTERFACE) }
+ }.orEmpty()
val allImplementedInterfaces: List<DRI>
get() = inheritance.flatMap { it.interfaces }.distinct()
diff --git a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
index 9ed37c30..cd43e635 100644
--- a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
@@ -43,8 +43,8 @@ class DefaultPsiToDocumentableTranslator(
override fun invoke(sourceSet: DokkaSourceSet, context: DokkaContext): DModule {
- fun isFileInSourceRoots(file: File) : Boolean {
- return sourceSet.sourceRoots.any { root -> file.path.startsWith(File(root.path).absolutePath) }
+ fun isFileInSourceRoots(file: File): Boolean {
+ return sourceSet.sourceRoots.any { root -> file.startsWith(root.directory) }
}
val (environment, _) = kotlinAnalysis[sourceSet]
@@ -133,7 +133,7 @@ class DefaultPsiToDocumentableTranslator(
val superMethods = mutableListOf<Pair<PsiMethod, DRI>>()
methods.forEach { superMethodsKeys.add(it.hash) }
fun parseSupertypes(superTypes: Array<PsiClassType>, level: Int = 0) {
- if(superTypes.isEmpty()) return
+ if (superTypes.isEmpty()) return
val parsedClasses = superTypes.filter { !it.shouldBeIgnored }.mapNotNull {
it.resolve()?.let {
when {
@@ -178,7 +178,8 @@ class DefaultPsiToDocumentableTranslator(
}) + it.interfaces.map { DriWithKind(dri = it, kind = JavaClassKindTypes.INTERFACE) }
}.toSourceSetDependent()
val modifiers = getModifier().toSourceSetDependent()
- val implementedInterfacesExtra = ImplementedInterfaces(inheritanceTree.flatMap { it.interfaces }.distinct().toSourceSetDependent())
+ val implementedInterfacesExtra =
+ ImplementedInterfaces(inheritanceTree.flatMap { it.interfaces }.distinct().toSourceSetDependent())
return when {
isAnnotationType ->
DAnnotation(
@@ -195,8 +196,11 @@ class DefaultPsiToDocumentableTranslator(
constructors.map { parseFunction(it, true) },
mapTypeParameters(dri),
setOf(sourceSetData),
- PropertyContainer.withAll(implementedInterfacesExtra, annotations.toList().toListOfAnnotations().toSourceSetDependent()
- .toAnnotations())
+ PropertyContainer.withAll(
+ implementedInterfacesExtra,
+ annotations.toList().toListOfAnnotations().toSourceSetDependent()
+ .toAnnotations()
+ )
)
isEnum -> DEnum(
dri,
@@ -211,8 +215,11 @@ class DefaultPsiToDocumentableTranslator(
emptyList(),
emptyList(),
setOf(sourceSetData),
- PropertyContainer.withAll(implementedInterfacesExtra, annotations.toList().toListOfAnnotations().toSourceSetDependent()
- .toAnnotations())
+ PropertyContainer.withAll(
+ implementedInterfacesExtra,
+ annotations.toList().toListOfAnnotations().toSourceSetDependent()
+ .toAnnotations()
+ )
)
},
documentation,
@@ -226,8 +233,10 @@ class DefaultPsiToDocumentableTranslator(
constructors.map { parseFunction(it, true) },
ancestors,
setOf(sourceSetData),
- PropertyContainer.withAll(implementedInterfacesExtra, annotations.toList().toListOfAnnotations().toSourceSetDependent()
- .toAnnotations())
+ PropertyContainer.withAll(
+ implementedInterfacesExtra, annotations.toList().toListOfAnnotations().toSourceSetDependent()
+ .toAnnotations()
+ )
)
isInterface -> DInterface(
dri,
@@ -243,8 +252,10 @@ class DefaultPsiToDocumentableTranslator(
mapTypeParameters(dri),
ancestors,
setOf(sourceSetData),
- PropertyContainer.withAll(implementedInterfacesExtra, annotations.toList().toListOfAnnotations().toSourceSetDependent()
- .toAnnotations())
+ PropertyContainer.withAll(
+ implementedInterfacesExtra, annotations.toList().toListOfAnnotations().toSourceSetDependent()
+ .toAnnotations()
+ )
)
else -> DClass(
dri,
@@ -262,8 +273,10 @@ class DefaultPsiToDocumentableTranslator(
null,
modifiers,
setOf(sourceSetData),
- PropertyContainer.withAll(implementedInterfacesExtra, annotations.toList().toListOfAnnotations().toSourceSetDependent()
- .toAnnotations())
+ PropertyContainer.withAll(
+ implementedInterfacesExtra, annotations.toList().toListOfAnnotations().toSourceSetDependent()
+ .toAnnotations()
+ )
)
}
}
@@ -305,7 +318,8 @@ class DefaultPsiToDocumentableTranslator(
PropertyContainer.withAll(
InheritedFunction(inheritedFrom.toSourceSetDependent()),
it.toSourceSetDependent().toAdditionalModifiers(),
- (psi.annotations.toList().toListOfAnnotations() + it.toListOfAnnotations()).toSourceSetDependent()
+ (psi.annotations.toList()
+ .toListOfAnnotations() + it.toListOfAnnotations()).toSourceSetDependent()
.toAnnotations()
)
}
@@ -434,7 +448,8 @@ class DefaultPsiToDocumentableTranslator(
psi.additionalExtras().let {
PropertyContainer.withAll<DProperty>(
it.toSourceSetDependent().toAdditionalModifiers(),
- (psi.annotations.toList().toListOfAnnotations() + it.toListOfAnnotations()).toSourceSetDependent()
+ (psi.annotations.toList()
+ .toListOfAnnotations() + it.toListOfAnnotations()).toSourceSetDependent()
.toAnnotations()
)
}
diff --git a/plugins/base/src/test/kotlin/expect/AbstractExpectTest.kt b/plugins/base/src/test/kotlin/expect/AbstractExpectTest.kt
index 4dfdc410..57571cd3 100644
--- a/plugins/base/src/test/kotlin/expect/AbstractExpectTest.kt
+++ b/plugins/base/src/test/kotlin/expect/AbstractExpectTest.kt
@@ -24,7 +24,7 @@ abstract class AbstractExpectTest(
var result: Path? = null
testFromData(config, cleanupOutput = false) {
- renderingStage = { _, context -> result = Paths.get(context.configuration.outputDir) }
+ renderingStage = { _, context -> result = context.configuration.outputDir.toPath() }
}
return result
}
diff --git a/plugins/base/src/test/kotlin/renderers/html/HtmlRenderingOnlyTestBase.kt b/plugins/base/src/test/kotlin/renderers/html/HtmlRenderingOnlyTestBase.kt
index b6765fda..ae494929 100644
--- a/plugins/base/src/test/kotlin/renderers/html/HtmlRenderingOnlyTestBase.kt
+++ b/plugins/base/src/test/kotlin/renderers/html/HtmlRenderingOnlyTestBase.kt
@@ -52,7 +52,7 @@ abstract class HtmlRenderingOnlyTestBase : RenderingOnlyTestBase<Element>() {
DokkaBase().externalLocationProviderFactory to { ::DokkaExternalLocationProviderFactory },
DokkaBase().tabSortingStrategy to { DefaultTabSortingStrategy() },
testConfiguration = DokkaConfigurationImpl(
- "", null, false, listOf(js, jvm, native), emptyList(), emptyMap(), emptyList(), false
+ sourceSets = listOf(js, jvm, native)
)
)
diff --git a/plugins/gfm/src/test/kotlin/renderers/gfm/DivergentTest.kt b/plugins/gfm/src/test/kotlin/renderers/gfm/DivergentTest.kt
index 0c8b942e..2381ad07 100644
--- a/plugins/gfm/src/test/kotlin/renderers/gfm/DivergentTest.kt
+++ b/plugins/gfm/src/test/kotlin/renderers/gfm/DivergentTest.kt
@@ -9,6 +9,7 @@ import org.jetbrains.dokka.pages.ContentDivergentGroup
import org.junit.jupiter.api.Test
import renderers.defaultSourceSet
import renderers.TestPage
+import java.io.File
class DivergentTest : GfmRenderingOnlyTestBase() {
private val js = defaultSourceSet.copy(
@@ -371,4 +372,4 @@ class DivergentTest : GfmRenderingOnlyTestBase() {
CommonmarkRenderer(context).render(page)
assert(renderedContent == expect)
}
-} \ No newline at end of file
+}
diff --git a/plugins/gfm/src/test/kotlin/renderers/gfm/GfmRenderingOnlyTestBase.kt b/plugins/gfm/src/test/kotlin/renderers/gfm/GfmRenderingOnlyTestBase.kt
index 6d0dd3a6..7c9590c6 100644
--- a/plugins/gfm/src/test/kotlin/renderers/gfm/GfmRenderingOnlyTestBase.kt
+++ b/plugins/gfm/src/test/kotlin/renderers/gfm/GfmRenderingOnlyTestBase.kt
@@ -21,9 +21,7 @@ abstract class GfmRenderingOnlyTestBase : RenderingOnlyTestBase<String>() {
DokkaBase().externalLocationProviderFactory to { ::DokkaExternalLocationProviderFactory },
GfmPlugin().gfmPreprocessors to { _ -> RootCreator },
- testConfiguration = DokkaConfigurationImpl(
- "", null, false, emptyList(), emptyList(), emptyMap(), emptyList(), false
- )
+ testConfiguration = DokkaConfigurationImpl()
)
override val renderedContent: String by lazy {
diff --git a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocPackageTemplateMapTest.kt b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocPackageTemplateMapTest.kt
index 447be3f8..89d5b286 100644
--- a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocPackageTemplateMapTest.kt
+++ b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocPackageTemplateMapTest.kt
@@ -8,6 +8,7 @@ import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
import org.jetbrains.dokka.testApi.utils.assertIsInstance
+import java.io.File
internal class JavadocPackageTemplateMapTest : AbstractJavadocTemplateMapTest() {
@@ -109,7 +110,7 @@ internal class JavadocPackageTemplateMapTest : AbstractJavadocTemplateMapTest()
configuration = config.copy(
sourceSets = config.sourceSets.map { sourceSet ->
sourceSet.copy(
- includes = listOf("packages.md")
+ includes = listOf(File("packages.md"))
)
}
)
diff --git a/runners/cli/src/main/kotlin/cli/main.kt b/runners/cli/src/main/kotlin/cli/main.kt
index f8d5c55c..df763596 100644
--- a/runners/cli/src/main/kotlin/cli/main.kt
+++ b/runners/cli/src/main/kotlin/cli/main.kt
@@ -17,11 +17,11 @@ class GlobalArguments(args: Array<String>) : DokkaConfiguration {
val json: String? by parser.argument(ArgType.String, description = "Json file name").optional()
- override val outputDir by parser.option(ArgType.String, description = "Output directory path")
+ override val outputDir by parser.option(ArgTypeFile, description = "Output directory path")
.default(DokkaDefaults.outputDir)
override val cacheRoot by parser.option(
- ArgType.String,
+ ArgTypeFile,
description = "Path to cache folder, or 'default' to use ~/.cache/dokka, if not provided caching is disabled"
)
@@ -132,12 +132,12 @@ private fun parseSourceSet(args: Array<String>): DokkaConfiguration.DokkaSourceS
).default(DokkaDefaults.sourceSetDisplayName)
val classpath by parser.option(
- ArgType.String,
+ ArgTypeFile,
description = "Classpath for symbol resolution (allows many paths separated by the semicolon `;`)"
).delimiter(";")
val sourceRoots by parser.option(
- ArgType.String,
+ ArgTypeFile,
description = "Source file or directory (allows many paths separated by the semicolon `;`)",
fullName = "src"
).delimiter(";")
@@ -148,12 +148,12 @@ private fun parseSourceSet(args: Array<String>): DokkaConfiguration.DokkaSourceS
).delimiter(";")
val samples by parser.option(
- ArgType.String,
+ ArgTypeFile,
description = "Source root for samples (allows many paths separated by the semicolon `;`)"
).delimiter(";")
val includes by parser.option(
- ArgType.String,
+ ArgTypeFile,
description = "Markdown files to load (allows many paths separated by the semicolon `;`)"
).delimiter(";")
@@ -196,7 +196,7 @@ private fun parseSourceSet(args: Array<String>): DokkaConfiguration.DokkaSourceS
.default(DokkaDefaults.noJdkLink)
val suppressedFiles by parser.option(
- ArgType.String,
+ ArgTypeFile,
description = "Paths to files to be suppressed (allows many paths separated by the semicolon `;`)"
).delimiter(";")
@@ -228,12 +228,12 @@ private fun parseSourceSet(args: Array<String>): DokkaConfiguration.DokkaSourceS
override val displayName = displayName
override val sourceSetID = DokkaSourceSetID(moduleName, sourceSetName)
override val classpath = classpath
- override val sourceRoots = sourceRoots.map { SourceRootImpl(it.toAbsolutePath()) }
+ override val sourceRoots = sourceRoots.map { SourceRootImpl(it) }
override val dependentSourceSets: Set<DokkaSourceSetID> = dependentSourceSets
.map { dependentSourceSetName -> dependentSourceSetName.split('/').let { DokkaSourceSetID(it[0], it[1]) } }
.toSet()
- override val samples = samples.map { it.toAbsolutePath() }
- override val includes = includes.map { it.toAbsolutePath() }
+ override val samples = samples
+ override val includes = includes
override val includeNonPublic = includeNonPublic
override val includeRootPackage = includeRootPackage
override val reportUndocumented = reportUndocumented
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaParentTask.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaParentTask.kt
new file mode 100644
index 00000000..bf8308bf
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaParentTask.kt
@@ -0,0 +1,73 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.Project
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.Internal
+import org.gradle.api.tasks.Nested
+import org.jetbrains.dokka.DokkaBootstrap
+import org.jetbrains.dokka.DokkaBootstrapImpl
+import kotlin.reflect.KClass
+
+// TODO NOW: Test UP-TO-DATE behaviour
+abstract class AbstractDokkaParentTask(
+ bootstrapClass: KClass<out DokkaBootstrap> = DokkaBootstrapImpl::class
+) : AbstractDokkaTask(bootstrapClass) {
+
+ @Input
+ open var dokkaTaskNames: Set<String> = setOf()
+
+ @Input
+ var subprojectPaths: Set<String> = project.subprojects.map { project -> project.path }.toSet()
+
+ @get:Internal
+ val subprojects: List<Project>
+ get() = subprojectPaths.map { path -> project.project(path) }.distinct()
+
+ @get:Nested
+ internal val dokkaTasks: List<AbstractDokkaTask>
+ get() = dokkaTaskNames.flatMap { dokkaTaskName -> findSubprojectDokkaTasks(dokkaTaskName) }
+
+
+ /**
+ * Will remove a single project from participating in this parent task.
+ * Note: This will not remove the [project]s subprojects.
+ *
+ * @see removeAllProjects
+ */
+ fun removeSubproject(project: Project) {
+ subprojectPaths = subprojectPaths - project.path
+ }
+
+ /**
+ * Will remove the [project] and all its subprojects from participating in this parent task.
+ * @see removeSubproject
+ */
+ fun removeAllProjects(project: Project) {
+ project.allprojects.forEach(::removeSubproject)
+ }
+
+ /**
+ * Includes the [project] to participate in this parent task.
+ * Note: This will not include any of the [project]s subprojects.
+ * @see addAllProjects
+ */
+ fun addSubproject(project: Project) {
+ subprojectPaths = (subprojectPaths + project.path)
+ }
+
+ /**
+ * Includes the [project] and all its subprojects to participate in this parent task.
+ * @see addSubproject
+ */
+ fun addAllProjects(project: Project) {
+ project.allprojects.forEach(::addSubproject)
+ }
+
+ protected fun findSubprojectDokkaTasks(dokkaTaskNames: Set<String>): List<AbstractDokkaTask> {
+ return dokkaTaskNames.flatMap { dokkaTaskName -> findSubprojectDokkaTasks(dokkaTaskName) }
+ }
+
+ private fun findSubprojectDokkaTasks(dokkaTaskName: String): List<AbstractDokkaTask> {
+ return subprojects.mapNotNull { subproject -> subproject.tasks.findByName(dokkaTaskName) as? DokkaTask }
+ }
+}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaTask.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaTask.kt
index 1269b305..6413d788 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaTask.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaTask.kt
@@ -1,21 +1,33 @@
package org.jetbrains.dokka.gradle
import org.gradle.api.DefaultTask
-import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
-import org.gradle.api.attributes.Usage
-import org.gradle.api.tasks.Classpath
-import org.gradle.api.tasks.Input
-import org.gradle.api.tasks.Internal
-import org.gradle.api.tasks.TaskAction
-import org.gradle.kotlin.dsl.dependencies
+import org.gradle.api.plugins.JavaBasePlugin
+import org.gradle.api.tasks.*
import org.jetbrains.dokka.DokkaBootstrap
+import org.jetbrains.dokka.DokkaConfigurationImpl
import org.jetbrains.dokka.plugability.Configurable
+import org.jetbrains.dokka.toJsonString
+import java.io.File
+import java.util.function.BiConsumer
+import kotlin.reflect.KClass
+abstract class AbstractDokkaTask(
+ private val bootstrapClass: KClass<out DokkaBootstrap> = DokkaBootstrap::class
+) : DefaultTask(), Configurable {
+
+ @OutputDirectory
+ var outputDirectory: File = defaultDokkaOutputDirectory()
+
+ @Optional
+ @InputDirectory
+ var cacheRoot: File? = null
+
+ @Input
+ var failOnWarning: Boolean = false
-abstract class AbstractDokkaTask : DefaultTask(), Configurable {
@Input
- var outputDirectory: String = defaultDokkaOutputDirectory().absolutePath
+ var offlineMode: Boolean = false
@Input
override val pluginsConfiguration: MutableMap<String, String> = mutableMapOf()
@@ -27,19 +39,26 @@ abstract class AbstractDokkaTask : DefaultTask(), Configurable {
val runtime: Configuration = project.maybeCreateDokkaRuntimeConfiguration(name)
@TaskAction
- protected fun run() {
- val kotlinColorsEnabledBefore = System.getProperty(DokkaTask.COLORS_ENABLED_PROPERTY) ?: "false"
- System.setProperty(DokkaTask.COLORS_ENABLED_PROPERTY, "false")
- try {
+ protected open fun generateDocumentation() {
+ DokkaBootstrap(runtime, bootstrapClass).apply {
+ configure(buildDokkaConfiguration().toJsonString(), createProxyLogger())
generate()
- } finally {
- System.setProperty(DokkaTask.COLORS_ENABLED_PROPERTY, kotlinColorsEnabledBefore)
}
}
- protected abstract fun generate()
+ internal abstract fun buildDokkaConfiguration(): DokkaConfigurationImpl
+
+ private fun createProxyLogger(): BiConsumer<String, String> = BiConsumer { level, message ->
+ when (level) {
+ "debug" -> logger.debug(message)
+ "info" -> logger.info(message)
+ "progress" -> logger.lifecycle(message)
+ "warn" -> logger.warn(message)
+ "error" -> logger.error(message)
+ }
+ }
- protected fun DokkaBootstrap(bootstrapClassFQName: String): DokkaBootstrap {
- return DokkaBootstrap(runtime, bootstrapClassFQName)
+ init {
+ group = JavaBasePlugin.DOCUMENTATION_GROUP
}
}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt
deleted file mode 100644
index 6217703f..00000000
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt
+++ /dev/null
@@ -1,185 +0,0 @@
-package org.jetbrains.dokka.gradle
-
-import org.gradle.api.Project
-import org.gradle.api.Task
-import org.gradle.api.UnknownDomainObjectException
-import org.gradle.api.artifacts.ResolveException
-import org.gradle.api.file.FileCollection
-import org.gradle.api.plugins.JavaPluginConvention
-import org.gradle.api.tasks.SourceSet
-import org.gradle.api.tasks.compile.AbstractCompile
-import org.jetbrains.dokka.ReflectDsl
-import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
-import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
-import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension
-import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
-import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
-import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-import java.io.File
-import java.io.Serializable
-
-class ConfigurationExtractor(private val project: Project) {
- fun extractConfiguration(sourceSetName: String): PlatformData? {
- val projectExtension = project.extensions.findByType(KotlinProjectExtension::class.java) ?: run {
- project.logger.error("Missing kotlin project extension")
- return null
- }
-
- val sourceSet = projectExtension.sourceSets.findByName(sourceSetName) ?: run {
- project.logger.error("No source set with name '$sourceSetName' found")
- return null
- }
-
- val compilation = try {
- when (projectExtension) {
- is KotlinMultiplatformExtension -> {
- val targets = projectExtension.targets.flatMap { it.compilations }
- targets.find { it.name == sourceSetName }
- ?: targets.find { it.kotlinSourceSets.contains(sourceSet) }
- }
- is KotlinSingleTargetExtension -> projectExtension.target.compilations.find {
- it.kotlinSourceSets.contains(sourceSet)
- }
- else -> null
- }
- } catch (e: NoClassDefFoundError) { // Old Kotlin plugin versions
- null
- }
-
- val sourceRoots = sourceSet.sourceFiles
- val classpath = compilation?.classpath
- ?: sourceRoots + sourceSet.allParentSourceFiles()
-
- return PlatformData(
- sourceSetName,
- classpath.filter { it.exists() },
- sourceRoots,
- sourceSet.dependsOn.map { it.name },
- compilation?.target?.platformType?.name ?: "common"
- )
- }
-
- private fun KotlinSourceSet.allParentSourceFiles(): List<File> =
- sourceFiles + dependsOn.flatMap { it.allParentSourceFiles() }
-
- fun extractFromJavaPlugin(): PlatformData? =
- project.convention.findPlugin(JavaPluginConvention::class.java)
- ?.run { sourceSets.findByName(SourceSet.MAIN_SOURCE_SET_NAME)?.allSource?.srcDirs }
- ?.let { PlatformData(null, emptyList(), it.toList(), emptyList(), "") }
-
- fun extractFromKotlinTasks(kotlinTasks: List<Task>): List<PlatformData> =
- try {
- kotlinTasks.map { extractFromKotlinTask(it) }
- } catch (e: Throwable) {
- when (e) {
- is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException ->
- listOfNotNull(extractFromKotlinTasksTheHardWay(kotlinTasks))
- else -> throw e
- }
- }
-
- private fun extractFromKotlinTask(task: Task): PlatformData =
- try {
- project.extensions.getByType(KotlinSingleTargetExtension::class.java).target
- .compilations
- .find { it.compileKotlinTask == task }
- } catch (e: Throwable) {
- when (e) {
- is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException ->
- project.extensions.getByType(KotlinMultiplatformExtension::class.java).targets
- .flatMap { it.compilations }.firstOrNull { it.compileKotlinTask == task }
- else -> throw e
- }
- }.let { compilation ->
- PlatformData(
- task.name,
- compilation?.classpath.orEmpty(),
- compilation?.sourceFiles.orEmpty(),
- compilation?.dependentSourceSets?.map { it.name }.orEmpty(),
- compilation?.platformType?.toString() ?: ""
- )
- }
-
- private fun extractFromKotlinTasksTheHardWay(kotlinTasks: List<Task>): PlatformData? {
- val allClasspath = mutableSetOf<File>()
- var allClasspathFileCollection: FileCollection = project.files()
- val allSourceRoots = mutableSetOf<File>()
-
- kotlinTasks.forEach {
- with(ReflectDsl) {
- val taskSourceRoots: List<File>
- val abstractKotlinCompileClz: Class<out Any>
- try {
- taskSourceRoots = it["sourceRootsContainer"]["sourceRoots"].v()
- abstractKotlinCompileClz = DokkaTask.getAbstractKotlinCompileFor(it)!!
- } catch (e: NullPointerException) {
- println("Error during extraction of sources from kotlinTasks. This may be a result of outdated Kotlin Gradle Plugin")
- return null
- }
-
- val taskClasspath: Iterable<File> =
- (it["getClasspath", AbstractCompile::class].takeIfIsFunc()?.invoke()
- ?: it["compileClasspath", abstractKotlinCompileClz].takeIfIsProp()?.v()
- ?: it["getClasspath", abstractKotlinCompileClz]())
-
- if (taskClasspath is FileCollection) {
- allClasspathFileCollection += taskClasspath
- } else {
- allClasspath += taskClasspath
- }
- allSourceRoots += taskSourceRoots.filter { it.exists() }
- }
- }
- val classpath: MutableList<File> = try {
- allClasspathFileCollection.toMutableList()
- } catch (e: ResolveException) {
- mutableListOf()
- }
- classpath.addAll(project.files(allClasspath).toList())
-
- return PlatformData(null, classpath, allSourceRoots.toList(), emptyList(), "")
- }
-
- private val KotlinCompilation<*>.sourceFiles: List<File>
- get() = kotlinSourceSets.flatMap { it.sourceFiles }
-
- private val KotlinSourceSet.sourceFiles: List<File>
- get() = kotlin.sourceDirectories.filter { it.exists() }.toList()
-
- private val KotlinCompilation<*>.dependentSourceSets: Set<KotlinSourceSet>
- get() = (allKotlinSourceSets - kotlinSourceSets)
-
- private val KotlinCompilation<*>.classpath: List<File>
- get() = if (target.isAndroidTarget()) {
- getClasspathFromAndroidTask(this)
- } else {
- getClasspathFromRegularTask(this)
- }
-
- // This is a workaround for KT-33893
- private fun getClasspathFromAndroidTask(compilation: KotlinCompilation<*>): List<File> = (compilation
- .compileKotlinTask as? KotlinCompile)
- ?.classpath?.files?.toList() ?: getClasspathFromRegularTask(compilation)
-
- private fun getClasspathFromRegularTask(compilation: KotlinCompilation<*>): List<File> {
- // explicit dependencies of the compilation
- val ownDependencyFiles: Set<File> = compilation.compileDependencyFiles.files
-
- // the dependencies provided by the platform (e.g. Kotlin/Native platform libs)
- val platformDependencyFiles: Set<File> = (compilation as? KotlinNativeCompilation)
- ?.target?.project?.configurations
- ?.findByName(compilation.defaultSourceSet.implementationMetadataConfigurationName)?.files
- ?: emptySet()
-
- return (ownDependencyFiles + platformDependencyFiles).toList().filter { it.exists() }
- }
-
- data class PlatformData(
- val name: String?,
- val classpath: List<File>,
- val sourceRoots: List<File>,
- val dependentSourceSets: List<String>,
- val platform: String
- ) : Serializable
-}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTask.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTask.kt
index 8d337795..7a73d633 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTask.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTask.kt
@@ -1,59 +1,24 @@
package org.jetbrains.dokka.gradle
-import com.google.gson.GsonBuilder
-import org.gradle.api.plugins.JavaBasePlugin.DOCUMENTATION_GROUP
-import org.gradle.api.tasks.Input
-import org.jetbrains.dokka.toJsonString
-
-open class DokkaCollectorTask : AbstractDokkaTask() {
-
- @Input
- var modules: List<String> = emptyList()
-
- @Input
- var dokkaTaskNames: Set<String> = setOf()
-
- override fun generate() {
- val configurations = getSubprojectDokkaTasks(dokkaTaskNames)
- .mapNotNull { dokkaTask -> dokkaTask.getConfigurationOrNull() }
-
- val initial = GradleDokkaConfigurationImpl().apply {
- outputDir = outputDirectory
- cacheRoot = configurations.first().cacheRoot
- }
-
- val configuration = configurations.fold(initial) { acc, it: GradleDokkaConfigurationImpl ->
- if (acc.cacheRoot != it.cacheRoot)
- throw IllegalStateException("Dokka task configurations differ on core argument cacheRoot")
- acc.sourceSets = acc.sourceSets + it.sourceSets
- acc.pluginsClasspath = (acc.pluginsClasspath + it.pluginsClasspath).distinct()
- acc
+import org.jetbrains.dokka.DokkaConfigurationImpl
+
+open class DokkaCollectorTask : AbstractDokkaParentTask() {
+
+ override fun buildDokkaConfiguration(): DokkaConfigurationImpl {
+ val initialDokkaConfiguration = DokkaConfigurationImpl(
+ outputDir = outputDirectory,
+ cacheRoot = cacheRoot,
+ failOnWarning = failOnWarning,
+ offlineMode = offlineMode,
+ pluginsClasspath = plugins.resolve().toList(),
+ )
+
+ val subprojectDokkaConfigurations = dokkaTasks.map { dokkaTask -> dokkaTask.buildDokkaConfiguration() }
+ return subprojectDokkaConfigurations.fold(initialDokkaConfiguration) { acc, it: DokkaConfigurationImpl ->
+ acc.copy(
+ sourceSets = acc.sourceSets + it.sourceSets,
+ pluginsClasspath = acc.pluginsClasspath + it.pluginsClasspath
+ )
}
-
- val bootstrap = DokkaBootstrap("org.jetbrains.dokka.DokkaBootstrapImpl")
- bootstrap.configure(configuration.toJsonString()) { level, message ->
- when (level) {
- "debug" -> logger.debug(message)
- "info" -> logger.info(message)
- "progress" -> logger.lifecycle(message)
- "warn" -> logger.warn(message)
- "error" -> logger.error(message)
- }
- }
- bootstrap.generate()
- }
-
- private fun getSubprojectDokkaTasks(dokkaTaskName: String): List<DokkaTask> {
- return project.subprojects
- .filter { subproject -> subproject.name in modules }
- .mapNotNull { subproject -> subproject.tasks.findByName(dokkaTaskName) as? DokkaTask }
- }
-
- private fun getSubprojectDokkaTasks(dokkaTaskNames: Set<String>): List<DokkaTask> {
- return dokkaTaskNames.flatMap { dokkaTaskName -> getSubprojectDokkaTasks(dokkaTaskName) }
- }
-
- init {
- group = DOCUMENTATION_GROUP
}
}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultimoduleTask.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultimoduleTask.kt
index 986b883a..8369954b 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultimoduleTask.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultimoduleTask.kt
@@ -1,66 +1,40 @@
package org.jetbrains.dokka.gradle
-import org.gradle.api.plugins.JavaBasePlugin.DOCUMENTATION_GROUP
+import org.gradle.api.internal.tasks.TaskDependencyInternal
import org.gradle.api.tasks.Input
-import org.gradle.api.tasks.Internal
+import org.jetbrains.dokka.DokkaConfigurationImpl
+import org.jetbrains.dokka.DokkaModuleDescriptionImpl
+import org.jetbrains.dokka.DokkaMultimoduleBootstrapImpl
import org.jetbrains.dokka.plugability.Configurable
-import org.jetbrains.dokka.toJsonString
-open class DokkaMultimoduleTask : AbstractDokkaTask(), Configurable {
+open class DokkaMultimoduleTask : AbstractDokkaParentTask(DokkaMultimoduleBootstrapImpl::class), Configurable {
+ /**
+ * Name of the file containing all necessary module information.
+ * This file has to be placed inside the subrpojects root directory.
+ */
@Input
var documentationFileName: String = "README.md"
-
- @Input
- var dokkaTaskNames: Set<String> = setOf()
- set(value) {
- field = value.toSet()
- setDependsOn(getSubprojectDokkaTasks(value))
- }
-
-
- override fun generate() {
- val bootstrap = DokkaBootstrap("org.jetbrains.dokka.DokkaMultimoduleBootstrapImpl")
- val configuration = getConfiguration()
- bootstrap.configure(configuration.toJsonString()) { level, message ->
- when (level) {
- "debug" -> logger.debug(message)
- "info" -> logger.info(message)
- "progress" -> logger.lifecycle(message)
- "warn" -> logger.warn(message)
- "error" -> logger.error(message)
- }
- }
- bootstrap.generate()
+ override fun getTaskDependencies(): TaskDependencyInternal {
+ return super.getTaskDependencies() + dokkaTasks
}
- @Internal
- internal fun getConfiguration(): GradleDokkaConfigurationImpl =
- GradleDokkaConfigurationImpl().apply {
- outputDir = project.file(outputDirectory).absolutePath
- pluginsClasspath = plugins.resolve().toList()
- pluginsConfiguration = this@DokkaMultimoduleTask.pluginsConfiguration
- modules = getSubprojectDokkaTasks(dokkaTaskNames).map { dokkaTask ->
- GradleDokkaModuleDescription().apply {
- name = dokkaTask.project.name
- path = dokkaTask.project.projectDir.resolve(dokkaTask.outputDirectory)
- .toRelativeString(project.file(outputDirectory))
- docFile = dokkaTask.project.projectDir.resolve(documentationFileName).absolutePath
- }
+ override fun buildDokkaConfiguration(): DokkaConfigurationImpl {
+ return DokkaConfigurationImpl(
+ outputDir = outputDirectory,
+ cacheRoot = cacheRoot,
+ pluginsConfiguration = pluginsConfiguration,
+ failOnWarning = failOnWarning,
+ offlineMode = offlineMode,
+ pluginsClasspath = plugins.resolve().toList(),
+ modules = dokkaTasks.map { dokkaTask ->
+ DokkaModuleDescriptionImpl(
+ name = dokkaTask.project.name,
+ path = dokkaTask.outputDirectory.relativeTo(outputDirectory),
+ docFile = dokkaTask.project.projectDir.resolve(documentationFileName).absoluteFile
+ )
}
- }
-
- private fun getSubprojectDokkaTasks(dokkaTaskName: String): List<DokkaTask> {
- return project.subprojects
- .mapNotNull { subproject -> subproject.tasks.findByName(dokkaTaskName) as? DokkaTask }
- }
-
- private fun getSubprojectDokkaTasks(dokkaTaskNames: Set<String>): List<DokkaTask> {
- return dokkaTaskNames.flatMap { dokkaTaskName -> getSubprojectDokkaTasks(dokkaTaskName) }
- }
-
- init {
- group = DOCUMENTATION_GROUP
+ )
}
}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt
index b4601acf..a74068ae 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt
@@ -1,306 +1,35 @@
package org.jetbrains.dokka.gradle
import org.gradle.api.NamedDomainObjectContainer
-import org.gradle.api.Project
-import org.gradle.api.Task
-import org.gradle.api.file.FileCollection
import org.gradle.api.internal.plugins.DslObject
-import org.gradle.api.plugins.JavaBasePlugin
-import org.gradle.api.tasks.*
-import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink.Builder
-import org.jetbrains.dokka.DokkaConfiguration.SourceRoot
-import org.jetbrains.dokka.DokkaException
-import org.jetbrains.dokka.Platform
-import org.jetbrains.dokka.ReflectDsl
-import org.jetbrains.dokka.ReflectDsl.isNotInstance
-import org.jetbrains.dokka.gradle.ConfigurationExtractor.PlatformData
-import org.jetbrains.dokka.toJsonString
-import java.io.File
-import java.net.URL
-import java.util.concurrent.Callable
+import org.gradle.api.tasks.Nested
+import org.jetbrains.dokka.DokkaBootstrapImpl
+import org.jetbrains.dokka.DokkaConfigurationImpl
+import org.jetbrains.dokka.build
-open class DokkaTask : AbstractDokkaTask() {
- private val ANDROID_REFERENCE_URL = Builder("https://developer.android.com/reference/").build()
-
- private val ANDROIDX_REFERENCE_URL = Builder(
- url = URL("https://developer.android.com/reference/kotlin/"),
- packageListUrl = URL("https://developer.android.com/reference/androidx/package-list")
- ).build()
-
- private val configExtractor = ConfigurationExtractor(project)
-
- @Suppress("MemberVisibilityCanBePrivate")
- fun defaultKotlinTasks(): List<Task> = with(ReflectDsl) {
- val abstractKotlinCompileClz = try {
- project.buildscript.classLoader.loadClass(ABSTRACT_KOTLIN_COMPILE)
- } catch (cnfe: ClassNotFoundException) {
- logger.warn("$ABSTRACT_KOTLIN_COMPILE class not found, default kotlin tasks ignored")
- return@with emptyList<Task>()
- }
-
- return@with project.tasks.filter { it isInstance abstractKotlinCompileClz }.filter { "Test" !in it.name }
- }
-
- init {
- group = JavaBasePlugin.DOCUMENTATION_GROUP
- description = "Generates dokka documentation for Kotlin"
-
- @Suppress("LeakingThis")
- dependsOn(Callable { kotlinTasks.map { it.taskDependencies } })
- }
-
- @Optional
- @Input
- var cacheRoot: String? = null
-
-
- /**
- * Hack used by DokkaCollector to enforce a different configuration to be used.
- */
- @get:Internal
- internal var enforcedConfiguration: GradleDokkaConfigurationImpl? = null
+open class DokkaTask : AbstractDokkaTask(DokkaBootstrapImpl::class) {
@get:Nested
- val dokkaSourceSets: NamedDomainObjectContainer<GradleDokkaSourceSet> =
- project.container(GradleDokkaSourceSet::class.java) { name -> GradleDokkaSourceSet(name, project) }
- .also { container -> DslObject(this).extensions.add("dokkaSourceSets", container) }
-
-
- private val kotlinTasks: List<Task> by lazy {
- extractKotlinCompileTasks(
- dokkaSourceSets.mapNotNull {
- it.collectKotlinTasks?.invoke()
- }.takeIf { it.isNotEmpty() }?.flatten() ?: defaultKotlinTasks()
- )
- }
-
- @Input
- var disableAutoconfiguration: Boolean = false
-
- @Input
- var failOnWarning: Boolean = false
-
- @Input
- var offlineMode: Boolean = false
-
- private var outputDiagnosticInfo: Boolean =
- false // Workaround for Gradle, which fires some methods (like collectConfigurations()) multiple times in its lifecycle
-
- protected fun extractKotlinCompileTasks(collectTasks: List<Any?>?): List<Task> {
- val inputList = (collectTasks ?: emptyList()).filterNotNull()
- val (paths, other) = inputList.partition { it is String }
-
- val tasksByPath = paths.map {
- project.tasks.findByPath(it as String) ?: throw IllegalArgumentException("Task with path '$it' not found")
- }
-
- other
- .filter { it !is Task || it isNotInstance getAbstractKotlinCompileFor(it) }
- .forEach { throw IllegalArgumentException("Illegal entry in kotlinTasks, must be subtype of $ABSTRACT_KOTLIN_COMPILE or String, but was $it") }
-
- tasksByPath
- .filter { it isNotInstance getAbstractKotlinCompileFor(it) }
- .forEach { throw IllegalArgumentException("Illegal task path in kotlinTasks, must be subtype of $ABSTRACT_KOTLIN_COMPILE, but was $it") }
-
- @Suppress("UNCHECKED_CAST")
- return (tasksByPath + other) as List<Task>
- }
-
- private fun Iterable<File>.toSourceRoots(): List<GradleSourceRootImpl> =
- this.filter { it.exists() }.map { GradleSourceRootImpl().apply { path = it.path } }
-
- private fun Iterable<String>.toProjects(): List<Project> =
- project.subprojects.toList().filter { this.contains(it.name) }
-
- protected open fun collectSuppressedFiles(sourceRoots: List<SourceRoot>) =
- if (project.isAndroidProject()) {
- val generatedRoot = project.buildDir.resolve("generated").absoluteFile
- sourceRoots
- .map { File(it.path) }
- .filter { it.startsWith(generatedRoot) }
- .flatMap { it.walk().toList() }
- .map { it.absolutePath }
- } else {
- emptyList()
- }
-
- override fun generate() = enforcedConfiguration?.let { generate(it) } ?: generate(getConfigurationOrThrow())
-
- protected open fun generate(configuration: GradleDokkaConfigurationImpl) {
- outputDiagnosticInfo = true
- val bootstrap = DokkaBootstrap("org.jetbrains.dokka.DokkaBootstrapImpl")
-
- bootstrap.configure(configuration.toJsonString()) { level, message ->
- when (level) {
- "debug" -> logger.debug(message)
- "info" -> logger.info(message)
- "progress" -> logger.lifecycle(message)
- "warn" -> logger.warn(message)
- "error" -> logger.error(message)
- }
- }
- bootstrap.generate()
- }
-
-
- @Internal
- internal fun getConfigurationOrNull(): GradleDokkaConfigurationImpl? {
- val defaultModulesConfiguration = configuredDokkaSourceSets
- .map { configureDefault(it) }.takeIf { it.isNotEmpty() }
- ?: listOf(
- configureDefault(configureDokkaSourceSet(dokkaSourceSets.create("main")))
- ).takeIf { project.isNotMultiplatformProject() } ?: emptyList()
-
- if (defaultModulesConfiguration.isEmpty()) {
- return null
- }
-
- return GradleDokkaConfigurationImpl().apply {
- outputDir = project.file(outputDirectory).absolutePath
- cacheRoot = this@DokkaTask.cacheRoot
- offlineMode = this@DokkaTask.offlineMode
- sourceSets = defaultModulesConfiguration
- pluginsClasspath = plugins.resolve().toList()
- pluginsConfiguration = this@DokkaTask.pluginsConfiguration
- failOnWarning = this@DokkaTask.failOnWarning
- }
- }
-
- @Internal
- internal fun getConfigurationOrThrow(): GradleDokkaConfigurationImpl {
- return getConfigurationOrNull() ?: throw DokkaException(
- """
- No source sets to document found.
- Make source to configure at least one source set e.g.
-
- tasks {
- dokkaHtml {
- dokkaSourceSets {
- register("commonMain") {
- displayName = "common"
- platform = "common"
- }
- }
+ val dokkaSourceSets: NamedDomainObjectContainer<GradleDokkaSourceSetBuilder> =
+ project.container(GradleDokkaSourceSetBuilder::class.java, GradleDokkaSourceSetBuilderFactory())
+ .also { container ->
+ DslObject(this).extensions.add("dokkaSourceSets", container)
+ project.findKotlinSourceSets().orEmpty().forEach { kotlinSourceSet ->
+ container.register(kotlinSourceSet.name) { dokkaSourceSet ->
+ dokkaSourceSet.configureWithKotlinSourceSetGist(kotlinSourceSet)
}
}
- """
- )
- }
-
- @get:Internal
- protected val configuredDokkaSourceSets: List<GradleDokkaSourceSet>
- get() = dokkaSourceSets.map { configureDokkaSourceSet(it) }
-
- private fun configureDokkaSourceSet(config: GradleDokkaSourceSet): GradleDokkaSourceSet {
- val userConfig = config
- .apply {
- collectKotlinTasks?.let {
- configExtractor.extractFromKotlinTasks(extractKotlinCompileTasks(it()))
- .fold(this) { config, platformData ->
- mergeUserConfigurationAndPlatformData(config, platformData)
- }
- }
- }
-
- if (disableAutoconfiguration) return userConfig
-
- return configExtractor.extractConfiguration(userConfig.name)
- ?.let { mergeUserConfigurationAndPlatformData(userConfig, it) }
- ?: if (this.dokkaSourceSets.isNotEmpty()) {
- if (outputDiagnosticInfo)
- logger.warn(
- "Could not find source set with name: ${userConfig.name} in Kotlin Gradle Plugin, " +
- "using only user provided configuration for this source set"
- )
- userConfig
- } else {
- if (outputDiagnosticInfo)
- logger.warn("Could not find source set with name: ${userConfig.name} in Kotlin Gradle Plugin")
- collectFromSinglePlatformOldPlugin(userConfig.name, userConfig)
}
- }
-
- private fun collectFromSinglePlatformOldPlugin(name: String, userConfig: GradleDokkaSourceSet) =
- kotlinTasks.find { it.name == name }
- ?.let { configExtractor.extractFromKotlinTasks(listOf(it)) }
- ?.singleOrNull()
- ?.let { mergeUserConfigurationAndPlatformData(userConfig, it) }
- ?: configExtractor.extractFromJavaPlugin()
- ?.let { mergeUserConfigurationAndPlatformData(userConfig, it) }
- ?: userConfig
-
- private fun mergeUserConfigurationAndPlatformData(
- userConfig: GradleDokkaSourceSet,
- autoConfig: PlatformData
- ) = userConfig.copy().apply {
- sourceRoots.addAll(userConfig.sourceRoots.union(autoConfig.sourceRoots.toSourceRoots()).distinct())
- dependentSourceSets.addAll(userConfig.dependentSourceSets)
- dependentSourceSets.addAll(autoConfig.dependentSourceSets.map { DokkaSourceSetID(project, it) })
- classpath = userConfig.classpath.union(autoConfig.classpath.map { it.absolutePath }).distinct()
- if (userConfig.platform == null && autoConfig.platform != "")
- platform = autoConfig.platform
- }
-
- private fun configureDefault(config: GradleDokkaSourceSet): GradleDokkaSourceSet {
- if (config.moduleDisplayName.isBlank()) {
- config.moduleDisplayName = project.name
- }
-
- if (config.displayName.isBlank()) {
- config.displayName = config.name.substringBeforeLast("Main", config.platform.toString())
- }
-
- if (project.isAndroidProject() && !config.noAndroidSdkLink) {
- config.externalDocumentationLinks.add(ANDROID_REFERENCE_URL)
- config.externalDocumentationLinks.add(ANDROIDX_REFERENCE_URL)
- }
-
- if (config.platform?.isNotBlank() == true) {
- config.analysisPlatform = dokkaPlatformFromString(config.platform.toString())
- }
- // Workaround for Groovy's GStringImpl
- config.classpath = (config.classpath as List<Any>).map { it.toString() }.distinct()
- config.sourceRoots = config.sourceRoots.distinct().toMutableList()
- config.samples = config.samples.map { project.file(it).absolutePath }
- config.includes = config.includes.map { project.file(it).absolutePath }
- config.suppressedFiles += collectSuppressedFiles(config.sourceRoots)
- config.suppressedFiles = config.suppressedFiles.map { project.file(it).absolutePath }
-
- return config
- }
-
- private fun dokkaPlatformFromString(platform: String) = when (platform.toLowerCase()) {
- "androidjvm", "android" -> Platform.jvm
- "metadata" -> Platform.common
- else -> Platform.fromString(platform)
- }
-
- // Needed for Gradle incremental build
- @OutputDirectory
- fun getOutputDirectoryAsFile(): File = project.file(outputDirectory)
-
- // Needed for Gradle incremental build
- @InputFiles
- fun getInputFiles(): FileCollection = configuredDokkaSourceSets.let { config ->
- project.files(config.flatMap { it.sourceRoots }.map { project.fileTree(File(it.path)) }) +
- project.files(config.flatMap { it.includes }) +
- project.files(config.flatMap { it.samples }.map { project.fileTree(File(it)) })
- }
-
- @Classpath
- fun getInputClasspath(): FileCollection =
- project.files((configuredDokkaSourceSets.flatMap { it.classpath } as List<Any>)
- .map { project.fileTree(File(it.toString())) })
-
- companion object {
- const val COLORS_ENABLED_PROPERTY = "kotlin.colors.enabled"
- const val ABSTRACT_KOTLIN_COMPILE = "org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile"
-
- internal fun getAbstractKotlinCompileFor(task: Task) = try {
- task.project.buildscript.classLoader.loadClass(ABSTRACT_KOTLIN_COMPILE)
- } catch (e: ClassNotFoundException) {
- null
- }
+ override fun buildDokkaConfiguration(): DokkaConfigurationImpl {
+ return DokkaConfigurationImpl(
+ outputDir = outputDirectory,
+ cacheRoot = cacheRoot,
+ offlineMode = offlineMode,
+ failOnWarning = failOnWarning,
+ sourceSets = dokkaSourceSets.build(),
+ pluginsConfiguration = pluginsConfiguration,
+ pluginsClasspath = plugins.resolve().toList()
+ )
}
}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt
new file mode 100644
index 00000000..e420e1a5
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt
@@ -0,0 +1,298 @@
+@file:Suppress("FunctionName")
+
+package org.jetbrains.dokka.gradle
+
+import com.android.build.gradle.api.AndroidSourceSet
+import com.fasterxml.jackson.annotation.JsonIgnore
+import groovy.lang.Closure
+import org.gradle.api.Action
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.api.tasks.*
+import org.gradle.util.ConfigureUtil
+import org.jetbrains.dokka.*
+import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
+import java.io.File
+import java.net.URL
+import org.jetbrains.kotlin.gradle.model.SourceSet as KotlinModelSourceSet
+
+
+internal fun Task.GradleDokkaSourceSetBuilderFactory(): (name: String) -> GradleDokkaSourceSetBuilder =
+ { name -> GradleDokkaSourceSetBuilder(name, project) }
+
+open class GradleDokkaSourceSetBuilder constructor(
+ @get:JsonIgnore @Transient @get:Input val name: String,
+ @get:JsonIgnore @Transient @get:Internal internal val project: Project
+) : DokkaConfigurationBuilder<DokkaSourceSetImpl> {
+
+ @Classpath
+ @Optional
+ var classpath: List<File> = emptyList()
+
+ @Input
+ @Optional
+ var moduleDisplayName: String? = null
+
+ @Input
+ @Optional
+ var displayName: String? = null
+
+ @get:Internal
+ val sourceSetID: DokkaSourceSetID = DokkaSourceSetID(project, name)
+
+ @Nested
+ var sourceRoots: MutableList<GradleSourceRootBuilder> = mutableListOf()
+
+ @Input
+ var dependentSourceSets: MutableSet<DokkaSourceSetID> = mutableSetOf()
+
+ @InputFiles
+ @Optional
+ var samples: List<File> = emptyList()
+
+ @InputFiles
+ @Optional
+ var includes: List<File> = emptyList()
+
+ @Input
+ var includeNonPublic: Boolean = DokkaDefaults.includeNonPublic
+
+ @Input
+ var includeRootPackage: Boolean = DokkaDefaults.includeRootPackage
+
+ @Input
+ var reportUndocumented: Boolean = DokkaDefaults.reportUndocumented
+
+ @Input
+ var skipEmptyPackages: Boolean = DokkaDefaults.skipEmptyPackages
+
+ @Input
+ var skipDeprecated: Boolean = DokkaDefaults.skipDeprecated
+
+ @Input
+ var jdkVersion: Int = DokkaDefaults.jdkVersion
+
+ @Nested
+ var sourceLinks: MutableList<GradleSourceLinkBuilder> = mutableListOf()
+
+ @Nested
+ var perPackageOptions: MutableList<GradlePackageOptionsBuilder> = mutableListOf()
+
+ @Nested
+ var externalDocumentationLinks: MutableList<GradleExternalDocumentationLinkBuilder> = mutableListOf()
+
+ @Input
+ @Optional
+ var languageVersion: String? = null
+
+ @Input
+ @Optional
+ var apiVersion: String? = null
+
+ @Input
+ var noStdlibLink: Boolean = DokkaDefaults.noStdlibLink
+
+ @Input
+ var noJdkLink: Boolean = DokkaDefaults.noJdkLink
+
+ @Input
+ var noAndroidSdkLink: Boolean = false
+
+ @Input
+ var suppressedFiles: List<File> = emptyList()
+
+ @Input
+ @Optional
+ var analysisPlatform: Platform? = null
+
+ @Input
+ @Optional
+ var platform: String? = null
+
+ fun DokkaSourceSetID(sourceSetName: String): DokkaSourceSetID {
+ return DokkaSourceSetID(project, sourceSetName)
+ }
+
+ fun dependsOn(sourceSet: SourceSet) {
+ dependsOn(DokkaSourceSetID(sourceSet.name))
+ }
+
+ fun dependsOn(sourceSet: GradleDokkaSourceSetBuilder) {
+ dependsOn(sourceSet.sourceSetID)
+ }
+
+ fun dependsOn(sourceSet: DokkaConfiguration.DokkaSourceSet) {
+ dependsOn(sourceSet.sourceSetID)
+ }
+
+ fun dependsOn(sourceSetName: String) {
+ dependsOn(DokkaSourceSetID(sourceSetName))
+ }
+
+ fun dependsOn(sourceSetID: DokkaSourceSetID) {
+ dependentSourceSets.add(sourceSetID)
+ }
+
+ // TODO NOW: Cover with tests
+ fun sourceRoot(c: Closure<Unit>) {
+ val configured = ConfigureUtil.configure(c, GradleSourceRootBuilder())
+ sourceRoots.add(configured)
+ }
+
+ fun sourceRoot(action: Action<in GradleSourceRootBuilder>) {
+ val sourceRoot = GradleSourceRootBuilder()
+ action.execute(sourceRoot)
+ sourceRoots.add(sourceRoot)
+ }
+
+ fun sourceLink(c: Closure<Unit>) {
+ val configured = ConfigureUtil.configure(c, GradleSourceLinkBuilder())
+ sourceLinks.add(configured)
+ }
+
+ fun sourceLink(action: Action<in GradleSourceLinkBuilder>) {
+ val sourceLink = GradleSourceLinkBuilder()
+ action.execute(sourceLink)
+ sourceLinks.add(sourceLink)
+ }
+
+ fun perPackageOption(c: Closure<Unit>) {
+ val configured = ConfigureUtil.configure(c, GradlePackageOptionsBuilder())
+ perPackageOptions.add(configured)
+ }
+
+ fun perPackageOption(action: Action<in GradlePackageOptionsBuilder>) {
+ val option = GradlePackageOptionsBuilder()
+ action.execute(option)
+ perPackageOptions.add(option)
+ }
+
+ fun externalDocumentationLink(c: Closure<Unit>) {
+ val link = ConfigureUtil.configure(c, GradleExternalDocumentationLinkBuilder())
+ externalDocumentationLinks.add(link)
+ }
+
+ fun externalDocumentationLink(action: Action<in GradleExternalDocumentationLinkBuilder>) {
+ val link = GradleExternalDocumentationLinkBuilder()
+ action.execute(link)
+ externalDocumentationLinks.add(link)
+ }
+
+ fun externalDocumentationLink(url: String, packageListUrl: String? = null) {
+ externalDocumentationLinks.add(
+ GradleExternalDocumentationLinkBuilder().apply {
+ this.url = URL(url)
+ this.packageListUrl = URL(packageListUrl)
+ }
+ )
+ }
+
+ fun externalDocumentationLink(url: URL, packageListUrl: URL? = null) {
+ externalDocumentationLinks.add(
+ GradleExternalDocumentationLinkBuilder().apply {
+ this.url = url
+ if (packageListUrl != null) {
+ this.packageListUrl = packageListUrl
+ }
+ }
+ )
+ }
+
+ override fun build(): DokkaSourceSetImpl {
+ val moduleDisplayName = moduleDisplayName ?: project.name
+
+ val displayName = displayName ?: name.substringBeforeLast("Main", platform.toString())
+
+ val externalDocumentationLinks = externalDocumentationLinks.map { it.build() }
+ .run {
+ if (noJdkLink) this
+ else this + ExternalDocumentationLink(
+ url =
+ if (jdkVersion < 11) "https://docs.oracle.com/javase/${jdkVersion}/docs/api/"
+ else "https://docs.oracle.com/en/java/javase/${jdkVersion}/docs/api/java.base/",
+ packageListUrl =
+ if (jdkVersion < 11) "https://docs.oracle.com/javase/${jdkVersion}/docs/api/package-list"
+ else "https://docs.oracle.com/en/java/javase/${jdkVersion}/docs/api/element-list"
+ )
+ }
+ .run {
+ if (noStdlibLink) this
+ else this + ExternalDocumentationLink("https://kotlinlang.org/api/latest/jvm/stdlib/")
+ }
+ .run {
+ if (noAndroidSdkLink || !project.isAndroidProject()) this
+ else this +
+ ExternalDocumentationLink("https://developer.android.com/reference/") +
+ ExternalDocumentationLink(
+ url = URL("https://developer.android.com/reference/kotlin/"),
+ packageListUrl = URL("https://developer.android.com/reference/androidx/package-list")
+ )
+ }
+
+ val analysisPlatform = when {
+ analysisPlatform != null -> checkNotNull(analysisPlatform)
+
+ platform?.isNotBlank() == true -> when (val platform = platform.toString().toLowerCase()) {
+ "androidjvm", "android" -> Platform.jvm
+ "metadata" -> Platform.common
+ else -> Platform.fromString(platform)
+ }
+
+ else -> Platform.DEFAULT
+ }
+
+ val sourceRoots = sourceRoots.build().distinct()
+
+ val suppressedFiles = suppressedFiles + project.collectSuppressedFiles(sourceRoots)
+
+ return DokkaSourceSetImpl(
+ classpath = classpath.distinct().toList(),
+ moduleDisplayName = moduleDisplayName,
+ displayName = displayName,
+ sourceSetID = sourceSetID,
+ sourceRoots = sourceRoots,
+ dependentSourceSets = dependentSourceSets.toSet(),
+ samples = samples.toList(),
+ includes = includes.toList(),
+ includeNonPublic = includeNonPublic,
+ includeRootPackage = includeRootPackage,
+ reportUndocumented = reportUndocumented,
+ skipEmptyPackages = skipEmptyPackages,
+ skipDeprecated = skipDeprecated,
+ jdkVersion = jdkVersion,
+ sourceLinks = sourceLinks.build(),
+ perPackageOptions = perPackageOptions.build(),
+ externalDocumentationLinks = externalDocumentationLinks,
+ languageVersion = languageVersion,
+ apiVersion = apiVersion,
+ noStdlibLink = noStdlibLink,
+ noJdkLink = noJdkLink,
+ suppressedFiles = suppressedFiles,
+ analysisPlatform = analysisPlatform
+ )
+ }
+}
+
+fun GradleDokkaSourceSetBuilder.dependsOn(sourceSet: KotlinModelSourceSet) {
+ dependsOn(DokkaSourceSetID(sourceSet.name))
+}
+
+fun GradleDokkaSourceSetBuilder.dependsOn(sourceSet: KotlinSourceSet) {
+ dependsOn(DokkaSourceSetID(sourceSet.name))
+}
+
+fun GradleDokkaSourceSetBuilder.dependsOn(sourceSet: AndroidSourceSet) {
+ dependsOn(DokkaSourceSetID(sourceSet.name))
+}
+
+// TODO NOW: Test
+private fun Project.collectSuppressedFiles(sourceRoots: List<DokkaConfiguration.SourceRoot>): List<File> =
+ if (project.isAndroidProject()) {
+ val generatedRoot = project.buildDir.resolve("generated").absoluteFile
+ sourceRoots
+ .map { it.directory }
+ .filter { it.startsWith(generatedRoot) }
+ .flatMap { it.walk().toList() }
+ } else {
+ emptyList()
+ }
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleExternalDocumentationLinkBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleExternalDocumentationLinkBuilder.kt
new file mode 100644
index 00000000..84ad6c1e
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleExternalDocumentationLinkBuilder.kt
@@ -0,0 +1,22 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.tasks.Input
+import org.jetbrains.dokka.DokkaConfigurationBuilder
+import org.jetbrains.dokka.ExternalDocumentationLink
+import org.jetbrains.dokka.ExternalDocumentationLinkImpl
+import java.net.URL
+
+class GradleExternalDocumentationLinkBuilder : DokkaConfigurationBuilder<ExternalDocumentationLinkImpl> {
+ @Input
+ var url: URL? = null
+
+ @Input
+ var packageListUrl: URL? = null
+
+ override fun build(): ExternalDocumentationLinkImpl {
+ return ExternalDocumentationLink(
+ url = checkNotNull(url) { "url not specified " },
+ packageListUrl = packageListUrl
+ )
+ }
+}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradlePackageOptionsBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradlePackageOptionsBuilder.kt
new file mode 100644
index 00000000..fdc0275e
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradlePackageOptionsBuilder.kt
@@ -0,0 +1,36 @@
+@file:Suppress("FunctionName")
+
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.tasks.Input
+import org.jetbrains.dokka.DokkaConfigurationBuilder
+import org.jetbrains.dokka.DokkaDefaults
+import org.jetbrains.dokka.PackageOptionsImpl
+
+
+class GradlePackageOptionsBuilder : DokkaConfigurationBuilder<PackageOptionsImpl> {
+ @Input
+ var prefix: String = ""
+
+ @Input
+ var includeNonPublic: Boolean = DokkaDefaults.includeNonPublic
+
+ @Input
+ var reportUndocumented: Boolean = DokkaDefaults.reportUndocumented
+
+ @Input
+ var skipDeprecated: Boolean = DokkaDefaults.skipDeprecated
+
+ @Input
+ var suppress: Boolean = DokkaDefaults.suppress
+
+ override fun build(): PackageOptionsImpl {
+ return PackageOptionsImpl(
+ prefix = prefix,
+ includeNonPublic = includeNonPublic,
+ reportUndocumented = reportUndocumented,
+ skipDeprecated = skipDeprecated,
+ suppress = suppress
+ )
+ }
+}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt
new file mode 100644
index 00000000..007575ec
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt
@@ -0,0 +1,25 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.tasks.Input
+import org.jetbrains.dokka.DokkaConfigurationBuilder
+import org.jetbrains.dokka.SourceLinkDefinitionImpl
+
+class GradleSourceLinkBuilder : DokkaConfigurationBuilder<SourceLinkDefinitionImpl> {
+ // TODO NOW: CHECK UP TO DATE
+ @Input
+ var path: String = ""
+
+ @Input
+ var url: String = ""
+
+ @Input
+ var lineSuffix: String? = null
+
+ override fun build(): SourceLinkDefinitionImpl {
+ return SourceLinkDefinitionImpl(
+ path = path,
+ url = url,
+ lineSuffix = lineSuffix
+ )
+ }
+}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceRootBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceRootBuilder.kt
new file mode 100644
index 00000000..687dec9c
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceRootBuilder.kt
@@ -0,0 +1,15 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.tasks.InputDirectory
+import org.jetbrains.dokka.DokkaConfigurationBuilder
+import org.jetbrains.dokka.SourceRootImpl
+import java.io.File
+
+class GradleSourceRootBuilder : DokkaConfigurationBuilder<SourceRootImpl> {
+ @InputDirectory
+ var directory: File? = null
+
+ override fun build(): SourceRootImpl {
+ return SourceRootImpl(checkNotNull(directory) { "directory not set" })
+ }
+}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/KotlinSourceSetGist.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/KotlinSourceSetGist.kt
new file mode 100644
index 00000000..334aae15
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/KotlinSourceSetGist.kt
@@ -0,0 +1,105 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.Project
+import org.jetbrains.dokka.utilities.cast
+import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
+import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
+import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
+import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension
+import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
+import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+import java.io.File
+
+private typealias KotlinCompilation =
+ org.jetbrains.kotlin.gradle.plugin.KotlinCompilation<KotlinCommonOptions>
+
+internal data class KotlinSourceSetGist(
+ val name: String,
+ val platform: String,
+ val classpath: List<File>,
+ val sourceRoots: List<File>,
+ val dependentSourceSets: List<String>,
+)
+
+/**
+ * @return null if the kotlin extension cannot be found,
+ * A list of [KotlinSourceSetGist] for every currently registered kotlin source set
+ */
+internal fun Project.findKotlinSourceSets(): List<KotlinSourceSetGist>? {
+ val kotlin = kotlinExtensionOrNull ?: return null
+ return kotlin.sourceSets.map { sourceSet -> kotlin.gistOf(sourceSet) }
+}
+
+internal fun KotlinProjectExtension.gistOf(sourceSet: KotlinSourceSet): KotlinSourceSetGist {
+ return KotlinSourceSetGist(
+ name = sourceSet.name,
+ platform = platformOf(sourceSet),
+ classpath = classpathOf(sourceSet).filter(File::exists),
+ sourceRoots = sourceSet.kotlin.sourceDirectories.toList().filter(File::exists),
+ dependentSourceSets = sourceSet.dependsOn.map { dependentSourceSet -> dependentSourceSet.name },
+ )
+}
+
+private fun KotlinProjectExtension.classpathOf(sourceSet: KotlinSourceSet): List<File> {
+ val compilations = compilationsOf(sourceSet)
+ if (compilations.isNotEmpty()) {
+ return compilations
+ .flatMap { compilation -> compileClasspathOf(compilation) }
+ .distinct()
+ }
+
+ return sourceSet.withAllDependentSourceSets()
+ .toList()
+ .flatMap { it.kotlin.sourceDirectories }
+}
+
+private fun KotlinProjectExtension.platformOf(sourceSet: KotlinSourceSet): String {
+ val targetNames = compilationsOf(sourceSet).map { compilation -> compilation.target.platformType.name }.distinct()
+ return when (targetNames.size) {
+ 0 -> KotlinPlatformType.common.name
+ 1 -> targetNames.single()
+ else -> throw IllegalArgumentException(
+ "Source set ${sourceSet.name} is expected to have only one target. Found $targetNames"
+ )
+ }
+}
+
+private fun KotlinProjectExtension.compilationsOf(
+ sourceSet: KotlinSourceSet
+): List<KotlinCompilation> {
+ return when (this) {
+ is KotlinMultiplatformExtension -> compilationsOf(sourceSet)
+ is KotlinSingleTargetExtension -> compilationsOf(sourceSet)
+ else -> emptyList()
+ }
+}
+
+private fun KotlinMultiplatformExtension.compilationsOf(sourceSet: KotlinSourceSet): List<KotlinCompilation> {
+ val allCompilations = targets.flatMap { target -> target.compilations }
+ return allCompilations.filter { compilation -> sourceSet in compilation.kotlinSourceSets }
+}
+
+private fun KotlinSingleTargetExtension.compilationsOf(sourceSet: KotlinSourceSet): List<KotlinCompilation> {
+ return target.compilations.filter { compilation -> sourceSet in compilation.kotlinSourceSets }
+}
+
+private fun compileClasspathOf(compilation: KotlinCompilation): List<File> {
+ if (compilation.target.isAndroidTarget()) {
+ // This is a workaround for https://youtrack.jetbrains.com/issue/KT-33893
+ return compilation.compileKotlinTask.cast<KotlinCompile>().classpath.files.toList()
+ }
+ return compilation.compileDependencyFiles.files.toList()
+}
+
+private fun KotlinSourceSet.withAllDependentSourceSets(): Sequence<KotlinSourceSet> {
+ return sequence {
+ yield(this@withAllDependentSourceSets)
+ for (dependentSourceSet in dependsOn) {
+ yieldAll(dependentSourceSet.withAllDependentSourceSets())
+ }
+ }
+}
+
+
+
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ReflectDsl.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ReflectDsl.kt
deleted file mode 100644
index 4b511022..00000000
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ReflectDsl.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.jetbrains.dokka
-
-import kotlin.reflect.*
-import kotlin.reflect.full.memberFunctions
-import kotlin.reflect.full.memberProperties
-import kotlin.reflect.jvm.isAccessible
-
-internal object ReflectDsl {
-
- class CallOrPropAccess(private val receiver: Any?,
- private val clz: KClass<*>,
- private val selector: String) {
-
- @Suppress("UNCHECKED_CAST")
- operator fun <T : Any?> invoke(vararg a: Any?): T {
- return func!!.call(receiver, *a) as T
- }
-
- operator fun get(s: String): CallOrPropAccess {
- return v<Any?>()!![s]
- }
-
- val func: KFunction<*>? by lazy { clz.memberFunctions.find { it.name == selector } }
- val prop: KProperty<*>? by lazy { clz.memberProperties.find { it.name == selector } }
-
- fun takeIfIsFunc(): CallOrPropAccess? = if (func != null) this else null
-
- fun takeIfIsProp(): CallOrPropAccess? = if (prop != null) this else null
-
- @Suppress("UNCHECKED_CAST")
- fun <T : Any?> v(): T {
- val prop = prop!!
- return try {
- prop.getter.apply { isAccessible = true }.call(receiver) as T
- } catch (e: KotlinNullPointerException) {
- // Hack around kotlin-reflect bug KT-18480
- val jclass = clz.java
- val customGetterName = prop.getter.name
- val getterName = if (customGetterName.startsWith("<")) "get" + prop.name.capitalize() else customGetterName
- val getter = jclass.getDeclaredMethod(getterName)
- getter.isAccessible = true
-
- getter.invoke(receiver) as T
-
- }
- }
-
- @Suppress("UNCHECKED_CAST")
- fun v(x: Any?) {
- (prop as KMutableProperty).setter.apply { isAccessible = true }.call(receiver, x)
- }
-
-
- }
-
- operator fun Any.get(s: String): CallOrPropAccess {
- val clz = this.javaClass.kotlin
- return CallOrPropAccess(this, clz, s)
- }
-
- operator fun Any.get(s: String, clz: Class<*>): CallOrPropAccess {
- val kclz = clz.kotlin
- return CallOrPropAccess(this, kclz, s)
- }
-
- operator fun Any.get(s: String, clz: KClass<*>): CallOrPropAccess {
- return CallOrPropAccess(this, clz, s)
- }
-
- inline infix fun Any.isInstance(clz: Class<*>?): Boolean = clz != null && clz.isAssignableFrom(this.javaClass)
- inline infix fun Any.isNotInstance(clz: Class<*>?): Boolean = !(this isInstance clz)
-} \ No newline at end of file
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/TaskDependencyInternalWithAdditions.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/TaskDependencyInternalWithAdditions.kt
new file mode 100644
index 00000000..fb648c02
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/TaskDependencyInternalWithAdditions.kt
@@ -0,0 +1,20 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.Task
+import org.gradle.api.internal.tasks.AbstractTaskDependency
+import org.gradle.api.internal.tasks.TaskDependencyInternal
+import org.gradle.api.internal.tasks.TaskDependencyResolveContext
+
+operator fun TaskDependencyInternal.plus(tasks: Iterable<Task>): TaskDependencyInternal {
+ return TaskDependencyInternalWithAdditions(this, tasks.toSet())
+}
+
+private class TaskDependencyInternalWithAdditions(
+ private val dependency: TaskDependencyInternal,
+ private val additionalTaskDependencies: Set<Task>
+) : AbstractTaskDependency() {
+ override fun visitDependencies(context: TaskDependencyResolveContext) {
+ dependency.visitDependencies(context)
+ additionalTaskDependencies.forEach(context::add)
+ }
+}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ProxyUtils.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/automagicTypedProxy.kt
index 468f597f..13f9c2ff 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ProxyUtils.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/automagicTypedProxy.kt
@@ -1,6 +1,9 @@
package org.jetbrains.dokka.gradle
-import java.lang.reflect.*
+import java.lang.reflect.InvocationHandler
+import java.lang.reflect.InvocationTargetException
+import java.lang.reflect.Method
+import java.lang.reflect.Proxy
/**
@@ -21,14 +24,14 @@ internal inline fun <reified T : Any> automagicTypedProxy(targetClassLoader: Cla
* to create access proxy for [delegate] into [targetClassLoader].
*
*/
-internal fun automagicProxy(targetClassLoader: ClassLoader, targetType: Class<*>, delegate: Any): Any =
+private fun automagicProxy(targetClassLoader: ClassLoader, targetType: Class<*>, delegate: Any): Any =
Proxy.newProxyInstance(
targetClassLoader,
arrayOf(targetType),
DelegatedInvocationHandler(delegate)
)
-internal class DelegatedInvocationHandler(private val delegate: Any) : InvocationHandler {
+private class DelegatedInvocationHandler(private val delegate: Any) : InvocationHandler {
@Throws(Throwable::class)
override fun invoke(proxy: Any, method: Method, args: Array<Any?>?): Any? {
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/configurationImplementations.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/configurationImplementations.kt
deleted file mode 100644
index bed73d6d..00000000
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/configurationImplementations.kt
+++ /dev/null
@@ -1,259 +0,0 @@
-@file:Suppress("FunctionName")
-
-package org.jetbrains.dokka.gradle
-
-import com.android.build.gradle.api.AndroidSourceSet
-import com.fasterxml.jackson.annotation.JsonIgnore
-import groovy.lang.Closure
-import org.gradle.api.Action
-import org.gradle.api.Project
-import org.gradle.api.tasks.Input
-import org.gradle.api.tasks.Internal
-import org.gradle.api.tasks.Optional
-import org.gradle.util.ConfigureUtil
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.DokkaConfiguration.*
-import org.jetbrains.dokka.DokkaDefaults
-import org.jetbrains.dokka.DokkaSourceSetID
-import org.jetbrains.dokka.Platform
-import java.io.File
-import java.net.URL
-import java.util.concurrent.Callable
-import kotlin.reflect.KMutableProperty
-import kotlin.reflect.full.memberProperties
-import org.gradle.api.tasks.SourceSet as GradleSourceSet
-import org.jetbrains.kotlin.gradle.model.SourceSet as KotlinSourceSet
-
-class GradleSourceRootImpl : SourceRoot {
- override var path: String = ""
- set(value) {
- field = File(value).absolutePath
- }
-
- override fun toString(): String = path
-}
-
-open class GradleDokkaSourceSet constructor(
- @get:JsonIgnore @Transient @get:Input val name: String,
- @get:JsonIgnore @Transient @get:Internal internal val project: Project
-) : DokkaSourceSet {
-
- @Input
- @Optional
- override var classpath: List<String> = emptyList()
-
- @Input
- override var moduleDisplayName: String = ""
-
- @Input
- override var displayName: String = ""
-
- @get:Internal
- override val sourceSetID: DokkaSourceSetID = DokkaSourceSetID(project, name)
-
- @Input
- override var sourceRoots: MutableList<SourceRoot> = mutableListOf()
-
- @Input
- override var dependentSourceSets: MutableSet<DokkaSourceSetID> = mutableSetOf()
-
- @Input
- override var samples: List<String> = emptyList()
-
- @Input
- override var includes: List<String> = emptyList()
-
- @Input
- override var includeNonPublic: Boolean = DokkaDefaults.includeNonPublic
-
- @Input
- override var includeRootPackage: Boolean = DokkaDefaults.includeRootPackage
-
- @Input
- override var reportUndocumented: Boolean = DokkaDefaults.reportUndocumented
-
- @Input
- override var skipEmptyPackages: Boolean = DokkaDefaults.skipEmptyPackages
-
- @Input
- override var skipDeprecated: Boolean = DokkaDefaults.skipDeprecated
-
- @Input
- override var jdkVersion: Int = DokkaDefaults.jdkVersion
-
- @Input
- override var sourceLinks: MutableList<SourceLinkDefinition> = mutableListOf()
-
- @Input
- override var perPackageOptions: MutableList<PackageOptions> = mutableListOf()
-
- @Input
- override var externalDocumentationLinks: MutableList<ExternalDocumentationLink> = mutableListOf()
-
- @Input
- @Optional
- override var languageVersion: String? = null
-
- @Input
- @Optional
- override var apiVersion: String? = null
-
- @Input
- override var noStdlibLink: Boolean = DokkaDefaults.noStdlibLink
-
- @Input
- override var noJdkLink: Boolean = DokkaDefaults.noJdkLink
-
- @Input
- var noAndroidSdkLink: Boolean = false
-
- @Input
- override var suppressedFiles: List<String> = emptyList()
-
- @Input
- override var analysisPlatform: Platform = DokkaDefaults.analysisPlatform
-
- @Input
- @Optional
- var platform: String? = null
-
- @JsonIgnore
- @Internal
- @Transient
- var collectKotlinTasks: (() -> List<Any?>?)? = null
-
- fun DokkaSourceSetID(sourceSetName: String): DokkaSourceSetID {
- return DokkaSourceSetID(project, sourceSetName)
- }
-
- fun dependsOn(sourceSet: GradleSourceSet) {
- dependsOn(DokkaSourceSetID(sourceSet.name))
- }
-
- fun dependsOn(sourceSet: DokkaSourceSet) {
- dependsOn(sourceSet.sourceSetID)
- }
-
- fun dependsOn(sourceSetName: String) {
- dependsOn(DokkaSourceSetID(sourceSetName))
- }
-
- fun dependsOn(sourceSetID: DokkaSourceSetID) {
- dependentSourceSets.add(sourceSetID)
- }
-
- fun kotlinTasks(taskSupplier: Callable<List<Any>>) {
- collectKotlinTasks = { taskSupplier.call() }
- }
-
- fun kotlinTasks(closure: Closure<Any?>) {
- collectKotlinTasks = { closure.call() as? List<Any?> }
- }
-
- fun sourceRoot(c: Closure<Unit>) {
- val configured = ConfigureUtil.configure(c, GradleSourceRootImpl())
- sourceRoots.add(configured)
- }
-
- fun sourceRoot(action: Action<in GradleSourceRootImpl>) {
- val sourceRoot = GradleSourceRootImpl()
- action.execute(sourceRoot)
- sourceRoots.add(sourceRoot)
- }
-
- fun sourceLink(c: Closure<Unit>) {
- val configured = ConfigureUtil.configure(c, GradleSourceLinkDefinitionImpl())
- sourceLinks.add(configured)
- }
-
- fun sourceLink(action: Action<in GradleSourceLinkDefinitionImpl>) {
- val sourceLink = GradleSourceLinkDefinitionImpl()
- action.execute(sourceLink)
- sourceLinks.add(sourceLink)
- }
-
- fun perPackageOption(c: Closure<Unit>) {
- val configured = ConfigureUtil.configure(c, GradlePackageOptionsImpl())
- perPackageOptions.add(configured)
- }
-
- fun perPackageOption(action: Action<in GradlePackageOptionsImpl>) {
- val option = GradlePackageOptionsImpl()
- action.execute(option)
- perPackageOptions.add(option)
- }
-
- fun externalDocumentationLink(c: Closure<Unit>) {
- val link = ConfigureUtil.configure(c, GradleExternalDocumentationLinkImpl())
- externalDocumentationLinks.add(ExternalDocumentationLink.Builder(link.url, link.packageListUrl).build())
- }
-
- fun externalDocumentationLink(action: Action<in GradleExternalDocumentationLinkImpl>) {
- val link = GradleExternalDocumentationLinkImpl()
- action.execute(link)
- externalDocumentationLinks.add(ExternalDocumentationLink.Builder(link.url, link.packageListUrl).build())
- }
-}
-
-fun GradleDokkaSourceSet.dependsOn(sourceSet: KotlinSourceSet) {
- dependsOn(DokkaSourceSetID(sourceSet.name))
-}
-
-fun GradleDokkaSourceSet.dependsOn(sourceSet: org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet) {
- dependsOn(DokkaSourceSetID(sourceSet.name))
-}
-
-fun GradleDokkaSourceSet.dependsOn(sourceSet: AndroidSourceSet) {
- dependsOn(DokkaSourceSetID(sourceSet.name))
-}
-
-class GradleSourceLinkDefinitionImpl : SourceLinkDefinition {
- override var path: String = ""
- override var url: String = ""
- override var lineSuffix: String? = null
-}
-
-class GradleExternalDocumentationLinkImpl : ExternalDocumentationLink {
- override var url: URL = URL("http://")
- override var packageListUrl: URL = URL("http://")
-}
-
-class GradleDokkaModuleDescription : DokkaModuleDescription {
- override var name: String = ""
- override var path: String = ""
- override var docFile: String = ""
-}
-
-class GradleDokkaConfigurationImpl : DokkaConfiguration {
- override var outputDir: String = ""
- override var cacheRoot: String? = DokkaDefaults.cacheRoot
- override var offlineMode: Boolean = DokkaDefaults.offlineMode
- override var failOnWarning: Boolean = DokkaDefaults.failOnWarning
- override var sourceSets: List<GradleDokkaSourceSet> = emptyList()
- override var pluginsClasspath: List<File> = emptyList()
- override var pluginsConfiguration: Map<String, String> = mutableMapOf()
- override var modules: List<GradleDokkaModuleDescription> = emptyList()
-}
-
-class GradlePackageOptionsImpl : PackageOptions {
- override var prefix: String = ""
- override var includeNonPublic: Boolean = DokkaDefaults.includeNonPublic
- override var reportUndocumented: Boolean = DokkaDefaults.reportUndocumented
- override var skipDeprecated: Boolean = DokkaDefaults.skipDeprecated
- override var suppress: Boolean = DokkaDefaults.suppress
-}
-
-internal fun GradleDokkaSourceSet.copy(): GradleDokkaSourceSet {
- val newObj = GradleDokkaSourceSet(this.name, this.project)
- this::class.memberProperties.forEach { field ->
- if (field is KMutableProperty<*>) {
- when (val value = field.getter.call(this)) {
- is List<*> -> field.setter.call(newObj, value.toMutableList())
- is Set<*> -> field.setter.call(newObj, value.toMutableSet())
- else -> field.setter.call(newObj, field.getter.call(this))
- }
-
- }
- }
- return newObj
-}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokka.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokka.kt
new file mode 100644
index 00000000..2625f64c
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokka.kt
@@ -0,0 +1,7 @@
+import org.gradle.api.Project
+import org.gradle.kotlin.dsl.withType
+import org.jetbrains.dokka.gradle.DokkaTask
+
+fun Project.dokka(configuration: DokkaTask.() -> Unit) {
+ tasks.withType<DokkaTask>().configureEach(configuration)
+}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaBootstrapFactory.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaBootstrapFactory.kt
index df29c19b..8a40ac89 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaBootstrapFactory.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaBootstrapFactory.kt
@@ -1,18 +1,21 @@
+@file:Suppress("FunctionName")
+
package org.jetbrains.dokka.gradle
import org.gradle.api.artifacts.Configuration
import org.jetbrains.dokka.DokkaBootstrap
import java.net.URLClassLoader
+import kotlin.reflect.KClass
-fun DokkaBootstrap(configuration: Configuration, bootstrapClassFQName: String): DokkaBootstrap {
+fun DokkaBootstrap(configuration: Configuration, bootstrapClass: KClass<out DokkaBootstrap>): DokkaBootstrap {
val runtimeJars = configuration.resolve()
val runtimeClassLoader = URLClassLoader(
runtimeJars.map { it.toURI().toURL() }.toTypedArray(),
ClassLoader.getSystemClassLoader().parent
)
- val bootstrapClass = runtimeClassLoader.loadClass(bootstrapClassFQName)
- val bootstrapInstance = bootstrapClass.constructors.first().newInstance()
- return automagicTypedProxy(DokkaPlugin::class.java.classLoader, bootstrapInstance)
+ val runtimeClassloaderBootstrapClass = runtimeClassLoader.loadClass(bootstrapClass.qualifiedName)
+ val runtimeClassloaderBootstrapInstance = runtimeClassloaderBootstrapClass.constructors.first().newInstance()
+ return automagicTypedProxy(DokkaPlugin::class.java.classLoader, runtimeClassloaderBootstrapInstance)
}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/defaultDokkaOutputDirectory.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaDefaultOutputDirectory.kt
index 0a7ab534..0a7ab534 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/defaultDokkaOutputDirectory.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaDefaultOutputDirectory.kt
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaSourceSetIDFactory.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaSourceSetIDFactory.kt
index 3fadb4fd..3fadb4fd 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaSourceSetIDFactory.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaSourceSetIDFactory.kt
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaConfigurations.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/gradleConfigurations.kt
index 20f54cc5..20f54cc5 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaConfigurations.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/gradleConfigurations.kt
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt
index 51356703..71fad405 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt
@@ -53,7 +53,6 @@ open class DokkaPlugin : Plugin<Project> {
}
if (collectorTaskSupported) {
project.tasks.register<DokkaCollectorTask>("${name}Collector") {
- modules = project.subprojects.map(Project::getName)
dokkaTaskNames = dokkaTaskNames + name
}
}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/sourceSetKotlinGistConfiguration.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/sourceSetKotlinGistConfiguration.kt
new file mode 100644
index 00000000..9bb11f36
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/sourceSetKotlinGistConfiguration.kt
@@ -0,0 +1,21 @@
+package org.jetbrains.dokka.gradle
+
+import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
+import java.io.File
+
+// TODO NOW: Test
+fun GradleDokkaSourceSetBuilder.configureWithKotlinSourceSet(sourceSet: KotlinSourceSet) {
+ configureWithKotlinSourceSetGist(project.kotlinExtension.gistOf(sourceSet))
+}
+
+internal fun GradleDokkaSourceSetBuilder.configureWithKotlinSourceSetGist(sourceSet: KotlinSourceSetGist) {
+ sourceRoots.addAll(sourceRoots.union(sourceSet.sourceRoots.toSourceRoots()).distinct())
+ dependentSourceSets.addAll(dependentSourceSets)
+ dependentSourceSets.addAll(sourceSet.dependentSourceSets.map { DokkaSourceSetID(project, it) })
+ classpath = classpath.union(sourceSet.classpath).distinct()
+ if (platform == null && sourceSet.platform != "")
+ platform = sourceSet.platform
+}
+
+private fun Iterable<File>.toSourceRoots(): List<GradleSourceRootBuilder> =
+ this.filter { it.exists() }.map { GradleSourceRootBuilder().apply { directory = it } }
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt
index b6c5cbd8..12e22f5d 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt
@@ -4,9 +4,20 @@ import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.UnknownDomainObjectException
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
+import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
+internal val Project.kotlinExtensionOrNull: KotlinProjectExtension?
+ get() = try {
+ project.extensions.findByType(KotlinProjectExtension::class.java)
+ } catch (e: NoClassDefFoundError) {
+ null
+ }
+
+internal val Project.kotlinExtension: KotlinProjectExtension
+ get() = project.extensions.getByType(KotlinProjectExtension::class.java)
+
internal fun Project.isAndroidProject() = try {
project.extensions.getByName("android")
@@ -35,3 +46,4 @@ internal fun KotlinTarget.isAndroidTarget() = this.platformType == KotlinPlatfor
internal fun <T : Any> NamedDomainObjectContainer<T>.maybeCreate(name: String, configuration: T.() -> Unit): T {
return findByName(name) ?: create(name, configuration)
}
+
diff --git a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaParentTaskTest.kt b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaParentTaskTest.kt
new file mode 100644
index 00000000..da0f3f35
--- /dev/null
+++ b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaParentTaskTest.kt
@@ -0,0 +1,107 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.kotlin.dsl.register
+import org.gradle.kotlin.dsl.withType
+import org.gradle.testfixtures.ProjectBuilder
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+class AbstractDokkaParentTaskTest {
+
+ private val rootProject = ProjectBuilder.builder().build()
+ private val subproject0 = ProjectBuilder.builder().withName("subproject0").withParent(rootProject).build()
+ private val subproject1 = ProjectBuilder.builder().withName("subproject1").withParent(rootProject).build()
+ private val subSubproject0a = ProjectBuilder.builder().withName("subSubproject0a").withParent(subproject0).build()
+
+ init {
+ rootProject.allprojects { project -> project.plugins.apply("org.jetbrains.dokka") }
+ }
+
+ private val parentTasks = rootProject.tasks.withType<AbstractDokkaParentTask>().toList()
+
+ @Test
+ fun `at least one parent task is registered`() {
+ assertTrue(
+ parentTasks.isNotEmpty(),
+ "Expected at least one ${AbstractDokkaParentTask::class.simpleName} task in rootProject"
+ )
+ }
+
+ @Test
+ fun `configuring subprojects`() {
+ parentTasks.forEach { task ->
+ assertEquals(
+ setOf(":subproject0", ":subproject1", ":subproject0:subSubproject0a"), task.subprojectPaths,
+ "Expected all sub projects registered by default"
+ )
+
+ assertEquals(
+ listOf(subproject0, subproject1, subSubproject0a), task.subprojects,
+ "Expected all sub projects registered by default"
+ )
+
+ assertEquals(3, task.dokkaTasks.size, "Expected three referenced dokka tasks")
+ assertTrue(listOf(subproject0, subproject1, subSubproject0a).all { project ->
+ task.dokkaTasks.any { task -> task in project.tasks }
+ }, "Expected all sub projects to contribute to referenced dokka tasks")
+
+ task.removeSubproject(subproject0)
+ assertEquals(
+ setOf(":subproject1", ":subproject0:subSubproject0a"), task.subprojectPaths,
+ "Expected subproject0 to be removed (without removing its children)"
+ )
+
+ task.addSubproject(subproject0)
+ assertEquals(
+ setOf(":subproject1", ":subproject0:subSubproject0a", ":subproject0"), task.subprojectPaths,
+ "Expected subproject0 being added again"
+ )
+
+ task.addSubproject(subproject0)
+ assertEquals(
+ setOf(":subproject1", ":subproject0:subSubproject0a", ":subproject0"), task.subprojectPaths,
+ "Expected adding same project twice to be ignored"
+ )
+
+ task.removeAllProjects(subproject0)
+ assertEquals(
+ setOf(":subproject1"), task.subprojectPaths,
+ "Expected subproject0 and subSubproject0a to be removed"
+ )
+
+ task.addAllProjects(subproject0)
+ assertEquals(
+ setOf(":subproject1", ":subproject0", ":subproject0:subSubproject0a"), task.subprojectPaths,
+ "Expected subproject0 and subSubproject0a to be added again"
+ )
+ }
+ }
+
+ @Test
+ fun `configure dokkaTaskNames`() {
+ parentTasks.forEach { task ->
+ assertEquals(
+ 3, task.dokkaTasks.size,
+ "Expected 3 tasks referenced by default"
+ )
+
+ val customDokkaTaskName = "custom${task.name}"
+ task.dokkaTaskNames = setOf(customDokkaTaskName)
+ assertTrue(task.dokkaTasks.isEmpty(), "Expected no $customDokkaTaskName. Found: ${task.dokkaTasks}")
+
+ rootProject.subprojects { subproject ->
+ subproject.tasks.register<DokkaTask>(customDokkaTaskName)
+ }
+
+ assertEquals(
+ 3, task.dokkaTasks.size,
+ "Expected three $customDokkaTaskName found"
+ )
+
+ task.dokkaTasks.forEach { dokkaTask ->
+ assertEquals(customDokkaTaskName, dokkaTask.name)
+ }
+ }
+ }
+}
diff --git a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTaskTest.kt b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTaskTest.kt
new file mode 100644
index 00000000..2d8dc21a
--- /dev/null
+++ b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTaskTest.kt
@@ -0,0 +1,60 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.artifacts.Dependency
+import org.gradle.api.artifacts.FileCollectionDependency
+import org.gradle.kotlin.dsl.withType
+import org.gradle.testfixtures.ProjectBuilder
+import org.jetbrains.dokka.DokkaConfigurationImpl
+import java.io.File
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+class DokkaCollectorTaskTest {
+
+ @Test
+ fun buildDokkaConfiguration() {
+ val rootProject = ProjectBuilder.builder().build()
+ val childProject = ProjectBuilder.builder().withParent(rootProject).build()
+ childProject.plugins.apply("org.jetbrains.kotlin.jvm")
+
+ rootProject.allprojects { project ->
+ project.plugins.apply("org.jetbrains.dokka")
+ project.tasks.withType<AbstractDokkaTask>().configureEach { task ->
+ task.plugins.withDependencies { dependencies -> dependencies.clear() }
+ }
+ }
+
+ val collectorTasks = rootProject.tasks.withType<DokkaCollectorTask>()
+ collectorTasks.configureEach { task ->
+ task.outputDirectory = File("customOutputDirectory")
+ task.cacheRoot = File("customCacheRoot")
+ task.failOnWarning = true
+ task.offlineMode = true
+ }
+
+ assertTrue(collectorTasks.isNotEmpty(), "Expected at least one collector task")
+
+ collectorTasks.forEach { task ->
+ val dokkaConfiguration = task.buildDokkaConfiguration()
+ assertEquals(
+ DokkaConfigurationImpl(
+ outputDir = File("customOutputDirectory"),
+ cacheRoot = File("customCacheRoot"),
+ failOnWarning = true,
+ offlineMode = true,
+ sourceSets = task.dokkaTasks
+ .map { it.buildDokkaConfiguration() }
+ .map { it.sourceSets }
+ .reduce { acc, list -> acc + list },
+ pluginsClasspath = task.dokkaTasks
+ .map { it.plugins.resolve() }
+ .reduce { acc, mutableSet -> acc + mutableSet }
+ .toList()
+ ),
+ dokkaConfiguration
+ )
+ }
+
+ }
+}
diff --git a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationJsonTest.kt b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationJsonTest.kt
index d80f43e4..f6a9c909 100644
--- a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationJsonTest.kt
+++ b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationJsonTest.kt
@@ -3,6 +3,7 @@ package org.jetbrains.dokka.gradle
import org.gradle.kotlin.dsl.withType
import org.gradle.testfixtures.ProjectBuilder
import org.jetbrains.dokka.*
+import java.io.File
import java.net.URL
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -20,8 +21,8 @@ class DokkaConfigurationJsonTest {
dokkaTask.apply {
this.failOnWarning = true
this.offlineMode = true
- this.outputDirectory = "customOutputDir"
- this.cacheRoot = "customCacheRoot"
+ this.outputDirectory = File("customOutputDir")
+ this.cacheRoot = File("customCacheRoot")
this.pluginsConfiguration["0"] = "a"
this.pluginsConfiguration["1"] = "b"
this.dokkaSourceSets.create("main") { sourceSet ->
@@ -33,12 +34,6 @@ class DokkaConfigurationJsonTest {
link.packageListUrl = URL("http://some.url")
link.url = URL("http://some.other.url")
}
- sourceSet.collectKotlinTasks = {
- println(this@DokkaConfigurationJsonTest)
- println("This lambda is capturing the entire test")
- emptyList()
- }
-
sourceSet.perPackageOption { packageOption ->
packageOption.includeNonPublic = true
packageOption.reportUndocumented = true
@@ -47,47 +42,11 @@ class DokkaConfigurationJsonTest {
}
}
- val sourceConfiguration = dokkaTask.getConfigurationOrThrow()
+ val sourceConfiguration = dokkaTask.buildDokkaConfiguration()
val configurationJson = sourceConfiguration.toJsonString()
val parsedConfiguration = DokkaConfigurationImpl(configurationJson)
- assertEquals(
- DokkaConfigurationImpl(
- failOnWarning = sourceConfiguration.failOnWarning,
- offlineMode = sourceConfiguration.offlineMode,
- outputDir = sourceConfiguration.outputDir,
- cacheRoot = sourceConfiguration.cacheRoot,
- pluginsClasspath = emptyList(),
- pluginsConfiguration = sourceConfiguration.pluginsConfiguration.toMap(),
- sourceSets = listOf(
- DokkaSourceSetImpl(
- moduleDisplayName = sourceConfiguration.sourceSets.single().moduleDisplayName,
- displayName = sourceConfiguration.sourceSets.single().displayName,
- reportUndocumented = sourceConfiguration.sourceSets.single().reportUndocumented,
- externalDocumentationLinks = sourceConfiguration.sourceSets.single().externalDocumentationLinks
- .map { link ->
- ExternalDocumentationLinkImpl(
- url = link.url,
- packageListUrl = link.packageListUrl
- )
- },
- perPackageOptions = sourceConfiguration.sourceSets.single().perPackageOptions.map { option ->
- PackageOptionsImpl(
- prefix = option.prefix,
- includeNonPublic = option.includeNonPublic,
- reportUndocumented = option.reportUndocumented,
- skipDeprecated = option.skipDeprecated,
- suppress = option.suppress
- )
- },
- sourceSetID = sourceConfiguration.sourceSets.single().sourceSetID,
- sourceRoots = sourceConfiguration.sourceSets.single().sourceRoots.map { sourceRoot ->
- SourceRootImpl(sourceRoot.path)
- }
- )
- )
- ), parsedConfiguration
- )
+ assertEquals(sourceConfiguration, parsedConfiguration)
println(parsedConfiguration)
}
}
diff --git a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationSerializableTest.kt b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationSerializableTest.kt
index 70ecfcf0..e4fd0676 100644
--- a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationSerializableTest.kt
+++ b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationSerializableTest.kt
@@ -6,6 +6,7 @@ import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.toJsonString
import org.junit.Rule
import org.junit.rules.TemporaryFolder
+import java.io.File
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.net.URL
@@ -28,8 +29,8 @@ class DokkaConfigurationSerializableTest {
dokkaTask.apply {
this.failOnWarning = true
this.offlineMode = true
- this.outputDirectory = "customOutputDir"
- this.cacheRoot = "customCacheRoot"
+ this.outputDirectory = File("customOutputDir")
+ this.cacheRoot = File("customCacheRoot")
this.pluginsConfiguration["0"] = "a"
this.pluginsConfiguration["1"] = "b"
this.dokkaSourceSets.create("main") { sourceSet ->
@@ -41,9 +42,6 @@ class DokkaConfigurationSerializableTest {
link.packageListUrl = URL("http://some.url")
link.url = URL("http://some.other.url")
}
- sourceSet.collectKotlinTasks = {
- emptyList()
- }
sourceSet.perPackageOption { packageOption ->
packageOption.includeNonPublic = true
@@ -53,7 +51,7 @@ class DokkaConfigurationSerializableTest {
}
}
- val sourceConfiguration = dokkaTask.getConfigurationOrThrow()
+ val sourceConfiguration = dokkaTask.buildDokkaConfiguration()
val configurationFile = temporaryFolder.root.resolve("config.bin")
ObjectOutputStream(configurationFile.outputStream()).use { stream ->
stream.writeObject(sourceConfiguration)
@@ -62,7 +60,6 @@ class DokkaConfigurationSerializableTest {
stream.readObject() as DokkaConfiguration
}
- /* Abusing toJsonString, since there is no proper .equals on the gradle implementations yet */
- assertEquals(sourceConfiguration.toJsonString(), parsedConfiguration.toJsonString())
+ assertEquals(sourceConfiguration, parsedConfiguration)
}
}
diff --git a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleTaskTest.kt b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleTaskTest.kt
new file mode 100644
index 00000000..ff318bdf
--- /dev/null
+++ b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleTaskTest.kt
@@ -0,0 +1,112 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.kotlin.dsl.create
+import org.gradle.kotlin.dsl.withType
+import org.gradle.testfixtures.ProjectBuilder
+import org.jetbrains.dokka.DokkaConfigurationImpl
+import org.jetbrains.dokka.DokkaModuleDescriptionImpl
+import java.io.File
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+class DokkaMultiModuleTaskTest {
+
+ private val rootProject = ProjectBuilder.builder()
+ .withName("root")
+ .build()
+
+ private val childProject = ProjectBuilder.builder()
+ .withName("child")
+ .withProjectDir(rootProject.projectDir.resolve("child"))
+ .withParent(rootProject).build()
+
+ init {
+ rootProject.allprojects { project ->
+ project.plugins.apply("org.jetbrains.kotlin.jvm")
+ project.plugins.apply("org.jetbrains.dokka")
+ project.tasks.withType<AbstractDokkaTask>().configureEach { task ->
+ task.plugins.withDependencies { dependencies -> dependencies.clear() }
+ }
+ }
+ }
+
+ @Test
+ fun `child project is withing root project`() {
+ assertEquals(
+ rootProject.projectDir, childProject.projectDir.parentFile,
+ "Expected child project being inside the root project"
+ )
+
+ assertEquals(
+ childProject.projectDir.name, "child",
+ "Expected folder of child project to be called 'child'"
+ )
+ }
+
+ @Test
+ fun buildDokkaConfiguration() {
+ childProject.tasks.withType<DokkaTask>().configureEach { task ->
+ task.outputDirectory = task.project.buildDir.resolve("output")
+ }
+
+ val multimoduleTasks = rootProject.tasks.withType<DokkaMultimoduleTask>()
+ assertTrue(multimoduleTasks.isNotEmpty(), "Expected at least one multimodule task")
+
+ multimoduleTasks.configureEach { task ->
+ task.documentationFileName = "customDocumentationFileName.md"
+ task.outputDirectory = task.project.buildDir.resolve("customOutputDirectory")
+ task.cacheRoot = File("customCacheRoot")
+ task.pluginsConfiguration["pluginA"] = "configA"
+ task.failOnWarning = true
+ task.offlineMode = true
+ }
+
+ multimoduleTasks.forEach { task ->
+ val dokkaConfiguration = task.buildDokkaConfiguration()
+ assertEquals(
+ DokkaConfigurationImpl(
+ outputDir = task.project.buildDir.resolve("customOutputDirectory"),
+ cacheRoot = File("customCacheRoot"),
+ pluginsConfiguration = mapOf("pluginA" to "configA"),
+ pluginsClasspath = emptyList(),
+ failOnWarning = true,
+ offlineMode = true,
+ modules = listOf(
+ DokkaModuleDescriptionImpl(
+ name = "child",
+ path = File("../../child/build/output"),
+ docFile = childProject.projectDir.resolve("customDocumentationFileName.md")
+ )
+ )
+ ),
+ dokkaConfiguration
+ )
+ }
+ }
+
+ @Test
+ fun `setting dokkaTaskNames declares proper task dependencies`() {
+ val multimoduleTasks = rootProject.tasks.withType<DokkaMultimoduleTask>()
+ assertTrue(multimoduleTasks.isNotEmpty(), "Expected at least one multimodule task")
+
+ multimoduleTasks.toList().forEach { task ->
+ val dependencies = task.taskDependencies.getDependencies(task).toSet()
+ assertEquals(1, dependencies.size, "Expected one dependency")
+ val dependency = dependencies.single()
+
+ assertTrue(dependency is DokkaTask, "Expected dependency to be of Type ${DokkaTask::class.simpleName}")
+ assertEquals(childProject, dependency.project, "Expected dependency from child project")
+ }
+
+ val customDokkaTask = childProject.tasks.create<DokkaTask>("customDokkaTask")
+
+ multimoduleTasks.toList().forEach { task ->
+ task.dokkaTaskNames += "customDokkaTask"
+ val dependencies = task.taskDependencies.getDependencies(task).toSet()
+
+ assertEquals(2, dependencies.size, "Expected two dependencies")
+ assertTrue(customDokkaTask in dependencies, "Expected 'customDokkaTask' in dependencies")
+ }
+ }
+}
diff --git a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/KotlinDslDokkaTaskConfigurationTest.kt b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/KotlinDslDokkaTaskConfigurationTest.kt
index 7b78fb55..f4029bd5 100644
--- a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/KotlinDslDokkaTaskConfigurationTest.kt
+++ b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/KotlinDslDokkaTaskConfigurationTest.kt
@@ -3,6 +3,7 @@ package org.jetbrains.dokka.gradle
import org.gradle.testfixtures.ProjectBuilder
import org.jetbrains.dokka.DokkaSourceSetID
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
+import java.io.File
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -13,11 +14,11 @@ class KotlinDslDokkaTaskConfigurationTest {
val project = ProjectBuilder.builder().build()
project.plugins.apply("org.jetbrains.dokka")
project.tasks.withType(DokkaTask::class.java).forEach { dokkaTask ->
- dokkaTask.outputDirectory = "test"
+ dokkaTask.outputDirectory = File("test")
}
project.tasks.withType(DokkaTask::class.java).forEach { dokkaTask ->
- assertEquals("test", dokkaTask.outputDirectory)
+ assertEquals(File("test"), dokkaTask.outputDirectory)
}
}
diff --git a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt
index 514df151..3df2a17e 100644
--- a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt
+++ b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt
@@ -53,9 +53,12 @@ class ExternalDocumentationLinkBuilder : DokkaConfiguration.ExternalDocumentatio
}
abstract class AbstractDokkaMojo(private val defaultDokkaPlugins: List<Dependency>) : AbstractMojo() {
- class SourceRoot : DokkaConfiguration.SourceRoot {
+ class SourceRoot : DokkaConfigurationBuilder<DokkaConfiguration.SourceRoot> {
@Parameter(required = true)
- override var path: String = ""
+ var path: String = ""
+ override fun build(): DokkaConfiguration.SourceRoot {
+ return SourceRootImpl(File(path))
+ }
}
@Parameter(defaultValue = "\${project}", readonly = true)
@@ -200,11 +203,11 @@ abstract class AbstractDokkaMojo(private val defaultDokkaPlugins: List<Dependenc
moduleDisplayName = moduleDisplayName.takeIf(String::isNotBlank) ?: moduleName,
displayName = displayName,
sourceSetID = DokkaSourceSetID(moduleName, sourceSetName),
- classpath = classpath,
- sourceRoots = sourceDirectories.map { SourceRootImpl(it) },
+ classpath = classpath.map(::File),
+ sourceRoots = sourceDirectories.map(::File).map(::SourceRootImpl),
dependentSourceSets = emptySet(),
- samples = samples,
- includes = includes,
+ samples = samples.map(::File),
+ includes = includes.map(::File),
includeNonPublic = includeNonPublic,
includeRootPackage = includeRootPackage,
reportUndocumented = reportUndocumented,
@@ -226,7 +229,7 @@ abstract class AbstractDokkaMojo(private val defaultDokkaPlugins: List<Dependenc
apiVersion = apiVersion,
noStdlibLink = noStdlibLink,
noJdkLink = noJdkLink,
- suppressedFiles = suppressedFiles,
+ suppressedFiles = suppressedFiles.map(::File),
analysisPlatform = if (platform.isNotEmpty()) Platform.fromString(platform) else Platform.DEFAULT
).let {
it.copy(
@@ -237,9 +240,9 @@ abstract class AbstractDokkaMojo(private val defaultDokkaPlugins: List<Dependenc
val logger = MavenDokkaLogger(log)
val configuration = DokkaConfigurationImpl(
- outputDir = getOutDir(),
+ outputDir = File(getOutDir()),
offlineMode = offlineMode,
- cacheRoot = cacheRoot,
+ cacheRoot = cacheRoot?.let(::File),
sourceSets = listOf(sourceSet).also {
if (sourceSet.moduleDisplayName.isEmpty()) logger.warn("Not specified module name. It can result in unexpected behaviour while including documentation for module")
},
diff --git a/testApi/src/main/kotlin/testApi/testRunner/TestRunner.kt b/testApi/src/main/kotlin/testApi/testRunner/TestRunner.kt
index 457325cf..6d80d15a 100644
--- a/testApi/src/main/kotlin/testApi/testRunner/TestRunner.kt
+++ b/testApi/src/main/kotlin/testApi/testRunner/TestRunner.kt
@@ -38,7 +38,7 @@ abstract class AbstractCoreTest(
logger.info("Output generated under: ${tempDir.root.absolutePath}")
val newConfiguration =
configuration.copy(
- outputDir = tempDir.root.toPath().toAbsolutePath().toString()
+ outputDir = tempDir.root
)
DokkaTestGenerator(
newConfiguration,
@@ -62,20 +62,21 @@ abstract class AbstractCoreTest(
fileMap.materializeFiles(testDirPath.toAbsolutePath())
if (!cleanupOutput)
loggerForTest.info("Output generated under: ${testDirPath.toAbsolutePath()}")
- val newConfiguration =
- configuration.copy(
- outputDir = testDirPath.toAbsolutePath().toString(),
- sourceSets = configuration.sourceSets.map { sourceSet ->
- sourceSet.copy(
- sourceRoots = sourceSet.sourceRoots.map { sourceRoot ->
- sourceRoot.copy(path = "${testDirPath.toAbsolutePath()}/${sourceRoot.path}")
- },
- suppressedFiles = sourceSet.suppressedFiles.map { suppressedFile ->
- testDirPath.toAbsolutePath().toFile().resolve(suppressedFile).absolutePath
- }
- )
- },
- )
+ val newConfiguration = configuration.copy(
+ outputDir = testDirPath.toFile(),
+ sourceSets = configuration.sourceSets.map { sourceSet ->
+ sourceSet.copy(
+ sourceRoots = sourceSet.sourceRoots.map { sourceRoot ->
+ sourceRoot.copy(
+ directory = testDirPath.toFile().resolve(sourceRoot.directory)
+ )
+ },
+ suppressedFiles = sourceSet.suppressedFiles.map { file ->
+ testDirPath.toFile().resolve(file)
+ }
+ )
+ }
+ )
DokkaTestGenerator(
newConfiguration,
loggerForTest,
@@ -172,8 +173,8 @@ abstract class AbstractCoreTest(
var failOnWarning: Boolean = false
private val sourceSets = mutableListOf<DokkaSourceSetImpl>()
fun build() = DokkaConfigurationImpl(
- outputDir = outputDir,
- cacheRoot = cacheRoot,
+ outputDir = File(outputDir),
+ cacheRoot = cacheRoot?.let(::File),
offlineMode = offlineMode,
sourceSets = sourceSets,
pluginsClasspath = pluginsClasspath,
@@ -224,11 +225,11 @@ abstract class AbstractCoreTest(
moduleDisplayName = moduleDisplayName ?: moduleName,
displayName = displayName,
sourceSetID = DokkaSourceSetID(moduleName, name),
- classpath = classpath,
- sourceRoots = sourceRoots.map { SourceRootImpl(it) },
+ classpath = classpath.map(::File),
+ sourceRoots = sourceRoots.map(::File).map(::SourceRootImpl),
dependentSourceSets = dependentSourceSets,
- samples = samples,
- includes = includes,
+ samples = samples.map(::File),
+ includes = includes.map(::File),
includeNonPublic = includeNonPublic,
includeRootPackage = includeRootPackage,
reportUndocumented = reportUndocumented,
@@ -242,7 +243,7 @@ abstract class AbstractCoreTest(
apiVersion = apiVersion,
noStdlibLink = noStdlibLink,
noJdkLink = noJdkLink,
- suppressedFiles = suppressedFiles,
+ suppressedFiles = suppressedFiles.map(::File),
analysisPlatform = Platform.fromString(analysisPlatform)
)
}