diff options
| author | Paweł Marks <pmarks@virtuslab.com> | 2020-07-17 16:36:09 +0200 |
|---|---|---|
| committer | Paweł Marks <pmarks@virtuslab.com> | 2020-07-17 16:36:09 +0200 |
| commit | 6996b1135f61c7d2cb60b0652c6a2691dda31990 (patch) | |
| tree | d568096c25e31c28d14d518a63458b5a7526b896 /runners/gradle-plugin | |
| parent | de56cab76f556e5b4af0b8c8cb08d8b482b86d0a (diff) | |
| parent | 1c3530dcbb50c347f80bef694829dbefe89eca77 (diff) | |
| download | dokka-6996b1135f61c7d2cb60b0652c6a2691dda31990.tar.gz dokka-6996b1135f61c7d2cb60b0652c6a2691dda31990.tar.bz2 dokka-6996b1135f61c7d2cb60b0652c6a2691dda31990.zip | |
Merge branch 'dev-0.11.0'
Diffstat (limited to 'runners/gradle-plugin')
20 files changed, 1072 insertions, 556 deletions
diff --git a/runners/gradle-plugin/build.gradle b/runners/gradle-plugin/build.gradle deleted file mode 100644 index ceb03bae..00000000 --- a/runners/gradle-plugin/build.gradle +++ /dev/null @@ -1,108 +0,0 @@ -import com.gradle.publish.DependenciesBuilder - -apply plugin: 'java' -apply plugin: 'kotlin' - - -apply plugin: 'com.github.johnrengelman.shadow' -apply plugin: "com.gradle.plugin-publish" - -sourceCompatibility = 1.8 - -tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { - kotlinOptions { - freeCompilerArgs += "-Xjsr305=strict" - languageVersion = language_version - apiVersion = language_version - jvmTarget = "1.8" - } -} - -repositories { - jcenter() - google() -} - -dependencies { - testCompile group: 'junit', name: 'junit', version: '4.12' - - shadow group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: kotlin_for_gradle_runtime_version - shadow group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: kotlin_for_gradle_runtime_version - - compile project(":integration") - - compileOnly "org.jetbrains.kotlin:kotlin-gradle-plugin" - compileOnly("com.android.tools.build:gradle:3.0.0") - compileOnly("com.android.tools.build:gradle-core:3.0.0") - compileOnly("com.android.tools.build:builder-model:3.0.0") - compileOnly gradleApi() - compileOnly localGroovy() - implementation "com.google.code.gson:gson:$gson_version" -} - -task sourceJar(type: Jar) { - from sourceSets.main.allSource -} - -processResources { - eachFile { - if (it.name == "org.jetbrains.dokka.properties") { - it.filter { line -> - line.replace("<version>", dokka_version) - } - } - } -} - -shadowJar { - baseName = 'dokka-gradle-plugin' - classifier = '' -} - -apply plugin: 'maven-publish' - -publishing { - publications { - dokkaGradlePlugin(MavenPublication) { publication -> - artifactId = 'dokka-gradle-plugin' - - artifact sourceJar { - classifier "sources" - } - - project.shadow.component(publication) - } - } -} - -bintrayPublication(project, ['dokkaGradlePlugin']) - -configurations.archives.artifacts.clear() -artifacts { - archives shadowJar -} - -pluginBundle { - website = 'https://www.kotlinlang.org/' - vcsUrl = 'https://github.com/kotlin/dokka.git' - description = 'Dokka, the Kotlin documentation tool' - tags = ['dokka', 'kotlin', 'kdoc', 'android'] - - plugins { - dokkaGradlePlugin { - id = 'org.jetbrains.dokka' - displayName = 'Dokka plugin' - } - } - - withDependencies { List<Dependency> list -> - list.clear() - def builder = new DependenciesBuilder() - builder.addUniqueScopedDependencies(list, configurations.shadow, "compile") - } - - mavenCoordinates { - groupId = "org.jetbrains.dokka" - artifactId = "dokka-gradle-plugin" - } -}
\ No newline at end of file diff --git a/runners/gradle-plugin/build.gradle.kts b/runners/gradle-plugin/build.gradle.kts new file mode 100644 index 00000000..0222f5e0 --- /dev/null +++ b/runners/gradle-plugin/build.gradle.kts @@ -0,0 +1,63 @@ +import org.jetbrains.configureBintrayPublication +import org.jetbrains.dokkaVersion + +plugins { + `java-gradle-plugin` +} + +repositories { + google() +} + +dependencies { + implementation(project(":core")) + compileOnly("org.jetbrains.kotlin:kotlin-gradle-plugin") + compileOnly("com.android.tools.build:gradle:3.0.0") + compileOnly("com.android.tools.build:gradle-core:3.0.0") + compileOnly("com.android.tools.build:builder-model:3.0.0") + compileOnly(gradleApi()) + compileOnly(gradleKotlinDsl()) + testImplementation(gradleApi()) + testImplementation(gradleKotlinDsl()) + testImplementation(kotlin("test-junit")) + testImplementation("org.jetbrains.kotlin:kotlin-gradle-plugin") + + constraints { + val kotlin_version: String by project + compileOnly("org.jetbrains.kotlin:kotlin-reflect:${kotlin_version}") { + because("kotlin-gradle-plugin and :core both depend on this") + } + } +} + +val sourceJar by tasks.registering(Jar::class) { + archiveClassifier.set("sources") + from(sourceSets["main"].allSource) +} + +gradlePlugin { + plugins { + create("dokkaGradlePlugin") { + id = "org.jetbrains.dokka" + implementationClass = "org.jetbrains.dokka.gradle.DokkaPlugin" + version = dokkaVersion + } + } +} + +publishing { + publications { + register<MavenPublication>("pluginMaven") { + artifactId = "dokka-gradle-plugin" + } + + register<MavenPublication>("dokkaGradlePluginForIntegrationTests") { + artifactId = "dokka-gradle-plugin" + from(components["java"]) + version = "for-integration-tests-SNAPSHOT" + } + } +} + + +configureBintrayPublication("dokkaGradlePluginPluginMarkerMaven", "pluginMaven") 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 new file mode 100644 index 00000000..846f021c --- /dev/null +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaTask.kt @@ -0,0 +1,45 @@ +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.jetbrains.dokka.DokkaBootstrap +import org.jetbrains.dokka.plugability.Configurable + + +abstract class AbstractDokkaTask : DefaultTask(), Configurable { + @Input + var outputDirectory: String = defaultDokkaOutputDirectory().absolutePath + + @Input + override val pluginsConfiguration: Map<String, String> = mutableMapOf() + + @Classpath + val plugins: Configuration = project.maybeCreateDokkaPluginConfiguration(name) + + @Classpath + 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 { + generate() + } finally { + System.setProperty(DokkaTask.COLORS_ENABLED_PROPERTY, kotlinColorsEnabledBefore) + } + } + + protected abstract fun generate() + + protected fun DokkaBootstrap(bootstrapClassFQName: String): DokkaBootstrap { + return DokkaBootstrap(runtime, bootstrapClassFQName) + } +} 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 index 39672b9a..1bfd2c78 100644 --- 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 @@ -1,9 +1,5 @@ package org.jetbrains.dokka.gradle -import com.android.build.gradle.* -import com.android.build.gradle.api.BaseVariant -import com.android.builder.core.BuilderConstants -import org.gradle.api.NamedDomainObjectCollection import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.UnknownDomainObjectException @@ -13,90 +9,71 @@ 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.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.KotlinCompilation -import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType -import org.jetbrains.kotlin.gradle.plugin.KotlinTarget +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import java.io.File import java.io.Serializable class ConfigurationExtractor(private val project: Project) { - - fun extractConfiguration(targetName: String, variantNames: List<String>) = - if (project.isMultiplatformProject()) { - extractFromMultiPlatform(targetName, variantNames) - } else { - extractFromSinglePlatform(variantNames) + fun extractConfiguration(sourceSetName: String): PlatformData? { + val projectExtension = project.extensions.findByType(KotlinProjectExtension::class.java) ?: run { + project.logger.error("Missing kotlin project extension") + return null } - private fun extractFromSinglePlatform(variantNames: List<String>): PlatformData? { - val target: KotlinTarget - try { - target = project.extensions.getByType(KotlinSingleTargetExtension::class.java).target - } catch (e: Throwable) { - when (e) { - is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException -> - return null - else -> throw e - } + val sourceSet = projectExtension.sourceSets.findByName(sourceSetName) ?: run { + project.logger.error("No source set with name '$sourceSetName' found") + return null } - return try { - PlatformData( - null, - accumulateClassPaths(variantNames, target), - accumulateSourceSets(variantNames, target), - getPlatformName(target.platformType) - ) - } catch (e: NoSuchMethodError) { + 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 extractFromMultiPlatform(targetName: String, variantNames: List<String>): PlatformData? = - try { - project.extensions.getByType(KotlinMultiplatformExtension::class.java).targets - } catch (e: Throwable) { - when (e) { - is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException -> - null - else -> throw e - } - }?.let { - val fixedName = if (targetName.toLowerCase() == "common") "metadata" else targetName.toLowerCase() - it.find { target -> target.name.toLowerCase() == fixedName }?.let { target -> - PlatformData( - fixedName, - accumulateClassPaths(variantNames, target), - accumulateSourceSets(variantNames, target), - target.platformType.toString() - ) - } - } + 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(), "") } + ?.let { PlatformData(null, emptyList(), it.toList(), emptyList(), "") } - fun extractFromKotlinTasks(kotlinTasks: List<Task>): PlatformData? = + fun extractFromKotlinTasks(kotlinTasks: List<Task>): List<PlatformData> = try { - kotlinTasks.map { extractFromKotlinTask(it) }.let { platformDataList -> - PlatformData( - null, - platformDataList.flatMap { it.classpath }, - platformDataList.flatMap { it.sourceRoots }, - "" - ) - } + kotlinTasks.map { extractFromKotlinTask(it) } } catch (e: Throwable) { when (e) { is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException -> - extractFromKotlinTasksTheHardWay(kotlinTasks) + listOfNotNull(extractFromKotlinTasksTheHardWay(kotlinTasks)) else -> throw e } } @@ -110,10 +87,18 @@ class ConfigurationExtractor(private val project: Project) { when (e) { is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException -> project.extensions.getByType(KotlinMultiplatformExtension::class.java).targets - .firstNotNullResult { target -> target.compilations.find { it.compileKotlinTask == task } } + .flatMap { it.compilations }.firstOrNull { it.compileKotlinTask == task } else -> throw e } - }.let { PlatformData(task.name, getClasspath(it), getSourceSet(it), it?.platformType?.toString() ?: "") } + }.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>() @@ -134,8 +119,8 @@ class ConfigurationExtractor(private val project: Project) { val taskClasspath: Iterable<File> = (it["getClasspath", AbstractCompile::class].takeIfIsFunc()?.invoke() - ?: it["compileClasspath", abstractKotlinCompileClz].takeIfIsProp()?.v() - ?: it["getClasspath", abstractKotlinCompileClz]()) + ?: it["compileClasspath", abstractKotlinCompileClz].takeIfIsProp()?.v() + ?: it["getClasspath", abstractKotlinCompileClz]()) if (taskClasspath is FileCollection) { allClasspathFileCollection += taskClasspath @@ -152,97 +137,42 @@ class ConfigurationExtractor(private val project: Project) { } classpath.addAll(project.files(allClasspath).toList()) - return PlatformData(null, classpath, allSourceRoots.toList(), "") + return PlatformData(null, classpath, allSourceRoots.toList(), emptyList(), "") } - private fun getSourceSet(target: KotlinTarget, variantName: String): List<File> = - if (target.isAndroidTarget()) - getSourceSet(getCompilation(target, variantName)) - else - getSourceSet(getMainCompilation(target)) - - private fun getClasspath(target: KotlinTarget, variantName: String): List<File> = - if (target.isAndroidTarget()) - getClasspathFromAndroidTask(getCompilation(target, variantName)) - else - getClasspath(getMainCompilation(target)) - - private fun getSourceSet(compilation: KotlinCompilation<*>?): List<File> = compilation - ?.allKotlinSourceSets - ?.flatMap { it.kotlin.sourceDirectories } - ?.filter { it.exists() } - .orEmpty() - - private fun getClasspath(compilation: KotlinCompilation<*>?): List<File> = compilation - ?.compileDependencyFiles - ?.files - ?.toList() - ?.filter { it.exists() } - .orEmpty() - - // This is a workaround for KT-33893 - private fun getClasspathFromAndroidTask(compilation: KotlinCompilation<*>): List<File> = (compilation - .compileKotlinTask as? KotlinCompile) - ?.classpath?.files?.toList() ?: getClasspath(compilation) - - private fun getMainCompilation(target: KotlinTarget) = - getCompilation(target, getMainCompilationName(target)) - - private fun getCompilation(target: KotlinTarget, name: String) = - target.compilations.getByName(name) - - private fun getMainCompilationName(target: KotlinTarget) = if (target.isAndroidTarget()) - getVariants(project).filter { it.buildType.name == BuilderConstants.RELEASE }.map { it.name }.first() - else - KotlinCompilation.MAIN_COMPILATION_NAME - - private fun getVariants(project: Project): Set<BaseVariant> { - val androidExtension = project.extensions.getByName("android") - val baseVariants = when (androidExtension) { - is AppExtension -> androidExtension.applicationVariants.toSet() - is LibraryExtension -> { - androidExtension.libraryVariants.toSet() + - if (androidExtension is FeatureExtension) { - androidExtension.featureVariants.toSet() - } else { - emptySet<BaseVariant>() - } - } - is TestExtension -> androidExtension.applicationVariants.toSet() - else -> emptySet() - } - val testVariants = if (androidExtension is TestedExtension) { - androidExtension.testVariants.toSet() + androidExtension.unitTestVariants.toSet() - } else { - emptySet<BaseVariant>() - } + private val KotlinCompilation<*>.sourceFiles: List<File> + get() = kotlinSourceSets.flatMap { it.sourceFiles } - return baseVariants + testVariants - } + private val KotlinSourceSet.sourceFiles: List<File> + get() = kotlin.sourceDirectories.filter { it.exists() }.toList() - private fun getPlatformName(platform: KotlinPlatformType): String = - if (platform == KotlinPlatformType.androidJvm) KotlinPlatformType.jvm.toString() else platform.toString() + private val KotlinCompilation<*>.dependentSourceSets: Set<KotlinSourceSet> + get() = (allKotlinSourceSets - kotlinSourceSets) - private fun accumulateClassPaths(variantNames: List<String>, target: KotlinTarget) = - if (variantNames.isNotEmpty()) { - variantNames.flatMap { getClasspath(target, it) }.distinct() + private val KotlinCompilation<*>.classpath: List<File> + get() = if (target.isAndroidTarget()) { + getClasspathFromAndroidTask(this) } else { - if (target.isAndroidTarget()) - getClasspathFromAndroidTask(getMainCompilation(target)) - else - getClasspath(getMainCompilation(target)) + getClasspathFromRegularTask(this) } - private fun accumulateSourceSets(variantNames: List<String>, target: KotlinTarget) = - if (variantNames.isNotEmpty()) - variantNames.flatMap { getSourceSet(target, it) }.distinct() - else - getSourceSet(getMainCompilation(target)) + // 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> = + compilation + .compileDependencyFiles + .files + .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 -}
\ No newline at end of file +} diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaArtifacts.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaArtifacts.kt new file mode 100644 index 00000000..90d51015 --- /dev/null +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaArtifacts.kt @@ -0,0 +1,17 @@ +package org.jetbrains.dokka.gradle + +import org.gradle.api.Project +import org.jetbrains.dokka.DokkaVersion + +internal val Project.dokkaArtifacts get() = DokkaArtifacts(this) + +internal class DokkaArtifacts(private val project: Project) { + private fun fromModuleName(name: String) = + project.dependencies.create("org.jetbrains.dokka:$name:${DokkaVersion.version}") + + val dokkaCore get() = fromModuleName("dokka-core") + val dokkaBase get() = fromModuleName("dokka-base") + val javadocPlugin get() = fromModuleName("javadoc-plugin") + val gfmPlugin get() = fromModuleName("gfm-plugin") + val jekyllPlugin get() = fromModuleName("jekyll-plugin") +} 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 new file mode 100644 index 00000000..df29c19b --- /dev/null +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaBootstrapFactory.kt @@ -0,0 +1,18 @@ +package org.jetbrains.dokka.gradle + +import org.gradle.api.artifacts.Configuration +import org.jetbrains.dokka.DokkaBootstrap +import java.net.URLClassLoader + + +fun DokkaBootstrap(configuration: Configuration, bootstrapClassFQName: String): 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) +} 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 new file mode 100644 index 00000000..37952ea8 --- /dev/null +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTask.kt @@ -0,0 +1,58 @@ +package org.jetbrains.dokka.gradle + +import org.gradle.api.DefaultTask +import org.gradle.api.plugins.JavaBasePlugin +import org.gradle.api.plugins.JavaBasePlugin.DOCUMENTATION_GROUP +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction +import java.lang.IllegalStateException + +open class DokkaCollectorTask : DefaultTask() { + + @Input + var modules: List<String> = emptyList() + + @Input + var outputDirectory: String = defaultDokkaOutputDirectory().absolutePath + + private lateinit var configuration: GradleDokkaConfigurationImpl + + @Input + var dokkaTaskNames: Set<String> = setOf() + + @TaskAction + fun collect() { + val configurations = project.subprojects + .filter { subProject -> subProject.name in modules } + .flatMap { subProject -> dokkaTaskNames.mapNotNull(subProject.tasks::findByName) } + .filterIsInstance<DokkaTask>() + .mapNotNull { dokkaTask -> dokkaTask.getConfigurationOrNull() } + + + val initial = GradleDokkaConfigurationImpl().apply { + outputDir = outputDirectory + cacheRoot = configurations.first().cacheRoot + } + + // TODO this certainly not the ideal solution + 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 + } + project.tasks.withType(DokkaTask::class.java).configureEach { it.enforcedConfiguration = configuration } + } + + init { + // TODO: This this certainly not the ideal solution + dokkaTaskNames.forEach { dokkaTaskName -> + finalizedBy(dokkaTaskName) + } + + 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 new file mode 100644 index 00000000..6fd58afe --- /dev/null +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultimoduleTask.kt @@ -0,0 +1,68 @@ +package org.jetbrains.dokka.gradle + +import com.google.gson.GsonBuilder +import org.gradle.api.plugins.JavaBasePlugin +import org.gradle.api.plugins.JavaBasePlugin.DOCUMENTATION_GROUP +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Internal +import org.jetbrains.dokka.plugability.Configurable + +open class DokkaMultimoduleTask : AbstractDokkaTask(), Configurable { + + @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 gson = GsonBuilder().setPrettyPrinting().create() + val configuration = getConfiguration() + bootstrap.configure(gson.toJson(configuration)) { 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 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 + } + } + } + + 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/DokkaSourceSetIDFactory.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaSourceSetIDFactory.kt new file mode 100644 index 00000000..3fadb4fd --- /dev/null +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaSourceSetIDFactory.kt @@ -0,0 +1,10 @@ +@file:Suppress("FunctionName") + +package org.jetbrains.dokka.gradle + +import org.gradle.api.Project +import org.jetbrains.dokka.DokkaSourceSetID + +internal fun DokkaSourceSetID(project: Project, sourceSetName: String): DokkaSourceSetID { + return DokkaSourceSetID(moduleName = project.path, sourceSetName = sourceSetName) +} 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 bafe657e..0d7e74a3 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,28 +1,26 @@ package org.jetbrains.dokka.gradle import com.google.gson.GsonBuilder -import org.gradle.api.* -import org.gradle.api.artifacts.Configuration +import org.gradle.api.NamedDomainObjectContainer +import org.gradle.api.Project +import org.gradle.api.Task |
