From 514cbb11962ba77abf5b35f7698b84f1aef1e813 Mon Sep 17 00:00:00 2001 From: Adam <897017+aSemy@users.noreply.github.com> Date: Thu, 12 Oct 2023 11:40:43 +1300 Subject: [PATCH] Fix Maven plugin help task (#3036) Fixes #3035 --- .../conventions/maven-cli-setup.gradle.kts | 3 - .../dokka/it/maven/MavenIntegrationTest.kt | 50 +++++++++- .../jetbrains/dokka/it/TestOutputCopier.kt | 2 +- runners/maven-plugin/api/maven-plugin.api | 5 + runners/maven-plugin/build.gradle.kts | 93 +++++++++++-------- runners/maven-plugin/pom.template.xml | 26 ++++++ 6 files changed, 133 insertions(+), 46 deletions(-) diff --git a/build-logic/src/main/kotlin/org/jetbrains/conventions/maven-cli-setup.gradle.kts b/build-logic/src/main/kotlin/org/jetbrains/conventions/maven-cli-setup.gradle.kts index 8d228bc355..f07ff98d6b 100644 --- a/build-logic/src/main/kotlin/org/jetbrains/conventions/maven-cli-setup.gradle.kts +++ b/build-logic/src/main/kotlin/org/jetbrains/conventions/maven-cli-setup.gradle.kts @@ -22,7 +22,6 @@ plugins { abstract class MavenCliSetupExtension { abstract val mavenVersion: Property abstract val mavenPluginToolsVersion: Property - abstract val mavenBuildDir: DirectoryProperty /** Directory that will contain the unpacked Apache Maven dependency */ abstract val mavenInstallDir: DirectoryProperty @@ -43,7 +42,6 @@ val mavenCliSetupExtension = mavenVersion.convention(libs.versions.apacheMaven.core) mavenPluginToolsVersion.convention(libs.versions.apacheMaven.pluginTools) - mavenBuildDir.convention(layout.buildDirectory.dir("maven")) mavenInstallDir.convention(layout.buildDirectory.dir("apache-maven")) val isWindowsProvider = @@ -81,7 +79,6 @@ val mavenBinary by configurations.registering { } tasks.clean { - delete(mavenCliSetupExtension.mavenBuildDir) delete(mavenCliSetupExtension.mavenInstallDir) } diff --git a/integration-tests/maven/src/integrationTest/kotlin/org/jetbrains/dokka/it/maven/MavenIntegrationTest.kt b/integration-tests/maven/src/integrationTest/kotlin/org/jetbrains/dokka/it/maven/MavenIntegrationTest.kt index 92bdc45ecd..7606072c80 100644 --- a/integration-tests/maven/src/integrationTest/kotlin/org/jetbrains/dokka/it/maven/MavenIntegrationTest.kt +++ b/integration-tests/maven/src/integrationTest/kotlin/org/jetbrains/dokka/it/maven/MavenIntegrationTest.kt @@ -4,9 +4,10 @@ package org.jetbrains.dokka.it.maven +import org.intellij.lang.annotations.Language import org.jetbrains.dokka.it.AbstractIntegrationTest -import org.jetbrains.dokka.it.awaitProcessResult import org.jetbrains.dokka.it.ProcessResult +import org.jetbrains.dokka.it.awaitProcessResult import java.io.File import kotlin.test.* @@ -26,11 +27,33 @@ class MavenIntegrationTest : AbstractIntegrationTest() { writeText(readText().replace("\$dokka_version", currentDokkaVersion)) } val customResourcesDir = File(templateProjectDir, "customResources") - if(customResourcesDir.exists() && customResourcesDir.isDirectory) { + if (customResourcesDir.exists() && customResourcesDir.isDirectory) { customResourcesDir.copyRecursively(File(projectDir, "customResources"), overwrite = true) } } + @Test + fun `dokka help`() { + val result = ProcessBuilder().directory(projectDir) + .command(mavenBinaryFile.absolutePath, "dokka:help", "-U", "-e") + .start() + .awaitProcessResult() + + // format the output to remove blank lines and make newlines system-independent + val output = result.output.lines().filter { it.isNotBlank() }.joinToString("\n") + + assertContains( + output, + """ + |This plugin has 4 goals: + |dokka:dokka + |dokka:help + |dokka:javadoc + |dokka:javadocJar + """.trimMargin() + ) + } + @Test fun `dokka dokka`() { val result = ProcessBuilder().directory(projectDir) @@ -67,7 +90,12 @@ class MavenIntegrationTest : AbstractIntegrationTest() { ) assertTrue(stylesDir.resolve("custom-style-to-add.css").isFile) projectDir.allHtmlFiles().forEach { file -> - if(file.name != "navigation.html") assertTrue("custom-style-to-add.css" in file.readText(), "custom styles not added to html file ${file.name}") + if (file.name != "navigation.html") { + assertTrue( + "custom-style-to-add.css" in file.readText(), + "custom styles not added to html file ${file.name}" + ) + } } assertTrue(stylesDir.resolve("custom-style-to-add.css").readText().contains("""/* custom stylesheet */""")) assertTrue(imagesDir.resolve("custom-resource.svg").isFile) @@ -172,4 +200,20 @@ class MavenIntegrationTest : AbstractIntegrationTest() { ) ) } + + companion object { + /* + * TODO replace with kotlin.test.assertContains after migrating to Kotlin language version 1.5+ + */ + fun assertContains( + charSequence: CharSequence, + @Language("TEXT") other: CharSequence, + ignoreCase: Boolean = false + ) { + asserter.assertTrue( + { "Expected the char sequence to contain the substring.\nCharSequence <$charSequence>, substring <$other>, ignoreCase <$ignoreCase>." }, + charSequence.contains(other, ignoreCase) + ) + } + } } diff --git a/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/TestOutputCopier.kt b/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/TestOutputCopier.kt index 681c9d539f..2e2113a910 100644 --- a/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/TestOutputCopier.kt +++ b/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/TestOutputCopier.kt @@ -15,6 +15,6 @@ public interface TestOutputCopier { System.getenv("DOKKA_TEST_OUTPUT_PATH")?.also { location -> println("Copying to ${File(location).absolutePath}") projectOutputLocation.copyRecursively(File(location)) - } ?: println("No path via env. varbiable 'DOKKA_TEST_OUTPUT_PATH' provided, skipping copying") + } ?: println("No path via env. variable 'DOKKA_TEST_OUTPUT_PATH' provided, skipping copying") } } diff --git a/runners/maven-plugin/api/maven-plugin.api b/runners/maven-plugin/api/maven-plugin.api index 28d96bd3b6..069e7744ee 100644 --- a/runners/maven-plugin/api/maven-plugin.api +++ b/runners/maven-plugin/api/maven-plugin.api @@ -94,6 +94,11 @@ public final class org/jetbrains/dokka/maven/ExternalDocumentationLinkBuilder { public final fun setUrl (Ljava/net/URL;)V } +public class org/jetbrains/dokka/maven/HelpMojo : org/apache/maven/plugin/AbstractMojo { + public fun ()V + public fun execute ()V +} + public final class org/jetbrains/dokka/maven/MavenDokkaLogger : org/jetbrains/dokka/utilities/DokkaLogger { public fun (Lorg/apache/maven/plugin/logging/Log;)V public fun debug (Ljava/lang/String;)V diff --git a/runners/maven-plugin/build.gradle.kts b/runners/maven-plugin/build.gradle.kts index 5e27929835..825493ad27 100644 --- a/runners/maven-plugin/build.gradle.kts +++ b/runners/maven-plugin/build.gradle.kts @@ -2,7 +2,6 @@ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -import org.gradle.kotlin.dsl.support.appendReproducibleNewLine import org.jetbrains.registerDokkaArtifactPublication plugins { @@ -47,77 +46,93 @@ val generatePom by tasks.registering(Sync::class) { into(temporaryDir) } -val prepareMavenPluginBuildDir by tasks.registering(Sync::class) { - description = "Prepares all files for Maven Plugin task execution" +val prepareHelpMojoDir by tasks.registering(Sync::class) { + description = "Prepare files for generating the Maven Plugin HelpMojo" group = mavenPluginTaskGroup - from(tasks.compileKotlin.flatMap { it.destinationDirectory }) { into("classes/java/main") } - from(tasks.compileJava.flatMap { it.destinationDirectory }) { into("classes/java/main") } - + into(layout.buildDirectory.dir("maven-help-mojo")) from(generatePom) - - into(mavenCliSetup.mavenBuildDir) } val helpMojo by tasks.registering(Exec::class) { + description = "Generate the Maven Plugin HelpMojo" group = mavenPluginTaskGroup - dependsOn(tasks.installMavenBinary, prepareMavenPluginBuildDir) + dependsOn(tasks.installMavenBinary, prepareHelpMojoDir) - workingDir(mavenCliSetup.mavenBuildDir) + workingDir(prepareHelpMojoDir.map { it.destinationDir }) executable(mavenCliSetup.mvn.get()) args("-e", "-B", "org.apache.maven.plugins:maven-plugin-plugin:helpmojo") - outputs.dir(mavenCliSetup.mavenBuildDir) - - doLast("normalize maven-plugin-help.properties") { - // The maven-plugin-help.properties file contains a timestamp by default. - // It should be removed as it is not reproducible and impacts Gradle caching - val pluginHelpProperties = workingDir.resolve("maven-plugin-help.properties") - pluginHelpProperties.writeText( - buildString { - val lines = pluginHelpProperties.readText().lines().iterator() - // the first line is a descriptive comment - appendReproducibleNewLine(lines.next()) - // the second line is the timestamp, which should be ignored - lines.next() - // the remaining lines are properties - lines.forEach { appendReproducibleNewLine(it) } - } - ) + outputs.dir(workingDir) +} + +val helpMojoSources by tasks.registering(Sync::class) { + description = "Sync the HelpMojo source files into a SourceSet SrcDir" + group = mavenPluginTaskGroup + from(helpMojo) { + eachFile { + // drop 2 leading directories + relativePath = RelativePath(true, *relativePath.segments.drop(2).toTypedArray()) + } } + includeEmptyDirs = false + into(temporaryDir) + include("**/*.java") +} + +val helpMojoResources by tasks.registering(Sync::class) { + description = "Sync the HelpMojo resource files into a SourceSet SrcDir" + group = mavenPluginTaskGroup + from(helpMojo) + into(temporaryDir) + include("**/**") + exclude("**/*.java") +} + +sourceSets.main { + // use the generated HelpMojo as compilation input, so Gradle will automatically generate the mojo + java.srcDirs(helpMojoSources) + resources.srcDirs(helpMojoResources) +} + +val preparePluginDescriptorDir by tasks.registering(Sync::class) { + description = "Prepare files for generating the Maven Plugin descriptor" + group = mavenPluginTaskGroup + + into(layout.buildDirectory.dir("maven-plugin-descriptor")) + + from(tasks.compileKotlin) { into("classes/java/main") } + from(tasks.compileJava) { into("classes/java/main") } + from(helpMojoResources) } val pluginDescriptor by tasks.registering(Exec::class) { + description = "Generate the Maven Plugin descriptor" group = mavenPluginTaskGroup - dependsOn(tasks.installMavenBinary, prepareMavenPluginBuildDir) + dependsOn(tasks.installMavenBinary, preparePluginDescriptorDir) - workingDir(mavenCliSetup.mavenBuildDir) + workingDir(preparePluginDescriptorDir.map { it.destinationDir }) executable(mavenCliSetup.mvn.get()) - args( - "-e", - "-B", - "org.apache.maven.plugins:maven-plugin-plugin:descriptor" - ) + args("-e", "-B", "org.apache.maven.plugins:maven-plugin-plugin:descriptor") - outputs.dir(layout.buildDirectory.dir("maven/classes/java/main/META-INF/maven")) + outputs.dir("$workingDir/classes/java/main/META-INF/maven") } tasks.jar { - dependsOn(pluginDescriptor, helpMojo) metaInf { - from(mavenCliSetup.mavenBuildDir.map { it.dir("classes/java/main/META-INF") }) + from(pluginDescriptor) { + into("maven") + } } manifest { attributes("Class-Path" to configurations.runtimeClasspath.map { configuration -> configuration.resolve().joinToString(" ") { it.name } }) } - duplicatesStrategy = DuplicatesStrategy.WARN } - registerDokkaArtifactPublication("dokkaMavenPlugin") { artifactId = "dokka-maven-plugin" } diff --git a/runners/maven-plugin/pom.template.xml b/runners/maven-plugin/pom.template.xml index 01ad60d268..b47951125d 100644 --- a/runners/maven-plugin/pom.template.xml +++ b/runners/maven-plugin/pom.template.xml @@ -12,6 +12,7 @@ maven-plugin ${mavenVersion} + UTF-8 @@ -21,10 +22,35 @@ ${mavenPluginToolsVersion} org.jetbrains.dokka.maven + true + + + default-descriptor + + descriptor + + process-classes + + + help-descriptor + + helpmojo + + process-classes + + ./ ./classes/java/main + + + org.apache.maven.plugin-tools + maven-plugin-annotations + ${mavenPluginToolsVersion} + provided + +