diff --git a/dokka-runners/gradle-plugin/build.gradle.kts b/dokka-runners/gradle-plugin/build.gradle.kts index daf7c37f1f..c518725c15 100644 --- a/dokka-runners/gradle-plugin/build.gradle.kts +++ b/dokka-runners/gradle-plugin/build.gradle.kts @@ -4,19 +4,15 @@ @file:Suppress("UnstableApiUsage") // jvm test suites & test report aggregation are incubating -import buildsrc.utils.buildDir_ import buildsrc.utils.skipTestFixturesPublications plugins { buildsrc.conventions.`kotlin-gradle-plugin` kotlin("plugin.serialization") - buildsrc.conventions.`maven-publishing` - `java-test-fixtures` `jvm-test-suite` `test-report-aggregation` - buildsrc.conventions.`maven-publish-test` } description = "Generates documentation for Kotlin projects (using Dokka)" @@ -114,83 +110,8 @@ kotlin { } } -testing.suites { - withType().configureEach { - useJUnitJupiter() - - dependencies { - implementation(project.dependencies.gradleTestKit()) - - implementation(project.dependencies.testFixtures(project())) - - implementation(project.dependencies.platform(libs.kotlinx.serialization.bom)) - implementation(libs.kotlinx.serialization.json) - } - - targets.configureEach { - testTask.configure { - val projectTestTempDirPath = "$buildDir_/test-temp-dir" - inputs.property("projectTestTempDir", projectTestTempDirPath) - systemProperty("projectTestTempDir", projectTestTempDirPath) - - when (testType.get()) { - TestSuiteType.FUNCTIONAL_TEST, - TestSuiteType.INTEGRATION_TEST -> { - dependsOn(tasks.matching { it.name == "publishAllPublicationsToTestRepository" }) - - systemProperties( - "testMavenRepoDir" to file(mavenPublishTest.testMavenRepo).canonicalPath, - ) - - // depend on the test-publication task, but not the test-maven repo - // (otherwise this task will never be up-to-date) - dependsOn(tasks.publishToTestMavenRepo) - } - } - } - } - } - - - /** Unit tests suite */ - val test by getting(JvmTestSuite::class) { - description = "Standard unit tests" - } - - - /** Functional tests suite */ - val testFunctional by registering(JvmTestSuite::class) { - description = "Tests that use Gradle TestKit to test functionality" - testType.set(TestSuiteType.FUNCTIONAL_TEST) - - targets.all { - testTask.configure { - shouldRunAfter(test) - } - } - } - - tasks.check { dependsOn(test, testFunctional) } -} - skipTestFixturesPublications() -val aggregateTestReports by tasks.registering(TestReport::class) { - group = LifecycleBasePlugin.VERIFICATION_GROUP - destinationDirectory.set(layout.buildDirectory.dir("reports/tests/aggregated")) - - dependsOn(tasks.withType()) - - // hardcoded dirs is a bit of a hack, but a fileTree just didn't work - testResults.from("$buildDir_/test-results/test/binary") - testResults.from("$buildDir_/test-results/testFunctional/binary") - testResults.from("$buildDir_/test-results/testIntegration/binary") - - doLast { - logger.lifecycle("Aggregated test report: file://${destinationDirectory.asFile.get()}/index.html") - } -} - val dokkatooVersion = provider { project.version.toString() } val dokkatooConstantsProperties = objects.mapProperty().apply { diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/android-setup.gradle.kts b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/android-setup.gradle.kts deleted file mode 100644 index d1426621e7..0000000000 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/android-setup.gradle.kts +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package buildsrc.conventions - -import org.jetbrains.kotlin.util.suffixIfNot - - -/** - * Utilities for preparing Android projects - */ - -plugins { - base - id("buildsrc.conventions.base") -} - - -val androidSdkDirPath: Provider = providers - // first try getting the SDK installed on via GitHub step setup-android - .environmentVariable("ANDROID_SDK_ROOT").map(::File) - // else get the project-local SDK - .orElse(layout.projectDirectory.file("projects/ANDROID_SDK").asFile) - .map { it.invariantSeparatorsPath } - - -val createAndroidLocalPropertiesFile by tasks.registering { - - val localPropertiesFile = temporaryDir.resolve("local.properties") - outputs.file(localPropertiesFile).withPropertyName("localPropertiesFile") - - val androidSdkDirPath = androidSdkDirPath - inputs.property("androidSdkDirPath", androidSdkDirPath) - - doLast { - localPropertiesFile.apply { - parentFile.mkdirs() - createNewFile() - writeText( - """ - |# DO NOT EDIT - Generated by $path - | - |sdk.dir=${androidSdkDirPath.get()} - | - """.trimMargin() - ) - } - } -} - - -val updateAndroidLocalProperties by tasks.registering { - - // find all local.properties files - val localPropertiesFiles = layout.projectDirectory.dir("projects") - .asFileTree - .matching { include("**/local.properties") } - .files - - outputs.files(localPropertiesFiles).withPropertyName("localPropertiesFiles") - - val androidSdkDirPath = androidSdkDirPath - inputs.property("androidSdkDirPath", androidSdkDirPath) - - doLast { - localPropertiesFiles - .filter { it.exists() } - .forEach { file -> - file.writeText( - file.useLines { lines -> - lines.joinToString("\n") { line -> - when { - line.startsWith("sdk.dir=") -> "sdk.dir=${androidSdkDirPath.get()}" - else -> line - } - }.suffixIfNot("\n") - } - ) - } - } -} diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/base.gradle.kts b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/base.gradle.kts index 5e3d0f3dc0..dc9e088823 100644 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/base.gradle.kts +++ b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/base.gradle.kts @@ -4,9 +4,6 @@ package buildsrc.conventions -import java.time.Duration -import org.gradle.api.tasks.testing.logging.TestLogEvent - /** * A convention plugin that sets up common config and sensible defaults for all subprojects. */ @@ -26,134 +23,6 @@ tasks.withType().configureEach { isReproducibleFileOrder = true } -tasks.withType().configureEach { - timeout.set(Duration.ofMinutes(60)) - - testLogging { - showCauses = true - showExceptions = true - showStackTraces = true - showStandardStreams = true - events( - TestLogEvent.PASSED, - TestLogEvent.FAILED, - TestLogEvent.SKIPPED, - TestLogEvent.STARTED, - TestLogEvent.STANDARD_ERROR, - TestLogEvent.STANDARD_OUT, - ) - } -} - tasks.withType().configureEach { includeEmptyDirs = false } - -val updateTestReportCss by tasks.registering { - description = "Hack so the Gradle test reports have dark mode" - // the CSS is based on https://github.com/gradle/gradle/pull/12177 - - mustRunAfter(tasks.withType()) - mustRunAfter(tasks.withType()) - - val cssFiles = layout.buildDirectory.asFileTree.matching { - include("reports/**/css/base-style.css") - include("reports/**/css/style.css") - } - - outputs.files(cssFiles.files) - - doLast { - cssFiles.forEach { cssFile -> - val fileContent = cssFile.readText() - - if ("/* Dark mode */" in fileContent) { - return@forEach - } else { - when (cssFile.name) { - "base-style.css" -> cssFile.writeText( - fileContent + """ - - /* Dark mode */ - @media (prefers-color-scheme: dark) { - html { - background: black; - } - body, a, a:visited { - color: #E7E7E7FF; - } - #footer, #footer a { - color: #cacaca; - } - ul.tabLinks li { - border: solid 1px #cacaca; - background-color: #151515; - } - ul.tabLinks li:hover { - background-color: #383838; - } - ul.tabLinks li.selected { - background-color: #002d32; - border-color: #007987; - } - div.tab th, div.tab table { - border-bottom: solid #d0d0d0 1px; - } - span.code pre { - background-color: #0a0a0a; - border: solid 1px #5f5f5f; - } - } - """.trimIndent() - ) - - "style.css" -> cssFile.writeText( - fileContent + """ - - /* Dark mode */ - @media (prefers-color-scheme: dark) { - .breadcrumbs, .breadcrumbs a { - color: #9b9b9b; - } - #successRate, .summaryGroup { - border: solid 2px #d0d0d0; - } - .success, .success a { - color: #7fff7f; - } - div.success, #successRate.success { - background-color: #001c00; - border-color: #7fff7f; - } - .failures, .failures a { - color: #a30000; - } - .skipped, .skipped a { - color: #a26d13; - } - div.failures, #successRate.failures { - background-color: #170000; - border-color: #a30000; - } - } - """.trimIndent() - ) - } - } - } - } -} - -tasks.withType().configureEach { - finalizedBy(updateTestReportCss) -} - -tasks.withType().configureEach { - finalizedBy(updateTestReportCss) -} - -tasks.matching { it.name == "validatePlugins" }.configureEach { - // prevent warning - // Task ':validatePlugins' uses this output of task ':updateTestReportCss' without declaring an explicit or implicit dependency. - mustRunAfter(updateTestReportCss) -} diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/dokka-source-downloader.gradle.kts b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/dokka-source-downloader.gradle.kts deleted file mode 100644 index 445930c813..0000000000 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/dokka-source-downloader.gradle.kts +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package buildsrc.conventions - -import buildsrc.settings.DokkaSourceDownloaderSettings -import buildsrc.utils.asConsumer -import buildsrc.utils.asProvider -import buildsrc.utils.dropDirectories -import org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE -import org.gradle.kotlin.dsl.support.serviceOf - -plugins { - id("buildsrc.conventions.base") -} - -val dsdExt: DokkaSourceDownloaderSettings = extensions.create( - DokkaSourceDownloaderSettings.EXTENSION_NAME -) - -val kotlinDokkaSource by configurations.creating { - asConsumer() - attributes { - attribute(USAGE_ATTRIBUTE, objects.named("externals-dokka-src")) - } -} - -val kotlinDokkaSourceElements by configurations.registering { - asProvider() - attributes { - attribute(USAGE_ATTRIBUTE, objects.named("externals-dokka-src")) - } -} - -dependencies { - kotlinDokkaSource(dsdExt.dokkaVersion.map { "kotlin:dokka:$it@zip" }) -} - -val prepareDokkaSource by tasks.registering(Sync::class) { - group = "dokka setup" - description = "Download & unpack Kotlin Dokka source code" - - inputs.property("dokkaVersion", dsdExt.dokkaVersion).optional(false) - - val archives = serviceOf() - - from( - kotlinDokkaSource.incoming - .artifacts - .resolvedArtifacts - .map { artifacts -> - artifacts.map { archives.zipTree(it.file) } - } - ) { - // drop the first dir (dokka-$version) - eachFile { - relativePath = relativePath.dropDirectories(1) - } - } - - into(temporaryDir) - - exclude( - "*.github", - "*.gradle", - "**/gradlew", - "**/gradlew.bat", - "**/gradle/wrapper/gradle-wrapper.jar", - "**/gradle/wrapper/gradle-wrapper.properties", - ) -} diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/dokkatoo-example-projects-base.gradle.kts b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/dokkatoo-example-projects-base.gradle.kts deleted file mode 100644 index 7196a0aa9a..0000000000 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/dokkatoo-example-projects-base.gradle.kts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package buildsrc.conventions - -import buildsrc.utils.asConsumer -import buildsrc.utils.asProvider - -plugins { - id("buildsrc.conventions.base") -} - - -val exampleProjectsAttribute: Attribute = - Attribute.of("example-projects", String::class.java) - -dependencies.attributesSchema { - attribute(exampleProjectsAttribute) -} - - -val exampleProjects by configurations.registering { - asConsumer() - attributes { attribute(exampleProjectsAttribute, "dokka") } -} - -val exampleProjectsElements by configurations.registering { - asProvider() - attributes { attribute(exampleProjectsAttribute, "dokka") } -} diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/dokkatoo-example-projects.gradle.kts b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/dokkatoo-example-projects.gradle.kts deleted file mode 100644 index 768ae68f7a..0000000000 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/dokkatoo-example-projects.gradle.kts +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package buildsrc.conventions - -import buildsrc.settings.* -import buildsrc.tasks.* -import buildsrc.utils.* - -plugins { - id("buildsrc.conventions.base") - id("buildsrc.conventions.dokka-source-downloader") - id("buildsrc.conventions.maven-publish-test") - id("buildsrc.conventions.dokkatoo-example-projects-base") -} - -val mavenPublishTestExtension = extensions.getByType() -val dokkaTemplateProjectSettings = - extensions.create( - DokkaTemplateProjectSettings.EXTENSION_NAME, - { project.copySpec() } - ).apply { - this.destinationBaseDir.convention(layout.projectDirectory) - } - -val prepareDokkaSource by tasks.existing(Sync::class) - -dokkaTemplateProjectSettings.dokkaSourceDir.convention( - prepareDokkaSource.flatMap { - layout.dir(providers.provider { - it.destinationDir - }) - } -) - -tasks.withType().configureEach { - dependsOn(prepareDokkaSource) - - dokkaSourceDir.convention(dokkaTemplateProjectSettings.dokkaSourceDir) - destinationBaseDir.convention(dokkaTemplateProjectSettings.destinationBaseDir) - - templateProjects.addAllLater(provider { - dokkaTemplateProjectSettings.templateProjects - }) -} - -val setupDokkaTemplateProjects by tasks.registering(SetupDokkaProjects::class) - -fun createDokkatooExampleProjectsSettings( - projectDir: Directory = project.layout.projectDirectory -): DokkatooExampleProjectsSettings { - return extensions.create( - DokkatooExampleProjectsSettings.EXTENSION_NAME - ).apply { - - // find all Gradle settings files - val settingsFiles = projectDir.asFileTree - .matching { - include( - "**/*dokkatoo*/**/settings.gradle.kts", - "**/*dokkatoo*/**/settings.gradle", - ) - }.files - - // for each settings file, create a DokkatooExampleProjectSpec - settingsFiles.forEach { - val destinationDir = it.parentFile - val name = destinationDir.toRelativeString(projectDir.asFile).toAlphaNumericCamelCase() - exampleProjects.register(name) { - this.exampleProjectDir.set(destinationDir) - } - } - - exampleProjects.configureEach { - gradlePropertiesContent.add( - mavenPublishTestExtension.testMavenRepoPath.map { testMavenRepoPath -> - "testMavenRepo=$testMavenRepoPath" - } - ) - } - } -} - -val dokkatooExampleProjectsSettings = createDokkatooExampleProjectsSettings() - -val updateDokkatooExamplesGradleProperties by tasks.registering( - UpdateDokkatooExampleProjects::class -) { - group = DokkatooExampleProjectsSettings.TASK_GROUP - - mustRunAfter(tasks.withType()) - - exampleProjects.addAllLater(providers.provider { - dokkatooExampleProjectsSettings.exampleProjects - }) -} - -val dokkatooVersion = provider { project.version.toString() } - -val updateDokkatooExamplesBuildFiles by tasks.registering { - group = DokkatooExampleProjectsSettings.TASK_GROUP - description = "Update the Gradle build files in the Dokkatoo examples" - - outputs.upToDateWhen { false } - - mustRunAfter(tasks.withType()) - shouldRunAfter(updateDokkatooExamplesGradleProperties) - - val dokkatooVersion = dokkatooVersion - - val dokkatooDependencyVersionMatcher = """ - \"dev\.adamko\.dokkatoo\:dokkatoo\-plugin\:([^"]+?)\" - """.trimIndent().toRegex() - - val dokkatooPluginVersionMatcher = """ - id[^"]+?"dev\.adamko\.dokkatoo".+?version "([^"]+?)" - """.trimIndent().toRegex() - - val gradleBuildFiles = - layout.projectDirectory.asFileTree - .matching { - include( - "**/*dokkatoo*/**/build.gradle.kts", - "**/*dokkatoo*/**/build.gradle", - ) - }.elements - outputs.files(gradleBuildFiles) - - doLast { - gradleBuildFiles.get().forEach { fileLocation -> - val file = fileLocation.asFile - if (file.exists()) { - file.writeText( - file.readText() - .replace(dokkatooPluginVersionMatcher) { - val oldVersion = it.groupValues[1] - it.value.replace(oldVersion, dokkatooVersion.get()) - } - .replace(dokkatooDependencyVersionMatcher) { - val oldVersion = it.groupValues[1] - it.value.replace(oldVersion, dokkatooVersion.get()) - } - ) - } - } - } -} - - -val updateDokkatooExamples by tasks.registering { - group = DokkatooExampleProjectsSettings.TASK_GROUP - description = "lifecycle task for all '${DokkatooExampleProjectsSettings.TASK_GROUP}' tasks" - dependsOn( - setupDokkaTemplateProjects, - updateDokkatooExamplesGradleProperties, - updateDokkatooExamplesBuildFiles, - ) -} - -tasks.assemble { - dependsOn(updateDokkatooExamples) - dependsOn(setupDokkaTemplateProjects) -} diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/gradle-plugin-variants.gradle.kts b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/gradle-plugin-variants.gradle.kts deleted file mode 100644 index c8231c5ba4..0000000000 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/gradle-plugin-variants.gradle.kts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package buildsrc.conventions - -import org.gradle.api.attributes.plugin.GradlePluginApiVersion.GRADLE_PLUGIN_API_VERSION_ATTRIBUTE - -plugins { - id("buildsrc.conventions.base") - `java-gradle-plugin` -} - -fun registerGradleVariant(name: String, gradleVersion: String) { - val variantSources = sourceSets.create(name) - - java { - registerFeature(variantSources.name) { - usingSourceSet(variantSources) - capability("${project.group}", "${project.name}", "${project.version}") - - withJavadocJar() - withSourcesJar() - } - } - - configurations - .matching { it.isCanBeConsumed && it.name.startsWith(variantSources.name) } - .configureEach { - attributes { - attribute(GRADLE_PLUGIN_API_VERSION_ATTRIBUTE, objects.named(gradleVersion)) - } - } - - tasks.named(variantSources.processResourcesTaskName) { - val copyPluginDescriptors = rootSpec.addChild() - copyPluginDescriptors.into("META-INF/gradle-plugins") -// copyPluginDescriptors.into(tasks.pluginDescriptors.flatMap { it.outputDirectory }) - copyPluginDescriptors.from(tasks.pluginDescriptors) - } - - dependencies { - add(variantSources.compileOnlyConfigurationName, gradleApi()) - } -} - -registerGradleVariant("gradle7", "7.6") -registerGradleVariant("gradle8", "8.0") diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/java-base.gradle.kts b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/java-base.gradle.kts index 9dae3a3b7d..b11812b1d4 100644 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/java-base.gradle.kts +++ b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/java-base.gradle.kts @@ -4,12 +4,6 @@ package buildsrc.conventions -import org.gradle.api.JavaVersion -import org.gradle.api.plugins.JavaPluginExtension -import org.gradle.jvm.toolchain.JavaLanguageVersion -import org.gradle.kotlin.dsl.getByType -import org.gradle.kotlin.dsl.`java-base` - plugins { id("buildsrc.conventions.base") `java` diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/maven-publish-test.gradle.kts b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/maven-publish-test.gradle.kts deleted file mode 100644 index baa1073b9b..0000000000 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/maven-publish-test.gradle.kts +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package buildsrc.conventions - -import buildsrc.settings.MavenPublishTestSettings -import buildsrc.utils.* - - -/** Utility for publishing a project to a local Maven directory for use in integration tests. */ - -plugins { - base -} - -val Gradle.rootGradle: Gradle get() = generateSequence(gradle) { it.parent }.last() - -val mavenPublishTestExtension = extensions.create( - "mavenPublishTest", - gradle.rootGradle.rootProject.layout.buildDirectory.dir("test-maven-repo"), -) - - -val publishToTestMavenRepo by tasks.registering { - group = PublishingPlugin.PUBLISH_TASK_GROUP - description = "Publishes all Maven publications to the test Maven repository." -} - - -plugins.withType().all { - extensions - .getByType() - .publications - .withType().all publication@{ - val publicationName = this@publication.name - val installTaskName = "publish${publicationName.uppercaseFirstChar()}PublicationToTestMavenRepo" - - // Register a publication task for each publication. - // Use PublishToMavenLocal, because the PublishToMavenRepository task will *always* create - // a new jar, even if nothing has changed, and append a timestamp, which results in a large - // directory and tasks are never up-to-date. - // PublishToMavenLocal does not append a timestamp, so the target directory is smaller, and - // up-to-date checks work. - val installTask = tasks.register(installTaskName) { - description = "Publishes Maven publication '$publicationName' to the test Maven repository." - group = PublishingPlugin.PUBLISH_TASK_GROUP - outputs.cacheIf { true } - publication = this@publication - val destinationDir = mavenPublishTestExtension.testMavenRepo.get().asFile - inputs.property("testMavenRepoTempDir", destinationDir.invariantSeparatorsPath) - doFirst { - /** - * `maven.repo.local` will set the destination directory for this [PublishToMavenLocal] task. - * - * @see org.gradle.api.internal.artifacts.mvnsettings.DefaultLocalMavenRepositoryLocator.getLocalMavenRepository - */ - System.setProperty("maven.repo.local", destinationDir.absolutePath) - } - } - - publishToTestMavenRepo.configure { - dependsOn(installTask) - } - - tasks.check { - mustRunAfter(installTask) - } - } -} - - -val testMavenPublication by configurations.registering { - asConsumer() - attributes { - attribute(MavenPublishTestSettings.attribute, "testMavenRepo") - } -} - -val testMavenPublicationElements by configurations.registering { - asProvider() - extendsFrom(testMavenPublication.get()) - attributes { - attribute(MavenPublishTestSettings.attribute, "testMavenRepo") - } - outgoing { - artifact(mavenPublishTestExtension.testMavenRepo) { - builtBy(publishToTestMavenRepo) - } - } -} - -dependencies { - attributesSchema { - attribute(MavenPublishTestSettings.attribute) - } -} diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/maven-publishing.gradle.kts b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/maven-publishing.gradle.kts deleted file mode 100644 index 5ad6982631..0000000000 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/conventions/maven-publishing.gradle.kts +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package buildsrc.conventions - -import buildsrc.settings.MavenPublishingSettings - -plugins { - `maven-publish` - signing -} - -val mavenPublishing = - extensions.create(MavenPublishingSettings.EXTENSION_NAME, project) - - -//region POM convention -publishing { - publications.withType().configureEach { - pom { - name.convention("Dokkatoo") - description.convention("Dokkatoo is a Gradle plugin that generates documentation for your Kotlin projects") - url.convention("https://github.com/adamko-dev/dokkatoo") - - scm { - connection.convention("scm:git:https://github.com/adamko-dev/dokkatoo") - developerConnection.convention("scm:git:https://github.com/adamko-dev/dokkatoo") - url.convention("https://github.com/adamko-dev/dokkatoo") - } - - licenses { - license { - name.convention("Apache-2.0") - url.convention("https://www.apache.org/licenses/LICENSE-2.0.txt") - } - } - - developers { - developer { - email.set("adam@adamko.dev") - } - } - } - } -} -//endregion - - -//region GitHub branch publishing -publishing { - repositories { - maven(mavenPublishing.githubPublishDir) { - name = "GitHubPublish" - } - } -} -//endregion - - -//region Maven Central publishing/signing -publishing { - repositories { - val mavenCentralUsername = mavenPublishing.mavenCentralUsername.orNull - val mavenCentralPassword = mavenPublishing.mavenCentralPassword.orNull - if (!mavenCentralUsername.isNullOrBlank() && !mavenCentralPassword.isNullOrBlank()) { - maven(mavenPublishing.sonatypeReleaseUrl) { - name = "SonatypeRelease" - credentials { - username = mavenCentralUsername - password = mavenCentralPassword - } - } - } - } - - // com.gradle.plugin-publish automatically adds a Javadoc jar -} - -signing { - logger.info("maven-publishing.gradle.kts enabled signing for ${project.path}") - - val keyId = mavenPublishing.signingKeyId.orNull - val key = mavenPublishing.signingKey.orNull - val password = mavenPublishing.signingPassword.orNull - - if (!keyId.isNullOrBlank() && !key.isNullOrBlank() && !password.isNullOrBlank()) { - useInMemoryPgpKeys(keyId, key, password) - } - - setRequired({ - gradle.taskGraph.allTasks.filterIsInstance().any { - it.repository.name == "SonatypeRelease" - } - }) -} - -//afterEvaluate { -// com.gradle.plugin-publish automatically signs tasks in a weird way, that stops this from working: -// signing { -// sign(publishing.publications) -// } -//} -//endregion - - -//region Fix Gradle warning about signing tasks using publishing task outputs without explicit dependencies -// https://youtrack.jetbrains.com/issue/KT-46466 https://github.com/gradle/gradle/issues/26091 -tasks.withType().configureEach { - val signingTasks = tasks.withType() - mustRunAfter(signingTasks) -} -//endregion - - -//region publishing logging -tasks.withType().configureEach { - val publicationGAV = provider { publication?.run { "$group:$artifactId:$version" } } - doLast("log publication GAV") { - if (publicationGAV.isPresent) { - logger.lifecycle("[task: ${path}] ${publicationGAV.get()}") - } - } -} -//endregion - - -//region IJ workarounds -// manually define the Kotlin DSL accessors because IntelliJ _still_ doesn't load them properly -fun Project.publishing(configure: PublishingExtension.() -> Unit): Unit = - extensions.configure(configure) - -val Project.publishing: PublishingExtension - get() = extensions.getByType() - -fun Project.signing(configure: SigningExtension.() -> Unit): Unit = - extensions.configure(configure) - -val Project.signing: SigningExtension - get() = extensions.getByType() -//endregion diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/settings/DokkaSourceDownloaderSettings.kt b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/settings/DokkaSourceDownloaderSettings.kt deleted file mode 100644 index 51c8b46301..0000000000 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/settings/DokkaSourceDownloaderSettings.kt +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package buildsrc.settings - -import org.gradle.api.plugins.ExtensionAware -import org.gradle.api.provider.Property - -abstract class DokkaSourceDownloaderSettings : ExtensionAware { - - abstract val dokkaVersion: Property - - companion object { - const val EXTENSION_NAME = "dokkaSourceDownload" - } -} diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/settings/DokkaTemplateProjectSettings.kt b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/settings/DokkaTemplateProjectSettings.kt deleted file mode 100644 index 046dc0e437..0000000000 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/settings/DokkaTemplateProjectSettings.kt +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package buildsrc.settings - -import buildsrc.utils.adding -import buildsrc.utils.domainObjectContainer -import buildsrc.utils.toAlphaNumericCamelCase -import javax.inject.Inject -import org.gradle.api.Named -import org.gradle.api.NamedDomainObjectContainer -import org.gradle.api.file.ConfigurableFileCollection -import org.gradle.api.file.CopySpec -import org.gradle.api.file.DirectoryProperty -import org.gradle.api.model.ObjectFactory -import org.gradle.api.plugins.ExtensionAware -import org.gradle.api.provider.Property -import org.gradle.api.provider.SetProperty -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.InputFiles -import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.Optional -import org.gradle.kotlin.dsl.* - -private typealias TemplateProjectsContainer = NamedDomainObjectContainer - -abstract class DokkaTemplateProjectSettings @Inject constructor( - private val objects: ObjectFactory, - private val copySpecs: () -> CopySpec -) : ExtensionAware { - - /** Directory that will contain the projects downloaded from the Dokka source code. */ - abstract val dokkaSourceDir: DirectoryProperty - - abstract val destinationBaseDir: DirectoryProperty - - internal val templateProjects: TemplateProjectsContainer = - // create an extension so Gradle will generate DSL accessors - extensions.adding("templateProjects", objects.domainObjectContainer { name -> - objects.newInstance(name, copySpecs()) - }) - - /** - * Copy a directory from the Dokka source project into a local directory. - * - * @param[source] Source dir, relative to [templateProjectsDir] - * @param[destination] Destination dir, relative to [destinationBaseDir] - */ - fun register( - source: String, - destination: String, - configure: DokkaTemplateProjectSpec.() -> Unit = {}, - ) { - val name = source.toAlphaNumericCamelCase() - templateProjects.register(name) { - this.sourcePath.set(source) - this.destinationPath.set(destination) - configure() - } - } - - fun configureEach(configure: DokkaTemplateProjectSpec.() -> Unit) { - templateProjects.configureEach(configure) - } - - /** - * Details for how to copy a Dokka template project from the Dokka project to a local directory. - */ - abstract class DokkaTemplateProjectSpec @Inject constructor( - private val named: String, - @get:Internal - internal val copySpec: CopySpec, - ) : Named { - - @get:Input - abstract val sourcePath: Property - - @get:Input - @get:Optional - abstract val destinationPath: Property - - @get:Input - abstract val additionalPaths: SetProperty - - @get:InputFiles - abstract val additionalFiles: ConfigurableFileCollection - - fun configureCopy(configure: CopySpec.() -> Unit) { - copySpec.configure() - } - - @Input - override fun getName(): String = named - } - - companion object { - const val EXTENSION_NAME = "dokkaTemplateProjects" - } -} diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/settings/DokkatooExampleProjectsSettings.kt b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/settings/DokkatooExampleProjectsSettings.kt deleted file mode 100644 index d2b2c73f28..0000000000 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/settings/DokkatooExampleProjectsSettings.kt +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package buildsrc.settings - -import buildsrc.utils.adding -import buildsrc.utils.domainObjectContainer -import javax.inject.Inject -import org.gradle.api.Named -import org.gradle.api.NamedDomainObjectContainer -import org.gradle.api.file.DirectoryProperty -import org.gradle.api.file.RegularFile -import org.gradle.api.model.ObjectFactory -import org.gradle.api.plugins.ExtensionAware -import org.gradle.api.provider.ListProperty -import org.gradle.api.provider.Provider -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.Optional -import org.gradle.api.tasks.OutputFile - -/** - * Settings for the [buildsrc.conventions.Dokkatoo_example_projects_gradle] convention plugin - */ -abstract class DokkatooExampleProjectsSettings @Inject constructor( - objects: ObjectFactory, -) : ExtensionAware { - - val exampleProjects: NamedDomainObjectContainer = - // create an extension so Gradle will generate DSL accessors - extensions.adding("exampleProjects", objects.domainObjectContainer()) - - abstract class DokkatooExampleProjectSpec( - private val name: String - ) : Named { - - /** The `gradle.properties` file of the example project */ - @get:OutputFile - val gradlePropertiesFile: Provider - get() = exampleProjectDir.file("gradle.properties") - - /** The directory that contains the example project */ - @get:Internal - abstract val exampleProjectDir: DirectoryProperty - - /** - * Content to add to the `gradle.properties` file. - * - * Elements may span multiple lines. - * - * Elements will be sorted before appending to the file (to improve caching & reproducibility). - */ - @get:Input - @get:Optional - abstract val gradlePropertiesContent: ListProperty - - @Input - override fun getName(): String = name - } - - companion object { - const val TASK_GROUP = "dokkatoo examples" - const val EXTENSION_NAME = "dokkatooExampleProjects" - } -} diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/settings/MavenPublishTestSettings.kt b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/settings/MavenPublishTestSettings.kt deleted file mode 100644 index d9169480b2..0000000000 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/settings/MavenPublishTestSettings.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package buildsrc.settings - -import org.gradle.api.attributes.Attribute -import org.gradle.api.file.Directory -import org.gradle.api.plugins.ExtensionAware -import org.gradle.api.provider.Provider - -/** - * Settings for the [buildsrc.conventions.Maven_publish_test_gradle] convention plugin. - */ -abstract class MavenPublishTestSettings( - val testMavenRepo: Provider -) : ExtensionAware { - val testMavenRepoPath: Provider = testMavenRepo.map { it.asFile.invariantSeparatorsPath } - - companion object { - val attribute = Attribute.of("maven-publish-test", String::class.java) - } -} diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/settings/MavenPublishingSettings.kt b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/settings/MavenPublishingSettings.kt deleted file mode 100644 index de2026aac8..0000000000 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/settings/MavenPublishingSettings.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package buildsrc.settings - -import java.io.File -import javax.inject.Inject -import org.gradle.api.Project -import org.gradle.api.provider.Provider -import org.gradle.api.provider.ProviderFactory -import org.gradle.kotlin.dsl.* - - -/** - * Settings for the [buildsrc.conventions.Maven_publish_test_gradle] convention plugin. - */ -abstract class MavenPublishingSettings @Inject constructor( - private val project: Project, - private val providers: ProviderFactory, -) { - - private val isReleaseVersion: Provider = - providers.provider { !project.version.toString().endsWith("-SNAPSHOT") } - - val sonatypeReleaseUrl: Provider = - isReleaseVersion.map { isRelease -> - if (isRelease) { - "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/" - } else { - "https://s01.oss.sonatype.org/content/repositories/snapshots/" - } - } - - val mavenCentralUsername: Provider = - d2Prop("mavenCentralUsername") - .orElse(providers.environmentVariable("MAVEN_SONATYPE_USERNAME")) - val mavenCentralPassword: Provider = - d2Prop("mavenCentralPassword") - .orElse(providers.environmentVariable("MAVEN_SONATYPE_PASSWORD")) - - val signingKeyId: Provider = - d2Prop("signing.keyId") - .orElse(providers.environmentVariable("MAVEN_SONATYPE_SIGNING_KEY_ID")) - val signingKey: Provider = - d2Prop("signing.key") - .orElse(providers.environmentVariable("MAVEN_SONATYPE_SIGNING_KEY")) - val signingPassword: Provider = - d2Prop("signing.password") - .orElse(providers.environmentVariable("MAVEN_SONATYPE_SIGNING_PASSWORD")) - - val githubPublishDir: Provider = - providers.environmentVariable("GITHUB_PUBLISH_DIR").map { File(it) } - - private fun d2Prop(name: String): Provider = - providers.gradleProperty("org.jetbrains.dokka.dokkatoo.$name") - - private fun d2Prop(name: String, convert: (String) -> T): Provider = - d2Prop(name).map(convert) - - companion object { - const val EXTENSION_NAME = "mavenPublishing" - - /** Retrieve the [KayrayBuildProperties] extension. */ - internal val Project.mavenPublishing: MavenPublishingSettings - get() = extensions.getByType() - - /** Configure the [KayrayBuildProperties] extension. */ - internal fun Project.mavenPublishing(configure: MavenPublishingSettings.() -> Unit) = - extensions.configure(configure) - } -} diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/tasks/SetupDokkaProjects.kt b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/tasks/SetupDokkaProjects.kt deleted file mode 100644 index 3ba48c1241..0000000000 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/tasks/SetupDokkaProjects.kt +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package buildsrc.tasks - -import buildsrc.settings.DokkaTemplateProjectSettings.DokkaTemplateProjectSpec -import javax.inject.Inject -import org.gradle.api.DefaultTask -import org.gradle.api.NamedDomainObjectContainer -import org.gradle.api.file.DirectoryProperty -import org.gradle.api.file.FileCollection -import org.gradle.api.file.FileSystemOperations -import org.gradle.api.file.ProjectLayout -import org.gradle.api.provider.ProviderFactory -import org.gradle.api.tasks.* - -abstract class SetupDokkaProjects @Inject constructor( - private val fs: FileSystemOperations, - private val layout: ProjectLayout, - private val providers: ProviderFactory, -) : DefaultTask() { - - @get:OutputDirectories - val destinationDirs: FileCollection - get() = layout.files( - destinationBaseDir.map { base -> - templateProjects.map { spec -> base.dir(spec.destinationPath) } - } - ) - - @get:Internal // tracked by destinationDirs - abstract val destinationBaseDir: DirectoryProperty - - @get:Nested - abstract val templateProjects: NamedDomainObjectContainer - - @get:InputDirectory - abstract val dokkaSourceDir: DirectoryProperty - - @get:InputFiles - val additionalFiles: FileCollection - get() = layout.files( - providers.provider { - templateProjects.map { it.additionalFiles } - } - ) - - init { - group = "dokka examples" - } - - @TaskAction - internal fun action() { - val dokkaSourceDir = dokkaSourceDir.get() - val destinationBaseDir = destinationBaseDir.get() - val templateProjects = templateProjects.filter { it.destinationPath.isPresent } - - templateProjects.forEach { spec -> - fs.sync { - with(spec.copySpec) - - from(dokkaSourceDir.dir(spec.sourcePath)) - - from( - spec.additionalPaths.get().map { additionalPath -> - dokkaSourceDir.asFile.resolve(additionalPath) - } - ) - - from(spec.additionalFiles) - - into(destinationBaseDir.dir(spec.destinationPath)) - } - } - } -} diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/tasks/UpdateDokkatooExampleProjects.kt b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/tasks/UpdateDokkatooExampleProjects.kt deleted file mode 100644 index f4d7f90245..0000000000 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/tasks/UpdateDokkatooExampleProjects.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package buildsrc.tasks - -import buildsrc.settings.DokkatooExampleProjectsSettings.DokkatooExampleProjectSpec -import javax.inject.Inject -import org.gradle.api.DefaultTask -import org.gradle.api.NamedDomainObjectContainer -import org.gradle.api.model.ObjectFactory -import org.gradle.api.tasks.CacheableTask -import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.Nested -import org.gradle.api.tasks.TaskAction - -/** - * Utility for updating the `gradle.properties` of projects used in automated tests. - */ -@CacheableTask -abstract class UpdateDokkatooExampleProjects @Inject constructor( - @get:Internal - val objects: ObjectFactory -) : DefaultTask() { - - @get:Nested - abstract val exampleProjects: NamedDomainObjectContainer - - private val taskPath: String = path // renamed for clarity - - @TaskAction - fun update() { - exampleProjects.forEach { exampleProject -> - updateGradleProperties(exampleProject) - } - } - - private fun updateGradleProperties(exampleProject: DokkatooExampleProjectSpec) { - - val gradlePropertiesContent = exampleProject.gradlePropertiesContent.orNull?.sorted() ?: return - - val content = buildString { - appendLine("# DO NOT EDIT - Generated by $taskPath") - appendLine() - - gradlePropertiesContent.forEach { - appendLine(it) - } - } - - exampleProject.gradlePropertiesFile.get().asFile.writeText(content) - } -} diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/utils/gradle.kt b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/utils/gradle.kt index 608088cb10..d66da929f2 100644 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/utils/gradle.kt +++ b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/utils/gradle.kt @@ -4,69 +4,9 @@ package buildsrc.utils -import java.io.File -import org.gradle.api.NamedDomainObjectContainer -import org.gradle.api.NamedDomainObjectFactory import org.gradle.api.Project -import org.gradle.api.artifacts.Configuration import org.gradle.api.component.AdhocComponentWithVariants -import org.gradle.api.file.RelativePath -import org.gradle.api.model.ObjectFactory -import org.gradle.api.plugins.ExtensionContainer -import org.gradle.kotlin.dsl.* - -/** - * Mark this [Configuration] as one that will be consumed by other subprojects. - * - * ``` - * isCanBeResolved = false - * isCanBeConsumed = true - * ``` - */ -fun Configuration.asProvider( - visible: Boolean = true -) { - isVisible = visible - isCanBeResolved = false - isCanBeConsumed = true -} - -/** - * Mark this [Configuration] as one that will consume artifacts from other subprojects (also known as 'resolving') - * - * ``` - * isCanBeResolved = true - * isCanBeConsumed = false - * ``` - * */ -fun Configuration.asConsumer( - visible: Boolean = false -) { - isVisible = visible - isCanBeResolved = true - isCanBeConsumed = false -} - - -/** Drop the first [count] directories from the path */ -fun RelativePath.dropDirectories(count: Int): RelativePath = - RelativePath(true, *segments.drop(count).toTypedArray()) - - -/** Drop the first directory from the path */ -fun RelativePath.dropDirectory(): RelativePath = - dropDirectories(1) - - -/** Drop the first directory from the path */ -fun RelativePath.dropDirectoriesWhile( - segmentPrediate: (segment: String) -> Boolean -): RelativePath = - RelativePath( - true, - *segments.dropWhile(segmentPrediate).toTypedArray(), - ) - +import org.gradle.kotlin.dsl.get /** * Don't publish test fixtures (which causes warnings when publishing) @@ -78,45 +18,3 @@ fun Project.skipTestFixturesPublications() { javaComponent.withVariantsFromConfiguration(configurations["testFixturesApiElements"]) { skip() } javaComponent.withVariantsFromConfiguration(configurations["testFixturesRuntimeElements"]) { skip() } } - - -/** - * Add an extension to the [ExtensionContainer], and return the value. - * - * Adding an extension is especially useful for improving the DSL in build scripts when [T] is a - * [NamedDomainObjectContainer]. - * Using an extension will allow Gradle to generate - * [type-safe model accessors](https://docs.gradle.org/current/userguide/kotlin_dsl.html#kotdsl:accessor_applicability) - * for added types. - * - * ([name] should match the property name. This has to be done manually. I tried using a - * delegated-property provider but then Gradle can't introspect the types properly, so it fails to - * create accessors). - */ -internal inline fun ExtensionContainer.adding( - name: String, - value: T, -): T { - add(name, value) - return value -} - -/** - * Create a new [NamedDomainObjectContainer], using - * [org.gradle.kotlin.dsl.domainObjectContainer] - * (but [T] is `reified`). - * - * @param[factory] an optional factory for creating elements - * @see org.gradle.kotlin.dsl.domainObjectContainer - */ -internal inline fun ObjectFactory.domainObjectContainer( - factory: NamedDomainObjectFactory? = null -): NamedDomainObjectContainer = - if (factory == null) { - domainObjectContainer(T::class) - } else { - domainObjectContainer(T::class, factory) - } - -/** workaround for the overly verbose replacement for the deprecated [Project.getBuildDir] property */ -val Project.buildDir_: File get() = layout.buildDirectory.get().asFile diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/utils/intellij.kt b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/utils/intellij.kt deleted file mode 100644 index ef7ad8f29b..0000000000 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/utils/intellij.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package buildsrc.utils - -import org.gradle.api.Project -import org.gradle.api.file.ProjectLayout -import org.gradle.plugins.ide.idea.model.IdeaModule - - -/** exclude generated Gradle code, so it doesn't clog up search results */ -fun IdeaModule.excludeGeneratedGradleDsl(layout: ProjectLayout) { - - val generatedSrcDirs = listOf( - "kotlin-dsl-accessors", - "kotlin-dsl-external-plugin-spec-builders", - "kotlin-dsl-plugins", - ) - - excludeDirs.addAll( - layout.projectDirectory.asFile.walk() - .filter { it.isDirectory && it.parentFile.name in generatedSrcDirs } - .flatMap { file -> - file.walk().maxDepth(1).filter { it.isDirectory }.toList() - } - ) -} - - -/** Sets a logo for project IDEs */ -fun Project.initIdeProjectLogo( - svgLogoPath: String -) { - val logoSvg = rootProject.layout.projectDirectory.file(svgLogoPath) - val ideaDir = rootProject.layout.projectDirectory.dir(".idea") - - if ( - logoSvg.asFile.exists() - && ideaDir.asFile.exists() - && !ideaDir.file("icon.png").asFile.exists() - && !ideaDir.file("icon.svg").asFile.exists() - ) { - copy { - from(logoSvg) { rename { "icon.svg" } } - into(ideaDir) - } - } -} diff --git a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/utils/strings.kt b/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/utils/strings.kt deleted file mode 100644 index 53ad330cec..0000000000 --- a/dokka-runners/gradle-plugin/buildSrc/src/main/kotlin/buildsrc/utils/strings.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package buildsrc.utils - - -/** Title case the first char of a string */ -internal fun String.uppercaseFirstChar(): String = mapFirstChar(Character::toTitleCase) - - -/** Lowercase the first char of a string */ -internal fun String.lowercaseFirstChar(): String = mapFirstChar(Character::toLowerCase) - - -private inline fun String.mapFirstChar( - transform: (Char) -> Char -): String = if (isNotEmpty()) transform(this[0]) + substring(1) else this - - -/** - * Exclude all non-alphanumeric characters and converts the result into a camelCase string. - */ -internal fun String.toAlphaNumericCamelCase(): String = - map { if (it.isLetterOrDigit()) it else ' ' } - .joinToString("") - .split(" ") - .filter { it.isNotBlank() } - .joinToString("") { it.uppercaseFirstChar() } - .lowercaseFirstChar() diff --git a/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/DokkatooPluginTest.kt b/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/DokkatooPluginTest.kt deleted file mode 100644 index e811d7b2c7..0000000000 --- a/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/DokkatooPluginTest.kt +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo - -import io.kotest.core.spec.style.FunSpec -import io.kotest.matchers.shouldBe -import io.kotest.matchers.string.shouldEndWith -import org.gradle.kotlin.dsl.apply -import org.gradle.kotlin.dsl.getByType -import org.gradle.kotlin.dsl.hasPlugin -import org.gradle.testfixtures.ProjectBuilder -import org.jetbrains.dokka.dokkatoo.utils.create_ - -class DokkatooPluginTest : FunSpec({ - - test("expect plugin id can be applied to project successfully") { - val project = ProjectBuilder.builder().build() - project.plugins.apply("org.jetbrains.dokka.dokkatoo") - project.plugins.hasPlugin("org.jetbrains.dokka.dokkatoo") shouldBe true - project.plugins.hasPlugin(DokkatooPlugin::class) shouldBe true - } - - test("expect plugin class can be applied to project successfully") { - val project = ProjectBuilder.builder().build() - project.plugins.apply(type = DokkatooPlugin::class) - project.plugins.hasPlugin("org.jetbrains.dokka.dokkatoo") shouldBe true - project.plugins.hasPlugin(DokkatooPlugin::class) shouldBe true - } - - context("Dokkatoo property conventions") { - val project = ProjectBuilder.builder().build() - project.plugins.apply("org.jetbrains.dokka.dokkatoo") - - val extension = project.extensions.getByType() - - context("DokkatooSourceSets") { - val testSourceSet = extension.dokkatooSourceSets.create_("Test") { - externalDocumentationLinks.create_("gradle") { - url("https://docs.gradle.org/7.6.1/javadoc") - } - } - - context("JDK external documentation link") { - val jdkLink = testSourceSet.externalDocumentationLinks.getByName("jdk") - - test("when enableJdkDocumentationLink is false, expect jdk link is disabled") { - testSourceSet.enableJdkDocumentationLink.set(false) - jdkLink.enabled.get() shouldBe false - } - - test("when enableJdkDocumentationLink is true, expect jdk link is enabled") { - testSourceSet.enableJdkDocumentationLink.set(true) - jdkLink.enabled.get() shouldBe true - } - - (5..10).forEach { jdkVersion -> - test("when jdkVersion is $jdkVersion, expect packageListUrl uses package-list file") { - testSourceSet.jdkVersion.set(jdkVersion) - jdkLink.packageListUrl.get().toString() shouldEndWith "package-list" - } - } - - (11..22).forEach { jdkVersion -> - test("when jdkVersion is $jdkVersion, expect packageListUrl uses element-list file") { - testSourceSet.jdkVersion.set(jdkVersion) - jdkLink.packageListUrl.get().toString() shouldEndWith "element-list" - } - } - } - - context("external doc links") { - test("package-list url should be appended to Javadoc URL") { - val gradleDocLink = testSourceSet.externalDocumentationLinks.getByName("gradle") - gradleDocLink.packageListUrl.get() - .toString() shouldBe "https://docs.gradle.org/7.6.1/javadoc/package-list" - } - } - } - } -}) diff --git a/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/DokkaExternalDocumentationLinkSpecTest.kt b/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/DokkaExternalDocumentationLinkSpecTest.kt deleted file mode 100644 index 574bf63c55..0000000000 --- a/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/DokkaExternalDocumentationLinkSpecTest.kt +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.dokka.parameters - -import io.kotest.core.spec.style.FunSpec -import io.kotest.datatest.WithDataTestName -import io.kotest.datatest.withData -import io.kotest.matchers.shouldBe -import org.gradle.kotlin.dsl.apply -import org.gradle.kotlin.dsl.getByType -import org.gradle.testfixtures.ProjectBuilder -import org.jetbrains.dokka.dokkatoo.DokkatooExtension -import org.jetbrains.dokka.dokkatoo.DokkatooPlugin -import org.jetbrains.dokka.dokkatoo.utils.create_ - - -class DokkaExternalDocumentationLinkSpecTest : FunSpec({ - - context("expect url can be set") { - test("using a string") { - val actual = createExternalDocLinkSpec { - url("https://github.com/adamko-dev/dokkatoo/") - } - - actual.url.get().toString() shouldBe "https://github.com/adamko-dev/dokkatoo/" - } - - test("using a string-provider") { - val actual = createExternalDocLinkSpec { - url(project.provider { "https://github.com/adamko-dev/dokkatoo/" }) - } - - actual.url.get().toString() shouldBe "https://github.com/adamko-dev/dokkatoo/" - } - } - - context("expect packageListUrl can be set") { - test("using a string") { - val actual = createExternalDocLinkSpec { - packageListUrl("https://github.com/adamko-dev/dokkatoo/") - } - - actual.packageListUrl.get().toString() shouldBe "https://github.com/adamko-dev/dokkatoo/" - } - - test("using a string-provider") { - val actual = createExternalDocLinkSpec { - packageListUrl(project.provider { "https://github.com/adamko-dev/dokkatoo/" }) - } - - actual.packageListUrl.get().toString() shouldBe "https://github.com/adamko-dev/dokkatoo/" - } - } - - context("expect packageList defaults to url+package-list") { - data class TestCase( - val actualUrl: String, - val expected: String, - val testName: String, - ) : WithDataTestName { - override fun dataTestName(): String = testName - } - - withData( - TestCase( - testName = "non-empty path, with trailing slash", - actualUrl = "https://github.com/adamko-dev/dokkatoo/", - expected = "https://github.com/adamko-dev/dokkatoo/package-list", - ), - TestCase( - testName = "non-empty path, without trailing slash", - actualUrl = "https://github.com/adamko-dev/dokkatoo", - expected = "https://github.com/adamko-dev/dokkatoo/package-list", - ), - TestCase( - testName = "empty path, with trailing slash", - actualUrl = "https://github.com/", - expected = "https://github.com/package-list", - ), - TestCase( - testName = "empty path, without trailing slash", - actualUrl = "https://github.com", - expected = "https://github.com/package-list", - ) - ) { (actualUrl, expected) -> - val actual = createExternalDocLinkSpec { url(actualUrl) } - actual.packageListUrl.get().toString() shouldBe expected - } - } -}) - -private val project = ProjectBuilder.builder().build().also { project -> - project.plugins.apply(type = DokkatooPlugin::class) -} - -private fun createExternalDocLinkSpec( - configure: DokkaExternalDocumentationLinkSpec.() -> Unit -): DokkaExternalDocumentationLinkSpec { - - val dssContainer = project.extensions.getByType().dokkatooSourceSets - - return dssContainer.create_("test" + dssContainer.size) - .externalDocumentationLinks - .create("testLink", configure) -} diff --git a/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/DokkaSourceLinkSpecTest.kt b/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/DokkaSourceLinkSpecTest.kt deleted file mode 100644 index f6638f9480..0000000000 --- a/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/DokkaSourceLinkSpecTest.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.dokka.parameters - -import io.kotest.core.spec.style.FunSpec -import io.kotest.engine.spec.tempdir -import io.kotest.matchers.shouldBe -import org.gradle.api.Project -import org.gradle.api.provider.Provider -import org.gradle.kotlin.dsl.newInstance -import org.gradle.testfixtures.ProjectBuilder - -class DokkaSourceLinkSpecTest : FunSpec({ - val project = ProjectBuilder.builder().build() - - context("expect localDirectoryPath") { - test("is the invariantSeparatorsPath of localDirectory") { - val tempDir = tempdir() - - val actual = project.createDokkaSourceLinkSpec { - localDirectory.set(tempDir) - } - - actual.localDirectoryPath2.get() shouldBe tempDir.invariantSeparatorsPath - } - } - - - context("expect remoteUrl can be set") { - test("using a string") { - val actual = project.createDokkaSourceLinkSpec { - remoteUrl("https://github.com/adamko-dev/dokkatoo/") - } - - actual.remoteUrl.get().toString() shouldBe "https://github.com/adamko-dev/dokkatoo/" - } - - test("using a string-provider") { - val actual = project.createDokkaSourceLinkSpec { - remoteUrl(project.provider { "https://github.com/adamko-dev/dokkatoo/" }) - } - - actual.remoteUrl.get().toString() shouldBe "https://github.com/adamko-dev/dokkatoo/" - } - } -}) { - - /** Re-implement [DokkaSourceLinkSpec] to make [localDirectoryPath] accessible in tests */ - abstract class DokkaSourceLinkSpec2 : DokkaSourceLinkSpec() { - val localDirectoryPath2: Provider - get() = super.localDirectoryPath - } - - companion object { - private fun Project.createDokkaSourceLinkSpec( - configure: DokkaSourceLinkSpec.() -> Unit - ): DokkaSourceLinkSpec2 = - objects.newInstance(DokkaSourceLinkSpec2::class).apply(configure) - } -} diff --git a/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/KotlinPlatformTest.kt b/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/KotlinPlatformTest.kt deleted file mode 100644 index be24d0aa28..0000000000 --- a/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/KotlinPlatformTest.kt +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.dokka.parameters - -import io.kotest.core.spec.style.FunSpec -import io.kotest.inspectors.shouldForAll -import io.kotest.matchers.collections.shouldBeIn -import io.kotest.matchers.shouldBe -import org.jetbrains.dokka.Platform -import org.jetbrains.dokka.dokkatoo.dokka.parameters.KotlinPlatform.Companion.dokkaType - -class KotlinPlatformTest : FunSpec({ - - test("should have same default as Dokka type") { - KotlinPlatform.DEFAULT.dokkaType shouldBe Platform.DEFAULT - } - - test("Dokka platform should have equivalent KotlinPlatform") { - - Platform.values().shouldForAll { dokkaPlatform -> - dokkaPlatform shouldBeIn KotlinPlatform.values.map { it.dokkaType } - } - } - - test("platform strings should map to same KotlinPlatform and Platform") { - listOf( - "androidJvm", - "android", - "metadata", - "jvm", - "js", - "wasm", - "native", - "common", - ).shouldForAll { - Platform.fromString(it) shouldBe KotlinPlatform.fromString(it).dokkaType - } - } -}) diff --git a/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/VisibilityModifierTest.kt b/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/VisibilityModifierTest.kt deleted file mode 100644 index 84d15b042d..0000000000 --- a/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/VisibilityModifierTest.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.dokka.parameters - -import io.kotest.core.spec.style.FunSpec -import io.kotest.inspectors.shouldForAll -import io.kotest.inspectors.shouldForOne -import io.kotest.matchers.shouldBe -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.dokkatoo.dokka.parameters.VisibilityModifier.Companion.dokkaType - -class VisibilityModifierTest : FunSpec({ - - test("DokkaConfiguration.Visibility should have equivalent VisibilityModifier") { - DokkaConfiguration.Visibility.values().shouldForAll { dokkaVisibility -> - VisibilityModifier.entries.map { it.dokkaType }.shouldForOne { it shouldBe dokkaVisibility } - } - } -}) diff --git a/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/builders/DokkaModuleDescriptionBuilderTest.kt b/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/builders/DokkaModuleDescriptionBuilderTest.kt deleted file mode 100644 index be4ad51edd..0000000000 --- a/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/builders/DokkaModuleDescriptionBuilderTest.kt +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.dokka.parameters.builders - -import io.kotest.core.spec.style.FunSpec - -class DokkaModuleDescriptionBuilderTest : FunSpec({ - -}) diff --git a/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/builders/DokkaParametersBuilderTest.kt b/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/builders/DokkaParametersBuilderTest.kt deleted file mode 100644 index 9a759b60ae..0000000000 --- a/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/builders/DokkaParametersBuilderTest.kt +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.dokka.parameters.builders - -import io.kotest.core.spec.style.FunSpec - -class DokkaParametersBuilderTest : FunSpec({ - -}) diff --git a/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/builders/DokkaSourceSetBuilderTest.kt b/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/builders/DokkaSourceSetBuilderTest.kt deleted file mode 100644 index 8d4575d770..0000000000 --- a/dokka-runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/dokkatoo/dokka/parameters/builders/DokkaSourceSetBuilderTest.kt +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.dokka.parameters.builders - -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.FunSpec -import io.kotest.engine.spec.tempdir -import io.kotest.inspectors.shouldForAll -import io.kotest.matchers.collections.shouldBeSingleton -import io.kotest.matchers.equals.shouldNotBeEqual -import io.kotest.matchers.shouldBe -import io.kotest.matchers.string.shouldContain -import org.gradle.api.Project -import org.gradle.api.file.Directory -import org.gradle.api.internal.provider.MissingValueException -import org.gradle.kotlin.dsl.apply -import org.gradle.kotlin.dsl.getByType -import org.gradle.testfixtures.ProjectBuilder -import org.jetbrains.dokka.dokkatoo.DokkatooExtension -import org.jetbrains.dokka.dokkatoo.DokkatooPlugin -import org.jetbrains.dokka.dokkatoo.dokka.parameters.DokkaSourceSetSpec -import org.jetbrains.dokka.dokkatoo.utils.all_ -import org.jetbrains.dokka.dokkatoo.utils.create_ -import org.jetbrains.dokka.dokkatoo.utils.shouldContainAll -import org.jetbrains.dokka.dokkatoo.utils.sourceLink_ -import java.io.File -import java.net.URI - -class DokkaSourceSetBuilderTest : FunSpec({ - - context("when building a ExternalDocumentationLinkSpec") { - val project = createProject() - - test("expect url is required") { - val sourceSetSpec = project.createDokkaSourceSetSpec("test1") { - externalDocumentationLinks.create_("TestLink") { - url.set(null as URI?) - packageListUrl("https://github.com/adamko-dev/dokkatoo/") - } - } - - val caughtException = shouldThrow { - DokkaSourceSetBuilder.buildAll(setOf(sourceSetSpec)) - } - - caughtException.message shouldContain "Cannot query the value of property 'url' because it has no value available" - } - - test("expect packageListUrl is required") { - val sourceSetSpec = project.createDokkaSourceSetSpec("test2") { - externalDocumentationLinks.create_("TestLink") { - url("https://github.com/adamko-dev/dokkatoo/") - packageListUrl.convention(null as URI?) - packageListUrl.set(null as URI?) - } - } - - val caughtException = shouldThrow { - DokkaSourceSetBuilder.buildAll(setOf(sourceSetSpec)) - } - - caughtException.message shouldContain "Cannot query the value of property 'packageListUrl' because it has no value available" - } - - test("expect null when not enabled") { - val sourceSetSpec = project.createDokkaSourceSetSpec("test3") - val linkSpec = sourceSetSpec.externalDocumentationLinks.create_("TestLink") { - url("https://github.com/adamko-dev/dokkatoo/") - packageListUrl("https://github.com/adamko-dev/dokkatoo/") - enabled.set(false) - } - - DokkaSourceSetBuilder.buildAll(setOf(sourceSetSpec)).shouldBeSingleton { sourceSet -> - sourceSet.externalDocumentationLinks.shouldForAll { link -> - link.url shouldNotBeEqual linkSpec.url.get().toURL() - link.packageListUrl shouldNotBeEqual linkSpec.packageListUrl.get().toURL() - } - } - } - } - - - context("when DokkaSourceLinkSpec is built") { - val project = createProject() - - test("expect built object contains all properties") { - val tempDir = tempdir() - - val sourceSetSpec = project.createDokkaSourceSetSpec("testAllProperties") { - sourceLink_ { - localDirectory.set(tempDir) - remoteUrl("https://github.com/adamko-dev/dokkatoo/") - remoteLineSuffix.set("%L") - } - } - - val sourceSet = DokkaSourceSetBuilder.buildAll(setOf(sourceSetSpec)).single() - - sourceSet.sourceLinks.shouldBeSingleton { sourceLink -> - sourceLink.remoteUrl shouldBe URI("https://github.com/adamko-dev/dokkatoo/").toURL() - sourceLink.localDirectory shouldBe tempDir.invariantSeparatorsPath - sourceLink.remoteLineSuffix shouldBe "%L" - } - } - - test("expect localDirectory is required") { - val sourceSetSpec = project.createDokkaSourceSetSpec("testLocalDirRequired") { - sourceLink_ { - remoteUrl("https://github.com/adamko-dev/dokkatoo/") - remoteLineSuffix.set("%L") - } - } - - sourceSetSpec.sourceLinks.all_ { - localDirectory.convention(null as Directory?) - localDirectory.set(null as File?) - } - - val caughtException = shouldThrow { - DokkaSourceSetBuilder.buildAll(setOf(sourceSetSpec)) - } - - caughtException.message.shouldContainAll( - "Cannot query the value of this provider because it has no value available", - "The value of this provider is derived from", - "property 'localDirectory'", - ) - } - - test("expect localDirectory is an invariantSeparatorsPath") { - val tempDir = tempdir() - - val sourceSetSpec = project.createDokkaSourceSetSpec("testLocalDirPath") { - sourceLink_ { - localDirectory.set(tempDir) - remoteUrl("https://github.com/adamko-dev/dokkatoo/") - remoteLineSuffix.set(null as String?) - } - } - - val link = DokkaSourceSetBuilder.buildAll(setOf(sourceSetSpec)) - .single() - .sourceLinks - .single() - - link.localDirectory shouldBe tempDir.invariantSeparatorsPath - } - - test("expect remoteUrl is required") { - val sourceSetSpec = project.createDokkaSourceSetSpec("testRemoteUrlRequired") { - sourceLink_ { - localDirectory.set(tempdir()) - remoteUrl.set(project.providers.provider { null }) - remoteLineSuffix.set("%L") - } - } - - val caughtException = shouldThrow { - DokkaSourceSetBuilder.buildAll(setOf(sourceSetSpec)) - } - - caughtException.message shouldContain "Cannot query the value of property 'remoteUrl' because it has no value available" - } - - test("expect remoteLineSuffix is optional") { - val tempDir = tempdir() - - val sourceSetSpec = project.createDokkaSourceSetSpec("testRemoteLineSuffixOptional") { - sourceLink_ { - localDirectory.set(tempDir) - remoteUrl("https://github.com/adamko-dev/dokkatoo/") - remoteLineSuffix.set(project.providers.provider { null }) - } - } - - val sourceSet = DokkaSourceSetBuilder.buildAll(setOf(sourceSetSpec)).single() - - sourceSet.sourceLinks.shouldBeSingleton { sourceLink -> - sourceLink.remoteUrl shouldBe URI("https://github.com/adamko-dev/dokkatoo/").toURL() - sourceLink.localDirectory shouldBe tempDir.invariantSeparatorsPath - sourceLink.remoteLineSuffix shouldBe null - } - } - } -}) - -private fun createProject(): Project { - val project = ProjectBuilder.builder().build() - project.plugins.apply(type = DokkatooPlugin::class) - return project -} - -private fun Project.createDokkaSourceSetSpec( - name: String, - configure: DokkaSourceSetSpec.() -> Unit = {} -): DokkaSourceSetSpec { - return extensions - .getByType() - .dokkatooSourceSets - .create_(name, configure) -} diff --git a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/GradleTestKitUtils.kt b/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/GradleTestKitUtils.kt deleted file mode 100644 index 45d76f4252..0000000000 --- a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/GradleTestKitUtils.kt +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.utils - -import java.io.File -import java.nio.file.Path -import java.nio.file.Paths -import kotlin.properties.PropertyDelegateProvider -import kotlin.properties.ReadWriteProperty -import kotlin.reflect.KProperty -import org.gradle.testkit.runner.GradleRunner -import org.intellij.lang.annotations.Language - - -// utils for testing using Gradle TestKit - - -class GradleProjectTest( - override val projectDir: Path, -) : ProjectDirectoryScope { - - constructor( - testProjectName: String, - baseDir: Path = funcTestTempDir, - ) : this(projectDir = baseDir.resolve(testProjectName)) - - val runner: GradleRunner - get() = GradleRunner.create() - .withProjectDir(projectDir.toFile()) - .withJvmArguments( - "-XX:MaxMetaspaceSize=512m", - "-XX:+AlwaysPreTouch", // https://github.com/gradle/gradle/issues/3093#issuecomment-387259298 - ).addArguments( - // disable the logging task so the tests work consistently on local machines and CI/CD - "-P" + "org.jetbrains.dokka.dokkatoo.tasks.logHtmlPublicationLinkEnabled=false" - ) - - val testMavenRepoRelativePath: String = - projectDir.relativize(testMavenRepoDir).toFile().invariantSeparatorsPath - - companion object { - - /** file-based Maven Repo that contains the Dokka dependencies */ - val testMavenRepoDir: Path by systemProperty(Paths::get) - - val projectTestTempDir: Path by systemProperty(Paths::get) - - /** Temporary directory for the functional tests */ - val funcTestTempDir: Path by lazy { - projectTestTempDir.resolve("functional-tests") - } - - /** Dokka Source directory that contains Gradle projects used for integration tests */ - val integrationTestProjectsDir: Path by systemProperty(Paths::get) - - /** Dokka Source directory that contains example Gradle projects */ - val exampleProjectsDir: Path by systemProperty(Paths::get) - } -} - - -///** -// * Load a project from the [GradleProjectTest.dokkaSrcIntegrationTestProjectsDir] -// */ -//fun gradleKtsProjectIntegrationTest( -// testProjectName: String, -// build: GradleProjectTest.() -> Unit, -//): GradleProjectTest = -// GradleProjectTest( -// baseDir = GradleProjectTest.dokkaSrcIntegrationTestProjectsDir, -// testProjectName = testProjectName, -// ).apply(build) - - -/** - * Builder for testing a Gradle project that uses Kotlin script DSL and creates default - * `settings.gradle.kts` and `gradle.properties` files. - * - * @param[testProjectName] the path of the project directory, relative to [baseDir - */ -fun gradleKtsProjectTest( - testProjectName: String, - baseDir: Path = GradleProjectTest.funcTestTempDir, - build: GradleProjectTest.() -> Unit, -): GradleProjectTest { - return GradleProjectTest(baseDir = baseDir, testProjectName = testProjectName).apply { - - settingsGradleKts = """ - |rootProject.name = "test" - | - |@Suppress("UnstableApiUsage") - |dependencyResolutionManagement { - | repositories { - | mavenCentral() - | maven(file("$testMavenRepoRelativePath")) { - | mavenContent { - | includeGroup("org.jetbrains.dokka.dokkatoo") - | includeGroup("org.jetbrains.dokka.dokkatoo-html") - | } - | } - | } - |} - | - |pluginManagement { - | repositories { - | mavenCentral() - | gradlePluginPortal() - | maven(file("$testMavenRepoRelativePath")) { - | mavenContent { - | includeGroup("org.jetbrains.dokka.dokkatoo") - | includeGroup("org.jetbrains.dokka.dokkatoo-html") - | } - | } - | } - |} - | - """.trimMargin() - - gradleProperties = """ - |kotlin.mpp.stability.nowarn=true - |org.gradle.cache=true - """.trimMargin() - - build() - } -} - -/** - * Builder for testing a Gradle project that uses Groovy script and creates default, - * `settings.gradle`, and `gradle.properties` files. - * - * @param[testProjectName] the name of the test, which should be distinct across the project - */ -fun gradleGroovyProjectTest( - testProjectName: String, - baseDir: Path = GradleProjectTest.funcTestTempDir, - build: GradleProjectTest.() -> Unit, -): GradleProjectTest { - return GradleProjectTest(baseDir = baseDir, testProjectName = testProjectName).apply { - - settingsGradle = """ - |rootProject.name = "test" - | - |dependencyResolutionManagement { - | repositories { - | mavenCentral() - | maven { url = file("$testMavenRepoRelativePath") } - | } - |} - | - |pluginManagement { - | repositories { - | mavenCentral() - | gradlePluginPortal() - | maven { url = file("$testMavenRepoRelativePath") } - | } - |} - | - """.trimMargin() - - gradleProperties = """ - |kotlin.mpp.stability.nowarn=true - |org.gradle.cache=true - """.trimMargin() - - build() - } -} - - -fun GradleProjectTest.projectFile( - @Language("TEXT") - filePath: String -): PropertyDelegateProvider> = - PropertyDelegateProvider { _, _ -> - TestProjectFileProvidedDelegate(this, filePath) - } - - -/** Delegate for reading and writing a [GradleProjectTest] file. */ -private class TestProjectFileProvidedDelegate( - private val project: GradleProjectTest, - private val filePath: String, -) : ReadWriteProperty { - override fun getValue(thisRef: Any?, property: KProperty<*>): String = - project.projectDir.resolve(filePath).toFile().readText() - - override fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { - project.createFile(filePath, value) - } -} - -/** Delegate for reading and writing a [GradleProjectTest] file. */ -class TestProjectFileDelegate( - private val filePath: String, -) : ReadWriteProperty { - override fun getValue(thisRef: ProjectDirectoryScope, property: KProperty<*>): String = - thisRef.projectDir.resolve(filePath).toFile().readText() - - override fun setValue(thisRef: ProjectDirectoryScope, property: KProperty<*>, value: String) { - thisRef.createFile(filePath, value) - } -} - - -@DslMarker -annotation class ProjectDirectoryDsl - -@ProjectDirectoryDsl -interface ProjectDirectoryScope { - val projectDir: Path -} - -private data class ProjectDirectoryScopeImpl( - override val projectDir: Path -) : ProjectDirectoryScope - - -fun ProjectDirectoryScope.createFile(filePath: String, contents: String): File = - projectDir.resolve(filePath).toFile().apply { - parentFile.mkdirs() - createNewFile() - writeText(contents) - } - - -@ProjectDirectoryDsl -fun ProjectDirectoryScope.dir( - path: String, - block: ProjectDirectoryScope.() -> Unit = {}, -): ProjectDirectoryScope = - ProjectDirectoryScopeImpl(projectDir.resolve(path)).apply(block) - - -@ProjectDirectoryDsl -fun ProjectDirectoryScope.file( - path: String -): Path = projectDir.resolve(path) - - -fun ProjectDirectoryScope.findFiles(matcher: (File) -> Boolean): Sequence = - projectDir.toFile().walk().filter(matcher) - - -/** Set the content of `settings.gradle.kts` */ -@delegate:Language("kts") -var ProjectDirectoryScope.settingsGradleKts: String by TestProjectFileDelegate("settings.gradle.kts") - - -/** Set the content of `build.gradle.kts` */ -@delegate:Language("kts") -var ProjectDirectoryScope.buildGradleKts: String by TestProjectFileDelegate("build.gradle.kts") - - -/** Set the content of `settings.gradle` */ -@delegate:Language("groovy") -var ProjectDirectoryScope.settingsGradle: String by TestProjectFileDelegate("settings.gradle") - - -/** Set the content of `build.gradle` */ -@delegate:Language("groovy") -var ProjectDirectoryScope.buildGradle: String by TestProjectFileDelegate("build.gradle") - - -/** Set the content of `gradle.properties` */ -@delegate:Language("properties") -var ProjectDirectoryScope.gradleProperties: String by TestProjectFileDelegate( - /* language=text */ "gradle.properties" -) - - -fun ProjectDirectoryScope.createKotlinFile(filePath: String, @Language("kotlin") contents: String) = - createFile(filePath, contents) - - -fun ProjectDirectoryScope.createKtsFile(filePath: String, @Language("kts") contents: String) = - createFile(filePath, contents) diff --git a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/KotestProjectConfig.kt b/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/KotestProjectConfig.kt deleted file mode 100644 index 0972474cfc..0000000000 --- a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/KotestProjectConfig.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.utils - -import io.kotest.core.config.AbstractProjectConfig - -@Suppress("unused") // this class is automatically picked up by Kotest -object KotestProjectConfig : AbstractProjectConfig() { - init { - displayFullTestPath = true - } -} diff --git a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/fileTree.kt b/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/fileTree.kt deleted file mode 100644 index cdc3c6cdc0..0000000000 --- a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/fileTree.kt +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.utils - -import java.io.File -import java.nio.file.Path - -// based on https://gist.github.com/mfwgenerics/d1ec89eb80c95da9d542a03b49b5e15b -// context: https://kotlinlang.slack.com/archives/C0B8MA7FA/p1676106647658099 - -fun Path.toTreeString(): String = toFile().toTreeString() - -fun File.toTreeString(): String = when { - isDirectory -> name + "/\n" + buildTreeString(this) - else -> name -} - -private fun buildTreeString( - dir: File, - margin: String = "", -): String { - val entries = dir.listDirectoryEntries() - - return entries.joinToString("\n") { entry -> - val (currentPrefix, nextPrefix) = when (entry) { - entries.last() -> PrefixPair.LAST_ENTRY - else -> PrefixPair.INTERMEDIATE - } - - buildString { - append("$margin${currentPrefix}${entry.name}") - - if (entry.isDirectory) { - append("/") - if (entry.countDirectoryEntries() > 0) { - append("\n") - } - append(buildTreeString(entry, margin + nextPrefix)) - } - } - } -} - -private fun File.listDirectoryEntries(): Sequence = - walkTopDown().maxDepth(1).filter { it != this@listDirectoryEntries } - - -private fun File.countDirectoryEntries(): Int = - listDirectoryEntries().count() - -private data class PrefixPair( - /** The current entry should be prefixed with this */ - val currentPrefix: String, - /** If the next item is a directory, it should be prefixed with this */ - val nextPrefix: String, -) { - companion object { - /** Prefix pair for a non-last directory entry */ - val INTERMEDIATE = PrefixPair("├── ", "│ ") - - /** Prefix pair for the last directory entry */ - val LAST_ENTRY = PrefixPair("└── ", " ") - } -} diff --git a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/files.kt b/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/files.kt deleted file mode 100644 index 78a7b5f9c4..0000000000 --- a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/files.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.utils - -import java.io.File - -fun File.copyInto(directory: File, overwrite: Boolean = false) = - copyTo(directory.resolve(name), overwrite = overwrite) diff --git a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/gradleRunnerUtils.kt b/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/gradleRunnerUtils.kt deleted file mode 100644 index 43cc455db6..0000000000 --- a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/gradleRunnerUtils.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.utils - -import org.gradle.testkit.runner.BuildResult -import org.gradle.testkit.runner.BuildTask -import org.gradle.testkit.runner.GradleRunner -import org.gradle.testkit.runner.internal.DefaultGradleRunner - - -/** Edit environment variables in the Gradle Runner */ -@Deprecated("Windows does not support withEnvironment - https://github.com/gradle/gradle/issues/23959") -fun GradleRunner.withEnvironment(build: MutableMap.() -> Unit): GradleRunner { - val env = environment ?: mutableMapOf() - env.build() - return withEnvironment(env) -} - - -inline fun GradleRunner.build( - handleResult: BuildResult.() -> Unit -): Unit = build().let(handleResult) - - -inline fun GradleRunner.buildAndFail( - handleResult: BuildResult.() -> Unit -): Unit = buildAndFail().let(handleResult) - - -fun GradleRunner.withJvmArguments( - vararg jvmArguments: String -): GradleRunner = (this as DefaultGradleRunner).withJvmArguments(*jvmArguments) - - -/** - * Helper function to _append_ [arguments] to any existing - * [GradleRunner arguments][GradleRunner.getArguments]. - */ -fun GradleRunner.addArguments( - vararg arguments: String -): GradleRunner = - withArguments(this@addArguments.arguments + arguments) - - -/** - * Get the name of the task, without the leading [BuildTask.getPath]. - */ -val BuildTask.name: String - get() = path.substringAfterLast(':') diff --git a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/kotestCollectionMatchers.kt b/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/kotestCollectionMatchers.kt deleted file mode 100644 index 4a020e05c2..0000000000 --- a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/kotestCollectionMatchers.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.utils - -import io.kotest.matchers.collections.shouldBeSingleton -import io.kotest.matchers.maps.shouldContainAll -import io.kotest.matchers.maps.shouldContainExactly - -/** @see io.kotest.matchers.maps.shouldContainAll */ -fun Map.shouldContainAll( - vararg expected: Pair -): Unit = shouldContainAll(expected.toMap()) - -/** @see io.kotest.matchers.maps.shouldContainExactly */ -fun Map.shouldContainExactly( - vararg expected: Pair -): Unit = shouldContainExactly(expected.toMap()) - -/** Verify the sequence contains a single element, matching [match]. */ -fun Sequence.shouldBeSingleton(match: (T) -> Unit) { - toList().shouldBeSingleton(match) -} diff --git a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/kotestConditions.kt b/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/kotestConditions.kt deleted file mode 100644 index 53f2e244bc..0000000000 --- a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/kotestConditions.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.utils - -import io.kotest.core.annotation.EnabledCondition -import io.kotest.core.spec.Spec -import kotlin.reflect.KClass - -class NotWindowsCondition : EnabledCondition { - override fun enabled(kclass: KClass): Boolean = - "win" !in System.getProperty("os.name").lowercase() -} diff --git a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/kotestGradleAssertions.kt b/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/kotestGradleAssertions.kt deleted file mode 100644 index 1a76c71f59..0000000000 --- a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/kotestGradleAssertions.kt +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.utils - -import io.kotest.assertions.assertSoftly -import io.kotest.matchers.* -import org.gradle.api.NamedDomainObjectCollection -import org.gradle.testkit.runner.BuildResult -import org.gradle.testkit.runner.BuildTask -import org.gradle.testkit.runner.TaskOutcome - -infix fun NamedDomainObjectCollection?.shouldContainDomainObject( - name: String -): T { - this should containDomainObject(name) - return this?.getByName(name)!! -} - -infix fun NamedDomainObjectCollection?.shouldNotContainDomainObject( - name: String -): NamedDomainObjectCollection? { - this shouldNot containDomainObject(name) - return this -} - -private fun containDomainObject(name: String): Matcher?> = - neverNullMatcher { value -> - MatcherResult( - name in value.names, - { "NamedDomainObjectCollection(${value.names}) should contain DomainObject named '$name'" }, - { "NamedDomainObjectCollection(${value.names}) should not contain DomainObject named '$name'" }) - } - -/** Assert that a task ran. */ -infix fun BuildResult?.shouldHaveRunTask(taskPath: String): BuildTask { - this should haveTask(taskPath) - return this?.task(taskPath)!! -} - -/** Assert that a task ran, with an [expected outcome][expectedOutcome]. */ -fun BuildResult?.shouldHaveRunTask( - taskPath: String, - expectedOutcome: TaskOutcome -): BuildTask { - this should haveTask(taskPath) - val task = this?.task(taskPath)!! - task should haveOutcome(expectedOutcome) - return task -} - -/** - * Assert that a task did not run. - * - * A task might not have run if one of its dependencies failed before it could be run. - */ -infix fun BuildResult?.shouldNotHaveRunTask(taskPath: String) { - this shouldNot haveTask(taskPath) -} - -private fun haveTask(taskPath: String): Matcher = - neverNullMatcher { value -> - MatcherResult( - value.task(taskPath) != null, - { "BuildResult should have run task $taskPath. All tasks: ${value.tasks.joinToString { it.path }}" }, - { "BuildResult should not have run task $taskPath. All tasks: ${value.tasks.joinToString { it.path }}" }, - ) - } - - -infix fun BuildTask?.shouldHaveOutcome(outcome: TaskOutcome) { - this should haveOutcome(outcome) -} - - -infix fun BuildTask?.shouldHaveAnyOutcome(outcomes: Collection) { - this should haveAnyOutcome(outcomes) -} - - -infix fun BuildTask?.shouldNotHaveOutcome(outcome: TaskOutcome) { - this shouldNot haveOutcome(outcome) -} - - -private fun haveOutcome(outcome: TaskOutcome): Matcher = - haveAnyOutcome(listOf(outcome)) - - -private fun haveAnyOutcome(outcomes: Collection): Matcher { - val shouldHaveOutcome = when (outcomes.size) { - 0 -> error("Must provide 1 or more expected task outcome, but received none") - 1 -> "should have outcome ${outcomes.first().name}" - else -> "should have any outcome of ${outcomes.joinToString()}" - } - - return neverNullMatcher { value -> - MatcherResult( - value.outcome in outcomes, - { "Task ${value.path} $shouldHaveOutcome, but was ${value.outcome}" }, - { "Task ${value.path} $shouldHaveOutcome, but was ${value.outcome}" }, - ) - } -} - -fun BuildResult.shouldHaveTaskWithOutcome(taskPath: String, outcome: TaskOutcome) { - this shouldHaveRunTask taskPath shouldHaveOutcome outcome -} - - -fun BuildResult.shouldHaveTaskWithAnyOutcome(taskPath: String, outcomes: Collection) { - this shouldHaveRunTask taskPath shouldHaveAnyOutcome outcomes -} - -fun BuildResult.shouldHaveTasksWithOutcome( - vararg taskPathToExpectedOutcome: Pair -) { - assertSoftly { - taskPathToExpectedOutcome.forEach { (taskPath, outcome) -> - shouldHaveTaskWithOutcome(taskPath, outcome) - } - } -} - -fun BuildResult.shouldHaveTasksWithAnyOutcome( - vararg taskPathToExpectedOutcome: Pair> -) { - assertSoftly { - taskPathToExpectedOutcome.forEach { (taskPath, outcomes) -> - shouldHaveTaskWithAnyOutcome(taskPath, outcomes) - } - } -} diff --git a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/kotestStringMatchers.kt b/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/kotestStringMatchers.kt deleted file mode 100644 index 68ddb87f51..0000000000 --- a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/kotestStringMatchers.kt +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.utils - -import io.kotest.assertions.print.print -import io.kotest.matchers.MatcherResult -import io.kotest.matchers.neverNullMatcher -import io.kotest.matchers.should -import io.kotest.matchers.shouldNot - - -infix fun String?.shouldContainAll(substrings: Iterable): String? { - this should containAll(substrings) - return this -} - -infix fun String?.shouldNotContainAll(substrings: Iterable): String? { - this shouldNot containAll(substrings) - return this -} - -fun String?.shouldContainAll(vararg substrings: String): String? { - this should containAll(substrings.asList()) - return this -} - -fun String?.shouldNotContainAll(vararg substrings: String): String? { - this shouldNot containAll(substrings.asList()) - return this -} - -private fun containAll(substrings: Iterable) = - neverNullMatcher { value -> - MatcherResult( - substrings.all { it in value }, - { "${value.print().value} should include substrings ${substrings.print().value}" }, - { "${value.print().value} should not include substrings ${substrings.print().value}" }) - } - - -infix fun String?.shouldContainAnyOf(substrings: Iterable): String? { - this should containAnyOf(substrings) - return this -} - -infix fun String?.shouldNotContainAnyOf(substrings: Iterable): String? { - this shouldNot containAnyOf(substrings) - return this -} - -fun String?.shouldContainAnyOf(vararg substrings: String): String? { - this should containAnyOf(substrings.asList()) - return this -} - -fun String?.shouldNotContainAnyOf(vararg substrings: String): String? { - this shouldNot containAnyOf(substrings.asList()) - return this -} - -private fun containAnyOf(substrings: Iterable) = - neverNullMatcher { value -> - MatcherResult( - substrings.any { it in value }, - { "${value.print().value} should include any of these substrings ${substrings.print().value}" }, - { "${value.print().value} should not include any of these substrings ${substrings.print().value}" }) - } diff --git a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/samWithReceiverWorkarounds.kt b/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/samWithReceiverWorkarounds.kt deleted file mode 100644 index 09d31b7067..0000000000 --- a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/samWithReceiverWorkarounds.kt +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -@file:Suppress("FunctionName") - -package org.jetbrains.dokka.dokkatoo.utils - -import org.jetbrains.dokka.dokkatoo.dokka.parameters.DokkaPackageOptionsSpec -import org.jetbrains.dokka.dokkatoo.dokka.parameters.DokkaSourceLinkSpec -import org.jetbrains.dokka.dokkatoo.dokka.parameters.DokkaSourceSetSpec -import org.gradle.api.DomainObjectCollection -import org.gradle.api.NamedDomainObjectContainer -import org.gradle.api.NamedDomainObjectProvider -import org.gradle.api.Project -import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.DependencySet - - -/** - * Workarounds because `SamWithReceiver` not working in test sources - * https://youtrack.jetbrains.com/issue/KTIJ-14684 - * - * The `SamWithReceiver` plugin is automatically applied by the `kotlin-dsl` plugin. - * It converts all [org.gradle.api.Action] so the parameter is the receiver: - * - * ``` - * // with SamWithReceiver ✅ - * tasks.configureEach { - * val task: Task = this - * } - * - * // without SamWithReceiver - * tasks.configureEach { it -> - * val task: Task = it - * } - * ``` - * - * This is nice because it means that the Dokka Gradle Plugin more closely matches `build.gradle.kts` files. - * - * However, [IntelliJ is bugged](https://youtrack.jetbrains.com/issue/KTIJ-14684) and doesn't - * acknowledge that `SamWithReceiver` has been applied in test sources. The code works and compiles, - * but IntelliJ shows red errors. - * - * These functions are workarounds, and should be removed ASAP. - */ -@Suppress("unused") -private object Explain - -fun Project.subprojects_(configure: Project.() -> Unit) = - subprojects(configure) - -@Suppress("SpellCheckingInspection") -fun Project.allprojects_(configure: Project.() -> Unit) = - allprojects(configure) - -fun DomainObjectCollection.configureEach_(configure: T.() -> Unit) = - configureEach(configure) - -fun DomainObjectCollection.all_(configure: T.() -> Unit) = - all(configure) - -fun Configuration.withDependencies_(action: DependencySet.() -> Unit): Configuration = - withDependencies(action) - -fun NamedDomainObjectContainer.create_(name: String, configure: T.() -> Unit = {}): T = - create(name, configure) - -fun NamedDomainObjectContainer.register_( - name: String, - configure: T.() -> Unit -): NamedDomainObjectProvider = - register(name, configure) - -fun DokkaSourceSetSpec.sourceLink_( - action: DokkaSourceLinkSpec.() -> Unit -): Unit = sourceLink(action) - -fun DokkaSourceSetSpec.perPackageOption_( - action: DokkaPackageOptionsSpec.() -> Unit -): Unit = perPackageOption(action) diff --git a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/stringUtils.kt b/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/stringUtils.kt deleted file mode 100644 index 713381ee9b..0000000000 --- a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/stringUtils.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.utils - - -fun String.splitToPair(delimiter: String): Pair = - substringBefore(delimiter) to substringAfter(delimiter) - - -/** Title case the first char of a string */ -fun String.uppercaseFirstChar(): String = mapFirstChar(Character::toTitleCase) - - -private inline fun String.mapFirstChar( - transform: (Char) -> Char -): String = if (isNotEmpty()) transform(this[0]) + substring(1) else this - - -/** Split a string into lines, sort the lines, and re-join them (using [separator]). */ -fun String.sortLines(separator: String = "\n") = - lines() - .sorted() - .joinToString(separator) diff --git a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/systemVariableProviders.kt b/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/systemVariableProviders.kt deleted file mode 100644 index eb9a59e6ad..0000000000 --- a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/systemVariableProviders.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.utils - -import kotlin.properties.ReadOnlyProperty - -// Utilities for fetching System Properties and Environment Variables via delegated properties - - -internal fun optionalSystemProperty() = optionalSystemProperty { it } - -internal fun optionalSystemProperty( - convert: (String) -> T? -): ReadOnlyProperty = - ReadOnlyProperty { _, property -> - val value = System.getProperty(property.name) - if (value != null) convert(value) else null - } - - -internal fun systemProperty() = systemProperty { it } - -internal fun systemProperty( - convert: (String) -> T -): ReadOnlyProperty = - ReadOnlyProperty { _, property -> - val value = requireNotNull(System.getProperty(property.name)) { - "system property ${property.name} is unavailable" - } - convert(value) - } - - -internal fun optionalEnvironmentVariable() = optionalEnvironmentVariable { it } - -internal fun optionalEnvironmentVariable( - convert: (String) -> T? -): ReadOnlyProperty = - ReadOnlyProperty { _, property -> - val value = System.getenv(property.name) - if (value != null) convert(value) else null - } diff --git a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/text.kt b/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/text.kt deleted file mode 100644 index ded6d98890..0000000000 --- a/dokka-runners/gradle-plugin/src/testFixtures/kotlin/org/jetbrains/dokka/dokkatoo/utils/text.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo.utils - -/** Replace all newlines with `\n`, so the String can be used in assertions cross-platform */ -fun String.invariantNewlines(): String = - lines().joinToString("\n") - -fun Pair.sideBySide( - buffer: String = " ", -): String { - val (left, right) = this - - val leftLines = left.lines() - val rightLines = right.lines() - - val maxLeftWidth = leftLines.maxOf { it.length } - - return (0..maxOf(leftLines.size, rightLines.size)).joinToString("\n") { i -> - - val leftLine = (leftLines.getOrNull(i) ?: "").padEnd(maxLeftWidth, ' ') - val rightLine = rightLines.getOrNull(i) ?: "" - - leftLine + buffer + rightLine - } -} diff --git a/dokka-runners/gradle-plugin/src/testFunctional/kotlin/org/jetbrains/dokka/dokkatoo/DokkatooPluginFunctionalTest.kt b/dokka-runners/gradle-plugin/src/testFunctional/kotlin/org/jetbrains/dokka/dokkatoo/DokkatooPluginFunctionalTest.kt deleted file mode 100644 index abd485a0b4..0000000000 --- a/dokka-runners/gradle-plugin/src/testFunctional/kotlin/org/jetbrains/dokka/dokkatoo/DokkatooPluginFunctionalTest.kt +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo - -import org.jetbrains.dokka.dokkatoo.internal.DokkatooConstants.DOKKATOO_VERSION -import org.jetbrains.dokka.dokkatoo.utils.* -import io.kotest.assertions.asClue -import io.kotest.assertions.withClue -import io.kotest.core.spec.style.FunSpec -import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder -import io.kotest.matchers.string.shouldContain - -class DokkatooPluginFunctionalTest : FunSpec({ - val testProject = gradleKtsProjectTest("DokkatooPluginFunctionalTest") { - buildGradleKts = """ - |plugins { - | id("org.jetbrains.dokka.dokkatoo") version "$DOKKATOO_VERSION" - |} - | - """.trimMargin() - } - - test("expect Dokka Plugin creates Dokka tasks") { - testProject.runner - .addArguments("tasks", "--group=dokkatoo", "-q") - .build { - withClue(output) { - val dokkatooTasks = output - .substringAfter("Dokkatoo tasks") - .lines() - .filter { it.contains(" - ") } - .associate { it.splitToPair(" - ") } - - dokkatooTasks.shouldContainExactly( - //@formatter:off - "dokkatooGenerate" to "Generates Dokkatoo publications for all formats", - "dokkatooGenerateModuleGfm" to "Executes the Dokka Generator, generating a gfm module", - "dokkatooGenerateModuleHtml" to "Executes the Dokka Generator, generating a html module", - "dokkatooGenerateModuleJavadoc" to "Executes the Dokka Generator, generating a javadoc module", - "dokkatooGenerateModuleJekyll" to "Executes the Dokka Generator, generating a jekyll module", - "dokkatooGeneratePublicationGfm" to "Executes the Dokka Generator, generating the gfm publication", - "dokkatooGeneratePublicationHtml" to "Executes the Dokka Generator, generating the html publication", - "dokkatooGeneratePublicationJavadoc" to "Executes the Dokka Generator, generating the javadoc publication", - "dokkatooGeneratePublicationJekyll" to "Executes the Dokka Generator, generating the jekyll publication", - "prepareDokkatooModuleDescriptorGfm" to "Prepares the Dokka Module Descriptor for gfm", - "prepareDokkatooModuleDescriptorHtml" to "Prepares the Dokka Module Descriptor for html", - "prepareDokkatooModuleDescriptorJavadoc" to "Prepares the Dokka Module Descriptor for javadoc", - "prepareDokkatooModuleDescriptorJekyll" to "Prepares the Dokka Module Descriptor for jekyll", - //@formatter:on - ) - } - } - } - - test("expect Dokka Plugin creates Dokka outgoing variants") { - val build = testProject.runner - .addArguments("outgoingVariants", "-q") - .build { - val variants = output.invariantNewlines().replace('\\', '/') - - val dokkatooVariants = variants.lines() - .filter { it.contains("dokka", ignoreCase = true) } - .mapNotNull { it.substringAfter("Variant ", "").takeIf(String::isNotBlank) } - - - dokkatooVariants.shouldContainExactlyInAnyOrder( - "dokkatooModuleElementsGfm", - "dokkatooModuleElementsHtml", - "dokkatooModuleElementsJavadoc", - "dokkatooModuleElementsJekyll", - ) - - fun checkVariant(format: String) { - val formatCapitalized = format.uppercaseFirstChar() - - variants shouldContain /* language=text */ """ - |-------------------------------------------------- - |Variant dokkatooModuleElements$formatCapitalized - |-------------------------------------------------- - |Provide Dokka Module files for $format to other subprojects - | - |Capabilities - | - :test:unspecified (default capability) - |Attributes - | - org.jetbrains.dokka.dokkatoo.base = dokkatoo - | - org.jetbrains.dokka.dokkatoo.category = module-files - | - org.jetbrains.dokka.dokkatoo.format = $format - |Artifacts - | - build/dokka-config/$format/module_descriptor.json (artifactType = json) - | - build/dokka-module/$format (artifactType = directory) - | - """.trimMargin() - } - - checkVariant("gfm") - checkVariant("html") - checkVariant("javadoc") - checkVariant("jekyll") - } - } - - test("expect Dokka Plugin creates Dokka resolvable configurations") { - - val expectedFormats = listOf("Gfm", "Html", "Javadoc", "Jekyll") - - testProject.runner - .addArguments("resolvableConfigurations", "-q") - .build { - output.invariantNewlines().asClue { allConfigurations -> - - val dokkatooConfigurations = allConfigurations.lines() - .filter { it.contains("dokka", ignoreCase = true) } - .mapNotNull { it.substringAfter("Configuration ", "").takeIf(String::isNotBlank) } - - dokkatooConfigurations.shouldContainExactlyInAnyOrder( - buildList { - add("dokkatoo") - - addAll(expectedFormats.map { "dokkatooModule$it" }) - addAll(expectedFormats.map { "dokkatooGeneratorClasspath$it" }) - addAll(expectedFormats.map { "dokkatooPlugin$it" }) - addAll(expectedFormats.map { "dokkatooPluginIntransitive$it" }) - } - ) - - withClue("Configuration dokka") { - output.invariantNewlines() shouldContain /* language=text */ """ - |-------------------------------------------------- - |Configuration dokkatoo - |-------------------------------------------------- - |Fetch all Dokkatoo files from all configurations in other subprojects - | - |Attributes - | - org.jetbrains.dokka.dokkatoo.base = dokkatoo - | - """.trimMargin() - } - - fun checkConfigurations(format: String) { - val formatLowercase = format.lowercase() - - allConfigurations shouldContain /* language=text */ """ - |-------------------------------------------------- - |Configuration dokkatooGeneratorClasspath$format - |-------------------------------------------------- - |Dokka Generator runtime classpath for $formatLowercase - will be used in Dokka Worker. Should contain all transitive dependencies, plugins (and their transitive dependencies), so Dokka Worker can run. - | - |Attributes - | - org.jetbrains.dokka.dokkatoo.base = dokkatoo - | - org.jetbrains.dokka.dokkatoo.category = generator-classpath - | - org.jetbrains.dokka.dokkatoo.format = $formatLowercase - | - org.gradle.category = library - | - org.gradle.dependency.bundling = external - | - org.gradle.jvm.environment = standard-jvm - | - org.gradle.libraryelements = jar - | - org.gradle.usage = java-runtime - |Extended Configurations - | - dokkatooPlugin$format - | - """.trimMargin() - - allConfigurations shouldContain /* language=text */ """ - |-------------------------------------------------- - |Configuration dokkatooPlugin$format - |-------------------------------------------------- - |Dokka Plugins classpath for $formatLowercase - | - |Attributes - | - org.jetbrains.dokka.dokkatoo.base = dokkatoo - | - org.jetbrains.dokka.dokkatoo.category = plugins-classpath - | - org.jetbrains.dokka.dokkatoo.format = $formatLowercase - | - org.gradle.category = library - | - org.gradle.dependency.bundling = external - | - org.gradle.jvm.environment = standard-jvm - | - org.gradle.libraryelements = jar - | - org.gradle.usage = java-runtime - | - """.trimMargin() - - allConfigurations shouldContain /* language=text */ """ - |-------------------------------------------------- - |Configuration dokkatooPluginIntransitive$format - |-------------------------------------------------- - |Dokka Plugins classpath for $formatLowercase - for internal use. Fetch only the plugins (no transitive dependencies) for use in the Dokka JSON Configuration. - | - |Attributes - | - org.jetbrains.dokka.dokkatoo.base = dokkatoo - | - org.jetbrains.dokka.dokkatoo.category = plugins-classpath - | - org.jetbrains.dokka.dokkatoo.format = $formatLowercase - | - org.gradle.category = library - | - org.gradle.dependency.bundling = external - | - org.gradle.jvm.environment = standard-jvm - | - org.gradle.libraryelements = jar - | - org.gradle.usage = java-runtime - |Extended Configurations - | - dokkatooPlugin$format - | - """.trimMargin() - } - - expectedFormats.forEach { - checkConfigurations(it) - } - } - } - } -}) diff --git a/dokka-runners/gradle-plugin/src/testFunctional/kotlin/org/jetbrains/dokka/dokkatoo/GradlePluginProjectIntegrationTest.kt b/dokka-runners/gradle-plugin/src/testFunctional/kotlin/org/jetbrains/dokka/dokkatoo/GradlePluginProjectIntegrationTest.kt deleted file mode 100644 index 820b95f73d..0000000000 --- a/dokka-runners/gradle-plugin/src/testFunctional/kotlin/org/jetbrains/dokka/dokkatoo/GradlePluginProjectIntegrationTest.kt +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo - -import org.jetbrains.dokka.dokkatoo.internal.DokkatooConstants -import org.jetbrains.dokka.dokkatoo.utils.* -import io.kotest.assertions.withClue -import io.kotest.core.spec.style.FunSpec -import io.kotest.inspectors.shouldForAll -import io.kotest.matchers.sequences.shouldNotBeEmpty -import io.kotest.matchers.string.shouldContain -import io.kotest.matchers.string.shouldNotContain - -class GradlePluginProjectIntegrationTest : FunSpec({ - - context("given a gradle plugin project") { - val project = initGradlePluginProject() - - project.runner - .addArguments( - "clean", - "dokkatooGeneratePublicationHtml", - "--stacktrace", - ) - .forwardOutput() - .build { - - test("expect project builds successfully") { - output shouldContain "BUILD SUCCESSFUL" - } - - test("expect no 'unknown class' message in HTML files") { - val htmlFiles = project.projectDir.toFile() - .resolve("build/dokka/html") - .walk() - .filter { it.isFile && it.extension == "html" } - - htmlFiles.shouldNotBeEmpty() - - htmlFiles.forEach { htmlFile -> - val relativePath = htmlFile.relativeTo(project.projectDir.toFile()) - withClue("$relativePath should not contain Error class: unknown class") { - htmlFile.useLines { lines -> - lines.shouldForAll { line -> line.shouldNotContain("Error class: unknown class") } - } - } - } - } - } - } -}) - -private fun initGradlePluginProject( - config: GradleProjectTest.() -> Unit = {}, -): GradleProjectTest { - return gradleKtsProjectTest("gradle-plugin-project") { - - settingsGradleKts += """ - | - """.trimMargin() - - buildGradleKts = """ - |plugins { - | `kotlin-dsl` - | id("org.jetbrains.dokka.dokkatoo") version "${DokkatooConstants.DOKKATOO_VERSION}" - |} - | - """.trimMargin() - - dir("src/main/kotlin") { - - createKotlinFile( - "MyCustomGradlePlugin.kt", - """ - |package com.project.gradle.plugin - | - |import javax.inject.Inject - |import org.gradle.api.Plugin - |import org.gradle.api.Project - |import org.gradle.api.model.ObjectFactory - |import org.gradle.kotlin.dsl.* - | - |abstract class MyCustomGradlePlugin @Inject constructor( - | private val objects: ObjectFactory - |) : Plugin { - | override fun apply(project: Project) { - | println(objects.property().getOrElse("empty")) - | } - |} - - """.trimMargin() - ) - - createKotlinFile( - "MyCustomGradlePluginExtension.kt", - """ - |package com.project.gradle.plugin - | - |import org.gradle.api.provider.* - | - |interface MyCustomGradlePluginExtension { - | val versionProperty: Property - | val versionProvider: Provider - |} - | - """.trimMargin() - ) - } - - config() - } -} diff --git a/dokka-runners/gradle-plugin/src/testFunctional/kotlin/org/jetbrains/dokka/dokkatoo/KotlinMultiplatformFunctionalTest.kt b/dokka-runners/gradle-plugin/src/testFunctional/kotlin/org/jetbrains/dokka/dokkatoo/KotlinMultiplatformFunctionalTest.kt deleted file mode 100644 index 7c45f632af..0000000000 --- a/dokka-runners/gradle-plugin/src/testFunctional/kotlin/org/jetbrains/dokka/dokkatoo/KotlinMultiplatformFunctionalTest.kt +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo - -import org.jetbrains.dokka.dokkatoo.internal.DokkatooConstants -import org.jetbrains.dokka.dokkatoo.utils.* -import io.kotest.assertions.withClue -import io.kotest.core.spec.style.FunSpec -import io.kotest.inspectors.shouldForAll -import io.kotest.matchers.file.shouldBeAFile -import io.kotest.matchers.paths.shouldBeAFile -import io.kotest.matchers.sequences.shouldNotBeEmpty -import io.kotest.matchers.string.shouldContain -import io.kotest.matchers.string.shouldNotContain - -class KotlinMultiplatformFunctionalTest : FunSpec({ - - context("when dokkatoo generates all formats") { - val project = initKotlinMultiplatformProject() - - project.runner - .addArguments( - "clean", - ":dokkatooGeneratePublicationHtml", - "--stacktrace", - ) - .forwardOutput() - .build { - test("expect build is successful") { - output shouldContain "BUILD SUCCESSFUL" - } - } - - test("expect all dokka workers are successful") { - project - .findFiles { it.name == "dokka-worker.log" } - .shouldBeSingleton { dokkaWorkerLog -> - dokkaWorkerLog.shouldBeAFile() - dokkaWorkerLog.readText().shouldNotContainAnyOf( - "[ERROR]", - "[WARN]", - ) - } - } - - context("expect HTML site is generated") { - - test("with expected HTML files") { - project.projectDir.resolve("build/dokka/html/index.html").shouldBeAFile() - project.projectDir.resolve("build/dokka/html/com/project/hello/Hello.html") - .shouldBeAFile() - } - - test("and dokka_parameters.json is generated") { - project.projectDir.resolve("build/dokka/html/dokka_parameters.json") - .shouldBeAFile() - } - - test("with element-list") { - project.projectDir.resolve("build/dokka/html/test/package-list").shouldBeAFile() - project.projectDir.resolve("build/dokka/html/test/package-list").toFile().readText() - .sortLines() - .shouldContain( /* language=text */ """ - |${'$'}dokka.format:html-v1 - |${'$'}dokka.linkExtension:html - |${'$'}dokka.location:com.project////PointingToDeclaration/test/com.project/index.html - |${'$'}dokka.location:com.project//goodbye/#kotlinx.serialization.json.JsonObject/PointingToDeclaration/test/com.project/goodbye.html - |${'$'}dokka.location:com.project/Hello///PointingToDeclaration/test/com.project/-hello/index.html - |${'$'}dokka.location:com.project/Hello/Hello/#/PointingToDeclaration/test/com.project/-hello/-hello.html - |${'$'}dokka.location:com.project/Hello/sayHello/#kotlinx.serialization.json.JsonObject/PointingToDeclaration/test/com.project/-hello/say-hello.html - |com.project - """.trimMargin() - ) - } - - test("expect no 'unknown class' message in HTML files") { - val htmlFiles = project.projectDir.toFile() - .resolve("build/dokka/html") - .walk() - .filter { it.isFile && it.extension == "html" } - - htmlFiles.shouldNotBeEmpty() - - htmlFiles.forEach { htmlFile -> - val relativePath = htmlFile.relativeTo(project.projectDir.toFile()) - withClue("$relativePath should not contain Error class: unknown class") { - htmlFile.useLines { lines -> - lines.shouldForAll { line -> line.shouldNotContain("Error class: unknown class") } - } - } - } - } - } - } -}) - - -private fun initKotlinMultiplatformProject( - config: GradleProjectTest.() -> Unit = {}, -): GradleProjectTest { - return gradleKtsProjectTest("kotlin-multiplatform-project") { - - settingsGradleKts += """ - | - |dependencyResolutionManagement { - | - | repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS) - | - | repositories { - | mavenCentral() - | - | // Declare the Node.js & Yarn download repositories - | exclusiveContent { - | forRepository { - | ivy("https://nodejs.org/dist/") { - | name = "Node Distributions at ${'$'}url" - | patternLayout { artifact("v[revision]/[artifact](-v[revision]-[classifier]).[ext]") } - | metadataSources { artifact() } - | content { includeModule("org.nodejs", "node") } - | } - | } - | filter { includeGroup("org.nodejs") } - | } - | - | exclusiveContent { - | forRepository { - | ivy("https://github.com/yarnpkg/yarn/releases/download") { - | name = "Node Distributions at ${'$'}url" - | patternLayout { artifact("v[revision]/[artifact](-v[revision]).[ext]") } - | metadataSources { artifact() } - | content { includeModule("com.yarnpkg", "yarn") } - | } - | } - | filter { includeGroup("com.yarnpkg") } - | } - | } - |} - | - """.trimMargin() - - buildGradleKts = """ - |plugins { - | kotlin("multiplatform") version "1.8.22" - | id("org.jetbrains.dokka.dokkatoo") version "${DokkatooConstants.DOKKATOO_VERSION}" - |} - | - |kotlin { - | jvm() - | js(IR) { - | browser() - | } - | - | sourceSets { - | commonMain { - | dependencies { - | implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0") - | } - | } - | commonTest { - | dependencies { - | implementation(kotlin("test")) - | } - | } - | } - |} - | - |dependencies { - | // must manually add this dependency for aggregation to work - | //dokkatooPluginHtml("org.jetbrains.dokka:all-modules-page-plugin:1.8.10") - |} - | - |dokkatoo { - | dokkatooSourceSets.configureEach { - | externalDocumentationLinks { - | create("kotlinxSerialization") { - | url("https://kotlinlang.org/api/kotlinx.serialization/") - | } - | } - | } - |} - | - | - """.trimMargin() - - dir("src/commonMain/kotlin/") { - - createKotlinFile( - "Hello.kt", - """ - |package com.project - | - |import kotlinx.serialization.json.JsonObject - | - |/** The Hello class */ - |class Hello { - | /** prints `Hello` and [json] to the console */ - | fun sayHello(json: JsonObject) = println("Hello ${'$'}json") - |} - | - """.trimMargin() - ) - - createKotlinFile( - "goodbye.kt", - """ - |package com.project - | - |import kotlinx.serialization.json.JsonObject - | - |/** Should print `goodbye` and [json] to the console */ - |expect fun goodbye(json: JsonObject) - | - """.trimMargin() - ) - } - - dir("src/jvmMain/kotlin/") { - createKotlinFile( - "goodbyeJvm.kt", - """ - |package com.project - | - |import kotlinx.serialization.json.JsonObject - | - |/** JVM implementation - prints `goodbye` and [json] to the console */ - |actual fun goodbye(json: JsonObject) = println("[JVM] goodbye ${'$'}json") - | - """.trimMargin() - ) - } - - dir("src/jsMain/kotlin/") { - createKotlinFile( - "goodbyeJs.kt", - """ - |package com.project - | - |import kotlinx.serialization.json.JsonObject - | - |/** JS implementation - prints `goodbye` and [json] to the console */ - |actual fun goodbye(json: JsonObject) = println("[JS] goodbye ${'$'}json") - | - """.trimMargin() - ) - } - - config() - } -} diff --git a/dokka-runners/gradle-plugin/src/testFunctional/kotlin/org/jetbrains/dokka/dokkatoo/MultiModuleFunctionalTest.kt b/dokka-runners/gradle-plugin/src/testFunctional/kotlin/org/jetbrains/dokka/dokkatoo/MultiModuleFunctionalTest.kt deleted file mode 100644 index 3ad73ec3c5..0000000000 --- a/dokka-runners/gradle-plugin/src/testFunctional/kotlin/org/jetbrains/dokka/dokkatoo/MultiModuleFunctionalTest.kt +++ /dev/null @@ -1,472 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.dokkatoo - -import org.jetbrains.dokka.dokkatoo.internal.DokkatooConstants.DOKKATOO_VERSION -import org.jetbrains.dokka.dokkatoo.utils.* -import io.kotest.core.spec.style.FunSpec -import io.kotest.inspectors.shouldForAll -import io.kotest.matchers.collections.shouldBeIn -import io.kotest.matchers.collections.shouldContainAll -import io.kotest.matchers.file.shouldBeAFile -import io.kotest.matchers.paths.shouldBeAFile -import io.kotest.matchers.paths.shouldNotExist -import io.kotest.matchers.string.shouldBeEmpty -import io.kotest.matchers.string.shouldContain -import org.gradle.testkit.runner.TaskOutcome.* - -class MultiModuleFunctionalTest : FunSpec({ - - context("when dokkatoo generates all formats") { - val project = initDokkatooProject("all-formats") - - project.runner - .addArguments( - "clean", - ":dokkatooGenerate", - "--stacktrace", - ) - .forwardOutput() - .build { - test("expect build is successful") { - output shouldContain "BUILD SUCCESSFUL" - } - } - - test("expect all dokka workers are successful") { - project - .findFiles { it.name == "dokka-worker.log" } - .shouldForAll { dokkaWorkerLog -> - dokkaWorkerLog.shouldBeAFile() - dokkaWorkerLog.readText().shouldNotContainAnyOf( - "[ERROR]", - "[WARN]", - ) - } - } - - context("expect HTML site is generated") { - - test("with expected HTML files") { - project.file("subproject/build/dokka/html/index.html").shouldBeAFile() - project.file("subproject/build/dokka/html/com/project/hello/Hello.html") - .shouldBeAFile() - } - - test("and dokka_parameters.json is generated") { - project.file("subproject/build/dokka/html/dokka_parameters.json") - .shouldBeAFile() - } - - test("with element-list") { - project.file("build/dokka/html/package-list").shouldBeAFile() - project.file("build/dokka/html/package-list").toFile().readText() - .shouldContain( /* language=text */ """ - |${'$'}dokka.format:html-v1 - |${'$'}dokka.linkExtension:html - | - |module:subproject-hello - |com.project.hello - |module:subproject-goodbye - |com.project.goodbye - """.trimMargin() - ) - } - } - } - - context("Gradle caching") { - - context("expect Dokkatoo is compatible with Gradle Build Cache") { - val project = initDokkatooProject("build-cache") - - test("expect clean is successful") { - project.runner.addArguments("clean").build { - output shouldContain "BUILD SUCCESSFUL" - } - } - - project.runner - .addArguments( - //"clean", - ":dokkatooGenerate", - "--stacktrace", - "--build-cache", - ) - .forwardOutput() - .build { - test("expect build is successful") { - output shouldContain "BUILD SUCCESSFUL" - } - - test("expect all dokka workers are successful") { - project - .findFiles { it.name == "dokka-worker.log" } - .shouldForAll { dokkaWorkerLog -> - dokkaWorkerLog.shouldBeAFile() - dokkaWorkerLog.readText().shouldNotContainAnyOf( - "[ERROR]", - "[WARN]", - ) - } - } - } - - context("when build cache is enabled") { - project.runner - .addArguments( - ":dokkatooGenerate", - "--stacktrace", - "--build-cache", - ) - .forwardOutput() - .build { - test("expect build is successful") { - output shouldContainAll listOf( - "BUILD SUCCESSFUL", - "24 actionable tasks: 24 up-to-date", - ) - } - - test("expect all dokkatoo tasks are up-to-date") { - tasks - .filter { task -> - task.name.contains("dokkatoo", ignoreCase = true) - } - .shouldForAll { task -> - task.outcome.shouldBeIn(FROM_CACHE, UP_TO_DATE, SKIPPED) - } - } - } - } - } - - context("Gradle Configuration Cache") { - val project = initDokkatooProject("config-cache") - - test("expect clean is successful") { - project.runner.addArguments("clean").build { - output shouldContain "BUILD SUCCESSFUL" - } - } - - project.runner - .addArguments( - //"clean", - ":dokkatooGenerate", - "--stacktrace", - "--no-build-cache", - "--configuration-cache", - ) - .forwardOutput() - .build { - test("expect build is successful") { - output shouldContain "BUILD SUCCESSFUL" - } - } - - test("expect all dokka workers are successful") { - project - .findFiles { it.name == "dokka-worker.log" } - .shouldForAll { dokkaWorkerLog -> - dokkaWorkerLog.shouldBeAFile() - dokkaWorkerLog.readText().shouldNotContainAnyOf( - "[ERROR]", - "[WARN]", - ) - } - } - } - - - context("expect updates in subprojects re-run tasks") { - - val project = initDokkatooProject("submodule-update") - - test("expect clean is successful") { - project.runner.addArguments("clean").build { - output shouldContain "BUILD SUCCESSFUL" - } - } - - test("expect first build is successful") { - project.runner - .addArguments( - //"clean", - ":dokkatooGeneratePublicationHtml", - "--stacktrace", - "--build-cache", - ) - .forwardOutput() - .build { - output shouldContain "BUILD SUCCESSFUL" - } - } - - context("and when a file in a subproject changes") { - - val helloAgainIndexHtml = - @Suppress("KDocUnresolvedReference") - project.createKotlinFile( - "subproject-hello/src/main/kotlin/HelloAgain.kt", - """ - |package com.project.hello - | - |/** Like [Hello], but again */ - |class HelloAgain { - | /** prints `Hello Again` to the console */ - | fun sayHelloAgain() = println("Hello Again") - |} - | - """.trimMargin() - ).toPath() - - context("expect Dokka re-generates the publication") { - project.runner - .addArguments( - ":dokkatooGeneratePublicationHtml", - "--stacktrace", - "--build-cache", - ) - .forwardOutput() - .build { - - test("expect HelloAgain HTML file exists") { - helloAgainIndexHtml.shouldBeAFile() - } - - test("expect :subproject-goodbye tasks are up-to-date, because no files changed") { - shouldHaveTasksWithOutcome( - ":subproject-goodbye:dokkatooGenerateModuleHtml" to UP_TO_DATE, - ":subproject-goodbye:prepareDokkatooModuleDescriptorHtml" to UP_TO_DATE, - ) - } - - val successfulOutcomes = listOf(SUCCESS, FROM_CACHE) - test("expect :subproject-hello tasks should be re-run, since a file changed") { - shouldHaveTasksWithAnyOutcome( - ":subproject-hello:dokkatooGenerateModuleHtml" to successfulOutcomes, - ":subproject-hello:prepareDokkatooModuleDescriptorHtml" to successfulOutcomes, - ) - } - - test("expect aggregating tasks should re-run because the :subproject-hello Dokka Module changed") { - shouldHaveTasksWithAnyOutcome( - ":dokkatooGeneratePublicationHtml" to successfulOutcomes, - ) - } - - test("expect build is successful") { - output shouldContain "BUILD SUCCESSFUL" - } - - test("expect 5 tasks are run") { - output shouldContain "5 actionable tasks" - } - } - - context("and when the class is deleted") { - project.dir("subproject-hello") { - require(file("src/main/kotlin/HelloAgain.kt").toFile().delete()) { - "failed to delete HelloAgain.kt" - } - } - - project.runner - .addArguments( - ":dokkatooGeneratePublicationHtml", - "--stacktrace", - "--info", - "--build-cache", - ) - .forwardOutput() - .build { - - test("expect HelloAgain HTML file is now deleted") { - helloAgainIndexHtml.shouldNotExist() - - project.dir("build/dokka/html/") { - projectDir.toTreeString().shouldNotContainAnyOf( - "hello-again", - "-hello-again/", - "-hello-again.html", - ) - } - } - } - } - } - } - } - } - - context("logging") { - val project = initDokkatooProject("logging") - - test("expect no logs when built using --quiet log level") { - - project.runner - .addArguments( - "clean", - ":dokkatooGenerate", - "--no-configuration-cache", - "--no-build-cache", - "--quiet", - ) - .forwardOutput() - .build { - output.shouldBeEmpty() - } - } - - test("expect no Dokkatoo logs when built using lifecycle log level") { - - project.runner - .addArguments( - "clean", - ":dokkatooGenerate", - "--no-configuration-cache", - "--no-build-cache", - "--no-parallel", - // no logging option => lifecycle log level - ) - .forwardOutput() - .build { - - // projects are only configured the first time TestKit runs, and annoyingly there's no - // easy way to force Gradle to re-configure the projects - so only check conditionally. - if ("Configure project" in output) { - output shouldContain /*language=text*/ """ - ¦> Configure project : - ¦> Configure project :subproject-goodbye - ¦> Configure project :subproject-hello - ¦> Task :clean - """.trimMargin("¦") - } - - output.lines() - .filter { it.startsWith("> Task :") } - .shouldContainAll( - "> Task :clean", - "> Task :dokkatooGenerate", - "> Task :dokkatooGenerateModuleGfm", - "> Task :dokkatooGenerateModuleHtml", - "> Task :dokkatooGenerateModuleJavadoc", - "> Task :dokkatooGenerateModuleJekyll", - "> Task :dokkatooGeneratePublicationGfm", - "> Task :dokkatooGeneratePublicationHtml", - "> Task :dokkatooGeneratePublicationJavadoc", - "> Task :dokkatooGeneratePublicationJekyll", - "> Task :subproject-goodbye:clean", - "> Task :subproject-goodbye:dokkatooGenerateModuleGfm", - "> Task :subproject-goodbye:dokkatooGenerateModuleHtml", - "> Task :subproject-goodbye:dokkatooGenerateModuleJavadoc", - "> Task :subproject-goodbye:dokkatooGenerateModuleJekyll", - "> Task :subproject-goodbye:prepareDokkatooModuleDescriptorGfm", - "> Task :subproject-goodbye:prepareDokkatooModuleDescriptorHtml", - "> Task :subproject-goodbye:prepareDokkatooModuleDescriptorJavadoc", - "> Task :subproject-goodbye:prepareDokkatooModuleDescriptorJekyll", - "> Task :subproject-hello:clean", - "> Task :subproject-hello:dokkatooGenerateModuleGfm", - "> Task :subproject-hello:dokkatooGenerateModuleHtml", - "> Task :subproject-hello:dokkatooGenerateModuleJavadoc", - "> Task :subproject-hello:dokkatooGenerateModuleJekyll", - "> Task :subproject-hello:prepareDokkatooModuleDescriptorGfm", - "> Task :subproject-hello:prepareDokkatooModuleDescriptorHtml", - "> Task :subproject-hello:prepareDokkatooModuleDescriptorJavadoc", - "> Task :subproject-hello:prepareDokkatooModuleDescriptorJekyll", - ) - } - } - } -}) - -private fun initDokkatooProject( - testName: String, - config: GradleProjectTest.() -> Unit = {}, -): GradleProjectTest { - return gradleKtsProjectTest("multi-module-hello-goodbye/$testName") { - - settingsGradleKts += """ - | - |include(":subproject-hello") - |include(":subproject-goodbye") - | - """.trimMargin() - - buildGradleKts = """ - |plugins { - | // Kotlin plugin shouldn't be necessary here, but without it Dokka errors - | // with ClassNotFound KotlinPluginExtension... very weird - | kotlin("jvm") version "1.8.22" apply false - | id("org.jetbrains.dokka.dokkatoo") version "$DOKKATOO_VERSION" - |} - | - |dependencies { - | dokkatoo(project(":subproject-hello")) - | dokkatoo(project(":subproject-goodbye")) - | dokkatooPluginHtml( - | dokkatoo.versions.jetbrainsDokka.map { dokkaVersion -> - | "org.jetbrains.dokka:all-modules-page-plugin:${'$'}dokkaVersion" - | } - | ) - |} - | - """.trimMargin() - - dir("subproject-hello") { - buildGradleKts = """ - |plugins { - | kotlin("jvm") version "1.8.22" - | id("org.jetbrains.dokka.dokkatoo") version "$DOKKATOO_VERSION" - |} - | - """.trimMargin() - - createKotlinFile( - "src/main/kotlin/Hello.kt", - """ - |package com.project.hello - | - |/** The Hello class */ - |class Hello { - | /** prints `Hello` to the console */ - | fun sayHello() = println("Hello") - |} - | - """.trimMargin() - ) - - createKotlinFile("src/main/kotlin/HelloAgain.kt", "") - } - - dir("subproject-goodbye") { - - buildGradleKts = """ - |plugins { - | kotlin("jvm") version "1.8.22" - | id("org.jetbrains.dokka.dokkatoo") version "$DOKKATOO_VERSION" - |} - | - """.trimMargin() - - createKotlinFile( - "src/main/kotlin/Goodbye.kt", - """ - |package com.project.goodbye - | - |/** The Goodbye class */ - |class Goodbye { - | /** prints a goodbye message to the console */ - | fun sayHello() = println("Goodbye!") - |} - | - """.trimMargin() - ) - } - - config() - } -}