diff options
author | sebastian.sellmair <sebastian.sellmair@jetbrains.com> | 2020-07-22 14:31:11 +0200 |
---|---|---|
committer | Sebastian Sellmair <34319766+sellmair@users.noreply.github.com> | 2020-08-14 17:51:11 +0200 |
commit | aa21ab173d60bb69e50e7fc321e8b94c2815b6e8 (patch) | |
tree | 049c293b502b32130f8ff8b0ab1a90620cea46c1 /runners/gradle-plugin/src/main/kotlin/org | |
parent | 9ab5b60c257507ba2159be8b4a8d73f4ac43d9e9 (diff) | |
download | dokka-aa21ab173d60bb69e50e7fc321e8b94c2815b6e8.tar.gz dokka-aa21ab173d60bb69e50e7fc321e8b94c2815b6e8.tar.bz2 dokka-aa21ab173d60bb69e50e7fc321e8b94c2815b6e8.zip |
Use Gradle's new Property/Provider APIs
Diffstat (limited to 'runners/gradle-plugin/src/main/kotlin/org')
17 files changed, 419 insertions, 277 deletions
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaProperty.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaProperty.kt new file mode 100644 index 00000000..c24e369c --- /dev/null +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaProperty.kt @@ -0,0 +1,21 @@ +package org.jetbrains.dokka.gradle + +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider +import org.gradle.kotlin.dsl.property +import org.jetbrains.dokka.utilities.cast +import kotlin.reflect.typeOf + +internal inline fun <reified T : Any> ObjectFactory.safeProperty() = property<T?>() + +internal inline fun <reified T : Any> Property<T?>.safeConvention(value: T): Property<T> { + @Suppress("UnstableApiUsage") + return this.convention(value).cast() +} + +@OptIn(ExperimentalStdlibApi::class) +internal inline fun <reified T> Provider<T>.getSafe(): T { + return if (typeOf<T>().isMarkedNullable) orNull as T + else get() +} diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt index 06b936ce..c5713d16 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt @@ -6,6 +6,7 @@ import org.gradle.api.tasks.Nested import org.jetbrains.dokka.DokkaBootstrapImpl import org.jetbrains.dokka.DokkaConfigurationImpl import org.jetbrains.dokka.build +import org.jetbrains.dokka.gradle.kotlin.isMainSourceSet open class DokkaTask : AbstractDokkaTask(DokkaBootstrapImpl::class) { @@ -14,9 +15,11 @@ open class DokkaTask : AbstractDokkaTask(DokkaBootstrapImpl::class) { project.container(GradleDokkaSourceSetBuilder::class.java, GradleDokkaSourceSetBuilderFactory()) .also { container -> DslObject(this).extensions.add("dokkaSourceSets", container) - project.findKotlinSourceSets().orEmpty().forEach { kotlinSourceSet -> - container.register(kotlinSourceSet.name) { dokkaSourceSet -> - dokkaSourceSet.configureWithKotlinSourceSetGist(kotlinSourceSet) + project.kotlinOrNull?.sourceSets?.all { kotlinSourceSet -> + if (project.isMainSourceSet(kotlinSourceSet)) { + container.register(kotlinSourceSet.name) { dokkaSourceSet -> + dokkaSourceSet.configureWithKotlinSourceSet(kotlinSourceSet) + } } } } diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt index 09c9bec9..8f0a166b 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt @@ -1,14 +1,20 @@ -@file:Suppress("FunctionName") +@file:Suppress("FunctionName", "UnstableApiUsage") package org.jetbrains.dokka.gradle import com.android.build.gradle.api.AndroidSourceSet -import com.fasterxml.jackson.annotation.JsonIgnore import groovy.lang.Closure import org.gradle.api.Action import org.gradle.api.Project import org.gradle.api.Task +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Property +import org.gradle.api.provider.SetProperty import org.gradle.api.tasks.* +import org.gradle.kotlin.dsl.listProperty +import org.gradle.kotlin.dsl.property +import org.gradle.kotlin.dsl.setProperty import org.gradle.util.ConfigureUtil import org.jetbrains.dokka.* import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet @@ -16,98 +22,110 @@ import java.io.File import java.net.URL import org.jetbrains.kotlin.gradle.model.SourceSet as KotlinModelSourceSet - internal fun Task.GradleDokkaSourceSetBuilderFactory(): (name: String) -> GradleDokkaSourceSetBuilder = { name -> GradleDokkaSourceSetBuilder(name, project) } + +// TODO NOW: Cover with tests open class GradleDokkaSourceSetBuilder constructor( - @get:JsonIgnore @Transient @get:Input val name: String, - @get:JsonIgnore @Transient @get:Internal internal val project: Project + @Transient @get:Input val name: String, + @Transient @get:Internal internal val project: Project ) : DokkaConfigurationBuilder<DokkaSourceSetImpl> { + @Internal + val sourceSetID: DokkaSourceSetID = DokkaSourceSetID(project, name) + @Classpath @Optional - val classpath: MutableSet<File> = mutableSetOf() + val classpath: ConfigurableFileCollection = project.files() @Input @Optional - var moduleDisplayName: String? = null + val moduleDisplayName: Property<String?> = project.objects.safeProperty() @Input @Optional - var displayName: String? = null - - @get:Internal - val sourceSetID: DokkaSourceSetID = DokkaSourceSetID(project, name) + val displayName: Property<String?> = project.objects.safeProperty() @Nested - val sourceRoots: MutableSet<File> = mutableSetOf() + val sourceRoots: ConfigurableFileCollection = project.files() @Input - val dependentSourceSets: MutableSet<DokkaSourceSetID> = mutableSetOf() + val dependentSourceSets: SetProperty<DokkaSourceSetID> = project.objects.setProperty<DokkaSourceSetID>() + .convention(emptySet()) @InputFiles @Optional - val samples: MutableSet<File> = mutableSetOf() + val samples: ConfigurableFileCollection = project.files() @InputFiles @Optional - val includes: MutableSet<File> = mutableSetOf() + val includes: ConfigurableFileCollection = project.files() @Input - var includeNonPublic: Boolean = DokkaDefaults.includeNonPublic + val includeNonPublic: Property<Boolean> = project.objects.safeProperty<Boolean>() + .safeConvention(DokkaDefaults.includeNonPublic) @Input - var includeRootPackage: Boolean = DokkaDefaults.includeRootPackage + val reportUndocumented: Property<Boolean> = project.objects.safeProperty<Boolean>() + .safeConvention(DokkaDefaults.reportUndocumented) @Input - var reportUndocumented: Boolean = DokkaDefaults.reportUndocumented + val skipEmptyPackages: Property<Boolean> = project.objects.safeProperty<Boolean>() + .safeConvention(DokkaDefaults.skipEmptyPackages) @Input - var skipEmptyPackages: Boolean = DokkaDefaults.skipEmptyPackages + val skipDeprecated: Property<Boolean> = project.objects.safeProperty<Boolean>() + .safeConvention(DokkaDefaults.skipDeprecated) @Input - var skipDeprecated: Boolean = DokkaDefaults.skipDeprecated - - @Input - var jdkVersion: Int = DokkaDefaults.jdkVersion + val jdkVersion: Property<Int> = project.objects.safeProperty<Int>() + .safeConvention(DokkaDefaults.jdkVersion) @Nested - val sourceLinks: MutableSet<GradleSourceLinkBuilder> = mutableSetOf() + val sourceLinks: SetProperty<GradleSourceLinkBuilder> = project.objects.setProperty<GradleSourceLinkBuilder>() + .convention(emptySet()) @Nested - val perPackageOptions: MutableList<GradlePackageOptionsBuilder> = mutableListOf() + val perPackageOptions: ListProperty<GradlePackageOptionsBuilder> = + project.objects.listProperty<GradlePackageOptionsBuilder>() + .convention(emptyList()) @Nested - val externalDocumentationLinks: MutableSet<GradleExternalDocumentationLinkBuilder> = mutableSetOf() + val externalDocumentationLinks: SetProperty<GradleExternalDocumentationLinkBuilder> = + project.objects.setProperty<GradleExternalDocumentationLinkBuilder>() + .convention(emptySet()) @Input @Optional - var languageVersion: String? = null + val languageVersion: Property<String?> = project.objects.safeProperty<String>() @Input @Optional - var apiVersion: String? = null + val apiVersion: Property<String?> = project.objects.safeProperty() @Input - var noStdlibLink: Boolean = DokkaDefaults.noStdlibLink + val noStdlibLink: Property<Boolean> = project.objects.property<Boolean>() + .convention(DokkaDefaults.noStdlibLink) @Input - var noJdkLink: Boolean = DokkaDefaults.noJdkLink + val noJdkLink: Property<Boolean> = project.objects.property<Boolean>() + .convention(DokkaDefaults.noJdkLink) @Input - var noAndroidSdkLink: Boolean = false + val noAndroidSdkLink: Property<Boolean> = project.objects.property<Boolean>() + .convention(false) - @Input - val suppressedFiles: MutableSet<File> = mutableSetOf() + @InputFiles + val suppressedFiles: ConfigurableFileCollection = project.files() @Input @Optional - var analysisPlatform: Platform? = null + val analysisPlatform: Property<Platform?> = project.objects.safeProperty() @Input @Optional - var platform: String? = null + val platform: Property<String?> = project.objects.safeProperty() fun DokkaSourceSetID(sourceSetName: String): DokkaSourceSetID { return DokkaSourceSetID(project, sourceSetName) @@ -133,139 +151,73 @@ open class GradleDokkaSourceSetBuilder constructor( dependentSourceSets.add(sourceSetID) } - // TODO NOW: Cover with tests + fun kotlinSourceSet(kotlinSourceSet: KotlinSourceSet) { + configureWithKotlinSourceSet(kotlinSourceSet) + } fun sourceRoot(file: File) { - sourceRoots.add(file) + sourceRoots.from(file) } fun sourceRoot(path: String) { - sourceRoots.add(project.file(path)) + sourceRoot(project.file(path)) } fun sourceLink(c: Closure<Unit>) { - val configured = ConfigureUtil.configure(c, GradleSourceLinkBuilder()) + val configured = ConfigureUtil.configure(c, GradleSourceLinkBuilder(project)) sourceLinks.add(configured) } fun sourceLink(action: Action<in GradleSourceLinkBuilder>) { - val sourceLink = GradleSourceLinkBuilder() + val sourceLink = GradleSourceLinkBuilder(project) action.execute(sourceLink) sourceLinks.add(sourceLink) } fun perPackageOption(c: Closure<Unit>) { - val configured = ConfigureUtil.configure(c, GradlePackageOptionsBuilder()) + val configured = ConfigureUtil.configure(c, GradlePackageOptionsBuilder(project)) perPackageOptions.add(configured) } fun perPackageOption(action: Action<in GradlePackageOptionsBuilder>) { - val option = GradlePackageOptionsBuilder() + val option = GradlePackageOptionsBuilder(project) action.execute(option) perPackageOptions.add(option) } fun externalDocumentationLink(c: Closure<Unit>) { - val link = ConfigureUtil.configure(c, GradleExternalDocumentationLinkBuilder()) + val link = ConfigureUtil.configure(c, GradleExternalDocumentationLinkBuilder(project)) externalDocumentationLinks.add(link) } fun externalDocumentationLink(action: Action<in GradleExternalDocumentationLinkBuilder>) { - val link = GradleExternalDocumentationLinkBuilder() + val link = GradleExternalDocumentationLinkBuilder(project) action.execute(link) externalDocumentationLinks.add(link) } fun externalDocumentationLink(url: String, packageListUrl: String? = null) { externalDocumentationLinks.add( - GradleExternalDocumentationLinkBuilder().apply { - this.url = URL(url) - this.packageListUrl = URL(packageListUrl) + GradleExternalDocumentationLinkBuilder(project).apply { + this.url by URL(url) + this.packageListUrl by URL(packageListUrl) } ) } fun externalDocumentationLink(url: URL, packageListUrl: URL? = null) { externalDocumentationLinks.add( - GradleExternalDocumentationLinkBuilder().apply { - this.url = url + GradleExternalDocumentationLinkBuilder(project).apply { + this.url by url if (packageListUrl != null) { - this.packageListUrl = packageListUrl + this.packageListUrl by packageListUrl } } ) } override fun build(): DokkaSourceSetImpl { - val moduleDisplayName = moduleDisplayName ?: project.name - - val displayName = displayName ?: name.substringBeforeLast("Main", platform.toString()) - - val externalDocumentationLinks = externalDocumentationLinks.map { it.build() } - .run { - if (noJdkLink) this - else this + ExternalDocumentationLink( - url = - if (jdkVersion < 11) "https://docs.oracle.com/javase/${jdkVersion}/docs/api/" - else "https://docs.oracle.com/en/java/javase/${jdkVersion}/docs/api/java.base/", - packageListUrl = - if (jdkVersion < 11) "https://docs.oracle.com/javase/${jdkVersion}/docs/api/package-list" - else "https://docs.oracle.com/en/java/javase/${jdkVersion}/docs/api/element-list" - ) - } - .run { - if (noStdlibLink) this - else this + ExternalDocumentationLink("https://kotlinlang.org/api/latest/jvm/stdlib/") - } - .run { - if (noAndroidSdkLink || !project.isAndroidProject()) this - else this + - ExternalDocumentationLink("https://developer.android.com/reference/") + - ExternalDocumentationLink( - url = URL("https://developer.android.com/reference/kotlin/"), - packageListUrl = URL("https://developer.android.com/reference/androidx/package-list") - ) - } - - val analysisPlatform = when { - analysisPlatform != null -> checkNotNull(analysisPlatform) - - platform?.isNotBlank() == true -> when (val platform = platform.toString().toLowerCase()) { - "androidjvm", "android" -> Platform.jvm - "metadata" -> Platform.common - else -> Platform.fromString(platform) - } - - else -> Platform.DEFAULT - } - - val suppressedFiles = suppressedFiles + project.collectSuppressedFiles(sourceRoots.toSet()) - - return DokkaSourceSetImpl( - classpath = classpath.toSet(), - moduleDisplayName = moduleDisplayName, - displayName = displayName, - sourceSetID = sourceSetID, - sourceRoots = sourceRoots.toSet(), - dependentSourceSets = dependentSourceSets.toSet(), - samples = samples.toSet(), - includes = includes.toSet(), - includeNonPublic = includeNonPublic, - includeRootPackage = includeRootPackage, - reportUndocumented = reportUndocumented, - skipEmptyPackages = skipEmptyPackages, - skipDeprecated = skipDeprecated, - jdkVersion = jdkVersion, - sourceLinks = sourceLinks.build().toSet(), - perPackageOptions = perPackageOptions.build(), - externalDocumentationLinks = externalDocumentationLinks.toSet(), - languageVersion = languageVersion, - apiVersion = apiVersion, - noStdlibLink = noStdlibLink, - noJdkLink = noJdkLink, - suppressedFiles = suppressedFiles.toSet(), - analysisPlatform = analysisPlatform - ) + return toDokkaSourceSetImpl() } } @@ -280,15 +232,3 @@ fun GradleDokkaSourceSetBuilder.dependsOn(sourceSet: KotlinSourceSet) { fun GradleDokkaSourceSetBuilder.dependsOn(sourceSet: AndroidSourceSet) { dependsOn(DokkaSourceSetID(sourceSet.name)) } - -// TODO NOW: Test -private fun Project.collectSuppressedFiles(sourceRoots: Set<File>): Set<File> = - if (project.isAndroidProject()) { - val generatedRoot = project.buildDir.resolve("generated").absoluteFile - sourceRoots - .filter { it.startsWith(generatedRoot) } - .flatMap { it.walk().toList() } - .toSet() - } else { - emptySet() - } diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleExternalDocumentationLinkBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleExternalDocumentationLinkBuilder.kt index 84ad6c1e..2960ba23 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleExternalDocumentationLinkBuilder.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleExternalDocumentationLinkBuilder.kt @@ -1,22 +1,28 @@ package org.jetbrains.dokka.gradle +import org.gradle.api.Project +import org.gradle.api.provider.Property import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Internal import org.jetbrains.dokka.DokkaConfigurationBuilder import org.jetbrains.dokka.ExternalDocumentationLink import org.jetbrains.dokka.ExternalDocumentationLinkImpl import java.net.URL -class GradleExternalDocumentationLinkBuilder : DokkaConfigurationBuilder<ExternalDocumentationLinkImpl> { +class GradleExternalDocumentationLinkBuilder( + @get:Internal internal val project: Project +) : + DokkaConfigurationBuilder<ExternalDocumentationLinkImpl> { @Input - var url: URL? = null + val url: Property<URL?> = project.objects.safeProperty() @Input - var packageListUrl: URL? = null + val packageListUrl: Property<URL?> = project.objects.safeProperty() override fun build(): ExternalDocumentationLinkImpl { return ExternalDocumentationLink( - url = checkNotNull(url) { "url not specified " }, - packageListUrl = packageListUrl + url = checkNotNull(url.getSafe()) { "url not specified " }, + packageListUrl = packageListUrl.getSafe() ) } } diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradlePackageOptionsBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradlePackageOptionsBuilder.kt index fdc0275e..854dc9a0 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradlePackageOptionsBuilder.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradlePackageOptionsBuilder.kt @@ -2,35 +2,45 @@ package org.jetbrains.dokka.gradle +import org.gradle.api.Project +import org.gradle.api.provider.Property import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Internal import org.jetbrains.dokka.DokkaConfigurationBuilder import org.jetbrains.dokka.DokkaDefaults import org.jetbrains.dokka.PackageOptionsImpl -class GradlePackageOptionsBuilder : DokkaConfigurationBuilder<PackageOptionsImpl> { +class GradlePackageOptionsBuilder( + @get:Internal internal val project: Project +) : DokkaConfigurationBuilder<PackageOptionsImpl> { @Input - var prefix: String = "" + val prefix: Property<String> = project.objects.safeProperty<String>() + .safeConvention("") @Input - var includeNonPublic: Boolean = DokkaDefaults.includeNonPublic + val includeNonPublic: Property<Boolean> = project.objects.safeProperty<Boolean>() + .safeConvention(DokkaDefaults.includeNonPublic) @Input - var reportUndocumented: Boolean = DokkaDefaults.reportUndocumented + val reportUndocumented: Property<Boolean> = project.objects.safeProperty<Boolean>() + .safeConvention(DokkaDefaults.reportUndocumented) @Input - var skipDeprecated: Boolean = DokkaDefaults.skipDeprecated + val skipDeprecated: Property<Boolean> = project.objects.safeProperty<Boolean>() + .safeConvention(DokkaDefaults.skipDeprecated) @Input - var suppress: Boolean = DokkaDefaults.suppress + val suppress: Property<Boolean> = project.objects.safeProperty<Boolean>() + .safeConvention(DokkaDefaults.suppress) override fun build(): PackageOptionsImpl { return PackageOptionsImpl( - prefix = prefix, - includeNonPublic = includeNonPublic, - reportUndocumented = reportUndocumented, - skipDeprecated = skipDeprecated, - suppress = suppress + prefix = checkNotNull(prefix.getSafe()) { "prefix not specified" }, + includeNonPublic = includeNonPublic.getSafe(), + reportUndocumented = reportUndocumented.getSafe(), + skipDeprecated = skipDeprecated.getSafe(), + suppress = suppress.getSafe() ) } } diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt index 007575ec..2cd85c26 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt @@ -1,25 +1,33 @@ package org.jetbrains.dokka.gradle +import org.gradle.api.Project +import org.gradle.api.provider.Property import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.Optional import org.jetbrains.dokka.DokkaConfigurationBuilder import org.jetbrains.dokka.SourceLinkDefinitionImpl -class GradleSourceLinkBuilder : DokkaConfigurationBuilder<SourceLinkDefinitionImpl> { - // TODO NOW: CHECK UP TO DATE +class GradleSourceLinkBuilder( + @get:Internal internal val project: Project +) : DokkaConfigurationBuilder<SourceLinkDefinitionImpl> { @Input - var path: String = "" + val path: Property<String> = project.objects.safeProperty<String>() + .safeConvention("") @Input - var url: String = "" + val url: Property<String> = project.objects.safeProperty<String>() + .safeConvention("") + @Optional @Input - var lineSuffix: String? = null + val lineSuffix: Property<String?> = project.objects.safeProperty() override fun build(): SourceLinkDefinitionImpl { return SourceLinkDefinitionImpl( - path = path, - url = url, - lineSuffix = lineSuffix + path = path.getSafe(), + url = url.getSafe(), + lineSuffix = lineSuffix.getSafe() ) } } diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/KotlinSourceSetGist.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/KotlinSourceSetGist.kt deleted file mode 100644 index 6e202ac3..00000000 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/KotlinSourceSetGist.kt +++ /dev/null @@ -1,106 +0,0 @@ -package org.jetbrains.dokka.gradle - -import org.gradle.api.Project -import org.jetbrains.dokka.utilities.cast -import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions -import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension -import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension -import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension -import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType -import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -import java.io.File - -// TODO NOW: Test this all -private typealias KotlinCompilation = - org.jetbrains.kotlin.gradle.plugin.KotlinCompilation<KotlinCommonOptions> - -internal data class KotlinSourceSetGist( - val name: String, - val platform: String, - val classpath: List<File>, - val sourceRoots: List<File>, - val dependentSourceSets: List<String>, -) - -/** - * @return null if the kotlin extension cannot be found, - * A list of [KotlinSourceSetGist] for every currently registered kotlin source set - */ -internal fun Project.findKotlinSourceSets(): List<KotlinSourceSetGist>? { - val kotlin = kotlinExtensionOrNull ?: return null - return kotlin.sourceSets.map { sourceSet -> kotlin.gistOf(sourceSet) } -} - -internal fun KotlinProjectExtension.gistOf(sourceSet: KotlinSourceSet): KotlinSourceSetGist { - return KotlinSourceSetGist( - name = sourceSet.name, - platform = platformOf(sourceSet), - classpath = classpathOf(sourceSet).filter(File::exists), - sourceRoots = sourceSet.kotlin.sourceDirectories.toList().filter(File::exists), - dependentSourceSets = sourceSet.dependsOn.map { dependentSourceSet -> dependentSourceSet.name }, - ) -} - -private fun KotlinProjectExtension.classpathOf(sourceSet: KotlinSourceSet): List<File> { - val compilations = compilationsOf(sourceSet) - if (compilations.isNotEmpty()) { - return compilations - .flatMap { compilation -> compileClasspathOf(compilation) } - .distinct() - } - - return sourceSet.withAllDependentSourceSets() - .toList() - .flatMap { it.kotlin.sourceDirectories } -} - -private fun KotlinProjectExtension.platformOf(sourceSet: KotlinSourceSet): String { - val targetNames = compilationsOf(sourceSet).map { compilation -> compilation.target.platformType.name }.distinct() - return when (targetNames.size) { - 0 -> KotlinPlatformType.common.name - 1 -> targetNames.single() - else -> throw IllegalArgumentException( - "Source set ${sourceSet.name} is expected to have only one target. Found $targetNames" - ) - } -} - -private fun KotlinProjectExtension.compilationsOf( - sourceSet: KotlinSourceSet -): List<KotlinCompilation> { - return when (this) { - is KotlinMultiplatformExtension -> compilationsOf(sourceSet) - is KotlinSingleTargetExtension -> compilationsOf(sourceSet) - else -> emptyList() - } -} - -private fun KotlinMultiplatformExtension.compilationsOf(sourceSet: KotlinSourceSet): List<KotlinCompilation> { - val allCompilations = targets.flatMap { target -> target.compilations } - return allCompilations.filter { compilation -> sourceSet in compilation.kotlinSourceSets } -} - -private fun KotlinSingleTargetExtension.compilationsOf(sourceSet: KotlinSourceSet): List<KotlinCompilation> { - return target.compilations.filter { compilation -> sourceSet in compilation.kotlinSourceSets } -} - -private fun compileClasspathOf(compilation: KotlinCompilation): List<File> { - if (compilation.target.isAndroidTarget()) { - // This is a workaround for https://youtrack.jetbrains.com/issue/KT-33893 - return compilation.compileKotlinTask.cast<KotlinCompile>().classpath.files.toList() - } - return compilation.compileDependencyFiles.files.toList() -} - -private fun KotlinSourceSet.withAllDependentSourceSets(): Sequence<KotlinSourceSet> { - return sequence { - yield(this@withAllDependentSourceSets) - for (dependentSourceSet in dependsOn) { - yieldAll(dependentSourceSet.withAllDependentSourceSets()) - } - } -} - - - diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaBootstrapFactory.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaBootstrapFactory.kt index 8a40ac89..65c0cd67 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaBootstrapFactory.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaBootstrapFactory.kt @@ -7,7 +7,6 @@ import org.jetbrains.dokka.DokkaBootstrap import java.net.URLClassLoader import kotlin.reflect.KClass - fun DokkaBootstrap(configuration: Configuration, bootstrapClass: KClass<out DokkaBootstrap>): DokkaBootstrap { val runtimeJars = configuration.resolve() val runtimeClassLoader = URLClassLoader( diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/KotlinSourceSetGist.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/KotlinSourceSetGist.kt new file mode 100644 index 00000000..86551153 --- /dev/null +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/KotlinSourceSetGist.kt @@ -0,0 +1,32 @@ +package org.jetbrains.dokka.gradle.kotlin + +import org.gradle.api.Project +import org.gradle.api.file.FileCollection +import org.gradle.api.provider.Provider +import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet + +// TODO NOW: Test this all + +internal data class KotlinSourceSetGist( + val name: String, + val platform: KotlinPlatformType, + val isMain: Boolean, + val classpath: FileCollection, + val sourceRoots: FileCollection, + val dependentSourceSetNames: Provider<Set<String>>, +) + +internal fun Project.gistOf(sourceSet: KotlinSourceSet): KotlinSourceSetGist { + return KotlinSourceSetGist( + name = sourceSet.name, + platform = platformOf(sourceSet), + isMain = isMainSourceSet(sourceSet), + classpath = classpathOf(sourceSet), + // TODO: Needs to respect filters. + // We probably need to change from "sourceRoots" to support "sourceFiles" + // https://github.com/Kotlin/dokka/issues/1215 + sourceRoots = sourceSet.kotlin.sourceDirectories.filter { it.exists() }, + dependentSourceSetNames = project.provider { sourceSet.dependsOn.map { it.name }.toSet() }, + ) +} diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/isMainSourceSet.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/isMainSourceSet.kt new file mode 100644 index 00000000..2c1eba5b --- /dev/null +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/isMainSourceSet.kt @@ -0,0 +1,24 @@ +package org.jetbrains.dokka.gradle.kotlin + +import com.android.build.gradle.api.ApplicationVariant +import com.android.build.gradle.api.LibraryVariant +import org.gradle.api.Project +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation + +internal fun Project.isMainSourceSet(sourceSet: KotlinSourceSet): Boolean { + return allCompilationsOf(sourceSet).any { compilation -> isMainCompilation(compilation) } +} + +private fun isMainCompilation(compilation: KotlinCompilation): Boolean { + try { + val androidVariant = compilation.run { this as? KotlinJvmAndroidCompilation }?.androidVariant + if (androidVariant != null) { + return androidVariant is LibraryVariant || androidVariant is ApplicationVariant + } + } catch (e: NoSuchMethodError) { + // Kotlin Plugin version below 1.4 + return !compilation.name.toLowerCase().endsWith("test") + } + return compilation.name == "main" +} diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/kotlinClasspathUtils.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/kotlinClasspathUtils.kt new file mode 100644 index 00000000..921b6418 --- /dev/null +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/kotlinClasspathUtils.kt @@ -0,0 +1,30 @@ +package org.jetbrains.dokka.gradle.kotlin + +import org.gradle.api.Project +import org.gradle.api.file.FileCollection +import org.jetbrains.dokka.gradle.isAndroidTarget +import org.jetbrains.dokka.utilities.cast +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +internal fun Project.classpathOf(sourceSet: KotlinSourceSet): FileCollection { + val compilations = compilationsOf(sourceSet) + return if (compilations.isNotEmpty()) { + compilations + .map { compilation -> compileClasspathOf(compilation) } + .reduce { acc, fileCollection -> acc + fileCollection } + } else { + sourceSet.withAllDependentSourceSets() + .toList() + .map { it.kotlin.sourceDirectories } + .reduce { acc, fileCollection -> acc + fileCollection } + } +} + +private fun compileClasspathOf(compilation: KotlinCompilation): FileCollection { + if (compilation.target.isAndroidTarget()) { + // This is a workaround for https://youtrack.jetbrains.com/issue/KT-33893 + return compilation.compileKotlinTask.cast<KotlinCompile>().classpath + } + return compilation.compileDependencyFiles +} diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/kotlinCompilationUtils.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/kotlinCompilationUtils.kt new file mode 100644 index 00000000..4de499e9 --- /dev/null +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/kotlinCompilationUtils.kt @@ -0,0 +1,35 @@ +package org.jetbrains.dokka.gradle.kotlin + +import org.gradle.api.Project +import org.jetbrains.dokka.gradle.kotlin +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.KotlinSourceSet + +internal typealias KotlinCompilation = + org.jetbrains.kotlin.gradle.plugin.KotlinCompilation<KotlinCommonOptions> + +internal fun Project.allCompilationsOf( + sourceSet: KotlinSourceSet +): List<KotlinCompilation> { + return when (val kotlin = kotlin) { + is KotlinMultiplatformExtension -> kotlin.allCompilationsOf(sourceSet) + is KotlinSingleTargetExtension -> kotlin.allCompilationsOf(sourceSet) + else -> emptyList() + } +} + +// TODO NOW: Better name, clarify distinction to allCompilationsOf +internal fun Project.compilationsOf(sourceSet: KotlinSourceSet): List<KotlinCompilation> { + return allCompilationsOf(sourceSet).filter { compilation -> sourceSet in compilation.kotlinSourceSets } +} + +private fun KotlinMultiplatformExtension.allCompilationsOf(sourceSet: KotlinSourceSet): List<KotlinCompilation> { + val allCompilations = targets.flatMap { target -> target.compilations } + return allCompilations.filter { compilation -> sourceSet in compilation.allKotlinSourceSets } +} + +private fun KotlinSingleTargetExtension.allCompilationsOf(sourceSet: KotlinSourceSet): List<KotlinCompilation> { + return target.compilations.filter { compilation -> sourceSet in compilation.allKotlinSourceSets } +} diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/kotlinSourceSetUtils.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/kotlinSourceSetUtils.kt new file mode 100644 index 00000000..d2d4e324 --- /dev/null +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/kotlinSourceSetUtils.kt @@ -0,0 +1,13 @@ +package org.jetbrains.dokka.gradle.kotlin + +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet + + +internal fun KotlinSourceSet.withAllDependentSourceSets(): Sequence<KotlinSourceSet> { + return sequence { + yield(this@withAllDependentSourceSets) + for (dependentSourceSet in dependsOn) { + yieldAll(dependentSourceSet.withAllDependentSourceSets()) + } + } +} diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/platformOfSourceSet.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/platformOfSourceSet.kt new file mode 100644 index 00000000..75dd80b9 --- /dev/null +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/kotlin/platformOfSourceSet.kt @@ -0,0 +1,13 @@ +package org.jetbrains.dokka.gradle.kotlin + +import org.gradle.api.Project +import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet + +internal fun Project.platformOf(sourceSet: KotlinSourceSet): KotlinPlatformType { + val targetNames = allCompilationsOf(sourceSet).map { compilation -> compilation.target.platformType }.distinct() + return when (targetNames.size) { + 1 -> targetNames.single() + else -> KotlinPlatformType.common + } +} diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/sourceSetKotlinGistConfiguration.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/sourceSetKotlinGistConfiguration.kt index 88833a76..409f645f 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/sourceSetKotlinGistConfiguration.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/sourceSetKotlinGistConfiguration.kt @@ -1,20 +1,24 @@ package org.jetbrains.dokka.gradle +import org.jetbrains.dokka.gradle.kotlin.KotlinSourceSetGist +import org.jetbrains.dokka.gradle.kotlin.gistOf import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet -import java.io.File // TODO NOW: Test fun GradleDokkaSourceSetBuilder.configureWithKotlinSourceSet(sourceSet: KotlinSourceSet) { - configureWithKotlinSourceSetGist(project.kotlinExtension.gistOf(sourceSet)) + configureWithKotlinSourceSetGist(project.gistOf(sourceSet)) } +// TODO NOW: What about language version? internal fun GradleDokkaSourceSetBuilder.configureWithKotlinSourceSetGist(sourceSet: KotlinSourceSetGist) { - sourceRoots.addAll(sourceRoots.union(sourceSet.sourceRoots).distinct()) - dependentSourceSets.addAll(dependentSourceSets) - dependentSourceSets.addAll(sourceSet.dependentSourceSets.map { DokkaSourceSetID(project, it) }) - classpath.addAll(sourceSet.classpath) - if (platform == null && sourceSet.platform != "") - platform = sourceSet.platform + val dependentSourceSetIds = sourceSet.dependentSourceSetNames.map { sourceSetNames -> + sourceSetNames.map { sourceSetName -> DokkaSourceSetID(sourceSetName) } + } + + this.sourceRoots.from(sourceSet.sourceRoots) + this.classpath.from(sourceSet.classpath) + this.platform by sourceSet.platform.name + this.dependentSourceSets.set(dependentSourceSetIds) } diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/toDokkaSourceSetImpl.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/toDokkaSourceSetImpl.kt new file mode 100644 index 00000000..5ed0d17f --- /dev/null +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/toDokkaSourceSetImpl.kt @@ -0,0 +1,102 @@ +package org.jetbrains.dokka.gradle + +import org.jetbrains.dokka.* +import java.io.File +import java.net.URL + +// TODO NOW: Test +internal fun GradleDokkaSourceSetBuilder.toDokkaSourceSetImpl(): DokkaSourceSetImpl { + return DokkaSourceSetImpl( + classpath = classpath.toSet(), + moduleDisplayName = moduleNameOrDefault(), + displayName = displayNameOrDefault(), + sourceSetID = sourceSetID, + sourceRoots = sourceRoots.toSet(), + dependentSourceSets = dependentSourceSets.get().toSet(), + samples = samples.toSet(), + includes = includes.toSet(), + includeNonPublic = includeNonPublic.getSafe(), + reportUndocumented = reportUndocumented.getSafe(), + skipEmptyPackages = skipEmptyPackages.getSafe(), + skipDeprecated = skipDeprecated.getSafe(), + jdkVersion = jdkVersion.getSafe(), + sourceLinks = sourceLinks.getSafe().build().toSet(), + perPackageOptions = perPackageOptions.getSafe().build(), + externalDocumentationLinks = externalDocumentationLinksWithDefaults(), + languageVersion = languageVersion.getSafe(), + apiVersion = apiVersion.getSafe(), + noStdlibLink = noStdlibLink.getSafe(), + noJdkLink = noJdkLink.getSafe(), + suppressedFiles = suppressedFilesWithDefaults(), + analysisPlatform = analysisPlatformOrDefault() + ) +} + +private fun GradleDokkaSourceSetBuilder.moduleNameOrDefault(): String { + return moduleDisplayName.getSafe() ?: project.name +} + +private fun GradleDokkaSourceSetBuilder.displayNameOrDefault(): String { + return displayName.getSafe() ?: name.substringBeforeLast("Main", platform.getSafe().toString()) +} + +private fun GradleDokkaSourceSetBuilder.externalDocumentationLinksWithDefaults(): Set<ExternalDocumentationLinkImpl> { + return externalDocumentationLinks.getSafe().build() + .run { + if (noJdkLink.get()) this + else this + ExternalDocumentationLink( + url = + if (jdkVersion.getSafe() < 11) "https://docs.oracle.com/javase/" + + "${jdkVersion.getSafe()}/docs/api/" + else "https://docs.oracle.com/en/java/javase/" + + "${jdkVersion.getSafe()}/docs/api/java.base/", + packageListUrl = + if (jdkVersion.getSafe() < 11) "https://docs.oracle.com/javase/" + + "${jdkVersion.getSafe()}/docs/api/package-list" + else "https://docs.oracle.com/en/java/javase/" + + "${jdkVersion.getSafe()}/docs/api/element-list" + ) + } + .run { + if (noStdlibLink.getSafe()) this + else this + ExternalDocumentationLink("https://kotlinlang.org/api/latest/jvm/stdlib/") + } + .run { + if (noAndroidSdkLink.getSafe() || !project.isAndroidProject()) this + else this + + ExternalDocumentationLink("https://developer.android.com/reference/") + + ExternalDocumentationLink( + url = URL("https://developer.android.com/reference/kotlin/"), + packageListUrl = URL("https://developer.android.com/reference/androidx/package-list") + ) + } + .toSet() +} + +private fun GradleDokkaSourceSetBuilder.analysisPlatformOrDefault(): Platform { + val analysisPlatform = analysisPlatform.getSafe() + if (analysisPlatform != null) return analysisPlatform + + platform.getSafe()?.let { platform -> + return when (platform.toLowerCase()) { + "androidjvm", "android" -> Platform.jvm + "metadata" -> Platform.common + else -> Platform.fromString(platform) + } + } + return Platform.DEFAULT +} + +private fun GradleDokkaSourceSetBuilder.suppressedFilesWithDefaults(): Set<File> { + val suppressedFilesForAndroid = if (project.isAndroidProject()) { + val generatedRoot = project.buildDir.resolve("generated").absoluteFile + sourceRoots + .filter { it.startsWith(generatedRoot) } + .flatMap { it.walk().toList() } + .toSet() + } else { + emptySet() + } + + return suppressedFiles.toSet() + suppressedFilesForAndroid +} diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt index 12e22f5d..28c16a2a 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt @@ -3,22 +3,31 @@ package org.jetbrains.dokka.gradle import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Project import org.gradle.api.UnknownDomainObjectException +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.KotlinTarget -internal val Project.kotlinExtensionOrNull: KotlinProjectExtension? +internal infix fun <T> Property<T>.by(value: T?) { + this.set(value) +} + +internal infix fun <T> Property<T>.by(value: Provider<T>) { + this.set(value) +} + +internal val Project.kotlinOrNull: KotlinProjectExtension? get() = try { project.extensions.findByType(KotlinProjectExtension::class.java) } catch (e: NoClassDefFoundError) { null } -internal val Project.kotlinExtension: KotlinProjectExtension +internal val Project.kotlin: KotlinProjectExtension get() = project.extensions.getByType(KotlinProjectExtension::class.java) - internal fun Project.isAndroidProject() = try { project.extensions.getByName("android") true @@ -46,4 +55,3 @@ internal fun KotlinTarget.isAndroidTarget() = this.platformType == KotlinPlatfor internal fun <T : Any> NamedDomainObjectContainer<T>.maybeCreate(name: String, configuration: T.() -> Unit): T { return findByName(name) ?: create(name, configuration) } - |