diff options
7 files changed, 189 insertions, 143 deletions
diff --git a/runners/android-gradle-plugin/build.gradle b/runners/android-gradle-plugin/build.gradle index 6126510b..99e3abc6 100644 --- a/runners/android-gradle-plugin/build.gradle +++ b/runners/android-gradle-plugin/build.gradle @@ -21,6 +21,7 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { repositories { jcenter() + google() } dependencies { @@ -31,6 +32,9 @@ dependencies { compileOnly gradleApi() compileOnly localGroovy() + 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") } task sourceJar(type: Jar) { diff --git a/runners/android-gradle-plugin/src/main/kotlin/AndroidConfigurationExtractor.kt b/runners/android-gradle-plugin/src/main/kotlin/AndroidConfigurationExtractor.kt new file mode 100644 index 00000000..8a2a2dff --- /dev/null +++ b/runners/android-gradle-plugin/src/main/kotlin/AndroidConfigurationExtractor.kt @@ -0,0 +1,32 @@ +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.Project + +class AndroidConfigurationExtractor(private val project: Project): AbstractConfigurationExtractor(project) { + override fun getMainCompilationName(): String = getVariants(project).filter { it.name == BuilderConstants.RELEASE }.map { it.name }.first() + + private fun getVariants(project: Project): Set<BaseVariant> { + val androidExtension = project.extensions.getByName("android") + return 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() + } + + if (androidExtension is TestedExtension) { + androidExtension.testVariants.toSet() + androidExtension.unitTestVariants.toSet() + } else { + emptySet<BaseVariant>() + } + } +}
\ 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 index 8aa76ef8..8e293ed6 100644 --- a/runners/android-gradle-plugin/src/main/kotlin/mainAndroid.kt +++ b/runners/android-gradle-plugin/src/main/kotlin/mainAndroid.kt @@ -18,8 +18,8 @@ open class DokkaAndroidPlugin : DokkaPlugin() { private val ANDROID_REFERENCE_URL = Builder("https://developer.android.com/reference/").build() open class DokkaAndroidTask : DokkaTask() { - @Input var noAndroidSdkLink: Boolean = false + override val configurationExtractor = AndroidConfigurationExtractor(project) override fun collectSuppressedFiles(sourceRoots: List<SourceRoot>): List<String> { val generatedRoot = project.buildDir.resolve("generated").absoluteFile @@ -35,4 +35,4 @@ open class DokkaAndroidTask : DokkaTask() { if (!noAndroidSdkLink) externalDocumentationLinks.add(ANDROID_REFERENCE_URL) } } -} +}
\ No newline at end of file diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractConfigurationExtractor.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractConfigurationExtractor.kt new file mode 100644 index 00000000..b882923a --- /dev/null +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractConfigurationExtractor.kt @@ -0,0 +1,135 @@ +package org.jetbrains.dokka.gradle + +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.android.synthetic.diagnostic.AndroidExtensionPropertiesCallChecker +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 java.io.File +import java.io.Serializable + +abstract class AbstractConfigurationExtractor(private val project: Project) { + + fun extractFromSinglePlatform(): PlatformData? { + val target: KotlinTarget + try { + target = project.extensions.getByType(KotlinSingleTargetExtension::class.java).target + } catch(e: UnknownDomainObjectException) { + return null + } catch(e: NoClassDefFoundError) { + return null + } catch(e: ClassNotFoundException) { + return null + } + + return try { + PlatformData(null, getClasspath(target), getSourceSet(target), 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: UnknownDomainObjectException) { + return null + } catch(e: ClassNotFoundException) { + return null + } catch(e: NoClassDefFoundError) { + return null + } + + val commonTarget = targets.find { it.platformType == KotlinPlatformType.common } + val platformTargets = targets.filter { it.platformType != KotlinPlatformType.common } + val config = platformTargets.map { + PlatformData(it.name, getClasspath(it), getSourceSet(it), it.platformType.toString()) + } + + return config + PlatformData("common", getClasspath(commonTarget), getSourceSet(commonTarget), "common") + } + + fun extractFromKotlinTasks(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("Cannot extract sources from Kotlin tasks! Consider upgrading 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(), "") + } + + 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(), "") } + + private fun getSourceSet(target: KotlinTarget?): List<File> = getMainCompilation(target) + ?.allKotlinSourceSets + ?.flatMap { it.kotlin.sourceDirectories } + ?.filter { it.exists() } + .orEmpty() + + private fun getClasspath(target: KotlinTarget?): List<File> = getMainCompilation(target) + ?.compileDependencyFiles + ?.files + ?.toList() + ?.filter { it.exists() } + .orEmpty() + + private fun getMainCompilation(target: KotlinTarget?): KotlinCompilation<KotlinCommonOptions>? = + target?.compilations?.getByName(getMainCompilationName()) + + protected abstract fun getMainCompilationName(): String + + 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/ConfigurationExtractor.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt index 0ad1d1d3..9bc37f50 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt @@ -1,132 +1,8 @@ package org.jetbrains.dokka.gradle -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 java.io.File -import java.io.Serializable -object ConfigurationExtractor { - - fun extractFromSinglePlatform(project: Project): PlatformData? { - val target: KotlinTarget - try { - target = project.extensions.getByType(KotlinSingleTargetExtension::class.java).target - } catch(e: UnknownDomainObjectException) { - return null - } catch(e: NoClassDefFoundError) { - return null - } catch(e: ClassNotFoundException) { - return null - } - - return try { - return PlatformData(null, getClasspath(target), getSourceSet(target), getPlatformName(target.platformType)) - } catch(e: NoSuchMethodError){ - null - } - } - - fun extractFromMultiPlatform(project: Project): List<PlatformData>? { - val targets: NamedDomainObjectCollection<KotlinTarget> - try { - targets = project.extensions.getByType(KotlinMultiplatformExtension::class.java).targets - } catch(e: UnknownDomainObjectException) { - return null - } catch(e: ClassNotFoundException) { - return null - } catch(e: NoClassDefFoundError) { - return null - } - - val commonTarget = targets.find { it.platformType == KotlinPlatformType.common } - val platformTargets = targets.filter { it.platformType != KotlinPlatformType.common } - val config = platformTargets.map { - PlatformData(it.name, getClasspath(it), getSourceSet(it), it.platformType.toString()) - } - - return config + PlatformData("common", getClasspath(commonTarget), getSourceSet(commonTarget), "common") - } - - fun extractFromKotlinTasks(kotlinTasks: List<Task>, project: Project): 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("Cannot extract sources from Kotlin tasks! Consider upgrading 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(), "") - } - - fun extractFromJavaPlugin(project: Project): PlatformData? = - project.convention.findPlugin(JavaPluginConvention::class.java) - ?.run { sourceSets.findByName(SourceSet.MAIN_SOURCE_SET_NAME)?.allSource?.srcDirs } - ?.let { PlatformData(null, emptyList(), it.toList(), "") } - - private fun getSourceSet(target: KotlinTarget?): List<File> = getMainCompilation(target) - ?.allKotlinSourceSets - ?.flatMap { it.kotlin.sourceDirectories } - ?.filter { it.exists() } - .orEmpty() - - private fun getClasspath(target: KotlinTarget?): List<File> = getMainCompilation(target) - ?.compileDependencyFiles - ?.files - ?.toList() - ?.filter { it.exists() } - .orEmpty() - - private fun getMainCompilation(target: KotlinTarget?): KotlinCompilation<KotlinCommonOptions>? = - target?.compilations?.getByName(KotlinCompilation.MAIN_COMPILATION_NAME) - - private fun getPlatformName(platform: KotlinPlatformType): String = - if (platform == KotlinPlatformType.androidJvm) "jvm" else platform.toString() - - data class PlatformData(val name: String?, - val classpath: List<File>, - val sourceRoots: List<File>, - val platform: String) : Serializable +class ConfigurationExtractor(private val project: Project): AbstractConfigurationExtractor(project) { + override fun getMainCompilationName(): String = KotlinCompilation.MAIN_COMPILATION_NAME }
\ 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 index 6a4fbe4f..c4ce3730 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt @@ -1,7 +1,6 @@ package org.jetbrains.dokka.gradle import com.google.gson.GsonBuilder -import groovy.lang.Closure import org.gradle.api.* import org.gradle.api.artifacts.Configuration import org.gradle.api.file.FileCollection @@ -14,6 +13,7 @@ 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.AbstractConfigurationExtractor.PlatformData import java.io.File import java.net.URLClassLoader import java.util.concurrent.Callable @@ -73,6 +73,8 @@ open class DokkaTask : DefaultTask() { private val kotlinTasks: List<Task> by lazy { extractKotlinCompileTasks() } + protected open val configurationExtractor: AbstractConfigurationExtractor = ConfigurationExtractor(project) + @Input var subProjects: List<String> = emptyList() @@ -172,11 +174,11 @@ open class DokkaTask : DefaultTask() { val baseConfig = mergeUserAndAutoConfigurations( multiplatform.toList(), - ConfigurationExtractor.extractFromMultiPlatform(project).orEmpty() + configurationExtractor.extractFromMultiPlatform().orEmpty() ) return if (subProjects.isNotEmpty()) subProjects.toProjects().fold(baseConfig) { list, project -> - mergeUserAndAutoConfigurations(list, ConfigurationExtractor.extractFromMultiPlatform(project).orEmpty()) + mergeUserAndAutoConfigurations(list, configurationExtractor.extractFromMultiPlatform().orEmpty()) } else baseConfig @@ -185,7 +187,7 @@ open class DokkaTask : DefaultTask() { private fun collectFromSinglePlatform(): List<GradlePassConfigurationImpl> { if (disableAutoconfiguration) return listOf(configuration) - val extractedConfig = ConfigurationExtractor.extractFromSinglePlatform(project) + val extractedConfig = configurationExtractor.extractFromSinglePlatform() val baseConfig = if (extractedConfig != null && configuration.collectKotlinTasks == null) listOf(mergeUserConfigurationAndPlatformData(configuration, extractedConfig)) else @@ -194,7 +196,7 @@ open class DokkaTask : DefaultTask() { return if (subProjects.isNotEmpty()) { try { subProjects.toProjects().fold(baseConfig) { list, project -> - listOf(mergeUserConfigurationAndPlatformData(list.first(), ConfigurationExtractor.extractFromSinglePlatform(project)!!)) + listOf(mergeUserConfigurationAndPlatformData(list.first(), configurationExtractor.extractFromSinglePlatform()!!)) } } catch(e: NullPointerException) { logger.warn("Cannot extract sources from subProjects. Do you have the Kotlin plugin in version 1.3.30+ " + @@ -207,18 +209,18 @@ open class DokkaTask : DefaultTask() { } private fun collectFromSinglePlatformOldPlugin(): List<GradlePassConfigurationImpl> { - val kotlinTasks = ConfigurationExtractor.extractFromKotlinTasks(kotlinTasks, project) + val kotlinTasks = configurationExtractor.extractFromKotlinTasks(kotlinTasks) return if (kotlinTasks != null) { listOf(mergeUserConfigurationAndPlatformData(configuration, kotlinTasks)) } else { - val javaPlugin = ConfigurationExtractor.extractFromJavaPlugin(project) + val javaPlugin = configurationExtractor.extractFromJavaPlugin() if (javaPlugin != null) listOf(mergeUserConfigurationAndPlatformData(configuration, javaPlugin)) else listOf(configuration) } } private fun mergeUserAndAutoConfigurations(userConfigurations: List<GradlePassConfigurationImpl>, - autoConfigurations: List<ConfigurationExtractor.PlatformData>): List<GradlePassConfigurationImpl> { + autoConfigurations: List<PlatformData>): List<GradlePassConfigurationImpl> { val merged: MutableList<GradlePassConfigurationImpl> = mutableListOf() merged.addAll( userConfigurations.map { userConfig -> @@ -230,7 +232,7 @@ open class DokkaTask : DefaultTask() { } private fun mergeUserConfigurationAndPlatformData(userConfig: GradlePassConfigurationImpl, - autoConfig: ConfigurationExtractor.PlatformData): GradlePassConfigurationImpl { + autoConfig: PlatformData): GradlePassConfigurationImpl { val merged = userConfig.copy() merged.apply { sourceRoots.addAll(userConfig.sourceRoots.union(autoConfig.sourceRoots.toSourceRoots()).distinct()) diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt index a47c238f..a3aadd08 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt @@ -29,18 +29,15 @@ open class DokkaPlugin : Plugin<Project> { protected fun addTasks(project: Project, runtimeConfiguration: Configuration, taskClass: Class<out DokkaTask>) { if(GradleVersion.current() >= GradleVersion.version("4.10")) { - project.tasks.register(taskName, taskClass).configure { - it.outputDirectory = File(project.buildDir, taskName).absolutePath - } + project.tasks.register(taskName, taskClass) } else { - project.tasks.create(taskName, taskClass).apply { - outputDirectory = File(project.buildDir, taskName).absolutePath - } + 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 } } } |