aboutsummaryrefslogtreecommitdiff
path: root/runners
diff options
context:
space:
mode:
Diffstat (limited to 'runners')
-rw-r--r--runners/android-gradle-plugin/build.gradle101
-rw-r--r--runners/android-gradle-plugin/src/main/kotlin/mainAndroid.kt40
-rw-r--r--runners/android-gradle-plugin/src/main/resources/META-INF/gradle-plugins/org.jetbrains.dokka-android.properties2
-rw-r--r--runners/ant/build.gradle4
-rw-r--r--runners/ant/src/main/kotlin/ant/dokka.kt221
-rw-r--r--runners/cli/build.gradle8
-rw-r--r--runners/cli/src/main/kotlin/cli/DokkaArgumentsParser.kt185
-rw-r--r--runners/cli/src/main/kotlin/cli/main.kt334
-rw-r--r--runners/gradle-integration-tests/build.gradle15
-rw-r--r--runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaAndroidGradleTest.kt4
-rw-r--r--runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaGradleTest.kt8
-rw-r--r--runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AndroidLibDependsOnJavaLibTest.kt2
-rw-r--r--runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/BasicTest.kt4
-rw-r--r--runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiplatformProjectTest.kt54
-rw-r--r--runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/RebuildAfterSourceChangeTest.kt10
-rw-r--r--runners/gradle-integration-tests/testData/androidApp/app/build.gradle9
-rw-r--r--runners/gradle-integration-tests/testData/androidAppJavadoc/app/build.gradle5
-rw-r--r--runners/gradle-integration-tests/testData/androidLibDependsOnJavaLib/lib/build.gradle14
-rw-r--r--runners/gradle-integration-tests/testData/androidMultiFlavourApp/app/build.gradle18
-rw-r--r--runners/gradle-integration-tests/testData/basic/build.gradle6
-rw-r--r--runners/gradle-integration-tests/testData/multiProjectSingleOut/build.gradle11
-rw-r--r--runners/gradle-integration-tests/testData/multiplatformProject/build.gradle60
-rw-r--r--runners/gradle-integration-tests/testData/multiplatformProject/fileTree.txt17
-rw-r--r--runners/gradle-integration-tests/testData/multiplatformProject/settings.gradle1
-rw-r--r--runners/gradle-integration-tests/testData/multiplatformProject/src/jsMain/kotlin/org/kotlintestmpp/main.kt14
-rw-r--r--runners/gradle-integration-tests/testData/multiplatformProject/src/jvmMain/kotlin/org/kotlintestmpp/main.kt20
-rw-r--r--runners/gradle-integration-tests/testData/sourcesChange/build.gradle6
-rw-r--r--runners/gradle-integration-tests/testData/typeSafeConfiguration/build.gradle53
-rw-r--r--runners/gradle-plugin/build.gradle17
-rw-r--r--runners/gradle-plugin/src/main/kotlin/main.kt499
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt217
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt353
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ProxyUtils.kt (renamed from runners/gradle-plugin/src/main/kotlin/ProxyUtils.kt)8
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/configurationImplementations.kt150
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt58
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt19
-rw-r--r--runners/maven-plugin/build.gradle4
-rw-r--r--runners/maven-plugin/src/main/kotlin/DokkaMojo.kt122
38 files changed, 1668 insertions, 1005 deletions
diff --git a/runners/android-gradle-plugin/build.gradle b/runners/android-gradle-plugin/build.gradle
deleted file mode 100644
index 28b0cbb9..00000000
--- a/runners/android-gradle-plugin/build.gradle
+++ /dev/null
@@ -1,101 +0,0 @@
-import com.gradle.publish.DependenciesBuilder
-import org.jetbrains.CorrectShadowPublishing
-
-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 = "1.2"
- apiVersion = "1.1"
- jvmTarget = "1.8"
- }
-}
-
-repositories {
- jcenter()
-}
-
-dependencies {
- testCompile group: 'junit', name: 'junit', version: '4.12'
-
- shadow project(path: ':runners:gradle-plugin', configuration: 'shadow')
- compileOnly project(':integration')
-
- compileOnly gradleApi()
- compileOnly localGroovy()
-}
-
-task sourceJar(type: Jar) {
- from sourceSets.main.allSource
-}
-
-processResources {
- eachFile {
- if (it.name == "org.jetbrains.dokka-android.properties") {
- it.filter { line ->
- line.replace("<version>", dokka_version)
- }
- }
- }
-}
-
-shadowJar {
- baseName = 'dokka-android-gradle-plugin'
- classifier = ''
-}
-
-apply plugin: 'maven-publish'
-
-publishing {
- publications {
- dokkaAndroidGradlePlugin(MavenPublication) { MavenPublication publication ->
- artifactId = 'dokka-android-gradle-plugin'
-
- artifact sourceJar {
- classifier "sources"
- }
-
- CorrectShadowPublishing.configure(publication, project)
- }
- }
-}
-
-bintrayPublication(project, ['dokkaAndroidGradlePlugin'])
-
-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 {
- dokkaAndroidGradlePlugin {
- id = 'org.jetbrains.dokka-android'
- displayName = 'Dokka Android plugin'
- }
- }
-
- withDependencies { List<Dependency> list ->
- list.clear()
- def builder = new DependenciesBuilder()
- builder.addUniqueScopedDependencies(list, configurations.shadow, "compile")
- }
-
- mavenCoordinates {
- groupId = "org.jetbrains.dokka"
- artifactId = "dokka-android-gradle-plugin"
- }
-} \ No newline at end of file
diff --git a/runners/android-gradle-plugin/src/main/kotlin/mainAndroid.kt b/runners/android-gradle-plugin/src/main/kotlin/mainAndroid.kt
deleted file mode 100644
index b1996da0..00000000
--- a/runners/android-gradle-plugin/src/main/kotlin/mainAndroid.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.jetbrains.dokka.gradle
-
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.api.tasks.Input
-import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink.Builder
-import java.io.File
-
-open class DokkaAndroidPlugin : Plugin<Project> {
- override fun apply(project: Project) {
- DokkaVersion.loadFrom(javaClass.getResourceAsStream("/META-INF/gradle-plugins/org.jetbrains.dokka-android.properties"))
- project.tasks.create("dokka", DokkaAndroidTask::class.java).apply {
- dokkaRuntime = project.configurations.create("dokkaRuntime")
- moduleName = project.name
- outputDirectory = File(project.buildDir, "dokka").absolutePath
- }
- }
-}
-
-private val ANDROID_REFERENCE_URL = Builder("https://developer.android.com/reference/").build()
-
-open class DokkaAndroidTask : DokkaTask() {
-
- @Input var noAndroidSdkLink: Boolean = false
-
- override fun collectSuppressedFiles(sourceRoots: List<SourceRoot>): List<String> {
- val generatedRoot = project.buildDir.resolve("generated").absoluteFile
- return sourceRoots
- .map { File(it.path) }
- .filter { it.startsWith(generatedRoot) }
- .flatMap { it.walk().toList() }
- .map { it.absolutePath }
- }
-
- init {
- project.afterEvaluate {
- if (!noAndroidSdkLink) externalDocumentationLinks.add(ANDROID_REFERENCE_URL)
- }
- }
-}
diff --git a/runners/android-gradle-plugin/src/main/resources/META-INF/gradle-plugins/org.jetbrains.dokka-android.properties b/runners/android-gradle-plugin/src/main/resources/META-INF/gradle-plugins/org.jetbrains.dokka-android.properties
deleted file mode 100644
index b204da7b..00000000
--- a/runners/android-gradle-plugin/src/main/resources/META-INF/gradle-plugins/org.jetbrains.dokka-android.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-implementation-class=org.jetbrains.dokka.gradle.DokkaAndroidPlugin
-dokka-version=<version> \ No newline at end of file
diff --git a/runners/ant/build.gradle b/runners/ant/build.gradle
index e7dcd441..216420c6 100644
--- a/runners/ant/build.gradle
+++ b/runners/ant/build.gradle
@@ -5,8 +5,8 @@ sourceCompatibility = 1.8
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
freeCompilerArgs += "-Xjsr305=strict"
- languageVersion = "1.2"
- apiVersion = languageVersion
+ languageVersion = language_version
+ apiVersion = language_version
jvmTarget = "1.8"
}
}
diff --git a/runners/ant/src/main/kotlin/ant/dokka.kt b/runners/ant/src/main/kotlin/ant/dokka.kt
index b23328e0..3ecc7b94 100644
--- a/runners/ant/src/main/kotlin/ant/dokka.kt
+++ b/runners/ant/src/main/kotlin/ant/dokka.kt
@@ -17,54 +17,103 @@ class AntLogger(val task: Task): DokkaLogger {
class AntSourceLinkDefinition(var path: String? = null, var url: String? = null, var lineSuffix: String? = null)
-class AntSourceRoot(var path: String? = null, var platforms: String? = null) {
- fun toSourceRoot(): SourceRootImpl? = path?.let {
- path ->
- SourceRootImpl(path, platforms?.split(',').orEmpty())
+class AntSourceRoot(var path: String? = null) {
+ fun toSourceRoot(): SourceRootImpl? = path?.let { path ->
+ SourceRootImpl(path)
}
}
-class AntPackageOptions(
- override var prefix: String = "",
- override var includeNonPublic: Boolean = false,
- override var reportUndocumented: Boolean = true,
- override var skipDeprecated: Boolean = false,
- override var suppress: Boolean = false) : DokkaConfiguration.PackageOptions
-
+class TextProperty(var value: String = "")
+
+class AntPassConfig(task: Task) : DokkaConfiguration.PassConfiguration {
+ override var moduleName: String = ""
+ override val classpath: List<String>
+ get() = buildClassPath.list().toList()
+
+ override val sourceRoots: List<DokkaConfiguration.SourceRoot>
+ get() = sourcePath.list().map { SourceRootImpl(it) } + antSourceRoots.mapNotNull { it.toSourceRoot() }
+
+ override val samples: List<String>
+ get() = samplesPath.list().toList()
+ override val includes: List<String>
+ get() = includesPath.list().toList()
+ override var includeNonPublic: Boolean = false
+ override var includeRootPackage: Boolean = true
+ override var reportUndocumented: Boolean = false
+ override var skipEmptyPackages: Boolean = true
+ override var skipDeprecated: Boolean = false
+ override var jdkVersion: Int = 6
+ override val sourceLinks: List<DokkaConfiguration.SourceLinkDefinition>
+ get() = antSourceLinkDefinition.map {
+ val path = it.path!!
+ val url = it.url!!
+ SourceLinkDefinitionImpl(File(path).canonicalFile.absolutePath, url, it.lineSuffix)
+ }
+ override val perPackageOptions: MutableList<DokkaConfiguration.PackageOptions> = mutableListOf()
+ override val externalDocumentationLinks: List<ExternalDocumentationLink>
+ get() = buildExternalLinksBuilders.map { it.build() } + defaultExternalDocumentationLinks
+
+ override var languageVersion: String? = null
+ override var apiVersion: String? = null
+ override var noStdlibLink: Boolean = false
+ override var noJdkLink: Boolean = false
+ override var suppressedFiles: MutableList<String> = mutableListOf()
+ override var collectInheritedExtensionsFromLibraries: Boolean = false
+ override var analysisPlatform: Platform = Platform.DEFAULT
+ override var targets: List<String> = listOf()
+ get() = buildTargets.filter { it.value != "" }
+ .map { it.value }
+
+ override var sinceKotlin: String? = null
+
+ private val samplesPath: Path by lazy { Path(task.project) }
+ private val includesPath: Path by lazy { Path(task.project) }
+ private val buildClassPath: Path by lazy { Path(task.project) }
+ val sourcePath: Path by lazy { Path(task.project) }
+ val antSourceRoots: MutableList<AntSourceRoot> = mutableListOf()
+
+ private val buildTargets: MutableList<TextProperty> = mutableListOf()
+ private val buildExternalLinksBuilders: MutableList<ExternalDocumentationLink.Builder> = mutableListOf()
+ val antSourceLinkDefinition: MutableList<AntSourceLinkDefinition> = mutableListOf()
+
+ private val defaultExternalDocumentationLinks: List<DokkaConfiguration.ExternalDocumentationLink>
+ get() {
+ val links = mutableListOf<DokkaConfiguration.ExternalDocumentationLink>()
+ if (!noJdkLink)
+ links += DokkaConfiguration.ExternalDocumentationLink.Builder("https://docs.oracle.com/javase/$jdkVersion/docs/api/").build()
+
+ if (!noStdlibLink)
+ links += DokkaConfiguration.ExternalDocumentationLink.Builder("https://kotlinlang.org/api/latest/jvm/stdlib/").build()
+ return links
+ }
-class DokkaAntTask: Task() {
- var moduleName: String? = null
- var outputDir: String? = null
- var outputFormat: String = "html"
- var impliedPlatforms: String = ""
- var jdkVersion: Int = 6
- var noStdlibLink: Boolean = false
- var noJdkLink: Boolean = false
+ fun setSamples(ref: Path) {
+ samplesPath.append(ref)
+ }
- var skipDeprecated: Boolean = false
+ fun setSamplesRef(ref: Reference) {
+ samplesPath.createPath().refid = ref
+ }
- var cacheRoot: String? = null
+ fun setInclude(ref: Path) {
+ includesPath.append(ref)
+ }
- var languageVersion: String? = null
- var apiVersion: String? = null
+ fun setClasspath(classpath: Path) {
+ buildClassPath.append(classpath)
+ }
- val compileClasspath: Path by lazy { Path(getProject()) }
- val sourcePath: Path by lazy { Path(getProject()) }
- val samplesPath: Path by lazy { Path(getProject()) }
- val includesPath: Path by lazy { Path(getProject()) }
+ fun createPackageOptions(): AntPackageOptions = AntPackageOptions().apply { perPackageOptions.add(this) }
- val antSourceLinks: MutableList<AntSourceLinkDefinition> = arrayListOf()
- val antSourceRoots: MutableList<AntSourceRoot> = arrayListOf()
- val antPackageOptions: MutableList<AntPackageOptions> = arrayListOf()
- val antExternalDocumentationLinks = mutableListOf<ExternalDocumentationLink.Builder>()
+ fun createSourceRoot(): AntSourceRoot = AntSourceRoot().apply { antSourceRoots.add(this) }
- fun setClasspath(classpath: Path) {
- compileClasspath.append(classpath)
+ fun createTarget(): TextProperty = TextProperty().apply {
+ buildTargets.add(this)
}
fun setClasspathRef(ref: Reference) {
- compileClasspath.createPath().refid = ref
+ buildClassPath.createPath().refid = ref
}
fun setSrc(src: Path) {
@@ -75,73 +124,69 @@ class DokkaAntTask: Task() {
sourcePath.createPath().refid = ref
}
- fun setSamples(samples: Path) {
- samplesPath.append(samples)
- }
-
- fun setSamplesRef(ref: Reference) {
- samplesPath.createPath().refid = ref
- }
-
- fun setInclude(include: Path) {
- includesPath.append(include)
- }
-
fun createSourceLink(): AntSourceLinkDefinition {
val def = AntSourceLinkDefinition()
- antSourceLinks.add(def)
+ antSourceLinkDefinition.add(def)
return def
}
- fun createSourceRoot(): AntSourceRoot = AntSourceRoot().apply { antSourceRoots.add(this) }
+ fun createExternalDocumentationLink() =
+ ExternalDocumentationLink.Builder().apply { buildExternalLinksBuilders.add(this) }
+
+}
+
+class AntPackageOptions(
+ override var prefix: String = "",
+ override var includeNonPublic: Boolean = false,
+ override var reportUndocumented: Boolean = true,
+ override var skipDeprecated: Boolean = false,
+ override var suppress: Boolean = false) : DokkaConfiguration.PackageOptions
+
+class DokkaAntTask: Task(), DokkaConfiguration {
- fun createPackageOptions(): AntPackageOptions = AntPackageOptions().apply { antPackageOptions.add(this) }
+ override var format: String = "html"
+ override var generateIndexPages: Boolean = false
+ override var outputDir: String = ""
+ override var impliedPlatforms: List<String> = listOf()
+ get() = buildImpliedPlatforms.map { it.value }.toList()
+ private val buildImpliedPlatforms: MutableList<TextProperty> = mutableListOf()
+
+ override var cacheRoot: String? = null
+ override val passesConfigurations: MutableList<AntPassConfig> = mutableListOf()
+
+ fun createPassConfig() = AntPassConfig(this).apply { passesConfigurations.add(this) }
+ fun createImpliedPlatform(): TextProperty = TextProperty().apply { buildImpliedPlatforms.add(this) }
- fun createExternalDocumentationLink() = ExternalDocumentationLink.Builder().apply { antExternalDocumentationLinks.add(this) }
override fun execute() {
- if (sourcePath.list().isEmpty() && antSourceRoots.isEmpty()) {
- throw BuildException("At least one source path needs to be specified")
- }
- if (moduleName == null) {
- throw BuildException("Module name needs to be specified")
- }
- if (outputDir == null) {
- throw BuildException("Output directory needs to be specified")
- }
- val sourceLinks = antSourceLinks.map {
- val path = it.path ?: throw BuildException("'path' attribute of a <sourceLink> element is required")
- if (path.contains("\\")) {
- throw BuildException("'dir' attribute of a <sourceLink> - incorrect value, only Unix based path allowed.")
+ for (passConfig in passesConfigurations) {
+ if (passConfig.sourcePath.list().isEmpty() && passConfig.antSourceRoots.isEmpty()) {
+ throw BuildException("At least one source path needs to be specified")
}
- val url = it.url ?: throw BuildException("'url' attribute of a <sourceLink> element is required")
- SourceLinkDefinitionImpl(File(path).canonicalFile.absolutePath, url, it.lineSuffix)
+ if (passConfig.moduleName == "") {
+ throw BuildException("Module name needs to be specified and not empty")
+ }
+
+ for (sourceLink in passConfig.antSourceLinkDefinition) {
+ if (sourceLink.path == null) {
+ throw BuildException("'path' attribute of a <sourceLink> element is required")
+ }
+ if (sourceLink.path!!.contains("\\")) {
+ throw BuildException("'dir' attribute of a <sourceLink> - incorrect value, only Unix based path allowed")
+ }
+
+ if (sourceLink.url == null) {
+ throw BuildException("'url' attribute of a <sourceLink> element is required")
+ }
+ }
+ }
+
+ if (outputDir == "") {
+ throw BuildException("Output directory needs to be specified and not empty")
}
- val generator = DokkaGenerator(
- AntLogger(this),
- compileClasspath.list().toList(),
- sourcePath.list().map { SourceRootImpl(it) } + antSourceRoots.mapNotNull { it.toSourceRoot() },
- samplesPath.list().toList(),
- includesPath.list().toList(),
- moduleName!!,
- DocumentationOptions(
- outputDir!!,
- outputFormat,
- skipDeprecated = skipDeprecated,
- sourceLinks = sourceLinks,
- jdkVersion = jdkVersion,
- impliedPlatforms = impliedPlatforms.split(','),
- perPackageOptions = antPackageOptions,
- externalDocumentationLinks = antExternalDocumentationLinks.map { it.build() },
- noStdlibLink = noStdlibLink,
- noJdkLink = noJdkLink,
- cacheRoot = cacheRoot,
- languageVersion = languageVersion,
- apiVersion = apiVersion
- )
- )
+ val generator = DokkaGenerator(this, AntLogger(this))
generator.generate()
}
} \ No newline at end of file
diff --git a/runners/cli/build.gradle b/runners/cli/build.gradle
index 7f733140..24db0b1e 100644
--- a/runners/cli/build.gradle
+++ b/runners/cli/build.gradle
@@ -4,13 +4,13 @@ sourceCompatibility = 1.8
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
- languageVersion = "1.2"
- apiVersion = languageVersion
+ languageVersion = language_version
+ apiVersion = language_version
jvmTarget = "1.8"
}
}
dependencies {
- compile project(":core")
- compile "com.github.spullara.cli-parser:cli-parser:1.1.1"
+ implementation "org.jetbrains.kotlinx:kotlinx-cli-jvm:0.1.0-dev-3"
+ implementation project(":core")
}
diff --git a/runners/cli/src/main/kotlin/cli/DokkaArgumentsParser.kt b/runners/cli/src/main/kotlin/cli/DokkaArgumentsParser.kt
new file mode 100644
index 00000000..5d795da7
--- /dev/null
+++ b/runners/cli/src/main/kotlin/cli/DokkaArgumentsParser.kt
@@ -0,0 +1,185 @@
+package org.jetbrains.dokka
+
+import kotlinx.cli.*
+import kotlin.reflect.KProperty
+
+class ParseContext(val cli: CommandLineInterface = CommandLineInterface("dokka")) {
+ private val transformActions = mutableMapOf<KProperty<*>, (String) -> Unit>()
+ private val flagActions = mutableMapOf<KProperty<*>, () -> Unit>()
+
+ fun registerFlagAction(
+ keys: List<String>,
+ help: String,
+ property: KProperty<*>,
+ invoke: () -> Unit
+ ) {
+ if (property !in flagActions.keys) {
+ cli.flagAction(keys, help) {
+ flagActions[property]!!()
+ }
+ }
+ flagActions[property] = invoke
+
+ }
+
+ fun registerSingleOption(
+ keys: List<String>,
+ help: String,
+ property: KProperty<*>,
+ invoke: (String) -> Unit
+ ) {
+ if (property !in transformActions.keys) {
+ cli.singleAction(keys, help) {
+ transformActions[property]!!(it)
+ }
+ }
+ transformActions[property] = invoke
+ }
+
+ fun registerRepeatableOption(
+ keys: List<String>,
+ help: String,
+ property: KProperty<*>,
+ invoke: (String) -> Unit
+ ) {
+ if (property !in transformActions.keys) {
+ cli.repeatingAction(keys, help) {
+ transformActions[property]!!(it)
+ }
+ }
+ transformActions[property] = invoke
+ }
+
+ fun parse(args: Array<String>) {
+ cli.parseArgs(*args)
+ }
+
+}
+
+fun CommandLineInterface.singleAction(
+ keys: List<String>,
+ help: String,
+ invoke: (String) -> Unit
+) = registerAction(
+ object : FlagActionBase(keys, help) {
+ override fun invoke(arguments: ListIterator<String>) {
+ if (arguments.hasNext()) {
+ val msg = arguments.next()
+ invoke(msg)
+ }
+ }
+
+ override fun invoke() {
+ error("should be never called")
+ }
+ }
+)
+
+fun CommandLineInterface.repeatingAction(
+ keys: List<String>,
+ help: String,
+ invoke: (String) -> Unit
+) = registerAction(
+ object : FlagActionBase(keys, help) {
+ override fun invoke(arguments: ListIterator<String>) {
+ while (arguments.hasNext()) {
+ val message = arguments.next()
+
+ if (this@repeatingAction.getFlagAction(message) != null) {
+ arguments.previous()
+ break
+ }
+ invoke(message)
+ }
+ }
+
+ override fun invoke() {
+ error("should be never called")
+ }
+ }
+
+)
+
+
+class DokkaArgumentsParser(val args: Array<String>, val parseContext: ParseContext) {
+ class OptionDelegate<T>(
+ var value: T,
+ private val action: (delegate: OptionDelegate<T>, property: KProperty<*>) -> Unit
+ ) {
+ operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value
+ operator fun provideDelegate(thisRef: Any, property: KProperty<*>): OptionDelegate<T> {
+ action(this, property)
+ return this
+ }
+ }
+
+ fun <T> parseInto(dest: T): T {
+ // TODO: constructor: (DokkaArgumentsParser) -> T
+ parseContext.parse(args)
+ return dest
+ }
+
+ fun <T> repeatableOption(
+ keys: List<String>,
+ help: String,
+ transform: (String) -> T
+ ) = OptionDelegate(mutableListOf<T>()) { delegate, property ->
+ parseContext.registerRepeatableOption(keys, help, property) {
+ delegate.value.add(transform(it))
+ }
+ }
+
+ fun <T : String?> repeatableOption(
+ keys: List<String>,
+ help: String
+ ) = repeatableOption(keys, help) { it as T }
+
+ fun <T> repeatableFlag(
+ keys: List<String>,
+ help: String,
+ initElement: (ParseContext) -> T
+ ) = OptionDelegate(mutableListOf<T>()) { delegate, property ->
+ parseContext.registerFlagAction(keys, help, property) {
+ delegate.value.add(initElement(parseContext))
+ }
+ }
+
+ fun <T> singleFlag(
+ keys: List<String>,
+ help: String,
+ initElement: (ParseContext) -> T,
+ transform: () -> T
+ ) = OptionDelegate(initElement(parseContext)) { delegate, property ->
+ parseContext.registerFlagAction(keys, help, property) {
+ delegate.value = transform()
+ }
+ }
+
+ fun singleFlag(
+ keys: List<String>,
+ help: String
+ ) = singleFlag(keys, help, { false }, { true })
+
+ fun <T : String?> stringOption(
+ keys: List<String>,
+ help: String,
+ defaultValue: T
+ ) = singleOption(keys, help, { it as T }, { defaultValue })
+
+ fun <T> singleOption(
+ keys: List<String>,
+ help: String,
+ transform: (String) -> T,
+ initElement: (ParseContext) -> T
+ ) = OptionDelegate(initElement(parseContext)) { delegate, property ->
+ parseContext.registerSingleOption(keys, help, property) {
+ val toAdd = transform(it)
+ delegate.value = toAdd
+ }
+ }
+}
+
+
+//`(-perPackage fqName [-include-non-public] [...other flags])*` (edited)
+//`(-sourceLink dir url [-urlSuffix value])*`
+//`(-extLink url [packageListUrl])*` \ No newline at end of file
diff --git a/runners/cli/src/main/kotlin/cli/main.kt b/runners/cli/src/main/kotlin/cli/main.kt
index f871f406..52815e75 100644
--- a/runners/cli/src/main/kotlin/cli/main.kt
+++ b/runners/cli/src/main/kotlin/cli/main.kt
@@ -1,142 +1,190 @@
package org.jetbrains.dokka
-
-import com.sampullara.cli.Args
-import com.sampullara.cli.Argument
import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink
-
import java.io.File
import java.net.MalformedURLException
import java.net.URL
import java.net.URLClassLoader
-class DokkaArguments {
- @set:Argument(value = "src", description = "Source file or directory (allows many paths separated by the system path separator)")
- var src: String = ""
-
- @set:Argument(value = "srcLink", description = "Mapping between a source directory and a Web site for browsing the code")
- var srcLink: String = ""
-
- @set:Argument(value = "include", description = "Markdown files to load (allows many paths separated by the system path separator)")
- var include: String = ""
-
- @set:Argument(value = "samples", description = "Source root for samples")
- var samples: String = ""
-
- @set:Argument(value = "output", description = "Output directory path")
- var outputDir: String = "out/doc/"
-
- @set:Argument(value = "format", description = "Output format (text, html, markdown, jekyll, kotlin-website)")
- var outputFormat: String = "html"
-
- @set:Argument(value = "module", description = "Name of the documentation module")
- var moduleName: String = ""
-
- @set:Argument(value = "classpath", description = "Classpath for symbol resolution")
- var classpath: String = ""
-
- @set:Argument(value = "nodeprecated", description = "Exclude deprecated members from documentation")
- var nodeprecated: Boolean = false
-
- @set:Argument(value = "jdkVersion", description = "Version of JDK to use for linking to JDK JavaDoc")
- var jdkVersion: Int = 6
-
- @set:Argument(value = "impliedPlatforms", description = "List of implied platforms (comma-separated)")
- var impliedPlatforms: String = ""
-
- @set:Argument(value = "packageOptions", description = "List of package options in format \"prefix,-deprecated,-privateApi,+warnUndocumented,+suppress;...\" ")
- var packageOptions: String = ""
-
- @set:Argument(value = "links", description = "External documentation links in format url^packageListUrl^^url2...")
- var links: String = ""
-
- @set:Argument(value = "noStdlibLink", description = "Disable documentation link to stdlib")
- var noStdlibLink: Boolean = false
-
- @set:Argument(value = "noJdkLink", description = "Disable documentation link to jdk")
- var noJdkLink: Boolean = false
-
- @set:Argument(value = "cacheRoot", description = "Path to cache folder, or 'default' to use ~/.cache/dokka, if not provided caching is disabled")
- var cacheRoot: String? = null
-
- @set:Argument(value = "languageVersion", description = "Language Version to pass to Kotlin Analysis")
- var languageVersion: String? = null
-
- @set:Argument(value = "apiVersion", description = "Kotlin Api Version to pass to Kotlin Analysis")
- var apiVersion: String? = null
-
- @set:Argument(value = "collectInheritedExtensionsFromLibraries", description = "Search for applicable extensions in libraries")
- var collectInheritedExtensionsFromLibraries: Boolean = false
-
+open class GlobalArguments(parser: DokkaArgumentsParser) : DokkaConfiguration {
+ override val outputDir: String by parser.stringOption(
+ listOf("-output"),
+ "Output directory path",
+ "")
+
+ override val format: String by parser.stringOption(
+ listOf("-format"),
+ "Output format (text, html, markdown, jekyll, kotlin-website)",
+ "")
+
+ override val generateIndexPages: Boolean by parser.singleFlag(
+ listOf("-generateIndexPages"),
+ "Generate index page"
+ )
+
+ override val cacheRoot: String? by parser.stringOption(
+ listOf("-cacheRoot"),
+ "Path to cache folder, or 'default' to use ~/.cache/dokka, if not provided caching is disabled",
+ null)
+
+ override val impliedPlatforms: List<String> = emptyList()
+
+ override val passesConfigurations: List<Arguments> by parser.repeatableFlag(
+ listOf("-pass"),
+ "Single dokka pass"
+ ) {
+ Arguments(parser)
+ }
}
+class Arguments(val parser: DokkaArgumentsParser) : DokkaConfiguration.PassConfiguration {
+ override val moduleName: String by parser.stringOption(
+ listOf("-module"),
+ "Name of the documentation module",
+ "")
+
+ override val classpath: List<String> by parser.repeatableOption(
+ listOf("-classpath"),
+ "Classpath for symbol resolution"
+ )
+
+ override val sourceRoots: List<DokkaConfiguration.SourceRoot> by parser.repeatableOption(
+ listOf("-src"),
+ "Source file or directory (allows many paths separated by the system path separator)"
+ ) { SourceRootImpl(it) }
+
+ override val samples: List<String> by parser.repeatableOption(
+ listOf("-sample"),
+ "Source root for samples"
+ )
+
+ override val includes: List<String> by parser.repeatableOption(
+ listOf("-include"),
+ "Markdown files to load (allows many paths separated by the system path separator)"
+ )
+
+ override val includeNonPublic: Boolean by parser.singleFlag(
+ listOf("-includeNonPublic"),
+ "Include non public")
+
+ override val includeRootPackage: Boolean by parser.singleFlag(
+ listOf("-includeRootPackage"),
+ "Include root package")
+
+ override val reportUndocumented: Boolean by parser.singleFlag(
+ listOf("-reportUndocumented"),
+ "Report undocumented members")
+
+ override val skipEmptyPackages: Boolean by parser.singleFlag(
+ listOf("-skipEmptyPackages"),
+ "Do not create index pages for empty packages")
+
+ override val skipDeprecated: Boolean by parser.singleFlag(
+ listOf("-skipDeprecated"),
+ "Do not output deprecated members")
+
+ override val jdkVersion: Int by parser.singleOption(
+ listOf("-jdkVersion"),
+ "Version of JDK to use for linking to JDK JavaDoc",
+ { it.toInt() },
+ { 6 }
+ )
+
+ override val languageVersion: String? by parser.stringOption(
+ listOf("-languageVersion"),
+ "Language Version to pass to Kotlin Analysis",
+ null)
+
+ override val apiVersion: String? by parser.stringOption(
+ listOf("-apiVersion"),
+ "Kotlin Api Version to pass to Kotlin Analysis",
+ null
+ )
+
+ override val noStdlibLink: Boolean by parser.singleFlag(
+ listOf("-noStdlibLink"),
+ "Disable documentation link to stdlib")
+
+ override val noJdkLink: Boolean by parser.singleFlag(
+ listOf("-noJdkLink"),
+ "Disable documentation link to JDK")
+
+ override val suppressedFiles: List<String> by parser.repeatableOption(
+ listOf("-suppressedFile"),
+ ""
+ )
+
+ override val sinceKotlin: String? by parser.stringOption(
+ listOf("-sinceKotlin"),
+ "Kotlin Api version to use as base version, if none specified",
+ null
+ )
+
+ override val collectInheritedExtensionsFromLibraries: Boolean by parser.singleFlag(
+ listOf("-collectInheritedExtensionsFromLibraries"),
+ "Search for applicable extensions in libraries")
+
+ override val analysisPlatform: Platform by parser.singleOption(
+ listOf("-analysisPlatform"),
+ "Platform for analysis",
+ { Platform.fromString(it) },
+ { Platform.DEFAULT }
+ )
+
+ override val targets: List<String> by parser.repeatableOption(
+ listOf("-target"),
+ "Generation targets"
+ )
+
+ override val perPackageOptions: MutableList<DokkaConfiguration.PackageOptions> by parser.singleOption(
+ listOf("-packageOptions"),
+ "List of package passConfiguration in format \"prefix,-deprecated,-privateApi,+warnUndocumented,+suppress;...\" ",
+ { parsePerPackageOptions(it).toMutableList() },
+ { mutableListOf() }
+ )
+
+ override val externalDocumentationLinks: MutableList<DokkaConfiguration.ExternalDocumentationLink> by parser.singleOption(
+ listOf("-links"),
+ "External documentation links in format url^packageListUrl^^url2...",
+ { MainKt.parseLinks(it).toMutableList() },
+ { mutableListOf() }
+ )
+
+ override val sourceLinks: MutableList<DokkaConfiguration.SourceLinkDefinition> by parser.repeatableOption(
+ listOf("-srcLink"),
+ "Mapping between a source directory and a Web site for browsing the code"
+ ) {
+ if (it.isNotEmpty() && it.contains("="))
+ SourceLinkDefinitionImpl.parseSourceLinkDefinition(it)
+ else {
+ throw IllegalArgumentException("Warning: Invalid -srcLink syntax. Expected: <path>=<url>[#lineSuffix]. No source links will be generated.")
+ }
+ }
+}
object MainKt {
-
fun parseLinks(links: String): List<ExternalDocumentationLink> {
val (parsedLinks, parsedOfflineLinks) = links.split("^^")
- .map { it.split("^").map { it.trim() }.filter { it.isNotBlank() } }
- .filter { it.isNotEmpty() }
- .partition { it.size == 1 }
+ .map { it.split("^").map { it.trim() }.filter { it.isNotBlank() } }
+ .filter { it.isNotEmpty() }
+ .partition { it.size == 1 }
return parsedLinks.map { (root) -> ExternalDocumentationLink.Builder(root).build() } +
parsedOfflineLinks.map { (root, packageList) ->
val rootUrl = URL(root)
val packageListUrl =
- try {
- URL(packageList)
- } catch (ex: MalformedURLException) {
- File(packageList).toURI().toURL()
- }
+ try {
+ URL(packageList)
+ } catch (ex: MalformedURLException) {
+ File(packageList).toURI().toURL()
+ }
ExternalDocumentationLink.Builder(rootUrl, packageListUrl).build()
}
}
@JvmStatic
- fun entry(args: Array<String>) {
- val arguments = DokkaArguments()
- val freeArgs: List<String> = Args.parse(arguments, args) ?: listOf()
- val sources = if (arguments.src.isNotEmpty()) arguments.src.split(File.pathSeparatorChar).toList() + freeArgs else freeArgs
- val samples = if (arguments.samples.isNotEmpty()) arguments.samples.split(File.pathSeparatorChar).toList() else listOf()
- val includes = if (arguments.include.isNotEmpty()) arguments.include.split(File.pathSeparatorChar).toList() else listOf()
-
- val sourceLinks = if (arguments.srcLink.isNotEmpty() && arguments.srcLink.contains("="))
- listOf(SourceLinkDefinitionImpl.parseSourceLinkDefinition(arguments.srcLink))
- else {
- if (arguments.srcLink.isNotEmpty()) {
- println("Warning: Invalid -srcLink syntax. Expected: <path>=<url>[#lineSuffix]. No source links will be generated.")
- }
- listOf()
- }
-
- val classPath = arguments.classpath.split(File.pathSeparatorChar).toList()
-
- val documentationOptions = DocumentationOptions(
- arguments.outputDir.let { if (it.endsWith('/')) it else it + '/' },
- arguments.outputFormat,
- skipDeprecated = arguments.nodeprecated,
- sourceLinks = sourceLinks,
- impliedPlatforms = arguments.impliedPlatforms.split(','),
- perPackageOptions = parsePerPackageOptions(arguments.packageOptions),
- jdkVersion = arguments.jdkVersion,
- externalDocumentationLinks = parseLinks(arguments.links),
- noStdlibLink = arguments.noStdlibLink,
- cacheRoot = arguments.cacheRoot,
- languageVersion = arguments.languageVersion,
- apiVersion = arguments.apiVersion,
- collectInheritedExtensionsFromLibraries = arguments.collectInheritedExtensionsFromLibraries,
- noJdkLink = arguments.noJdkLink
- )
-
- val generator = DokkaGenerator(
- DokkaConsoleLogger,
- classPath,
- sources.map(SourceRootImpl.Companion::parseSourceRoot),
- samples,
- includes,
- arguments.moduleName,
- documentationOptions)
-
+ fun entry(configuration: DokkaConfiguration) {
+ val generator = DokkaGenerator(configuration, DokkaConsoleLogger)
generator.generate()
DokkaConsoleLogger.report()
}
@@ -162,27 +210,65 @@ object MainKt {
return URLClassLoader(urls, ClassLoader.getSystemClassLoader().parent)
}
- fun startWithToolsJar(args: Array<String>) {
+ fun startWithToolsJar(configuration: DokkaConfiguration) {
try {
javaClass.classLoader.loadClass("com.sun.tools.doclets.formats.html.HtmlDoclet")
- entry(args)
+ entry(configuration)
} catch (e: ClassNotFoundException) {
val classLoader = createClassLoaderWithTools()
classLoader.loadClass("org.jetbrains.dokka.MainKt")
- .methods.find { it.name == "entry" }!!
- .invoke(null, args)
+ .methods.find { it.name == "entry" }!!
+ .invoke(null, configuration)
+ }
+ }
+
+ fun createConfiguration(args: Array<String>): GlobalArguments {
+ val parseContext = ParseContext()
+ val parser = DokkaArgumentsParser(args, parseContext)
+ val configuration = GlobalArguments(parser)
+
+ parseContext.cli.singleAction(
+ listOf("-globalPackageOptions"),
+ "List of package passConfiguration in format \"prefix,-deprecated,-privateApi,+warnUndocumented,+suppress;...\" "
+ ) { link ->
+ configuration.passesConfigurations.all { it.perPackageOptions.addAll(parsePerPackageOptions(link)) }
}
+
+ parseContext.cli.singleAction(
+ listOf("-globalLinks"),
+ "External documentation links in format url^packageListUrl^^url2..."
+ ) { link ->
+ configuration.passesConfigurations.all { it.externalDocumentationLinks.addAll(parseLinks(link)) }
+ }
+
+ parseContext.cli.repeatingAction(
+ listOf("-globalSrcLink"),
+ "Mapping between a source directory and a Web site for browsing the code"
+ ) {
+ val newSourceLinks = if (it.isNotEmpty() && it.contains("="))
+ listOf(SourceLinkDefinitionImpl.parseSourceLinkDefinition(it))
+ else {
+ if (it.isNotEmpty()) {
+ println("Warning: Invalid -srcLink syntax. Expected: <path>=<url>[#lineSuffix]. No source links will be generated.")
+ }
+ listOf()
+ }
+
+ configuration.passesConfigurations.all { it.sourceLinks.addAll(newSourceLinks) }
+ }
+
+ parser.parseInto(configuration)
+ return configuration
}
@JvmStatic
fun main(args: Array<String>) {
- val arguments = DokkaArguments()
- Args.parse(arguments, args)
+ val configuration = createConfiguration(args)
- if (arguments.outputFormat == "javadoc")
- startWithToolsJar(args)
+ if (configuration.format.toLowerCase() == "javadoc")
+ startWithToolsJar(configuration)
else
- entry(args)
+ entry(configuration)
}
}
diff --git a/runners/gradle-integration-tests/build.gradle b/runners/gradle-integration-tests/build.gradle
index 297a175a..2430d46b 100644
--- a/runners/gradle-integration-tests/build.gradle
+++ b/runners/gradle-integration-tests/build.gradle
@@ -1,5 +1,3 @@
-
-
apply plugin: 'kotlin'
sourceCompatibility = 1.8
@@ -7,16 +5,16 @@ sourceCompatibility = 1.8
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
freeCompilerArgs += "-Xjsr305=strict"
- languageVersion = "1.2"
- apiVersion = "1.0"
+ languageVersion = language_version
+ apiVersion = language_version
jvmTarget = "1.8"
}
}
configurations {
dokkaPlugin
- dokkaAndroidPlugin
dokkaFatJar
+ kotlinGradle
}
dependencies {
@@ -26,9 +24,10 @@ dependencies {
testCompile ideaRT()
dokkaPlugin project(path: ':runners:gradle-plugin', configuration: 'shadow')
- dokkaAndroidPlugin project(path: ':runners:android-gradle-plugin', configuration: 'shadow')
dokkaFatJar project(path: ":runners:fatjar", configuration: 'shadow')
+ kotlinGradle "org.jetbrains.kotlin:kotlin-gradle-plugin"
+
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile gradleTestKit()
}
@@ -38,14 +37,14 @@ dependencies {
task createClasspathManifest {
def outputDir = file("$buildDir/$name")
- inputs.files(configurations.dokkaPlugin + configurations.dokkaAndroidPlugin + configurations.dokkaFatJar)
+ inputs.files(configurations.dokkaPlugin + configurations.dokkaFatJar)
outputs.dir outputDir
doLast {
outputDir.mkdirs()
file("$outputDir/dokka-plugin-classpath.txt").text = configurations.dokkaPlugin.join("\n")
- file("$outputDir/android-dokka-plugin-classpath.txt").text = configurations.dokkaAndroidPlugin.join("\n")
file("$outputDir/fatjar.txt").text = configurations.dokkaFatJar.join("\n")
+ file("$outputDir/kotlin-gradle.txt").text = configurations.kotlinGradle.join("\n")
}
}
diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaAndroidGradleTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaAndroidGradleTest.kt
index 06753342..334fc7c8 100644
--- a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaAndroidGradleTest.kt
+++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaAndroidGradleTest.kt
@@ -5,7 +5,7 @@ import java.io.File
abstract class AbstractDokkaAndroidGradleTest : AbstractDokkaGradleTest() {
- override val pluginClasspath: List<File> = androidPluginClasspathData.toFile().readLines().map { File(it) }
+ override val pluginClasspath: List<File> = pluginClasspathData.toFile().readLines().map { File(it) }
companion object {
@@ -31,7 +31,7 @@ abstract class AbstractDokkaAndroidGradleTest : AbstractDokkaGradleTest() {
acceptedLicenses.listFiles().forEach { licenseFile ->
val target = sdkLicensesDir.resolve(licenseFile.name)
if(!target.exists() || target.readText() != licenseFile.readText()) {
- val overwrite = System.getProperty("android.licenses.overwrite", "false").toBoolean()
+ val overwrite = System.getProperty("android.licenses.overwrite", "false")!!.toBoolean()
if (!target.exists() || overwrite) {
licenseFile.copyTo(target, true)
println("Accepted ${licenseFile.name}, by copying $licenseFile to $target")
diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaGradleTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaGradleTest.kt
index 255138a9..4814e707 100644
--- a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaGradleTest.kt
+++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaGradleTest.kt
@@ -7,15 +7,15 @@ import org.junit.Rule
import org.junit.rules.TemporaryFolder
import java.io.File
import java.nio.file.Files
+import java.nio.file.Path
import java.nio.file.Paths
-val testDataFolder = Paths.get("testData")
+val testDataFolder: Path = Paths.get("testData")
-val pluginClasspathData = Paths.get("build", "createClasspathManifest", "dokka-plugin-classpath.txt")
-val androidPluginClasspathData = pluginClasspathData.resolveSibling("android-dokka-plugin-classpath.txt")
+val pluginClasspathData: Path = Paths.get("build", "createClasspathManifest", "dokka-plugin-classpath.txt")
-val dokkaFatJarPathData = pluginClasspathData.resolveSibling("fatjar.txt")
+val dokkaFatJarPathData: Path = pluginClasspathData.resolveSibling("fatjar.txt")
val androidLocalProperties = testDataFolder.resolve("android.local.properties").let { if (Files.exists(it)) it else null }
diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AndroidLibDependsOnJavaLibTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AndroidLibDependsOnJavaLibTest.kt
index 2a4ce712..9bc52273 100644
--- a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AndroidLibDependsOnJavaLibTest.kt
+++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AndroidLibDependsOnJavaLibTest.kt
@@ -2,8 +2,6 @@ package org.jetbrains.dokka.gradle
import org.gradle.testkit.runner.TaskOutcome
import org.junit.Test
-import java.nio.file.Path
-import java.nio.file.Paths
import kotlin.test.assertEquals
class AndroidLibDependsOnJavaLibTest: AbstractDokkaAndroidGradleTest() {
diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/BasicTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/BasicTest.kt
index ebaf1653..2e1a0d41 100644
--- a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/BasicTest.kt
+++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/BasicTest.kt
@@ -37,10 +37,6 @@ class BasicTest : AbstractDokkaGradleTest() {
"""<a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html"><span class="identifier">String</span></a>""")
}
- @Test fun `test kotlin 1_1_2 and gradle 3_5`() {
- doTest("3.5", "1.1.2")
- }
-
@Test fun `test kotlin 1_0_7 and gradle 2_14_1`() {
doTest("2.14.1", "1.0.7")
}
diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiplatformProjectTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiplatformProjectTest.kt
new file mode 100644
index 00000000..3e61d79e
--- /dev/null
+++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiplatformProjectTest.kt
@@ -0,0 +1,54 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.testkit.runner.TaskOutcome
+import org.junit.Test
+import java.io.File
+import kotlin.test.assertEquals
+
+class MultiplatformProjectTest : AbstractDokkaGradleTest() {
+
+ fun prepareTestData(testDataRootPath: String) {
+ val testDataRoot = testDataFolder.resolve(testDataRootPath)
+ val tmpRoot = testProjectDir.root.toPath()
+
+ testDataRoot.apply {
+ resolve("build.gradle").copy(tmpRoot.resolve("build.gradle"))
+ resolve("settings.gradle").copy(tmpRoot.resolve("settings.gradle"))
+ resolve("src").copy(tmpRoot.resolve("src"))
+ }
+ }
+
+ private fun doTest(gradleVersion: String, kotlinVersion: String) {
+ val kotlinGradlePlugin = pluginClasspathData.resolveSibling("kotlin-gradle.txt").toFile().readLines().map { File(it) }
+ prepareTestData("multiplatformProject")
+
+ // Remove withDebug(false) when https://github.com/gradle/gradle/issues/6862 is solved
+ val result = configure(gradleVersion, kotlinVersion, arguments = arrayOf("dokka", "--stacktrace"))
+ .withDebug(false)
+ .withPluginClasspath(pluginClasspath.union(kotlinGradlePlugin))
+ .build()
+
+ println(result.output)
+
+ assertEquals(TaskOutcome.SUCCESS, result.task(":dokka")?.outcome)
+
+ val docsOutput = "build/dokka"
+
+ checkOutputStructure("multiplatformProject/fileTree.txt", docsOutput)
+
+ checkNoErrorClasses(docsOutput)
+ checkNoUnresolvedLinks(docsOutput)
+ }
+
+ @Test fun `test kotlin 1_3_30 and gradle 4_7`() {
+ doTest("4.7", "1.3.30")
+ }
+
+ @Test fun `test kotlin 1_3_40 and gradle 4_10_3`() {
+ doTest("4.10.3", "1.3.40")
+ }
+
+ @Test fun `test kotlin 1_3_40 and gradle 5_6_1`() {
+ doTest("5.6.1", "1.3.50")
+ }
+} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/RebuildAfterSourceChangeTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/RebuildAfterSourceChangeTest.kt
index f712998c..8b2db560 100644
--- a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/RebuildAfterSourceChangeTest.kt
+++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/RebuildAfterSourceChangeTest.kt
@@ -30,7 +30,7 @@ class RebuildAfterSourceChangeTest : AbstractDokkaGradleTest() {
}
- configure(gradleVersion, kotlinVersion, arguments = arrayOf("dokka", "--stacktrace")).build().let { result ->
+ configure(gradleVersion, kotlinVersion, arguments = arrayOf("dokka", "-i", "--stacktrace")).build().let { result ->
println(result.output)
assertEquals(TaskOutcome.UP_TO_DATE, result.task(":dokka")?.outcome)
@@ -53,13 +53,13 @@ class RebuildAfterSourceChangeTest : AbstractDokkaGradleTest() {
@Test
- fun `test kotlin 1_1_2 and gradle 3_5`() {
- doTest("3.5", "1.1.2")
+ fun `test kotlin 1_0_7 and gradle 2_14_1`() {
+ doTest("2.14.1", "1.0.7")
}
@Test
- fun `test kotlin 1_0_7 and gradle 2_14_1`() {
- doTest("2.14.1", "1.0.7")
+ fun `test kotlin 1_1_2 and gradle 3_5`() {
+ doTest("3.5", "1.1.2")
}
@Test
diff --git a/runners/gradle-integration-tests/testData/androidApp/app/build.gradle b/runners/gradle-integration-tests/testData/androidApp/app/build.gradle
index 1555de9f..2420107c 100644
--- a/runners/gradle-integration-tests/testData/androidApp/app/build.gradle
+++ b/runners/gradle-integration-tests/testData/androidApp/app/build.gradle
@@ -9,14 +9,13 @@ buildscript {
}
plugins {
- id 'org.jetbrains.dokka-android'
+ id 'org.jetbrains.dokka'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
-apply plugin: 'org.jetbrains.dokka-android'
android {
compileSdkVersion Integer.parseInt(sdk_version)
@@ -42,9 +41,5 @@ android {
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$test_kotlin_version"
-}
-
-
-dokka {
- dokkaFatJar = new File(dokka_fatjar)
+ dokkaRuntime files(dokka_fatjar)
} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/app/build.gradle b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/build.gradle
index 6a053a5e..66421f52 100644
--- a/runners/gradle-integration-tests/testData/androidAppJavadoc/app/build.gradle
+++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/build.gradle
@@ -9,13 +9,12 @@ buildscript {
}
plugins {
- id 'org.jetbrains.dokka-android'
+ id 'org.jetbrains.dokka'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
-apply plugin: 'org.jetbrains.dokka-android'
android {
compileSdkVersion Integer.parseInt(sdk_version)
@@ -41,10 +40,10 @@ android {
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$test_kotlin_version"
+ dokkaRuntime files(dokka_fatjar)
}
dokka {
outputFormat = "javadoc"
- dokkaFatJar = new File(dokka_fatjar)
} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/androidLibDependsOnJavaLib/lib/build.gradle b/runners/gradle-integration-tests/testData/androidLibDependsOnJavaLib/lib/build.gradle
index 0f27d365..b1ee52ab 100644
--- a/runners/gradle-integration-tests/testData/androidLibDependsOnJavaLib/lib/build.gradle
+++ b/runners/gradle-integration-tests/testData/androidLibDependsOnJavaLib/lib/build.gradle
@@ -7,13 +7,12 @@ buildscript {
plugins {
- id 'org.jetbrains.dokka-android'
+ id 'org.jetbrains.dokka'
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
-apply plugin: 'org.jetbrains.dokka-android'
android {
@@ -27,13 +26,14 @@ android {
dependencies {
api(project(":jlib"))
+ dokkaRuntime files(dokka_fatjar)
}
dokka {
- dokkaFatJar = new File(dokka_fatjar)
-
- externalDocumentationLink {
- url = new URL("https://example.com")
- packageListUrl = file("$rootDir/package-list").toURI().toURL()
+ configuration {
+ externalDocumentationLink {
+ url = new URL("https://example.com")
+ packageListUrl = file("$rootDir/package-list").toURI().toURL()
+ }
}
} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/androidMultiFlavourApp/app/build.gradle b/runners/gradle-integration-tests/testData/androidMultiFlavourApp/app/build.gradle
index ee68ba6d..660257ab 100644
--- a/runners/gradle-integration-tests/testData/androidMultiFlavourApp/app/build.gradle
+++ b/runners/gradle-integration-tests/testData/androidMultiFlavourApp/app/build.gradle
@@ -9,14 +9,13 @@ buildscript {
}
plugins {
- id 'org.jetbrains.dokka-android'
+ id 'org.jetbrains.dokka'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
-apply plugin: 'org.jetbrains.dokka-android'
android {
compileSdkVersion Integer.parseInt(sdk_version)
@@ -57,19 +56,20 @@ android {
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$test_kotlin_version"
+ dokkaRuntime files(dokka_fatjar)
}
dokka {
outputDirectory = "$buildDir/dokka/all"
- dokkaFatJar = new File(dokka_fatjar)
}
-task dokkaFullFlavourOnly(type: org.jetbrains.dokka.gradle.DokkaAndroidTask) {
- kotlinTasks {
- ["compileFullReleaseKotlin"]
- }
- dokkaFatJar = new File(dokka_fatjar)
+task dokkaFullFlavourOnly(type: org.jetbrains.dokka.gradle.DokkaTask) {
outputDirectory = "$buildDir/dokka/fullOnly"
- moduleName = "full"
+ configuration {
+ moduleName = "full"
+ kotlinTasks {
+ ["compileFullReleaseKotlin"]
+ }
+ }
} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/basic/build.gradle b/runners/gradle-integration-tests/testData/basic/build.gradle
index a3116751..79645204 100644
--- a/runners/gradle-integration-tests/testData/basic/build.gradle
+++ b/runners/gradle-integration-tests/testData/basic/build.gradle
@@ -29,12 +29,14 @@ repositories {
}
dependencies {
+ dokkaRuntime files(dokka_fatjar)
compile group: 'org.jetbrains.kotlin', name: 'kotlin-runtime', version: test_kotlin_version
compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: test_kotlin_version
}
dokka {
- dokkaFatJar = new File(dokka_fatjar)
- classpath += files("$projectDir/classDir")
+ configuration {
+ classpath += "$projectDir/classDir"
+ }
} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/multiProjectSingleOut/build.gradle b/runners/gradle-integration-tests/testData/multiProjectSingleOut/build.gradle
index 4f561472..0ea86d4c 100644
--- a/runners/gradle-integration-tests/testData/multiProjectSingleOut/build.gradle
+++ b/runners/gradle-integration-tests/testData/multiProjectSingleOut/build.gradle
@@ -22,11 +22,16 @@ subprojects {
}
}
+dependencies {
+ dokkaRuntime files(dokka_fatjar)
+}
+
apply plugin: 'org.jetbrains.dokka'
dokka {
- kotlinTasks {
- [":subA:compileKotlin", ":subB:compileKotlin"]
+ configuration {
+ kotlinTasks {
+ [":subA:compileKotlin", ":subB:compileKotlin"]
+ }
}
- dokkaFatJar = new File(dokka_fatjar)
} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/multiplatformProject/build.gradle b/runners/gradle-integration-tests/testData/multiplatformProject/build.gradle
new file mode 100644
index 00000000..b5454c55
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/multiplatformProject/build.gradle
@@ -0,0 +1,60 @@
+buildscript {
+ repositories {
+ mavenCentral()
+ jcenter()
+ maven { url "https://dl.bintray.com/kotlin/kotlin-eap-1.1" }
+ maven { url "https://dl.bintray.com/kotlin/kotlin-dev" }
+ }
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$test_kotlin_version"
+ }
+}
+
+plugins {
+ id 'org.jetbrains.dokka'
+}
+
+repositories {
+ jcenter()
+ mavenLocal()
+}
+
+group 'org.test'
+version '1.0-SNAPSHOT'
+
+apply plugin: "org.jetbrains.kotlin.multiplatform"
+
+kotlin {
+ jvm() // Create a JVM target with the default name 'jvm'
+ js()
+ sourceSets {
+ jsMain {
+ dependencies{
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-js"
+ }
+ }
+ jvmMain {
+ dependencies {
+ implementation kotlin('stdlib-jdk8')
+ }
+ }
+ }
+}
+
+dependencies {
+ dokkaRuntime files(dokka_fatjar)
+}
+
+apply plugin: 'org.jetbrains.dokka'
+
+dokka {
+
+ multiplatform {
+ javascript {
+ targets = ["js"]
+ platform = "js"
+ kotlinTasks { [tasks.getByPath(":compileKotlinJs")] }
+ }
+ jvm {}
+ }
+}
diff --git a/runners/gradle-integration-tests/testData/multiplatformProject/fileTree.txt b/runners/gradle-integration-tests/testData/multiplatformProject/fileTree.txt
new file mode 100644
index 00000000..51a5df94
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/multiplatformProject/fileTree.txt
@@ -0,0 +1,17 @@
+/
+ multiplatform-project-root/
+ alltypes/
+ index.html
+ index-outline.html
+ index.html
+ org.kotlintestmpp/
+ get-current-date.html
+ index.html
+ js.html
+ jvm.html
+ kotlin.-string/
+ index.html
+ main.html
+ shared.html
+ package-list
+ style.css
diff --git a/runners/gradle-integration-tests/testData/multiplatformProject/settings.gradle b/runners/gradle-integration-tests/testData/multiplatformProject/settings.gradle
new file mode 100644
index 00000000..0bb1e91b
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/multiplatformProject/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = "multiplatformProjectRoot"
diff --git a/runners/gradle-integration-tests/testData/multiplatformProject/src/jsMain/kotlin/org/kotlintestmpp/main.kt b/runners/gradle-integration-tests/testData/multiplatformProject/src/jsMain/kotlin/org/kotlintestmpp/main.kt
new file mode 100644
index 00000000..a77b50f9
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/multiplatformProject/src/jsMain/kotlin/org/kotlintestmpp/main.kt
@@ -0,0 +1,14 @@
+package org.kotlintestmpp
+
+fun main(args : Array<String>) {
+ console.log("Hello, world!")
+}
+
+fun js(){}
+fun shared(){}
+
+fun getCurrentDate(): String {
+ return "test"
+}
+
+fun String.myExtension() = println("test") \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/multiplatformProject/src/jvmMain/kotlin/org/kotlintestmpp/main.kt b/runners/gradle-integration-tests/testData/multiplatformProject/src/jvmMain/kotlin/org/kotlintestmpp/main.kt
new file mode 100644
index 00000000..96d725fc
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/multiplatformProject/src/jvmMain/kotlin/org/kotlintestmpp/main.kt
@@ -0,0 +1,20 @@
+package org.kotlintestmpp
+
+
+fun main(args : Array<String>) {
+ println("Hello, world!")
+}
+
+/**
+ * comment for this class
+ */
+fun jvm(){}
+fun shared(){}
+
+fun getCurrentDate(): String {
+ return "test"
+}
+
+fun String.myExtension() = println("test2")
+
+
diff --git a/runners/gradle-integration-tests/testData/sourcesChange/build.gradle b/runners/gradle-integration-tests/testData/sourcesChange/build.gradle
index 4627e8ef..a6270e23 100644
--- a/runners/gradle-integration-tests/testData/sourcesChange/build.gradle
+++ b/runners/gradle-integration-tests/testData/sourcesChange/build.gradle
@@ -29,11 +29,7 @@ repositories {
}
dependencies {
+ dokkaRuntime files(dokka_fatjar)
compile group: 'org.jetbrains.kotlin', name: 'kotlin-runtime', version: test_kotlin_version
compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: test_kotlin_version
-}
-
-
-dokka {
- dokkaFatJar = new File(dokka_fatjar)
} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/typeSafeConfiguration/build.gradle b/runners/gradle-integration-tests/testData/typeSafeConfiguration/build.gradle
index 327cead8..8688ae41 100644
--- a/runners/gradle-integration-tests/testData/typeSafeConfiguration/build.gradle
+++ b/runners/gradle-integration-tests/testData/typeSafeConfiguration/build.gradle
@@ -8,6 +8,7 @@ import java.util.concurrent.Callable
buildscript {
repositories {
jcenter()
+ mavenLocal()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$test_kotlin_version"
@@ -23,57 +24,45 @@ apply plugin: 'kotlin'
@CompileStatic
def configureDokkaTypeSafely(DokkaTask dokka) {
dokka.with {
- moduleName = "some String"
outputFormat = "some String"
outputDirectory = "some String"
- classpath = Collections.singleton(file("someClassDir"))
- includes = Collections.emptyList()
- linkMappings = new ArrayList<LinkMapping>()
- samples = Collections.emptyList()
+ cacheRoot = null as String
+ impliedPlatforms = new ArrayList<String>()
+ }
+ dokka.configuration.with {
+ moduleName = "some String"
+ classpath = Arrays.asList("someClassDir")
+ includes = Collections.<String> emptyList()
+ samples = Collections.<String> emptyList()
jdkVersion = 6
- sourceDirs = Collections.<File>emptyList()
- sourceRoots = new ArrayList<SourceRoot>()
- dokkaFatJar = file("some File")
+ sourceRoots = new ArrayList<GradleSourceRootImpl>() as List<DokkaConfiguration.SourceRoot>
+
includeNonPublic = false
skipDeprecated = false
skipEmptyPackages = true
reportUndocumented = true
- perPackageOptions = new ArrayList<PackageOptions>()
- impliedPlatforms = Collections.<String>emptyList()
+ perPackageOptions = new ArrayList<GradlePackageOptionsImpl>() as List<DokkaConfiguration.PackageOptions>
externalDocumentationLinks = new ArrayList<DokkaConfiguration.ExternalDocumentationLink>()
noStdlibLink = false
- cacheRoot = null as String
languageVersion = null as String
apiVersion = null as String
- kotlinTasks(new Callable<List<Object>>() {
- @Override
- List<Object> call() {
- return defaultKotlinTasks()
- }
- })
- linkMapping(new Action<LinkMapping>() {
+ sourceRoot(new Action<GradleSourceRootImpl>() {
@Override
- void execute(LinkMapping mapping) {
- mapping.dir = "some String"
- mapping.url = "some String"
- }
- })
- sourceRoot(new Action<SourceRoot>() {
- @Override
- void execute(SourceRoot sourceRoot) {
+ void execute(GradleSourceRootImpl sourceRoot) {
sourceRoot.path = "some String"
}
})
- packageOptions(new Action<PackageOptions>() {
+ externalDocumentationLink(new Action<GradleExternalDocumentationLinkImpl>() {
@Override
- void execute(PackageOptions packageOptions) {
- packageOptions.prefix = "some String"
+ void execute(GradleExternalDocumentationLinkImpl link) {
+ link.url = uri("some URI").toURL()
+ link.packageListUrl = uri("some URI").toURL()
}
})
- externalDocumentationLink(new Action<DokkaConfiguration.ExternalDocumentationLink.Builder>() {
+ kotlinTasks(new Callable<List<Object>>() {
@Override
- void execute(DokkaConfiguration.ExternalDocumentationLink.Builder builder) {
- builder.url = uri("some URI").toURL()
+ List<Object> call() {
+ return defaultKotlinTasks()
}
})
}
diff --git a/runners/gradle-plugin/build.gradle b/runners/gradle-plugin/build.gradle
index 8e59a7be..ceb03bae 100644
--- a/runners/gradle-plugin/build.gradle
+++ b/runners/gradle-plugin/build.gradle
@@ -12,12 +12,17 @@ sourceCompatibility = 1.8
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
freeCompilerArgs += "-Xjsr305=strict"
- languageVersion = "1.2"
- apiVersion = "1.1"
+ languageVersion = language_version
+ apiVersion = language_version
jvmTarget = "1.8"
}
}
+repositories {
+ jcenter()
+ google()
+}
+
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
@@ -26,8 +31,13 @@ dependencies {
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) {
@@ -54,7 +64,6 @@ apply plugin: 'maven-publish'
publishing {
publications {
dokkaGradlePlugin(MavenPublication) { publication ->
-
artifactId = 'dokka-gradle-plugin'
artifact sourceJar {
@@ -77,7 +86,7 @@ pluginBundle {
website = 'https://www.kotlinlang.org/'
vcsUrl = 'https://github.com/kotlin/dokka.git'
description = 'Dokka, the Kotlin documentation tool'
- tags = ['dokka', 'kotlin', 'kdoc']
+ tags = ['dokka', 'kotlin', 'kdoc', 'android']
plugins {
dokkaGradlePlugin {
diff --git a/runners/gradle-plugin/src/main/kotlin/main.kt b/runners/gradle-plugin/src/main/kotlin/main.kt
deleted file mode 100644
index f4adc1c3..00000000
--- a/runners/gradle-plugin/src/main/kotlin/main.kt
+++ /dev/null
@@ -1,499 +0,0 @@
-package org.jetbrains.dokka.gradle
-
-import groovy.lang.Closure
-import org.gradle.api.Action
-import org.gradle.api.DefaultTask
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.api.Task
-import org.gradle.api.artifacts.Configuration
-import org.gradle.api.file.FileCollection
-import org.gradle.api.plugins.JavaBasePlugin
-import org.gradle.api.plugins.JavaPluginConvention
-import org.gradle.api.tasks.*
-import org.gradle.api.tasks.Optional
-import org.gradle.api.tasks.compile.AbstractCompile
-import org.jetbrains.dokka.*
-import org.jetbrains.dokka.ReflectDsl.isNotInstance
-import org.jetbrains.dokka.gradle.ClassloaderContainer.fatJarClassLoader
-import org.jetbrains.dokka.gradle.DokkaVersion.version
-import ru.yole.jkid.JsonExclude
-import ru.yole.jkid.serialization.serialize
-import java.io.File
-import java.io.InputStream
-import java.io.Serializable
-import java.net.URLClassLoader
-import java.util.*
-import java.util.concurrent.Callable
-import java.util.function.BiConsumer
-
-open class DokkaPlugin : Plugin<Project> {
-
- override fun apply(project: Project) {
- DokkaVersion.loadFrom(javaClass.getResourceAsStream("/META-INF/gradle-plugins/org.jetbrains.dokka.properties"))
- project.tasks.create("dokka", DokkaTask::class.java).apply {
- dokkaRuntime = project.configurations.create("dokkaRuntime")
- moduleName = project.name
- outputDirectory = File(project.buildDir, "dokka").absolutePath
- }
- }
-}
-
-object DokkaVersion {
- var version: String? = null
-
- fun loadFrom(stream: InputStream) {
- version = Properties().apply {
- load(stream)
- }.getProperty("dokka-version")
- }
-}
-
-
-object ClassloaderContainer {
- @JvmField
- var fatJarClassLoader: ClassLoader? = null
-}
-
-const val `deprecationMessage reportNotDocumented` = "Will be removed in 0.9.17, see dokka#243"
-
-open class DokkaTask : DefaultTask() {
-
- fun defaultKotlinTasks() = 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 } })
- }
-
- @Input
- var moduleName: String = ""
- @Input
- var outputFormat: String = "html"
- var outputDirectory: String = ""
- var dokkaRuntime: Configuration? = null
-
- @Deprecated("Going to be removed in 0.9.16, use classpath + sourceDirs instead if kotlinTasks is not suitable for you")
- @Input var processConfigurations: List<Any?> = emptyList()
-
- @InputFiles var classpath: Iterable<File> = arrayListOf()
-
- @Input
- var includes: List<Any?> = arrayListOf()
- @Input
- var linkMappings: ArrayList<LinkMapping> = arrayListOf()
- @Input
- var samples: List<Any?> = arrayListOf()
- @Input
- var jdkVersion: Int = 6
- @Input
- var sourceDirs: Iterable<File> = emptyList()
-
- @Input
- var sourceRoots: MutableList<SourceRoot> = arrayListOf()
-
- @Input
- var dokkaFatJar: Any = "org.jetbrains.dokka:dokka-fatjar:$version"
-
- @Input var includeNonPublic = false
- @Input var skipDeprecated = false
- @Input var skipEmptyPackages = true
-
- @Deprecated(`deprecationMessage reportNotDocumented`, replaceWith = ReplaceWith("reportUndocumented"))
- var reportNotDocumented
- get() = reportUndocumented
- set(value) {
- logger.warn("Dokka: reportNotDocumented is deprecated and " + `deprecationMessage reportNotDocumented`.decapitalize())
- reportUndocumented = value
- }
-
- @Input var reportUndocumented = true
- @Input var perPackageOptions: MutableList<PackageOptions> = arrayListOf()
- @Input var impliedPlatforms: MutableList<String> = arrayListOf()
-
- @Input var externalDocumentationLinks = mutableListOf<DokkaConfiguration.ExternalDocumentationLink>()
-
- @Input var noStdlibLink: Boolean = false
-
- @Input
- var noJdkLink: Boolean = false
-
- @Optional @Input
- var cacheRoot: String? = null
-
-
- @Optional @Input
- var languageVersion: String? = null
-
- @Optional @Input
- var apiVersion: String? = null
-
- @Input
- var collectInheritedExtensionsFromLibraries: Boolean = false
-
- @get:Internal
- internal val kotlinCompileBasedClasspathAndSourceRoots: ClasspathAndSourceRoots by lazy { extractClasspathAndSourceRootsFromKotlinTasks() }
-
-
- private var kotlinTasksConfigurator: () -> List<Any?>? = { defaultKotlinTasks() }
- private val kotlinTasks: List<Task> by lazy { extractKotlinCompileTasks() }
-
- fun kotlinTasks(taskSupplier: Callable<List<Any>>) {
- kotlinTasksConfigurator = { taskSupplier.call() }
- }
-
- fun kotlinTasks(closure: Closure<Any?>) {
- kotlinTasksConfigurator = { closure.call() as? List<Any?> }
- }
-
- fun linkMapping(action: Action<LinkMapping>) {
- val mapping = LinkMapping()
- action.execute(mapping)
-
- if (mapping.path.isEmpty()) {
- throw IllegalArgumentException("Link mapping should have dir")
- }
- if (mapping.url.isEmpty()) {
- throw IllegalArgumentException("Link mapping should have url")
- }
-
- linkMappings.add(mapping)
- }
-
- fun linkMapping(closure: Closure<Unit>) {
- linkMapping(Action { mapping ->
- closure.delegate = mapping
- closure.call()
- })
- }
-
- fun sourceRoot(action: Action<SourceRoot>) {
- val sourceRoot = SourceRoot()
- action.execute(sourceRoot)
- sourceRoots.add(sourceRoot)
- }
-
- fun sourceRoot(closure: Closure<Unit>) {
- sourceRoot(Action { sourceRoot ->
- closure.delegate = sourceRoot
- closure.call()
- })
- }
-
- fun packageOptions(action: Action<PackageOptions>) {
- val packageOptions = PackageOptions()
- action.execute(packageOptions)
- perPackageOptions.add(packageOptions)
- }
-
- fun packageOptions(closure: Closure<Unit>) {
- packageOptions(Action { packageOptions ->
- closure.delegate = packageOptions
- closure.call()
- })
- }
-
- fun externalDocumentationLink(action: Action<DokkaConfiguration.ExternalDocumentationLink.Builder>) {
- val builder = DokkaConfiguration.ExternalDocumentationLink.Builder()
- action.execute(builder)
- externalDocumentationLinks.add(builder.build())
- }
-
- fun externalDocumentationLink(closure: Closure<Unit>) {
- externalDocumentationLink(Action { builder ->
- closure.delegate = builder
- closure.call()
- })
- }
-
- fun tryResolveFatJar(project: Project): Set<File> {
- return try {
- dokkaRuntime!!.resolve()
- } catch (e: Exception) {
- project.parent?.let { tryResolveFatJar(it) } ?: throw e
- }
- }
-
- fun loadFatJar() {
- if (fatJarClassLoader == null) {
- val jars = if (dokkaFatJar is File)
- setOf(dokkaFatJar as File)
- else
- tryResolveFatJar(project)
- fatJarClassLoader = URLClassLoader(jars.map { it.toURI().toURL() }.toTypedArray(), ClassLoader.getSystemClassLoader().parent)
- }
- }
-
- internal data class ClasspathAndSourceRoots(val classpathFileCollection: FileCollection, val sourceRoots: List<File>) : Serializable
-
- private fun extractKotlinCompileTasks(): List<Task> {
- val inputList = (kotlinTasksConfigurator.invoke() ?: emptyList()).filterNotNull()
- val (paths, other) = inputList.partition { it is String }
-
- val taskContainer = project.tasks
-
- val tasksByPath = paths.map { taskContainer.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 == null || it isNotInstance getAbstractKotlinCompileFor(it) }
- .forEach { throw IllegalArgumentException("Illegal task path in kotlinTasks, must be subtype of $ABSTRACT_KOTLIN_COMPILE, but was $it") }
-
-
- return (tasksByPath + other) as List<Task>
- }
-
- private fun extractClasspathAndSourceRootsFromKotlinTasks(): ClasspathAndSourceRoots {
-
- val allTasks = kotlinTasks
-
- val allClasspath = mutableSetOf<File>()
- var allClasspathFileCollection: FileCollection = project.files()
- val allSourceRoots = mutableSetOf<File>()
-
- allTasks.forEach {
-
- logger.debug("Dokka found AbstractKotlinCompile task: $it")
- with(ReflectDsl) {
- val taskSourceRoots: List<File> = it["sourceRootsContainer"]["sourceRoots"].v()
-
- val abstractKotlinCompileClz = getAbstractKotlinCompileFor(it)!!
-
- 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() }
- }
- }
-
- return ClasspathAndSourceRoots(allClasspathFileCollection + project.files(allClasspath), allSourceRoots.toList())
- }
-
- private fun Iterable<File>.toSourceRoots(): List<SourceRoot> = this.filter { it.exists() }.map { SourceRoot().apply { path = it.path } }
-
- protected open fun collectSuppressedFiles(sourceRoots: List<SourceRoot>): List<String> = emptyList()
-
- @TaskAction
- fun generate() {
- if (dokkaRuntime == null){
- dokkaRuntime = project.configurations.getByName("dokkaRuntime")
- }
-
- dokkaRuntime?.defaultDependencies{ dependencies -> dependencies.add(project.dependencies.create(dokkaFatJar)) }
- val kotlinColorsEnabledBefore = System.getProperty(COLORS_ENABLED_PROPERTY) ?: "false"
- System.setProperty(COLORS_ENABLED_PROPERTY, "false")
- try {
- loadFatJar()
-
- val (tasksClasspath, tasksSourceRoots) = kotlinCompileBasedClasspathAndSourceRoots
-
- val project = project
- val sourceRoots = collectSourceRoots() + tasksSourceRoots.toSourceRoots()
-
- if (sourceRoots.isEmpty()) {
- logger.warn("No source directories found: skipping dokka generation")
- return
- }
-
- val fullClasspath = collectClasspathFromOldSources() + tasksClasspath + classpath
-
- val bootstrapClass = fatJarClassLoader!!.loadClass("org.jetbrains.dokka.DokkaBootstrapImpl")
-
- val bootstrapInstance = bootstrapClass.constructors.first().newInstance()
-
- val bootstrapProxy: DokkaBootstrap = automagicTypedProxy(javaClass.classLoader, bootstrapInstance)
-
- val configuration = SerializeOnlyDokkaConfiguration(
- moduleName,
- fullClasspath.map { it.absolutePath },
- sourceRoots,
- samples.filterNotNull().map { project.file(it).absolutePath },
- includes.filterNotNull().map { project.file(it).absolutePath },
- outputDirectory,
- outputFormat,
- includeNonPublic,
- false,
- reportUndocumented,
- skipEmptyPackages,
- skipDeprecated,
- jdkVersion,
- true,
- linkMappings,
- impliedPlatforms,
- perPackageOptions,
- externalDocumentationLinks,
- noStdlibLink,
- noJdkLink,
- cacheRoot,
- collectSuppressedFiles(sourceRoots),
- languageVersion,
- apiVersion,
- collectInheritedExtensionsFromLibraries
- )
-
-
- bootstrapProxy.configure(
- BiConsumer { level, message ->
- when (level) {
- "info" -> logger.info(message)
- "warn" -> logger.warn(message)
- "error" -> logger.error(message)
- }
- },
- serialize(configuration)
- )
-
- bootstrapProxy.generate()
-
- } finally {
- System.setProperty(COLORS_ENABLED_PROPERTY, kotlinColorsEnabledBefore)
- }
- }
-
- private fun collectClasspathFromOldSources(): List<File> {
-
- val allConfigurations = project.configurations
-
- val fromConfigurations =
- processConfigurations.flatMap { allConfigurations.getByName(it.toString()) }
-
- return fromConfigurations
- }
-
- private fun collectSourceRoots(): List<SourceRoot> {
- val sourceDirs = if (sourceDirs.any()) {
- logger.info("Dokka: Taking source directories provided by the user")
- sourceDirs.toSet()
- } else if (kotlinTasks.isEmpty()) {
- project.convention.findPlugin(JavaPluginConvention::class.java)?.let { javaPluginConvention ->
- logger.info("Dokka: Taking source directories from default java plugin")
- val sourceSets = javaPluginConvention.sourceSets.findByName(SourceSet.MAIN_SOURCE_SET_NAME)
- sourceSets?.allSource?.srcDirs
- }
- } else {
- emptySet()
- }
-
- return sourceRoots + (sourceDirs?.toSourceRoots() ?: emptyList())
- }
-
-
- @Classpath
- fun getInputClasspath(): FileCollection {
- val (classpathFileCollection) = extractClasspathAndSourceRootsFromKotlinTasks()
- return project.files(collectClasspathFromOldSources() + classpath) + classpathFileCollection
- }
-
- @InputFiles
- fun getInputFiles(): FileCollection {
- val (_, tasksSourceRoots) = extractClasspathAndSourceRootsFromKotlinTasks()
- return project.files(tasksSourceRoots.map { project.fileTree(it) }) +
- project.files(collectSourceRoots().map { project.fileTree(File(it.path)) }) +
- project.files(includes) +
- project.files(samples.filterNotNull().map { project.fileTree(it) })
- }
-
- @OutputDirectory
- fun getOutputDirectoryAsFile(): File = project.file(outputDirectory)
-
- companion object {
- const val COLORS_ENABLED_PROPERTY = "kotlin.colors.enabled"
- const val ABSTRACT_KOTLIN_COMPILE = "org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile"
-
- private fun getAbstractKotlinCompileFor(task: Task) = try {
- task.project.buildscript.classLoader.loadClass(ABSTRACT_KOTLIN_COMPILE)
- } catch (e: ClassNotFoundException) {
- null
- }
- }
-}
-
-class SourceRoot : DokkaConfiguration.SourceRoot, Serializable {
- override var path: String = ""
- set(value) {
- field = File(value).absolutePath
- }
-
- override var platforms: List<String> = arrayListOf()
-
- override fun toString(): String {
- return "${platforms.joinToString()}::$path"
- }
-}
-
-open class LinkMapping : Serializable, DokkaConfiguration.SourceLinkDefinition {
- @JsonExclude
- var dir: String
- get() = path
- set(value) {
- if (value.contains("\\"))
- throw java.lang.IllegalArgumentException("Incorrect dir property, only Unix based path allowed.")
- else path = value
- }
-
- override var path: String = ""
- override var url: String = ""
-
- @JsonExclude
- var suffix: String?
- get() = lineSuffix
- set(value) {
- lineSuffix = value
- }
-
- override var lineSuffix: String? = null
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other?.javaClass != javaClass) return false
-
- other as LinkMapping
-
- if (path != other.path) return false
- if (url != other.url) return false
- if (lineSuffix != other.lineSuffix) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = path.hashCode()
- result = 31 * result + url.hashCode()
- result = 31 * result + (lineSuffix?.hashCode() ?: 0)
- return result
- }
-
- companion object {
- const val serialVersionUID: Long = -8133501684312445981L
- }
-}
-
-class PackageOptions : Serializable, DokkaConfiguration.PackageOptions {
- override var prefix: String = ""
- override var includeNonPublic: Boolean = false
- override var reportUndocumented: Boolean = true
- override var skipDeprecated: Boolean = false
- override var suppress: Boolean = false
-}
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
new file mode 100644
index 00000000..c66998d9
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt
@@ -0,0 +1,217 @@
+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
+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.KotlinCommonOptions
+import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
+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.tasks.KotlinCompile
+import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
+import java.io.File
+import java.io.Serializable
+
+class ConfigurationExtractor(private val project: Project) {
+
+ fun extractFromSinglePlatform(variantName: String? = null): 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
+ }
+ }
+
+ return try {
+ PlatformData(null, getClasspath(target, variantName), getSourceSet(target, variantName), getPlatformName(target.platformType))
+ } catch(e: NoSuchMethodError){
+ null
+ }
+ }
+
+ fun extractFromMultiPlatform(): List<PlatformData>? {
+ val targets: NamedDomainObjectCollection<KotlinTarget>
+ try {
+ targets = project.extensions.getByType(KotlinMultiplatformExtension::class.java).targets
+ } catch (e: Throwable) {
+ when (e){
+ is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException ->
+ return null
+ else -> throw e
+ }
+ }
+
+ val commonTargetPlatformData = targets.find { it.platformType == KotlinPlatformType.common }?.let {
+ PlatformData("common", getClasspath(it), getSourceSet(it), "common")
+ }
+ val config = targets.filter { it.platformType != KotlinPlatformType.common }.map {
+ PlatformData(it.name, getClasspath(it), getSourceSet(it), it.platformType.toString())
+ }
+
+ return (config + commonTargetPlatformData).filterNotNull()
+ }
+
+ 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(), "") }
+
+ fun extractFromKotlinTasks(kotlinTasks: List<Task>): PlatformData? =
+ try {
+ kotlinTasks.map { extractFromKotlinTask(it) }.let { platformDataList ->
+ PlatformData(null, platformDataList.flatMap { it.classpath }, platformDataList.flatMap { it.sourceRoots }, "")
+ }
+ } catch (e: Throwable) {
+ when (e){
+ is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException ->
+ 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
+ .firstNotNullResult { target -> target.compilations.find { it.compileKotlinTask == task } }
+ else -> throw e
+ }
+ }.let { PlatformData(task.name, getClasspath(it), getSourceSet(it), it?.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(), "")
+ }
+
+ private fun getSourceSet(target: KotlinTarget, variantName: String? = null): List<File> =
+ if(variantName != null)
+ getSourceSet(getCompilation(target, variantName))
+ else
+ getSourceSet(getMainCompilation(target))
+
+ private fun getClasspath(target: KotlinTarget, variantName: String? = null): List<File> = if (target.isAndroidTarget()) {
+ if(variantName != null)
+ getClasspathFromAndroidTask(getCompilation(target, variantName))
+ else
+ getClasspathFromAndroidTask(getMainCompilation(target))
+ } 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>()
+ }
+
+ return baseVariants + testVariants
+ }
+
+ private fun getPlatformName(platform: KotlinPlatformType): String =
+ if (platform == KotlinPlatformType.androidJvm) KotlinPlatformType.jvm.toString() else platform.toString()
+
+ data class PlatformData(val name: String?,
+ val classpath: List<File>,
+ val sourceRoots: List<File>,
+ val platform: String) : Serializable
+} \ No newline at end of file
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
new file mode 100644
index 00000000..5153ae1c
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt
@@ -0,0 +1,353 @@
+package org.jetbrains.dokka.gradle
+
+import com.google.gson.GsonBuilder
+import org.gradle.api.*
+import org.gradle.api.artifacts.Configuration
+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.DokkaBootstrap
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink.Builder
+import org.jetbrains.dokka.DokkaConfiguration.SourceRoot
+import org.jetbrains.dokka.Platform
+import org.jetbrains.dokka.ReflectDsl
+import org.jetbrains.dokka.ReflectDsl.isNotInstance
+import org.jetbrains.dokka.gradle.ConfigurationExtractor.PlatformData
+import java.io.File
+import java.net.URLClassLoader
+import java.util.concurrent.Callable
+import java.util.function.BiConsumer
+
+open class DokkaTask : DefaultTask() {
+ private val ANDROID_REFERENCE_URL = Builder("https://developer.android.com/reference/").build()
+ private val GLOBAL_PLATFORM_NAME = "global" // Used for copying perPackageOptions to other platforms
+
+ @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 } })
+ }
+
+ @Input
+ var outputFormat: String = "html"
+
+ @Input
+ var outputDirectory: String = ""
+
+ var dokkaRuntime: Configuration? = null
+
+ @Input
+ var impliedPlatforms: MutableList<String> = arrayListOf()
+
+ @Optional
+ @Input
+ var cacheRoot: String? = null
+
+ var multiplatform: NamedDomainObjectContainer<GradlePassConfigurationImpl>
+ @Suppress("UNCHECKED_CAST")
+ @Nested get() = (DslObject(this).extensions.getByName(MULTIPLATFORM_EXTENSION_NAME) as NamedDomainObjectContainer<GradlePassConfigurationImpl>)
+ internal set(value) = DslObject(this).extensions.add(MULTIPLATFORM_EXTENSION_NAME, value)
+
+ var configuration: GradlePassConfigurationImpl
+ @Suppress("UNCHECKED_CAST")
+ @Nested get() = DslObject(this).extensions.getByType(GradlePassConfigurationImpl::class.java)
+ internal set(value) = DslObject(this).extensions.add(CONFIGURATION_EXTENSION_NAME, value)
+
+ // Configure Dokka with closure in Gradle Kotlin DSL
+ fun configuration(action: Action<in GradlePassConfigurationImpl>) = action.execute(configuration)
+
+ private var externalDocumentationLinks: MutableList<DokkaConfiguration.ExternalDocumentationLink> = mutableListOf()
+
+ private val kotlinTasks: List<Task> by lazy { extractKotlinCompileTasks(configuration.collectKotlinTasks ?: { defaultKotlinTasks() }) }
+
+ private val configExtractor = ConfigurationExtractor(project)
+
+ @Input
+ var subProjects: List<String> = emptyList()
+
+ @Input
+ var disableAutoconfiguration: Boolean = false
+
+ private var outputDiagnosticInfo: Boolean = false // Workaround for Gradle, which fires some methods (like collectConfigurations()) multiple times in its lifecycle
+
+ private fun tryResolveFatJar(configuration: Configuration?): Set<File> {
+ return try {
+ configuration!!.resolve()
+ } catch (e: Exception) {
+ project.parent?.let { tryResolveFatJar(configuration) } ?: throw e
+ }
+ }
+
+ private fun loadFatJar() {
+ if (ClassloaderContainer.fatJarClassLoader == null) {
+ val jars = tryResolveFatJar(dokkaRuntime).toList()
+ ClassloaderContainer.fatJarClassLoader = URLClassLoader(jars.map { it.toURI().toURL() }.toTypedArray(), ClassLoader.getSystemClassLoader().parent)
+ }
+ }
+
+ private fun extractKotlinCompileTasks(collectTasks: () -> List<Any?>?): List<Task> {
+ val inputList = (collectTasks.invoke() ?: emptyList()).filterNotNull()
+ val (paths, other) = inputList.partition { it is String }
+
+ val taskContainer = project.tasks
+
+ val tasksByPath = paths.map { taskContainer.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) }
+
+ private 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()
+ }
+
+ @TaskAction
+ fun generate() {
+ outputDiagnosticInfo = true
+ val kotlinColorsEnabledBefore = System.getProperty(COLORS_ENABLED_PROPERTY) ?: "false"
+ System.setProperty(COLORS_ENABLED_PROPERTY, "false")
+ try {
+ loadFatJar()
+
+ val bootstrapClass = ClassloaderContainer.fatJarClassLoader!!.loadClass("org.jetbrains.dokka.DokkaBootstrapImpl")
+ val bootstrapInstance = bootstrapClass.constructors.first().newInstance()
+ val bootstrapProxy: DokkaBootstrap =
+ automagicTypedProxy(javaClass.classLoader, bootstrapInstance)
+
+ val gson = GsonBuilder().setPrettyPrinting().create()
+
+ val globalConfig = multiplatform.toList().find { it.name.toLowerCase() == GLOBAL_PLATFORM_NAME }
+ val passConfigurationList = collectConfigurations()
+ .map { defaultPassConfiguration(globalConfig, it) }
+
+ val configuration = GradleDokkaConfigurationImpl()
+ configuration.outputDir = outputDirectory
+ configuration.format = outputFormat
+ configuration.generateIndexPages = true
+ configuration.cacheRoot = cacheRoot
+ configuration.impliedPlatforms = impliedPlatforms
+ configuration.passesConfigurations = passConfigurationList
+
+ bootstrapProxy.configure(
+ BiConsumer { level, message ->
+ when (level) {
+ "info" -> logger.info(message)
+ "warn" -> logger.warn(message)
+ "error" -> logger.error(message)
+ }
+ },
+ gson.toJson(configuration)
+ )
+
+ bootstrapProxy.generate()
+
+ } finally {
+ System.setProperty(COLORS_ENABLED_PROPERTY, kotlinColorsEnabledBefore)
+ }
+ }
+
+ private fun collectConfigurations(): List<GradlePassConfigurationImpl> =
+ if (this.isMultiplatformProject()) collectFromMultiPlatform() else collectFromSinglePlatform()
+
+ private fun collectFromMultiPlatform(): List<GradlePassConfigurationImpl> {
+ val userConfig = multiplatform
+ .filterNot { it.name.toLowerCase() == GLOBAL_PLATFORM_NAME }
+ .map {
+ if (it.collectKotlinTasks != null) {
+ configExtractor.extractFromKotlinTasks(extractKotlinCompileTasks(it.collectKotlinTasks!!))
+ ?.let { platformData -> mergeUserConfigurationAndPlatformData(it, platformData) } ?: it
+ } else {
+ it
+ }
+ }
+
+ if (disableAutoconfiguration) return userConfig
+
+ val baseConfig = mergeUserAndAutoConfigurations(
+ userConfig,
+ configExtractor.extractFromMultiPlatform().orEmpty()
+ )
+
+ return if (subProjects.isNotEmpty())
+ subProjects.toProjects().fold(baseConfig) { list, subProject ->
+ mergeUserAndAutoConfigurations(list, ConfigurationExtractor(subProject).extractFromMultiPlatform().orEmpty())
+ }
+ else
+ baseConfig
+ }
+
+ private fun collectFromSinglePlatform(): List<GradlePassConfigurationImpl> {
+ val userConfig = configuration.let {
+ if (it.collectKotlinTasks != null) {
+ configExtractor.extractFromKotlinTasks(extractKotlinCompileTasks(it.collectKotlinTasks!!))
+ ?.let { platformData -> mergeUserConfigurationAndPlatformData(it, platformData) } ?: it
+ } else {
+ it
+ }
+ }
+
+ if (disableAutoconfiguration) return listOf(userConfig)
+
+ val extractedConfig = configExtractor.extractFromSinglePlatform(userConfig.androidVariant)
+ val baseConfig = if (extractedConfig != null)
+ listOf(mergeUserConfigurationAndPlatformData(userConfig, extractedConfig))
+ else
+ collectFromSinglePlatformOldPlugin()
+
+ return if (subProjects.isNotEmpty()) {
+ try {
+ subProjects.toProjects().fold(baseConfig) { list, subProject ->
+ listOf(mergeUserConfigurationAndPlatformData(
+ list.first(),
+ ConfigurationExtractor(subProject).extractFromSinglePlatform()!!
+ ))
+ }
+ } catch(e: NullPointerException) {
+ logger.warn("Cannot extract sources from subProjects. Do you have the Kotlin plugin in version 1.3.30+ " +
+ "and the Kotlin plugin applied in the root project?")
+ baseConfig
+ }
+ } else {
+ baseConfig
+ }
+ }
+
+ private fun collectFromSinglePlatformOldPlugin(): List<GradlePassConfigurationImpl> {
+ val kotlinTasks = configExtractor.extractFromKotlinTasks(kotlinTasks)
+ return if (kotlinTasks != null) {
+ listOf(mergeUserConfigurationAndPlatformData(configuration, kotlinTasks))
+ } else {
+ val javaPlugin = configExtractor.extractFromJavaPlugin()
+ if (javaPlugin != null)
+ listOf(mergeUserConfigurationAndPlatformData(configuration, javaPlugin)) else listOf(configuration)
+ }
+ }
+
+ private fun mergeUserAndAutoConfigurations(userConfigurations: List<GradlePassConfigurationImpl>,
+ autoConfigurations: List<PlatformData>): List<GradlePassConfigurationImpl> {
+ val merged: MutableList<GradlePassConfigurationImpl> = mutableListOf()
+ merged.addAll(
+ userConfigurations.map { userConfig ->
+ val autoConfig = autoConfigurations.find { autoConfig -> autoConfig.name == userConfig.name }
+ if (autoConfig != null) {
+ mergeUserConfigurationAndPlatformData(userConfig, autoConfig)
+ } else {
+ if(outputDiagnosticInfo) {
+ logger.warn(
+ "Could not find platform with name: ${userConfig.name} in Kotlin Gradle Plugin, " +
+ "using only user provided configuration for this platform"
+ )
+ }
+ userConfig
+ }
+ }
+ )
+ return merged.toList()
+ }
+
+ private fun mergeUserConfigurationAndPlatformData(userConfig: GradlePassConfigurationImpl,
+ autoConfig: PlatformData): GradlePassConfigurationImpl =
+ userConfig.copy().apply {
+ sourceRoots.addAll(userConfig.sourceRoots.union(autoConfig.sourceRoots.toSourceRoots()).distinct())
+ classpath = userConfig.classpath.union(autoConfig.classpath.map { it.absolutePath }).distinct()
+ if (userConfig.platform == null && autoConfig.platform != "")
+ platform = autoConfig.platform
+ }
+
+ private fun defaultPassConfiguration(globalConfig: GradlePassConfigurationImpl?, config: GradlePassConfigurationImpl): GradlePassConfigurationImpl {
+ if (config.moduleName == "") {
+ config.moduleName = project.name
+ }
+ if (config.targets.isEmpty() && multiplatform.isNotEmpty()){
+ config.targets = listOf(config.name)
+ }
+ config.classpath = (config.classpath as List<Any>).map { it.toString() }.distinct() // Workaround for Groovy's GStringImpl
+ 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)
+ if (project.isAndroidProject() && !config.noAndroidSdkLink) { // TODO: introduce Android as a separate Dokka platform?
+ config.externalDocumentationLinks.add(ANDROID_REFERENCE_URL)
+ }
+ config.externalDocumentationLinks.addAll(externalDocumentationLinks)
+ if (config.platform != null && config.platform.toString().isNotEmpty()) {
+ config.analysisPlatform = dokkaPlatformFromString(config.platform.toString())
+ }
+ if (globalConfig != null) {
+ config.perPackageOptions.addAll(globalConfig.perPackageOptions)
+ config.externalDocumentationLinks.addAll(globalConfig.externalDocumentationLinks)
+ config.sourceLinks.addAll(globalConfig.sourceLinks)
+ config.samples += globalConfig.samples.map { project.file(it).absolutePath }
+ config.includes += globalConfig.includes.map { project.file(it).absolutePath }
+ }
+ return config
+ }
+
+ private fun dokkaPlatformFromString(platform: String) = when (platform.toLowerCase()) {
+ "androidjvm", "android" -> Platform.jvm
+ 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 {
+ val config = collectConfigurations()
+ return 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((collectConfigurations().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
+ }
+ }
+}
diff --git a/runners/gradle-plugin/src/main/kotlin/ProxyUtils.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ProxyUtils.kt
index 7bdf2f9d..f8965993 100644
--- a/runners/gradle-plugin/src/main/kotlin/ProxyUtils.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ProxyUtils.kt
@@ -1,4 +1,4 @@
-package org.jetbrains.dokka
+package org.jetbrains.dokka.gradle
import java.lang.reflect.InvocationHandler
import java.lang.reflect.InvocationTargetException
@@ -26,9 +26,9 @@ inline fun <reified T : Any> automagicTypedProxy(targetClassLoader: ClassLoader,
*/
fun automagicProxy(targetClassLoader: ClassLoader, targetType: Class<*>, delegate: Any): Any =
Proxy.newProxyInstance(
- targetClassLoader,
- arrayOf(targetType),
- DelegatedInvocationHandler(delegate)
+ targetClassLoader,
+ arrayOf(targetType),
+ DelegatedInvocationHandler(delegate)
)
class DelegatedInvocationHandler(private val delegate: Any) : InvocationHandler {
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
new file mode 100644
index 00000000..767bf4f4
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/configurationImplementations.kt
@@ -0,0 +1,150 @@
+package org.jetbrains.dokka.gradle
+
+import groovy.lang.Closure
+import org.gradle.api.Action
+import org.gradle.api.tasks.Input
+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.Platform
+import java.io.File
+import java.io.Serializable
+import java.net.URL
+import java.util.concurrent.Callable
+import kotlin.reflect.KMutableProperty
+import kotlin.reflect.full.memberProperties
+
+class GradleSourceRootImpl: SourceRoot, Serializable {
+ override var path: String = ""
+ set(value) {
+ field = File(value).absolutePath
+ }
+
+ override fun toString(): String = path
+}
+
+open class GradlePassConfigurationImpl(@Transient val name: String = ""): PassConfiguration {
+ @Input @Optional override var classpath: List<String> = emptyList()
+ @Input override var moduleName: String = ""
+ @Input override var sourceRoots: MutableList<SourceRoot> = mutableListOf()
+ @Input override var samples: List<String> = emptyList()
+ @Input override var includes: List<String> = emptyList()
+ @Input override var includeNonPublic: Boolean = false
+ @Input override var includeRootPackage: Boolean = false
+ @Input override var reportUndocumented: Boolean = false
+ @Input override var skipEmptyPackages: Boolean = false
+ @Input override var skipDeprecated: Boolean = false
+ @Input override var jdkVersion: Int = 6
+ @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 = false
+ @Input override var noJdkLink: Boolean = false
+ @Input var noAndroidSdkLink: Boolean = false
+ @Input override var suppressedFiles: List<String> = emptyList()
+ @Input override var collectInheritedExtensionsFromLibraries: Boolean = false
+ @Input override var analysisPlatform: Platform = Platform.DEFAULT
+ @Input @Optional var platform: String? = null
+ @Input override var targets: List<String> = emptyList()
+ @Input @Optional override var sinceKotlin: String? = null
+ @Transient var collectKotlinTasks: (() -> List<Any?>?)? = null
+ @Input @Optional @Transient var androidVariant: String? = null
+
+ 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(link)
+ }
+
+ fun externalDocumentationLink(action: Action<in GradleExternalDocumentationLinkImpl>) {
+ val link = GradleExternalDocumentationLinkImpl()
+ action.execute(link)
+ externalDocumentationLinks.add(link)
+ }
+}
+
+class GradleSourceLinkDefinitionImpl : SourceLinkDefinition, Serializable {
+ override var path: String = ""
+ override var url: String = ""
+ override var lineSuffix: String? = null
+}
+
+class GradleExternalDocumentationLinkImpl : ExternalDocumentationLink, Serializable {
+ override var url: URL = URL("http://")
+ override var packageListUrl: URL = URL("http://")
+}
+
+class GradleDokkaConfigurationImpl: DokkaConfiguration {
+ override var outputDir: String = ""
+ override var format: String = "html"
+ override var generateIndexPages: Boolean = false
+ override var cacheRoot: String? = null
+ override var impliedPlatforms: List<String> = emptyList()
+ override var passesConfigurations: List<GradlePassConfigurationImpl> = emptyList()
+}
+
+class GradlePackageOptionsImpl: PackageOptions, Serializable {
+ override var prefix: String = ""
+ override var includeNonPublic: Boolean = false
+ override var reportUndocumented: Boolean = true
+ override var skipDeprecated: Boolean = true
+ override var suppress: Boolean = false
+}
+
+fun GradlePassConfigurationImpl.copy(): GradlePassConfigurationImpl {
+ val newObj = GradlePassConfigurationImpl(this.name)
+ this::class.memberProperties.forEach { field ->
+ if (field is KMutableProperty<*>) {
+ val value = field.getter.call(this)
+ if (value is Collection<*>) {
+ field.setter.call(newObj, value.toMutableList())
+ } else {
+ field.setter.call(newObj, field.getter.call(this))
+ }
+ }
+ }
+ return newObj
+} \ No newline at end of file
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
new file mode 100644
index 00000000..6f8d55e4
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt
@@ -0,0 +1,58 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.artifacts.Configuration
+import org.gradle.util.GradleVersion
+import java.io.File
+import java.io.InputStream
+import java.util.*
+
+internal const val CONFIGURATION_EXTENSION_NAME = "configuration"
+internal const val MULTIPLATFORM_EXTENSION_NAME = "multiplatform"
+
+open class DokkaPlugin : Plugin<Project> {
+ private val taskName = "dokka"
+
+ override fun apply(project: Project) {
+ loadDokkaVersion()
+ val dokkaRuntimeConfiguration = addConfiguration(project)
+ addTasks(project, dokkaRuntimeConfiguration, DokkaTask::class.java)
+ }
+
+ private fun loadDokkaVersion() = DokkaVersion.loadFrom(javaClass.getResourceAsStream("/META-INF/gradle-plugins/org.jetbrains.dokka.properties"))
+
+ private fun addConfiguration(project: Project) =
+ project.configurations.create("dokkaRuntime").apply {
+ defaultDependencies{ dependencies -> dependencies.add(project.dependencies.create("org.jetbrains.dokka:dokka-fatjar:${DokkaVersion.version}")) }
+ }
+
+ private fun addTasks(project: Project, runtimeConfiguration: Configuration, taskClass: Class<out DokkaTask>) {
+ if(GradleVersion.current() >= GradleVersion.version("4.10")) {
+ project.tasks.register(taskName, taskClass)
+ } else {
+ project.tasks.create(taskName, taskClass)
+ }
+ project.tasks.withType(taskClass) { task ->
+ task.multiplatform = project.container(GradlePassConfigurationImpl::class.java)
+ task.configuration = GradlePassConfigurationImpl()
+ task.dokkaRuntime = runtimeConfiguration
+ task.outputDirectory = File(project.buildDir, taskName).absolutePath
+ }
+ }
+}
+
+object DokkaVersion {
+ var version: String? = null
+
+ fun loadFrom(stream: InputStream) {
+ version = Properties().apply {
+ load(stream)
+ }.getProperty("dokka-version")
+ }
+}
+
+object ClassloaderContainer {
+ @JvmField
+ var fatJarClassLoader: ClassLoader? = null
+} \ No newline at end of file
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
new file mode 100644
index 00000000..d70b0499
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt
@@ -0,0 +1,19 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.Project
+import org.gradle.api.UnknownDomainObjectException
+import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
+import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
+
+
+fun Project.isAndroidProject() = try {
+ project.extensions.getByName("android")
+ true
+} catch(e: UnknownDomainObjectException) {
+ false
+} catch(e: ClassNotFoundException) {
+ false
+}
+
+fun KotlinTarget.isAndroidTarget() = this.platformType == KotlinPlatformType.androidJvm
+fun DokkaTask.isMultiplatformProject() = this.multiplatform.isNotEmpty() \ No newline at end of file
diff --git a/runners/maven-plugin/build.gradle b/runners/maven-plugin/build.gradle
index 2e9d0b1b..76fab68d 100644
--- a/runners/maven-plugin/build.gradle
+++ b/runners/maven-plugin/build.gradle
@@ -52,8 +52,8 @@ task setupMaven(type: Sync) {
def mavenBuildDir = "$buildDir/maven"
-sourceSets.main.resources {
- srcDirs += "$mavenBuildDir/classes/java/main"
+sourceSets.main.resources {
+ srcDirs += "$mavenBuildDir/classes/java/main"
exclude "**/*.class"
}
diff --git a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt
index 324703a0..fb11ecac 100644
--- a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt
+++ b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt
@@ -15,14 +15,14 @@ import java.io.File
import java.net.URL
class SourceLinkMapItem {
- @Parameter(name = "dir", required = true)
- var dir: String = ""
+ @Parameter(name = "path", required = true)
+ var path: String = ""
@Parameter(name = "url", required = true)
var url: String = ""
- @Parameter(name = "urlSuffix")
- var urlSuffix: String? = null
+ @Parameter(name = "lineSuffix")
+ var lineSuffix: String? = null
}
class ExternalDocumentationLinkBuilder : DokkaConfiguration.ExternalDocumentationLink.Builder() {
@@ -37,9 +37,6 @@ abstract class AbstractDokkaMojo : AbstractMojo() {
class SourceRoot : DokkaConfiguration.SourceRoot {
@Parameter(required = true)
override var path: String = ""
-
- @Parameter
- override var platforms: List<String> = emptyList()
}
class PackageOptions : DokkaConfiguration.PackageOptions {
@@ -62,11 +59,7 @@ abstract class AbstractDokkaMojo : AbstractMojo() {
var sourceRoots: List<SourceRoot> = emptyList()
@Parameter
- var samplesDirs: List<String> = emptyList()
-
- @Parameter
- @Deprecated("Use <includes> instead")
- var includeDirs: List<String> = emptyList()
+ var samples: List<String> = emptyList()
@Parameter
var includes: List<String> = emptyList()
@@ -75,7 +68,7 @@ abstract class AbstractDokkaMojo : AbstractMojo() {
var classpath: List<String> = emptyList()
@Parameter
- var sourceLinks: Array<SourceLinkMapItem> = emptyArray()
+ var sourceLinks: List<SourceLinkMapItem> = emptyList()
@Parameter(required = true, defaultValue = "\${project.artifactId}")
var moduleName: String = ""
@@ -87,11 +80,11 @@ abstract class AbstractDokkaMojo : AbstractMojo() {
var jdkVersion: Int = 6
@Parameter
- var skipDeprecated = false
+ var skipDeprecated: Boolean = false
@Parameter
- var skipEmptyPackages = true
+ var skipEmptyPackages: Boolean = true
@Parameter
- var reportNotDocumented = true
+ var reportUndocumented: Boolean = true
@Parameter
var impliedPlatforms: List<String> = emptyList()
@@ -117,7 +110,32 @@ abstract class AbstractDokkaMojo : AbstractMojo() {
@Parameter
var apiVersion: String? = null
+ @Parameter
+ var includeRootPackage: Boolean = false
+
+ @Parameter
+ var suppressedFiles: List<String> = emptyList()
+
+ @Parameter
+ var collectInheritedExtensionsFromLibraries: Boolean = false
+
+ @Parameter
+ var platform: String = ""
+
+ @Parameter
+ var targets: List<String> = emptyList()
+
+ @Parameter
+ var sinceKotlin: String? = null
+
+ @Parameter
+ var includeNonPublic: Boolean = false
+
+ @Parameter
+ var generateIndexPages: Boolean = false
+
protected abstract fun getOutDir(): String
+
protected abstract fun getOutFormat(): String
override fun execute() {
@@ -127,35 +145,55 @@ abstract class AbstractDokkaMojo : AbstractMojo() {
}
sourceLinks.forEach {
- if (it.dir.contains("\\")) {
- throw MojoExecutionException("Incorrect dir property, only Unix based path allowed.")
+ if (it.path.contains("\\")) {
+ throw MojoExecutionException("Incorrect path property, only Unix based path allowed.")
}
}
- val gen = DokkaGenerator(
- MavenDokkaLogger(log),
- classpath,
- sourceDirectories.map { SourceRootImpl(it) } + sourceRoots,
- samplesDirs,
- includeDirs + includes,
- moduleName,
- DocumentationOptions(getOutDir(), getOutFormat(),
- sourceLinks = sourceLinks.map { SourceLinkDefinitionImpl(it.dir, it.url, it.urlSuffix) },
- jdkVersion = jdkVersion,
- skipDeprecated = skipDeprecated,
- skipEmptyPackages = skipEmptyPackages,
- reportUndocumented = reportNotDocumented,
- impliedPlatforms = impliedPlatforms,
- perPackageOptions = perPackageOptions,
- externalDocumentationLinks = externalDocumentationLinks.map { it.build() },
- noStdlibLink = noStdlibLink,
- noJdkLink = noJdkLink,
- cacheRoot = cacheRoot,
- languageVersion = languageVersion,
- apiVersion = apiVersion
- )
+ val passConfiguration = PassConfigurationImpl(
+ classpath = classpath,
+ sourceRoots = sourceDirectories.map { SourceRootImpl(it) } + sourceRoots.map { SourceRootImpl(path = it.path) },
+ samples = samples,
+ includes = includes,
+ collectInheritedExtensionsFromLibraries = collectInheritedExtensionsFromLibraries, // TODO: Should we implement this?
+ sourceLinks = sourceLinks.map { SourceLinkDefinitionImpl(it.path, it.url, it.lineSuffix) },
+ jdkVersion = jdkVersion,
+ skipDeprecated = skipDeprecated,
+ skipEmptyPackages = skipEmptyPackages,
+ reportUndocumented = reportUndocumented,
+ perPackageOptions = perPackageOptions.map {
+ PackageOptionsImpl(
+ prefix = it.prefix,
+ includeNonPublic = it.includeNonPublic,
+ reportUndocumented = it.reportUndocumented,
+ skipDeprecated = it.skipDeprecated,
+ suppress = it.suppress
+ )},
+ externalDocumentationLinks = externalDocumentationLinks.map { it.build() as ExternalDocumentationLinkImpl },
+ noStdlibLink = noStdlibLink,
+ noJdkLink = noJdkLink,
+ languageVersion = languageVersion,
+ apiVersion = apiVersion,
+ moduleName = moduleName,
+ suppressedFiles = suppressedFiles,
+ sinceKotlin = sinceKotlin,
+ analysisPlatform = if (platform.isNotEmpty()) Platform.fromString(platform) else Platform.DEFAULT,
+ targets = targets,
+ includeNonPublic = includeNonPublic,
+ includeRootPackage = includeRootPackage
)
+ val configuration = DokkaConfigurationImpl(
+ outputDir = getOutDir(),
+ format = getOutFormat(),
+ impliedPlatforms = impliedPlatforms,
+ cacheRoot = cacheRoot,
+ passesConfigurations = listOf(passConfiguration),
+ generateIndexPages = generateIndexPages
+ )
+
+ val gen = DokkaGenerator(configuration, MavenDokkaLogger(log))
+
gen.generate()
}
}
@@ -246,11 +284,11 @@ class DokkaJavadocJarMojo : AbstractDokkaMojo() {
val javadocJar = File(jarOutputDirectory, jarFileName)
val archiver = MavenArchiver()
- archiver.setArchiver(jarArchiver)
+ archiver.archiver = jarArchiver
archiver.setOutputFile(javadocJar)
archiver.archiver.addDirectory(File(outputDir), arrayOf("**/**"), arrayOf())
- archive.setAddMavenDescriptor(false)
+ archive.isAddMavenDescriptor = false
archiver.createArchive(session, project, archive)
return javadocJar