diff --git a/dokka-runners/dokka-gradle-plugin/src/main/kotlin/internal/PluginFeaturesService.kt b/dokka-runners/dokka-gradle-plugin/src/main/kotlin/internal/PluginFeaturesService.kt index 6bdae5ff53..b192ce7f71 100644 --- a/dokka-runners/dokka-gradle-plugin/src/main/kotlin/internal/PluginFeaturesService.kt +++ b/dokka-runners/dokka-gradle-plugin/src/main/kotlin/internal/PluginFeaturesService.kt @@ -3,6 +3,7 @@ */ package org.jetbrains.dokka.gradle.internal +import org.gradle.TaskExecutionRequest import org.gradle.api.Action import org.gradle.api.GradleException import org.gradle.api.Project @@ -12,6 +13,8 @@ import org.gradle.api.provider.Provider import org.gradle.api.services.BuildService import org.gradle.api.services.BuildServiceParameters import org.gradle.kotlin.dsl.extra +import java.io.File +import java.util.* /** * Internal utility service for managing Dokka Plugin features and warnings. @@ -193,43 +196,81 @@ internal abstract class PluginFeaturesService : BuildService { - v2PluginEnabled.set(getFlag(V2_PLUGIN_ENABLED_FLAG)) - v2PluginNoWarn.set(getFlag(V2_PLUGIN_NO_WARN_FLAG_PRETTY).orElse(getFlag(V2_PLUGIN_NO_WARN_FLAG))) - v2PluginMigrationHelpersEnabled.set(getFlag(V2_PLUGIN_MIGRATION_HELPERS_FLAG)) - k2AnalysisEnabled.set(getFlag(K2_ANALYSIS_ENABLED_FLAG)) - k2AnalysisNoWarn.set( - getFlag(K2_ANALYSIS_NO_WARN_FLAG_PRETTY) - .orElse(getFlag(K2_ANALYSIS_NO_WARN_FLAG)) + get() = getOrCreateService(project) + + private fun getOrCreateService(project: Project): PluginFeaturesService { + val configureServiceParams = project.serviceParamsConfiguration() + + return try { + project.gradle.sharedServices.registerIfAbsent(PluginFeaturesService::class) { + parameters(configureServiceParams) + // This service was successfully registered, so it is considered 'primary'. + parameters.primaryService.set(true) + }.get() + } catch (ex: ClassCastException) { + try { + // Recover from Gradle bug: re-register the service, but don't mark it as 'primary'. + project.gradle.sharedServices.registerIfAbsent( + PluginFeaturesService::class, + classLoaderScoped = true, + ) { + parameters(configureServiceParams) + parameters.primaryService.set(false) + }.get() + } catch (ex: ClassCastException) { + throw GradleException( + "Failed to register BuildService. Please report this problem https://github.com/gradle/gradle/issues/17559", + ex ) } + } + } - return try { - gradle.sharedServices.registerIfAbsent(PluginFeaturesService::class) { - parameters(setFlags) - // This service was successfully registered, so it is considered 'primary'. - parameters.primaryService.set(true) - }.get() - } catch (ex: ClassCastException) { - try { - // Recover from Gradle bug: re-register the service, but don't mark it as 'primary'. - gradle.sharedServices.registerIfAbsent( - PluginFeaturesService::class, - classLoaderScoped = true, - ) { - parameters(setFlags) - parameters.primaryService.set(false) - }.get() - } catch (ex: ClassCastException) { - throw GradleException( - "Failed to register BuildService. Please report this problem https://github.com/gradle/gradle/issues/17559", - ex - ) + private fun Project.serviceParamsConfiguration(): Action = Action { + v2PluginEnabled.set(getFlag(V2_PLUGIN_ENABLED_FLAG)) + v2PluginNoWarn.set(getFlag(V2_PLUGIN_NO_WARN_FLAG_PRETTY).orElse(getFlag(V2_PLUGIN_NO_WARN_FLAG))) + v2PluginMigrationHelpersEnabled.set(getFlag(V2_PLUGIN_MIGRATION_HELPERS_FLAG)) + k2AnalysisEnabled.set(getFlag(K2_ANALYSIS_ENABLED_FLAG)) + k2AnalysisNoWarn.set( + getFlag(K2_ANALYSIS_NO_WARN_FLAG_PRETTY) + .orElse(getFlag(K2_ANALYSIS_NO_WARN_FLAG)) + ) + + try { + if (project.isGradleGeneratingAccessors()) { + logger.info("Gradle is generating accessors. Discovering Dokka Gradle Plugin flags manually. ${gradle.rootProject.name} | ${gradle.rootProject.rootDir}") + + // Disable all warnings, regardless of the discovered flag values. + // Log messages will be printed too soon and aren't useful for users. + v2PluginNoWarn.set(true) + + // Because Gradle is generating accessors, it won't give us access to Gradle properties + // defined for the main project. So, we must discover `gradle.properties` ourselves. + val propertiesFile = findGradlePropertiesFile() + + val properties = Properties().apply { + propertiesFile?.reader()?.use { reader -> + load(reader) + } + } + + // These are the only flags that are important when Gradle is generating accessors, + // because they control what accessors DGP registers. + properties[V2_PLUGIN_ENABLED_FLAG]?.toString()?.toBoolean()?.let { + v2PluginEnabled.set(it) + } + properties[V2_PLUGIN_MIGRATION_HELPERS_FLAG]?.toString()?.toBoolean()?.let { + v2PluginMigrationHelpersEnabled.set(it) } } + } catch (t: Throwable) { + // Ignore all errors. + // This is just a temporary util. It doesn't need to be stable long-term, + // and we don't want to risk breaking people's projects. } + } + /** Find a flag for [PluginFeaturesService]. */ private fun Project.getFlag(flag: String): Provider = providers .gradleProperty(flag) @@ -244,6 +285,7 @@ internal abstract class PluginFeaturesService : BuildService + fun dirHasFile(named: String): Boolean = dir.resolve(named).run { exists() && isFile } + dirHasFile(named = "gradlew") || dirHasFile(named = "gradlew.bat") + } + + return rootProjectDirectory + ?.resolve("gradle.properties") + ?.takeIf { it.exists() && it.isFile } +}