From 4947743f710e75e348ed43c8fb1522c0e7525321 Mon Sep 17 00:00:00 2001 From: Adam <897017+aSemy@users.noreply.github.com> Date: Sun, 11 Feb 2024 22:29:24 +0100 Subject: [PATCH] Updated automatic all-modules-page-plugin (#159) - improved 'missing all-modules-page-plugin' warning message - added option to disable 'missing all-modules-page-plugin' warning - all-modules-page-plugin now provided as a transitive dependency - exclude non-plugin dependencies from generator Dokka Plugins classpath (by checking for Dokka Plugin marker file) - updated some Configurations to be registered lazily - tidy up default Dokka dependencies (remove non-plugins from plugins classpath) --- .../kotlin/AndroidProjectIntegrationTest.kt | 5 + .../src/main/kotlin/DokkatooBasePlugin.kt | 6 +- .../src/main/kotlin/DokkatooExtension.kt | 2 +- .../dependencies/DependencyContainerNames.kt | 10 +- .../dependencies/FormatDependenciesManager.kt | 80 +++++++--- .../ModuleComponentDependencies.kt | 15 +- .../kotlin/dependencies/attributeValues.kt | 7 +- .../builders/DokkaParametersBuilder.kt | 24 ++- .../kotlin/formats/DokkatooFormatPlugin.kt | 26 ++-- .../kotlin/formats/DokkatooFormatTasks.kt | 6 +- .../main/kotlin/formats/DokkatooHtmlPlugin.kt | 143 ++++++++++++------ .../src/main/kotlin/internal/HasFormatName.kt | 7 +- .../tasks/DokkatooGenerateModuleTask.kt | 3 + .../tasks/DokkatooGeneratePublicationTask.kt | 5 +- .../main/kotlin/tasks/DokkatooGenerateTask.kt | 27 ++-- .../tasks/LogHtmlPublicationLinkTask.kt | 3 +- .../src/main/kotlin/tasks/TaskNames.kt | 2 +- .../kotlin/projects/MultiModuleProject.kt | 2 +- .../kotlin/DokkatooPluginFunctionalTest.kt | 4 +- .../kotlin/HtmlAggregationWarningTest.kt | 70 ++++++--- .../kotlin/MultiModuleFunctionalTest.kt | 5 +- settings.gradle.kts | 1 - 22 files changed, 321 insertions(+), 132 deletions(-) diff --git a/modules/dokkatoo-plugin-integration-tests/src/testIntegration/kotlin/AndroidProjectIntegrationTest.kt b/modules/dokkatoo-plugin-integration-tests/src/testIntegration/kotlin/AndroidProjectIntegrationTest.kt index 9dd08f9e..2be1aad5 100644 --- a/modules/dokkatoo-plugin-integration-tests/src/testIntegration/kotlin/AndroidProjectIntegrationTest.kt +++ b/modules/dokkatoo-plugin-integration-tests/src/testIntegration/kotlin/AndroidProjectIntegrationTest.kt @@ -63,6 +63,11 @@ class AndroidProjectIntegrationTest : FunSpec({ ) } } + + test("expect configurations are not resolved during configuration time") { + output shouldNotContain Regex("""Configuration '.*' was resolved during configuration time""") + output shouldNotContain "https://github.com/gradle/gradle/issues/2298" + } } } diff --git a/modules/dokkatoo-plugin/src/main/kotlin/DokkatooBasePlugin.kt b/modules/dokkatoo-plugin/src/main/kotlin/DokkatooBasePlugin.kt index c57dc34c..40e7ed5e 100644 --- a/modules/dokkatoo-plugin/src/main/kotlin/DokkatooBasePlugin.kt +++ b/modules/dokkatoo-plugin/src/main/kotlin/DokkatooBasePlugin.kt @@ -325,10 +325,12 @@ constructor( const val TASK_GROUP = "dokkatoo" /** The names of [Gradle tasks][org.gradle.api.Task] created by Dokkatoo */ - val taskNames = TaskNames(null) + val taskNames = TaskNames("") /** The names of [Configuration]s created by Dokkatoo */ - val dependencyContainerNames = DependencyContainerNames(null) + @Deprecated("no longer used") + @Suppress("unused") + val dependencyContainerNames = DependencyContainerNames("null") /** Name of the [Configuration] used to declare dependencies on other subprojects. */ const val DOKKATOO_CONFIGURATION_NAME = "dokkatoo" diff --git a/modules/dokkatoo-plugin/src/main/kotlin/DokkatooExtension.kt b/modules/dokkatoo-plugin/src/main/kotlin/DokkatooExtension.kt index 0d5138d7..d449ebc4 100644 --- a/modules/dokkatoo-plugin/src/main/kotlin/DokkatooExtension.kt +++ b/modules/dokkatoo-plugin/src/main/kotlin/DokkatooExtension.kt @@ -53,7 +53,7 @@ constructor( * This is primarily used by Kotlin Multiplatform projects, which can have multiple source sets * per subproject. * - * Defaults to [the path of the subproject][org.gradle.api.Project.getPath]. + * Defaults to [the Gradle path of the subproject][org.gradle.api.Project.getPath]. */ abstract val sourceSetScopeDefault: Property diff --git a/modules/dokkatoo-plugin/src/main/kotlin/dependencies/DependencyContainerNames.kt b/modules/dokkatoo-plugin/src/main/kotlin/dependencies/DependencyContainerNames.kt index 81adb86f..80cfc962 100644 --- a/modules/dokkatoo-plugin/src/main/kotlin/dependencies/DependencyContainerNames.kt +++ b/modules/dokkatoo-plugin/src/main/kotlin/dependencies/DependencyContainerNames.kt @@ -14,7 +14,7 @@ import org.gradle.api.artifacts.Configuration * - [DokkaConfiguration][org.jetbrains.dokka.DokkaConfiguration] - parameters for executing the Dokka Generator */ @DokkatooInternalApi -class DependencyContainerNames(override val formatName: String?) : HasFormatName() { +class DependencyContainerNames(override val formatName: String) : HasFormatName() { val dokkatoo = DOKKATOO_CONFIGURATION_NAME.appendFormat() val dokkatooResolver = "${dokkatoo}Resolver" @@ -24,7 +24,7 @@ class DependencyContainerNames(override val formatName: String?) : HasFormatName * * Includes transitive dependencies, so this can be passed to the Dokka Generator Worker classpath. * - * Will be used in user's build scripts to declare additional Dokka Plugins. + * Will be used in user's build scripts to declare additional format-specific Dokka Plugins. */ val pluginsClasspath = "dokkatooPlugin".appendFormat() @@ -51,4 +51,10 @@ class DependencyContainerNames(override val formatName: String?) : HasFormatName /** Resolver for [generatorClasspath] - internal Dokkatoo usage only. */ val generatorClasspathResolver = "${dokkatoo}GeneratorClasspathResolver" + + val publicationPluginClasspath = "${dokkatoo}PublicationPluginClasspath" + val publicationPluginClasspathApiOnly = "${publicationPluginClasspath}ApiOnly" + val publicationPluginClasspathResolver = "${publicationPluginClasspath}Resolver" + val publicationPluginClasspathApiOnlyConsumable = + "${publicationPluginClasspathApiOnly}Consumable" } diff --git a/modules/dokkatoo-plugin/src/main/kotlin/dependencies/FormatDependenciesManager.kt b/modules/dokkatoo-plugin/src/main/kotlin/dependencies/FormatDependenciesManager.kt index 1fef8429..2c8cda82 100644 --- a/modules/dokkatoo-plugin/src/main/kotlin/dependencies/FormatDependenciesManager.kt +++ b/modules/dokkatoo-plugin/src/main/kotlin/dependencies/FormatDependenciesManager.kt @@ -3,6 +3,7 @@ package dev.adamko.dokkatoo.dependencies import dev.adamko.dokkatoo.dependencies.DokkatooAttribute.Companion.DokkatooClasspathAttribute import dev.adamko.dokkatoo.dependencies.DokkatooAttribute.Companion.DokkatooFormatAttribute import dev.adamko.dokkatoo.internal.DokkatooInternalApi +import dev.adamko.dokkatoo.internal.consumable import dev.adamko.dokkatoo.internal.declarable import dev.adamko.dokkatoo.internal.resolvable import org.gradle.api.NamedDomainObjectProvider @@ -79,7 +80,7 @@ class FormatDependenciesManager( * * Should not contain runtime dependencies - use [dokkaGeneratorClasspath]. */ - val dokkaPluginsClasspath: NamedDomainObjectProvider = + private val dokkaPluginsClasspath: NamedDomainObjectProvider = project.configurations.register(configurationNames.pluginsClasspath) { description = "Dokka Plugins classpath for $formatName." declarable() @@ -90,8 +91,8 @@ class FormatDependenciesManager( * * It extends [dokkaPluginsClasspath]. */ - val dokkaPluginsIntransitiveClasspathResolver: Configuration = - project.configurations.create(configurationNames.pluginsClasspathIntransitiveResolver) { + val dokkaPluginsIntransitiveClasspathResolver: NamedDomainObjectProvider = + project.configurations.register(configurationNames.pluginsClasspathIntransitiveResolver) { description = "Resolves Dokka Plugins classpath for $formatName - for internal use. Fetch only the plugins (no transitive dependencies) for use in the Dokka JSON Configuration." resolvable() @@ -105,6 +106,51 @@ class FormatDependenciesManager( } //endregion + //region Dokka Plugins for Publication Generation + private val dokkaPublicationPluginClasspath: NamedDomainObjectProvider = + project.configurations.register(configurationNames.publicationPluginClasspath) { + description = + "Dokka Plugins classpath for a $formatName Publication (consisting of 1+ Dokka Module)." + declarable() + extendsFrom(baseDependencyManager.declaredDependencies) + } + + val dokkaPublicationPluginClasspathResolver: NamedDomainObjectProvider = + project.configurations.register(configurationNames.publicationPluginClasspathResolver) { + description = + "Resolves Dokka Plugins classpath for a $formatName Publication (consisting of 1+ Dokka Module)." + resolvable() + extendsFrom(dokkaPublicationPluginClasspath.get()) + attributes { + jvmJar() + attribute(DokkatooFormatAttribute, formatAttributes.format) + attribute(DokkatooClasspathAttribute, baseAttributes.dokkaPublicationPlugins) + } + } + + val dokkaPublicationPluginClasspathApiOnly: NamedDomainObjectProvider = + project.configurations.register(configurationNames.publicationPluginClasspathApiOnly) { + description = + "Dokka Plugins for consumers that will assemble a $formatName Publication using the Dokka Module that this project produces" + description = "TODO" + declarable() + } + + init { + project.configurations.register(configurationNames.publicationPluginClasspathApiOnlyConsumable) { + description = + "Shared Dokka Plugins for consumers that will assemble a $formatName Publication using the Dokka Module that this project produces" + consumable() + extendsFrom(dokkaPublicationPluginClasspathApiOnly.get()) + attributes { + jvmJar() + attribute(DokkatooFormatAttribute, formatAttributes.format) + attribute(DokkatooClasspathAttribute, baseAttributes.dokkaPublicationPlugins) + } + } + } + //endregion + //region Dokka Generator Classpath /** * Runtime classpath used to execute Dokka Worker. @@ -136,8 +182,8 @@ class FormatDependenciesManager( * @see dev.adamko.dokkatoo.workers.DokkaGeneratorWorker * @see dev.adamko.dokkatoo.tasks.DokkatooGenerateTask */ - val dokkaGeneratorClasspathResolver: Configuration = - project.configurations.create(configurationNames.generatorClasspathResolver) { + val dokkaGeneratorClasspathResolver: NamedDomainObjectProvider = + project.configurations.register(configurationNames.generatorClasspathResolver) { description = "Dokka Generator runtime classpath for $formatName - will be used in Dokka Worker. Should contain all transitive dependencies, plugins (and their transitive dependencies), so Dokka Worker can run." resolvable() @@ -153,18 +199,6 @@ class FormatDependenciesManager( } //endregion - private fun componentDependencies( - component: DokkatooAttribute.ModuleComponent - ): ModuleComponentDependencies = - ModuleComponentDependencies( - project = project, - component = component, - baseAttributes = baseAttributes, - formatAttributes = formatAttributes, - declaredDependencies = baseDependencyManager.declaredDependencies, - baseConfigurationName = configurationNames.dokkatoo, - ) - /** * Output directories of a Dokka Module. * @@ -179,4 +213,16 @@ class FormatDependenciesManager( */ val moduleOutputDirectories: ModuleComponentDependencies = componentDependencies(formatAttributes.moduleOutputDirectories) + + private fun componentDependencies( + component: DokkatooAttribute.ModuleComponent, + ): ModuleComponentDependencies = + ModuleComponentDependencies( + project = project, + component = component, + baseAttributes = baseAttributes, + formatAttributes = formatAttributes, + declaredDependencies = baseDependencyManager.declaredDependencies, + baseConfigurationName = configurationNames.dokkatoo, + ) } diff --git a/modules/dokkatoo-plugin/src/main/kotlin/dependencies/ModuleComponentDependencies.kt b/modules/dokkatoo-plugin/src/main/kotlin/dependencies/ModuleComponentDependencies.kt index 39a5d3e4..cfb3178d 100644 --- a/modules/dokkatoo-plugin/src/main/kotlin/dependencies/ModuleComponentDependencies.kt +++ b/modules/dokkatoo-plugin/src/main/kotlin/dependencies/ModuleComponentDependencies.kt @@ -4,6 +4,7 @@ import dev.adamko.dokkatoo.dependencies.DokkatooAttribute.Companion.DokkatooForm import dev.adamko.dokkatoo.dependencies.DokkatooAttribute.Companion.DokkatooModuleComponentAttribute import dev.adamko.dokkatoo.internal.* import java.io.File +import org.gradle.api.NamedDomainObjectProvider import org.gradle.api.Project import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.result.ResolvedArtifactResult @@ -25,8 +26,8 @@ class ModuleComponentDependencies( private val formatName: String get() = formatAttributes.format.name private val componentName: String get() = component.name - private val resolver: Configuration = - project.configurations.create("${baseConfigurationName}${componentName}Resolver") { + private val resolver: NamedDomainObjectProvider = + project.configurations.register("${baseConfigurationName}${componentName}Resolver") { description = "Resolves Dokkatoo $formatName $componentName files." resolvable() extendsFrom(declaredDependencies) @@ -37,11 +38,12 @@ class ModuleComponentDependencies( } } - val outgoing: Configuration = - project.configurations.create("${baseConfigurationName}${componentName}Consumable") { + val outgoing: NamedDomainObjectProvider = + project.configurations.register("${baseConfigurationName}${componentName}Consumable") { description = "Provides Dokkatoo $formatName $componentName files for consumption by other subprojects." consumable() + extendsFrom(declaredDependencies) attributes { attribute(USAGE_ATTRIBUTE, baseAttributes.dokkatooUsage) attribute(DokkatooFormatAttribute, formatAttributes.format) @@ -62,13 +64,14 @@ class ModuleComponentDependencies( * enabled, which might obscure errors. */ val incomingArtifactFiles: Provider> = - resolver.incomingArtifacts().map { it.map(ResolvedArtifactResult::getFile) } + resolver.get().incomingArtifacts().map { it.map(ResolvedArtifactResult::getFile) } private fun Configuration.incomingArtifacts(): Provider> { // Redefine variables locally, because Configuration Cache is easily confused // and produces confusing error messages. val baseAttributes = baseAttributes + val usage = baseAttributes.dokkatooUsage val formatAttributes = formatAttributes val incoming = incoming val incomingName = incoming.name @@ -79,7 +82,7 @@ class ModuleComponentDependencies( @Suppress("UnstableApiUsage") withVariantReselection() attributes { - attribute(USAGE_ATTRIBUTE, baseAttributes.dokkatooUsage) + attribute(USAGE_ATTRIBUTE, usage) attribute(DokkatooFormatAttribute, formatAttributes.format) attribute(DokkatooModuleComponentAttribute, component) } diff --git a/modules/dokkatoo-plugin/src/main/kotlin/dependencies/attributeValues.kt b/modules/dokkatoo-plugin/src/main/kotlin/dependencies/attributeValues.kt index a1f9a7dd..676a7339 100644 --- a/modules/dokkatoo-plugin/src/main/kotlin/dependencies/attributeValues.kt +++ b/modules/dokkatoo-plugin/src/main/kotlin/dependencies/attributeValues.kt @@ -6,7 +6,6 @@ import org.gradle.api.artifacts.Configuration import org.gradle.api.attributes.Attribute import org.gradle.api.attributes.Usage import org.gradle.api.model.ObjectFactory -import org.gradle.api.provider.Provider import org.gradle.kotlin.dsl.* @@ -17,6 +16,8 @@ class BaseAttributes( ) { val dokkatooUsage: Usage = objects.named("dev.adamko.dokkatoo") val dokkaPlugins: DokkatooAttribute.Classpath = objects.named("dokka-plugins") + val dokkaPublicationPlugins: DokkatooAttribute.Classpath = + objects.named("dokka-publication-plugins") val dokkaGenerator: DokkatooAttribute.Classpath = objects.named("dokka-generator") } @@ -28,5 +29,7 @@ class FormatAttributes( objects: ObjectFactory, ) { val format: DokkatooAttribute.Format = objects.named(formatName) - val moduleOutputDirectories: DokkatooAttribute.ModuleComponent = objects.named("ModuleOutputDirectories") + + val moduleOutputDirectories: DokkatooAttribute.ModuleComponent = + objects.named("ModuleOutputDirectories") } diff --git a/modules/dokkatoo-plugin/src/main/kotlin/dokka/parameters/builders/DokkaParametersBuilder.kt b/modules/dokkatoo-plugin/src/main/kotlin/dokka/parameters/builders/DokkaParametersBuilder.kt index cab26356..584709d6 100644 --- a/modules/dokkatoo-plugin/src/main/kotlin/dokka/parameters/builders/DokkaParametersBuilder.kt +++ b/modules/dokkatoo-plugin/src/main/kotlin/dokka/parameters/builders/DokkaParametersBuilder.kt @@ -4,9 +4,12 @@ import dev.adamko.dokkatoo.DokkatooBasePlugin import dev.adamko.dokkatoo.dokka.parameters.DokkaGeneratorParametersSpec import dev.adamko.dokkatoo.dokka.parameters.DokkaModuleDescriptionKxs import dev.adamko.dokkatoo.dokka.plugins.DokkaPluginParametersBaseSpec +import dev.adamko.dokkatoo.formats.DokkatooHtmlPlugin.Companion.extractDokkaPluginMarkers import dev.adamko.dokkatoo.internal.DokkatooInternalApi import java.io.File import org.gradle.api.Project +import org.gradle.api.file.ArchiveOperations +import org.gradle.api.file.FileCollection import org.gradle.api.logging.Logger import org.gradle.api.logging.Logging import org.jetbrains.dokka.* @@ -19,7 +22,9 @@ import org.jetbrains.dokka.* * leaking into the public API. */ @DokkatooInternalApi -internal object DokkaParametersBuilder { +internal class DokkaParametersBuilder( + private val archives: ArchiveOperations, +) { private val logger: Logger = Logging.getLogger(DokkaParametersBuilder::class.java) @@ -40,7 +45,10 @@ internal object DokkaParametersBuilder { val finalizeCoroutines = spec.finalizeCoroutines.get() val pluginsConfiguration = spec.pluginsConfiguration.toSet() - val pluginsClasspath = spec.pluginsClasspath.files.toList() + val pluginsClasspath = buildPluginsClasspath( + plugins = spec.pluginsClasspath, + ) + val includes = spec.includes.files return DokkaConfigurationImpl( @@ -62,6 +70,18 @@ internal object DokkaParametersBuilder { ) } + private fun buildPluginsClasspath( + plugins: FileCollection, + ): List { + // only include dependencies with Dokka Plugin markers + return plugins + .filter { file -> + val pluginIds = extractDokkaPluginMarkers(archives, file) + pluginIds.isNotEmpty() + } + .toList() + } + private fun buildModuleDescriptors( moduleDescriptorDirs: Iterable ): List { diff --git a/modules/dokkatoo-plugin/src/main/kotlin/formats/DokkatooFormatPlugin.kt b/modules/dokkatoo-plugin/src/main/kotlin/formats/DokkatooFormatPlugin.kt index 629a39b4..5af4eb5c 100644 --- a/modules/dokkatoo-plugin/src/main/kotlin/formats/DokkatooFormatPlugin.kt +++ b/modules/dokkatoo-plugin/src/main/kotlin/formats/DokkatooFormatPlugin.kt @@ -13,6 +13,7 @@ import dev.adamko.dokkatoo.dependencies.FormatDependenciesManager import dev.adamko.dokkatoo.internal.DokkatooInternalApi import javax.inject.Inject import org.gradle.api.Action +import org.gradle.api.NamedDomainObjectProvider import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.artifacts.Configuration @@ -27,7 +28,6 @@ import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.provider.ProviderFactory -import org.gradle.api.tasks.PathSensitivity.RELATIVE import org.gradle.kotlin.dsl.* /** @@ -89,6 +89,7 @@ abstract class DokkatooFormatPlugin( formatDependencies.moduleOutputDirectories .outgoing + .get() .outgoing .artifact(dokkatooTasks.generateModule.map { it.outputDirectory }) { builtBy(dokkatooTasks.generateModule) @@ -99,6 +100,9 @@ abstract class DokkatooFormatPlugin( generator.moduleOutputDirectories.from( formatDependencies.moduleOutputDirectories.incomingArtifactFiles ) + generator.pluginsClasspath.from( + formatDependencies.dokkaPublicationPluginClasspathResolver + ) } val context = DokkatooFormatPluginContext( @@ -122,15 +126,17 @@ abstract class DokkatooFormatPlugin( listOf( formatDependencies.dokkaPluginsIntransitiveClasspathResolver, formatDependencies.dokkaGeneratorClasspathResolver, - ).forEach { dependenciesContainer: Configuration -> + ).forEach { dependenciesContainer: NamedDomainObjectProvider -> // Add a version if one is missing, which will allow defining a org.jetbrains.dokka // dependency without a version. // (It would be nice to do this with a virtual-platform, but Gradle is bugged: // https://github.com/gradle/gradle/issues/27435) - dependenciesContainer.resolutionStrategy.eachDependency { - if (requested.group == "org.jetbrains.dokka" && requested.version.isNullOrBlank()) { - logger.info("adding version of dokka dependency '$requested'") - useVersion(dokkatooExtension.versions.jetbrainsDokka.get()) + dependenciesContainer.configure { + resolutionStrategy.eachDependency { + if (requested.group == "org.jetbrains.dokka" && requested.version.isNullOrBlank()) { + logger.info("adding version of dokka dependency '$requested'") + useVersion(dokkatooExtension.versions.jetbrainsDokka.get()) + } } } } @@ -211,17 +217,15 @@ abstract class DokkatooFormatPlugin( version.map { v -> create("$this:$v") } with(dokkatooExtension.versions) { - dokkaPlugin(dokka("analysis-kotlin-descriptors")) dokkaPlugin(dokka("templating-plugin")) dokkaPlugin(dokka("dokka-base")) - //dokkaPlugin(dokka("all-modules-page-plugin")) - - dokkaPlugin("org.jetbrains.kotlinx:kotlinx-html" version kotlinxHtml) - dokkaPlugin("org.freemarker:freemarker" version freemarker) + dokkaGenerator(dokka("analysis-kotlin-descriptors")) dokkaGenerator(dokka("dokka-core")) + dokkaGenerator("org.freemarker:freemarker" version freemarker) dokkaGenerator("org.jetbrains:markdown" version jetbrainsMarkdown) dokkaGenerator("org.jetbrains.kotlinx:kotlinx-coroutines-core" version kotlinxCoroutines) + dokkaGenerator("org.jetbrains.kotlinx:kotlinx-html" version kotlinxHtml) } } } diff --git a/modules/dokkatoo-plugin/src/main/kotlin/formats/DokkatooFormatTasks.kt b/modules/dokkatoo-plugin/src/main/kotlin/formats/DokkatooFormatTasks.kt index b418696e..f65fb488 100644 --- a/modules/dokkatoo-plugin/src/main/kotlin/formats/DokkatooFormatTasks.kt +++ b/modules/dokkatoo-plugin/src/main/kotlin/formats/DokkatooFormatTasks.kt @@ -54,7 +54,7 @@ class DokkatooFormatTasks( project.tasks.register( taskNames.generatePublication, publication.pluginsConfiguration, - ).configuring task@{ + ).configuring { description = "Executes the Dokka Generator, generating the $formatName publication" outputDirectory.convention(dokkatooExtension.dokkatooPublicationDirectory.dir(formatName)) @@ -66,7 +66,7 @@ class DokkatooFormatTasks( project.tasks.register( taskNames.generateModule, publication.pluginsConfiguration, - ).configuring task@{ + ).configuring { description = "Executes the Dokka Generator, generating a $formatName module" outputDirectory.convention(dokkatooExtension.dokkatooModuleDirectory.dir(formatName)) @@ -79,7 +79,7 @@ class DokkatooFormatTasks( val prepareModuleDescriptor: TaskProvider = project.tasks.register( taskNames.prepareModuleDescriptor - ) task@{ + ) { description = "[Deprecated ⚠️] Prepares the Dokka Module Descriptor for $formatName" } } diff --git a/modules/dokkatoo-plugin/src/main/kotlin/formats/DokkatooHtmlPlugin.kt b/modules/dokkatoo-plugin/src/main/kotlin/formats/DokkatooHtmlPlugin.kt index c39e094b..0ec54eb8 100644 --- a/modules/dokkatoo-plugin/src/main/kotlin/formats/DokkatooHtmlPlugin.kt +++ b/modules/dokkatoo-plugin/src/main/kotlin/formats/DokkatooHtmlPlugin.kt @@ -8,24 +8,31 @@ import dev.adamko.dokkatoo.internal.DokkatooInternalApi import dev.adamko.dokkatoo.internal.uppercaseFirstChar import dev.adamko.dokkatoo.tasks.DokkatooGeneratePublicationTask import dev.adamko.dokkatoo.tasks.LogHtmlPublicationLinkTask +import java.io.File +import javax.inject.Inject import org.gradle.api.Action import org.gradle.api.Task -import org.gradle.api.artifacts.component.ProjectComponentIdentifier +import org.gradle.api.file.ArchiveOperations import org.gradle.api.logging.Logging -import org.gradle.api.provider.Provider +import org.gradle.api.provider.ProviderFactory import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.* abstract class DokkatooHtmlPlugin @DokkatooInternalApi -constructor() : DokkatooFormatPlugin(formatName = "html") { +@Inject +constructor( + archives: ArchiveOperations, + providers: ProviderFactory, +) : DokkatooFormatPlugin(formatName = "html") { + + private val moduleAggregationCheck: HtmlModuleAggregationCheck = + HtmlModuleAggregationCheck(archives, providers) override fun DokkatooFormatPluginContext.configure() { registerDokkaBasePluginConfiguration() registerDokkaVersioningPlugin() - configureHtmlUrlLogging() - configureModuleAggregation() } @@ -40,8 +47,8 @@ constructor() : DokkatooFormatPlugin(formatName = "html") { } } + /** register and configure Dokka Versioning Plugin */ private fun DokkatooFormatPluginContext.registerDokkaVersioningPlugin() { - // register and configure Dokka Versioning Plugin with(dokkatooExtension.pluginsConfiguration) { registerBinding( DokkaVersioningPluginParameters::class, @@ -92,27 +99,14 @@ constructor() : DokkatooFormatPlugin(formatName = "html") { */ private fun DokkatooFormatPluginContext.configureModuleAggregation() { - val dokkatooIsAggregatingSubprojects: Provider = - formatDependencies.incoming.map { dokkatoo -> - dokkatoo.incoming.artifacts.artifacts.any { artifact -> - logger.info("${dokkatoo.name} depends on ${artifact.id}, project:${artifact.id.componentIdentifier is ProjectComponentIdentifier}") - artifact.id.componentIdentifier is ProjectComponentIdentifier - } - } - - formatDependencies.dokkaPluginsClasspath.configure { - dependencies.addAllLater(dokkatooIsAggregatingSubprojects.map { aggregating -> - buildList { - if (aggregating) { - logger.info("Automatically adding dependency on all-modules-page-plugin") - add("org.jetbrains.dokka:all-modules-page-plugin") - } - }.map { project.dependencies.create(it) } - }) + dokkatooTasks.generatePublication.configure { + doFirst("check all-modules-page-plugin is present", moduleAggregationCheck) } - dokkatooTasks.generatePublication.configure { - doFirst("check module aggregation has all-modules-page-plugin", ModuleAggregationCheck) + formatDependencies.dokkaPublicationPluginClasspathApiOnly.configure { + dependencies.addLater(dokkatooExtension.versions.jetbrainsDokka.map { v -> + project.dependencies.create("org.jetbrains.dokka:all-modules-page-plugin:$v") + }) } } @@ -120,35 +114,66 @@ constructor() : DokkatooFormatPlugin(formatName = "html") { * Log a warning if the publication has 1+ modules but `all-modules-page-plugin` is not present, * because otherwise Dokka happily runs and produces no output, which is baffling and unhelpful. */ - private object ModuleAggregationCheck : Action { + private class HtmlModuleAggregationCheck( + private val archives: ArchiveOperations, + private val providers: ProviderFactory, + ) : Action { + + private val checkEnabled: Boolean + get() = providers + .gradleProperty(HTML_MODULE_AGGREGATION_CHECK_ENABLED) + .map(String::toBoolean) + .getOrElse(true) + override fun execute(task: Task) { + if (!checkEnabled) { + logger.info("[${task.path} ModuleAggregationCheck] check is disabled") + return + } + require(task is DokkatooGeneratePublicationTask) { - "[DokkatooHtmlPlugin] ModuleAggregationCheck expected DokkatooGeneratePublicationTask but got ${task::class}" + "[${task.path} ModuleAggregationCheck] expected DokkatooGeneratePublicationTask but got ${task::class}" } val modulesCount = task.generator.moduleOutputDirectories.count() - if (modulesCount > 0) { - val moduleAggregationPluginInClasspath = - task.generator.pluginsClasspath.any { "all-modules-page-plugin" in it.name } - if (!moduleAggregationPluginInClasspath) { - val moduleName = task.generator.moduleName.get() - - logger.error( - /* language=text */ """ - |[${task.path}] org.jetbrains.dokka:all-modules-page-plugin is missing - | - |Publication '$moduleName' in has $modulesCount modules, but plugins classpath does not contain - |org.jetbrains.dokka:all-modules-page-plugin, which is required for aggregating HTML modules. - | - |all-modules-page-plugin should be added automatically. - | - | - verify that the dependency has not been excluded - | - raise an issue https://github.com/adamko-dev/dokkatoo/issues - | - """.trimMargin() - ) + if (modulesCount <= 0) { + logger.info("[${task.path} ModuleAggregationCheck] skipping check - publication does not have 1+ modules") + return + } + + val allDokkaPlugins = task.generator.pluginsClasspath + .flatMap { file -> + extractDokkaPluginMarkers(archives, file) } + + val allModulesPagePluginPresent = allDokkaPlugins.any { ALL_MODULES_PAGE_PLUGIN_FQN in it } + logger.info("[${task.path} ModuleAggregationCheck] allModulesPagePluginPresent:$allModulesPagePluginPresent") + + if (!allModulesPagePluginPresent) { + val moduleName = task.generator.moduleName.get() + + logger.warn(/* language=text */ """ + |[${task.path}] org.jetbrains.dokka:all-modules-page-plugin is missing. + | + |Publication '$moduleName' in has $modulesCount modules, but + |the Dokka Generator plugins classpath does not contain + | org.jetbrains.dokka:all-modules-page-plugin + |which is required for aggregating Dokka HTML modules. + | + |Dokkatoo should have added org.jetbrains.dokka:all-modules-page-plugin automatically. + | + |Generation will proceed, but the generated output might not contain the full HTML docs. + | + |Suggestions: + | - Verify that the dependency has not been excluded. + | - Raise an issue https://github.com/adamko-dev/dokkatoo/issues + | + |(all plugins: ${allDokkaPlugins.sorted().joinToString()}) + """ + .trimMargin() + .prependIndent("> ") + ) } } } @@ -156,5 +181,29 @@ constructor() : DokkatooFormatPlugin(formatName = "html") { @DokkatooInternalApi companion object { private val logger = Logging.getLogger(DokkatooHtmlPlugin::class.java) + + private const val ALL_MODULES_PAGE_PLUGIN_FQN = + "org.jetbrains.dokka.allModulesPage.AllModulesPagePlugin" + + private const val HTML_MODULE_AGGREGATION_CHECK_ENABLED = + "dev.adamko.dokkatoo.tasks.html.moduleAggregationCheckEnabled" + + private const val DOKKA_PLUGIN_MARKER_PATH = + "/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin" + + internal fun extractDokkaPluginMarkers(archives: ArchiveOperations, file: File): List { + val markers = archives.zipTree(file) + .matching { include(DOKKA_PLUGIN_MARKER_PATH) } + + val pluginIds = markers.flatMap { marker -> + marker.useLines { lines -> + lines + .filter { line -> line.isNotBlank() && !line.startsWith("#") } + .toList() + } + } + + return pluginIds + } } } diff --git a/modules/dokkatoo-plugin/src/main/kotlin/internal/HasFormatName.kt b/modules/dokkatoo-plugin/src/main/kotlin/internal/HasFormatName.kt index de5c279f..135314f5 100644 --- a/modules/dokkatoo-plugin/src/main/kotlin/internal/HasFormatName.kt +++ b/modules/dokkatoo-plugin/src/main/kotlin/internal/HasFormatName.kt @@ -2,12 +2,9 @@ package dev.adamko.dokkatoo.internal @DokkatooInternalApi abstract class HasFormatName { - abstract val formatName: String? + abstract val formatName: String /** Appends [formatName] to the end of the string, camelcase style, if [formatName] is not null */ protected fun String.appendFormat(): String = - when (val name = formatName) { - null -> this - else -> this + name.uppercaseFirstChar() - } + this + formatName.uppercaseFirstChar() } diff --git a/modules/dokkatoo-plugin/src/main/kotlin/tasks/DokkatooGenerateModuleTask.kt b/modules/dokkatoo-plugin/src/main/kotlin/tasks/DokkatooGenerateModuleTask.kt index b286c311..2e6fef65 100644 --- a/modules/dokkatoo-plugin/src/main/kotlin/tasks/DokkatooGenerateModuleTask.kt +++ b/modules/dokkatoo-plugin/src/main/kotlin/tasks/DokkatooGenerateModuleTask.kt @@ -6,6 +6,7 @@ import dev.adamko.dokkatoo.internal.DokkaPluginParametersContainer import dev.adamko.dokkatoo.internal.DokkatooInternalApi import java.io.File import javax.inject.Inject +import org.gradle.api.file.ArchiveOperations import org.gradle.api.file.FileSystemOperations import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Property @@ -28,6 +29,7 @@ abstract class DokkatooGenerateModuleTask constructor( objects: ObjectFactory, workers: WorkerExecutor, + archives: ArchiveOperations, private val fs: FileSystemOperations, /** * Configurations for Dokka Generator Plugins. Must be provided from @@ -38,6 +40,7 @@ constructor( objects = objects, workers = workers, pluginsConfiguration = pluginsConfiguration, + archives = archives, ) { @get:Input diff --git a/modules/dokkatoo-plugin/src/main/kotlin/tasks/DokkatooGeneratePublicationTask.kt b/modules/dokkatoo-plugin/src/main/kotlin/tasks/DokkatooGeneratePublicationTask.kt index c8b3ba9b..e4101e16 100644 --- a/modules/dokkatoo-plugin/src/main/kotlin/tasks/DokkatooGeneratePublicationTask.kt +++ b/modules/dokkatoo-plugin/src/main/kotlin/tasks/DokkatooGeneratePublicationTask.kt @@ -3,11 +3,10 @@ package dev.adamko.dokkatoo.tasks import dev.adamko.dokkatoo.internal.DokkaPluginParametersContainer import dev.adamko.dokkatoo.internal.DokkatooInternalApi import javax.inject.Inject -import org.gradle.api.file.DirectoryProperty +import org.gradle.api.file.ArchiveOperations import org.gradle.api.file.FileSystemOperations import org.gradle.api.model.ObjectFactory import org.gradle.api.tasks.CacheableTask -import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.TaskAction import org.gradle.workers.WorkerExecutor @@ -25,6 +24,7 @@ abstract class DokkatooGeneratePublicationTask constructor( objects: ObjectFactory, workers: WorkerExecutor, + archives: ArchiveOperations, private val fs: FileSystemOperations, /** @@ -36,6 +36,7 @@ constructor( objects = objects, workers = workers, pluginsConfiguration = pluginsConfiguration, + archives = archives, ) { @TaskAction diff --git a/modules/dokkatoo-plugin/src/main/kotlin/tasks/DokkatooGenerateTask.kt b/modules/dokkatoo-plugin/src/main/kotlin/tasks/DokkatooGenerateTask.kt index f5dd0086..4bb8b08b 100644 --- a/modules/dokkatoo-plugin/src/main/kotlin/tasks/DokkatooGenerateTask.kt +++ b/modules/dokkatoo-plugin/src/main/kotlin/tasks/DokkatooGenerateTask.kt @@ -12,6 +12,7 @@ import dev.adamko.dokkatoo.workers.WorkerIsolation import java.io.File import javax.inject.Inject import kotlinx.serialization.json.JsonElement +import org.gradle.api.file.ArchiveOperations import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.RegularFileProperty @@ -35,6 +36,7 @@ abstract class DokkatooGenerateTask @Inject constructor( objects: ObjectFactory, + archives: ArchiveOperations, private val workers: WorkerExecutor, /** @@ -44,6 +46,8 @@ constructor( pluginsConfiguration: DokkaPluginParametersContainer, ) : DokkatooTask() { + private val dokkaParametersBuilder = DokkaParametersBuilder(archives) + /** * Directory containing the generation result. The content and structure depends on whether * the task generates a Dokka Module or a Dokka Publication. @@ -97,12 +101,6 @@ constructor( Publication, } - @Deprecated("Removed - Module and Publication generation has been moved to specific subtasks") - enum class GenerationType { - MODULE, - PUBLICATION, - } - @DokkatooInternalApi protected fun generateDocumentation( generationType: GeneratorMode, @@ -176,7 +174,7 @@ constructor( val moduleOutputDirectories = generator.moduleOutputDirectories.toList() logger.info("[$path] got ${moduleOutputDirectories.size} moduleOutputDirectories: $moduleOutputDirectories") - return DokkaParametersBuilder.build( + return dokkaParametersBuilder.build( spec = generator, delayTemplateSubstitution = delayTemplateSubstitution, outputDirectory = outputDirectory, @@ -208,6 +206,7 @@ constructor( @get:Internal @Deprecated("Please move worker options to `DokkatooExtension.dokkaGeneratorIsolation`. Worker options were moved to allow for configuring worker isolation") abstract val workerDebugEnabled: Property + /** * Please move worker options: * @@ -229,6 +228,7 @@ constructor( @get:Internal @Deprecated("Please move worker options to `DokkatooExtension.dokkaGeneratorIsolation`. Worker options were moved to allow for configuring worker isolation") abstract val workerMinHeapSize: Property + /** * Please move worker options: * @@ -250,6 +250,7 @@ constructor( @get:Internal @Deprecated("Please move worker options to `DokkatooExtension.dokkaGeneratorIsolation`. Worker options were moved to allow for configuring worker isolation") abstract val workerMaxHeapSize: Property + /** * Please move worker options: * @@ -274,14 +275,22 @@ constructor( @Deprecated("Please move worker options to `DokkatooExtension.dokkaGeneratorIsolation`. Worker options were moved to allow for configuring worker isolation") abstract val workerJvmArgs: ListProperty + @Deprecated("Removed - Module and Publication generation have been moved to specific subtasks") + @Suppress("unused") + enum class GenerationType { + MODULE, + PUBLICATION, + } /** - * Generating a Dokka Module? Set this to [GenerationType.MODULE]. + * Deprecated - instead use specific subtasks for Module/Publication generation. * - * Generating a Dokka Publication? [GenerationType.PUBLICATION]. + * @see DokkatooGenerateModuleTask + * @see DokkatooGeneratePublicationTask */ @get:Internal @Deprecated("Created specific Module/Publication subclasses") + @Suppress("DEPRECATION", "unused") abstract val generationType: Property //endregion } diff --git a/modules/dokkatoo-plugin/src/main/kotlin/tasks/LogHtmlPublicationLinkTask.kt b/modules/dokkatoo-plugin/src/main/kotlin/tasks/LogHtmlPublicationLinkTask.kt index 1408ead5..24db80f8 100644 --- a/modules/dokkatoo-plugin/src/main/kotlin/tasks/LogHtmlPublicationLinkTask.kt +++ b/modules/dokkatoo-plugin/src/main/kotlin/tasks/LogHtmlPublicationLinkTask.kt @@ -87,8 +87,9 @@ constructor( val logHtmlPublicationLinkTaskEnabled = providers .gradleProperty(ENABLE_TASK_PROPERTY_NAME) - .orElse("true") .map(String::toBoolean) + .orElse(true) + super.onlyIf("task is enabled via property") { logHtmlPublicationLinkTaskEnabled.get() } diff --git a/modules/dokkatoo-plugin/src/main/kotlin/tasks/TaskNames.kt b/modules/dokkatoo-plugin/src/main/kotlin/tasks/TaskNames.kt index 9b23a6ca..c62f9fd0 100644 --- a/modules/dokkatoo-plugin/src/main/kotlin/tasks/TaskNames.kt +++ b/modules/dokkatoo-plugin/src/main/kotlin/tasks/TaskNames.kt @@ -4,7 +4,7 @@ import dev.adamko.dokkatoo.internal.DokkatooInternalApi import dev.adamko.dokkatoo.internal.HasFormatName @DokkatooInternalApi -class TaskNames(override val formatName: String?) : HasFormatName() { +class TaskNames(override val formatName: String) : HasFormatName() { val generate = "dokkatooGenerate".appendFormat() val generatePublication = "dokkatooGeneratePublication".appendFormat() val generateModule = "dokkatooGenerateModule".appendFormat() diff --git a/modules/dokkatoo-plugin/src/testFixtures/kotlin/projects/MultiModuleProject.kt b/modules/dokkatoo-plugin/src/testFixtures/kotlin/projects/MultiModuleProject.kt index 5230e3ac..c0ef8b1f 100644 --- a/modules/dokkatoo-plugin/src/testFixtures/kotlin/projects/MultiModuleProject.kt +++ b/modules/dokkatoo-plugin/src/testFixtures/kotlin/projects/MultiModuleProject.kt @@ -13,7 +13,7 @@ fun TestScope.initMultiModuleProject( // get the FQN of the class that contains the test, so even though multiple // tests uses this project it's unlikely that the project dirs clash val baseDirName = testCase.descriptor.ids().first().value - .substringAfter("dev.adamko.dokkatoo") // drop the package name + .substringAfter("dev.adamko.dokkatoo.") // drop the package name .replaceNonAlphaNumeric() return gradleKtsProjectTest("$baseDirName/multi-module-hello-goodbye/$testName") { diff --git a/modules/dokkatoo-plugin/src/testFunctional/kotlin/DokkatooPluginFunctionalTest.kt b/modules/dokkatoo-plugin/src/testFunctional/kotlin/DokkatooPluginFunctionalTest.kt index 86f277ba..a97e832c 100644 --- a/modules/dokkatoo-plugin/src/testFunctional/kotlin/DokkatooPluginFunctionalTest.kt +++ b/modules/dokkatoo-plugin/src/testFunctional/kotlin/DokkatooPluginFunctionalTest.kt @@ -64,6 +64,7 @@ class DokkatooPluginFunctionalTest : FunSpec({ expectedFormats.flatMap { listOf( "dokkatoo${it}ModuleOutputDirectoriesConsumable", + "dokkatoo${it}PublicationPluginClasspathApiOnlyConsumable", ) } ) @@ -111,8 +112,9 @@ class DokkatooPluginFunctionalTest : FunSpec({ buildSet { addAll(expectedFormats.map { "dokkatoo${it}Resolver" }) addAll(expectedFormats.map { "dokkatoo${it}GeneratorClasspathResolver" }) - addAll(expectedFormats.map { "dokkatoo${it}PluginsClasspathIntransitiveResolver" }) addAll(expectedFormats.map { "dokkatoo${it}ModuleOutputDirectoriesResolver" }) + addAll(expectedFormats.map { "dokkatoo${it}PluginsClasspathIntransitiveResolver" }) + addAll(expectedFormats.map { "dokkatoo${it}PublicationPluginClasspathResolver" }) } ) diff --git a/modules/dokkatoo-plugin/src/testFunctional/kotlin/HtmlAggregationWarningTest.kt b/modules/dokkatoo-plugin/src/testFunctional/kotlin/HtmlAggregationWarningTest.kt index 697ed8f8..a633f011 100644 --- a/modules/dokkatoo-plugin/src/testFunctional/kotlin/HtmlAggregationWarningTest.kt +++ b/modules/dokkatoo-plugin/src/testFunctional/kotlin/HtmlAggregationWarningTest.kt @@ -6,6 +6,7 @@ import dev.adamko.dokkatoo.utils.buildGradleKts import dev.adamko.dokkatoo.utils.projects.initMultiModuleProject import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.string.shouldContain +import io.kotest.matchers.string.shouldNotContain class HtmlAggregationWarningTest : FunSpec({ context("when all-modules-page-plugin is missing") { @@ -14,12 +15,9 @@ class HtmlAggregationWarningTest : FunSpec({ project.buildGradleKts += """ | |// hack, to remove all-modules-page-plugin for testing purposes - |afterEvaluate { - | configurations.getByName("dokkatooPluginHtml").dependencies.removeIf { - | it.group == "org.jetbrains.dokka" && it.name == "all-modules-page-plugin" - | } + |configurations.all { + | exclude("org.jetbrains.dokka", "all-modules-page-plugin") |} - | """.trimMargin() @@ -28,22 +26,60 @@ class HtmlAggregationWarningTest : FunSpec({ "clean", ":dokkatooGenerate", "--stacktrace", + "--info", ) .forwardOutput() .build { test("expect warning message is logged") { - output shouldContain /* language=text */ """ - |[:dokkatooGeneratePublicationHtml] org.jetbrains.dokka:all-modules-page-plugin is missing - | - |Publication 'test' in has 2 modules, but plugins classpath does not contain - |org.jetbrains.dokka:all-modules-page-plugin, which is required for aggregating HTML modules. - | - |all-modules-page-plugin should be added automatically. - | - | - verify that the dependency has not been excluded - | - raise an issue https://github.com/adamko-dev/dokkatoo/issues - """.trimMargin() + output shouldContain expectedWarning + output shouldContain allPlugins + } + } + } + + context("when all-modules-page-plugin is present") { + val project = initMultiModuleProject("with-all-pages-plugin") + + project.runner + .addArguments( + "clean", + ":dokkatooGenerate", + "--stacktrace", + "--info", + ) + .forwardOutput() + .build { + test("expect warning message is not logged") { + output shouldNotContain expectedWarning + output shouldNotContain allPlugins } } } -}) +}) { + companion object { + private val expectedWarning = /* language=text */ """ + |[:dokkatooGeneratePublicationHtml] org.jetbrains.dokka:all-modules-page-plugin is missing. + | + |Publication 'test' in has 2 modules, but + |the Dokka Generator plugins classpath does not contain + | org.jetbrains.dokka:all-modules-page-plugin + |which is required for aggregating Dokka HTML modules. + | + |Dokkatoo should have added org.jetbrains.dokka:all-modules-page-plugin automatically. + | + |Generation will proceed, but the generated output might not contain the full HTML docs. + | + |Suggestions: + | - Verify that the dependency has not been excluded. + | - Raise an issue https://github.com/adamko-dev/dokkatoo/issues + """ + .trimMargin() + .prependIndent("> ") + + private val allPlugins = /* language=text */ """ + |(all plugins: org.jetbrains.dokka.base.DokkaBase, org.jetbrains.dokka.templates.TemplatingPlugin) + """ + .trimMargin() + .prependIndent("> ") + } +} diff --git a/modules/dokkatoo-plugin/src/testFunctional/kotlin/MultiModuleFunctionalTest.kt b/modules/dokkatoo-plugin/src/testFunctional/kotlin/MultiModuleFunctionalTest.kt index 1885960f..7e624746 100644 --- a/modules/dokkatoo-plugin/src/testFunctional/kotlin/MultiModuleFunctionalTest.kt +++ b/modules/dokkatoo-plugin/src/testFunctional/kotlin/MultiModuleFunctionalTest.kt @@ -229,6 +229,7 @@ class MultiModuleFunctionalTest : FunSpec({ ":dokkatooGenerate", "--stacktrace", "--build-cache", + "-D" + "org.gradle.caching.debug=true" ) .forwardOutput() .build { @@ -623,7 +624,9 @@ class MultiModuleFunctionalTest : FunSpec({ .walk() .filter { it.isFile && it.extension == "html" } - htmlFiles.shouldNotBeEmpty() + withClue("html files should be generated") { + htmlFiles.shouldNotBeEmpty() + } htmlFiles.forEach { htmlFile -> val relativePath = htmlFile.relativeTo(project.projectDir.toFile()) diff --git a/settings.gradle.kts b/settings.gradle.kts index 497f3e34..506f5960 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -9,7 +9,6 @@ pluginManagement { @Suppress("UnstableApiUsage") dependencyResolutionManagement { - repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS) repositories {