diff options
3 files changed, 101 insertions, 48 deletions
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 dc9e7c1a..96cd0824 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 @@ -20,6 +20,7 @@ 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.utils.addToStdlib.firstNotNullResult import java.io.File import java.io.Serializable @@ -29,12 +30,12 @@ class ConfigurationExtractor(private val project: Project) { 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 + } catch (e: Throwable) { + when (e){ + is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException -> + return null + else -> throw e + } } return try { @@ -48,12 +49,12 @@ class ConfigurationExtractor(private val project: Project) { 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 + } catch (e: Throwable) { + when (e){ + is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException -> + return null + else -> throw e + } } val commonTarget = targets.find { it.platformType == KotlinPlatformType.common } @@ -65,7 +66,39 @@ class ConfigurationExtractor(private val project: Project) { return config + PlatformData("common", getClasspath(commonTarget), getSourceSet(commonTarget), "common") } - fun extractFromKotlinTasks(kotlinTasks: List<Task>): PlatformData? { + 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>() @@ -78,7 +111,7 @@ class ConfigurationExtractor(private val project: Project) { taskSourceRoots = it["sourceRootsContainer"]["sourceRoots"].v() abstractKotlinCompileClz = DokkaTask.getAbstractKotlinCompileFor(it)!! } catch (e: NullPointerException) { - println("Cannot extract sources from Kotlin tasks! Consider upgrading Kotlin Gradle Plugin") + println("Error during extraction of sources from kotlinTasks. This may be a result of outdated Kotlin Gradle Plugin") return null } @@ -105,18 +138,17 @@ class ConfigurationExtractor(private val project: Project) { 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> = getSourceSet(getMainCompilation(target)) + + private fun getClasspath(target: KotlinTarget?): List<File> = getClasspath(getMainCompilation(target)) - private fun getSourceSet(target: KotlinTarget?): List<File> = getMainCompilation(target) + private fun getSourceSet(compilation: KotlinCompilation<*>?): List<File> = compilation ?.allKotlinSourceSets ?.flatMap { it.kotlin.sourceDirectories } ?.filter { it.exists() } .orEmpty() - private fun getClasspath(target: KotlinTarget?): List<File> = getMainCompilation(target) + private fun getClasspath(compilation: KotlinCompilation<*>?): List<File> = compilation ?.compileDependencyFiles ?.files ?.toList() 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 017caeed..f20b6651 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 @@ -74,9 +74,9 @@ open class DokkaTask : DefaultTask() { private var externalDocumentationLinks: MutableList<DokkaConfiguration.ExternalDocumentationLink> = mutableListOf() - private val kotlinTasks: List<Task> by lazy { extractKotlinCompileTasks() } + private val kotlinTasks: List<Task> by lazy { extractKotlinCompileTasks(configuration.collectKotlinTasks ?: { defaultKotlinTasks() }) } - private val configurationExtractor = ConfigurationExtractor(project) + private val configExtractor = ConfigurationExtractor(project) @Input var subProjects: List<String> = emptyList() @@ -101,9 +101,7 @@ open class DokkaTask : DefaultTask() { } } - private fun extractKotlinCompileTasks(): List<Task> { - val collectTasks = configuration.collectKotlinTasks ?: { defaultKotlinTasks() } - + private fun extractKotlinCompileTasks(collectTasks: () -> List<Any?>?): List<Task> { val inputList = (collectTasks.invoke() ?: emptyList()).filterNotNull() val (paths, other) = inputList.partition { it is String } @@ -119,14 +117,14 @@ open class DokkaTask : DefaultTask() { .filter { it isNotInstance getAbstractKotlinCompileFor(it) } .forEach { throw IllegalArgumentException("Illegal task path in kotlinTasks, must be subtype of $ABSTRACT_KOTLIN_COMPILE, but was $it") } - + @Suppress("UNCHECKED_CAST") return (tasksByPath + other) as List<Task> } private fun Iterable<File>.toSourceRoots(): List<GradleSourceRootImpl> = this.filter { it.exists() }.map { GradleSourceRootImpl().apply { path = it.path } } private fun Iterable<String>.toProjects(): List<Project> = project.subprojects.toList().filter { this.contains(it.name) } - protected open fun collectSuppressedFiles(sourceRoots: List<SourceRoot>) = + private fun collectSuppressedFiles(sourceRoots: List<SourceRoot>) = if(project.isAndroidProject()) { val generatedRoot = project.buildDir.resolve("generated").absoluteFile sourceRoots @@ -184,36 +182,60 @@ open class DokkaTask : DefaultTask() { } private fun collectConfigurations(): List<GradlePassConfigurationImpl> = - if (multiplatform.toList().isNotEmpty()) collectFromMultiPlatform() else collectFromSinglePlatform() + if (this.isMultiplatformProject()) collectFromMultiPlatform() else collectFromSinglePlatform() private fun collectFromMultiPlatform(): List<GradlePassConfigurationImpl> { - if (disableAutoconfiguration) return multiplatform.filterNot { it.name.toLowerCase() == GLOBAL_PLATFORM_NAME }.toList() + 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( - multiplatform.filterNot { it.name.toLowerCase() == GLOBAL_PLATFORM_NAME }.toList(), - configurationExtractor.extractFromMultiPlatform().orEmpty() + userConfig, + configExtractor.extractFromMultiPlatform().orEmpty() ) + return if (subProjects.isNotEmpty()) - subProjects.toProjects().fold(baseConfig) { list, project -> - mergeUserAndAutoConfigurations(list, configurationExtractor.extractFromMultiPlatform().orEmpty()) + subProjects.toProjects().fold(baseConfig) { list, subProject -> + mergeUserAndAutoConfigurations(list, ConfigurationExtractor(subProject).extractFromMultiPlatform().orEmpty()) } else baseConfig } private fun collectFromSinglePlatform(): List<GradlePassConfigurationImpl> { - if (disableAutoconfiguration) return listOf(configuration) + 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 = configurationExtractor.extractFromSinglePlatform() - val baseConfig = if (extractedConfig != null && configuration.collectKotlinTasks == null) - listOf(mergeUserConfigurationAndPlatformData(configuration, extractedConfig)) + val extractedConfig = configExtractor.extractFromSinglePlatform() + val baseConfig = if (extractedConfig != null) + listOf(mergeUserConfigurationAndPlatformData(userConfig, extractedConfig)) else collectFromSinglePlatformOldPlugin() return if (subProjects.isNotEmpty()) { try { - subProjects.toProjects().fold(baseConfig) { list, project -> - listOf(mergeUserConfigurationAndPlatformData(list.first(), configurationExtractor.extractFromSinglePlatform()!!)) + 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+ " + @@ -226,11 +248,11 @@ open class DokkaTask : DefaultTask() { } private fun collectFromSinglePlatformOldPlugin(): List<GradlePassConfigurationImpl> { - val kotlinTasks = configurationExtractor.extractFromKotlinTasks(kotlinTasks) + val kotlinTasks = configExtractor.extractFromKotlinTasks(kotlinTasks) return if (kotlinTasks != null) { listOf(mergeUserConfigurationAndPlatformData(configuration, kotlinTasks)) } else { - val javaPlugin = configurationExtractor.extractFromJavaPlugin() + val javaPlugin = configExtractor.extractFromJavaPlugin() if (javaPlugin != null) listOf(mergeUserConfigurationAndPlatformData(configuration, javaPlugin)) else listOf(configuration) } @@ -259,16 +281,13 @@ open class DokkaTask : DefaultTask() { } private fun mergeUserConfigurationAndPlatformData(userConfig: GradlePassConfigurationImpl, - autoConfig: PlatformData): GradlePassConfigurationImpl { - val merged = userConfig.copy() - merged.apply { + 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) + if (userConfig.platform == null && autoConfig.platform != "") platform = autoConfig.platform } - return merged - } private fun defaultPassConfiguration(globalConfig: GradlePassConfigurationImpl?, config: GradlePassConfigurationImpl): GradlePassConfigurationImpl { if (config.moduleName == "") { 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 64ea2405..90dcde7b 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 @@ -11,4 +11,6 @@ fun Project.isAndroidProject() = try { false } catch(e: ClassNotFoundException) { false -}
\ No newline at end of file +} + +fun DokkaTask.isMultiplatformProject() = this.multiplatform.isNotEmpty()
\ No newline at end of file |