From 68baa6e7dfb5639cb292a3220e8c7e64cb7ef157 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 9 Aug 2023 08:06:38 +0100 Subject: [PATCH] Make section IDs consistent in Maven Plugin docs and enforce it Closes gh-26619 --- .../mavenplugin/DocumentPluginGoals.java | 51 ++++++-- .../spring-boot-maven-plugin/build.gradle | 14 +++ .../docs/asciidoc/anchor-rewrite.properties | 114 ++++++++++++++++++ .../src/docs/asciidoc/packaging.adoc | 2 +- .../src/docs/asciidoc/using.adoc | 2 +- 5 files changed, 173 insertions(+), 10 deletions(-) diff --git a/buildSrc/src/main/java/org/springframework/boot/build/mavenplugin/DocumentPluginGoals.java b/buildSrc/src/main/java/org/springframework/boot/build/mavenplugin/DocumentPluginGoals.java index 0a0bac5556..db355d8383 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/mavenplugin/DocumentPluginGoals.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/mavenplugin/DocumentPluginGoals.java @@ -21,10 +21,12 @@ import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import org.gradle.api.DefaultTask; import org.gradle.api.Task; +import org.gradle.api.tasks.Input; import org.gradle.api.tasks.InputFile; import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.TaskAction; @@ -46,6 +48,8 @@ public class DocumentPluginGoals extends DefaultTask { private File outputDir; + private Map goalSections; + @OutputDirectory public File getOutputDir() { return this.outputDir; @@ -55,6 +59,15 @@ public class DocumentPluginGoals extends DefaultTask { this.outputDir = outputDir; } + @Input + public Map getGoalSections() { + return this.goalSections; + } + + public void setGoalSections(Map goalSections) { + this.goalSections = goalSections; + } + @InputFile public File getPluginXml() { return this.pluginXml; @@ -80,7 +93,7 @@ public class DocumentPluginGoals extends DefaultTask { writer.println("| Goal | Description"); writer.println(); for (Mojo mojo : plugin.getMojos()) { - writer.printf("| <>%n", mojo.getGoal(), plugin.getGoalPrefix(), mojo.getGoal()); + writer.printf("| <<%s,%s:%s>>%n", goalSectionId(mojo), plugin.getGoalPrefix(), mojo.getGoal()); writer.printf("| %s%n", mojo.getDescription()); writer.println(); } @@ -90,7 +103,7 @@ public class DocumentPluginGoals extends DefaultTask { private void documentMojo(Plugin plugin, Mojo mojo) throws IOException { try (PrintWriter writer = new PrintWriter(new FileWriter(new File(this.outputDir, mojo.getGoal() + ".adoc")))) { - String sectionId = "goals-" + mojo.getGoal(); + String sectionId = goalSectionId(mojo); writer.println(); writer.println(); writer.printf("[[%s]]%n", sectionId); @@ -105,12 +118,11 @@ public class DocumentPluginGoals extends DefaultTask { List requiredParameters = parameters.stream() .filter(Parameter::isRequired) .collect(Collectors.toList()); - String parametersSectionId = sectionId + "-parameters"; - String detailsSectionId = parametersSectionId + "-details"; + String detailsSectionId = sectionId + ".parameter-details"; if (!requiredParameters.isEmpty()) { writer.println(); writer.println(); - writer.printf("[[%s-required]]%n", parametersSectionId); + writer.printf("[[%s.required-parameters]]%n", sectionId); writer.println("== Required parameters"); writeParametersTable(writer, detailsSectionId, requiredParameters); } @@ -120,7 +132,7 @@ public class DocumentPluginGoals extends DefaultTask { if (!optionalParameters.isEmpty()) { writer.println(); writer.println(); - writer.printf("[[%s-optional]]%n", parametersSectionId); + writer.printf("[[%s.optional-parameters]]%n", sectionId); writer.println("== Optional parameters"); writeParametersTable(writer, detailsSectionId, optionalParameters); } @@ -132,6 +144,15 @@ public class DocumentPluginGoals extends DefaultTask { } } + private String goalSectionId(Mojo mojo) { + String goalSection = this.goalSections.get(mojo.getGoal()); + if (goalSection == null) { + throw new IllegalStateException("Goal '" + mojo.getGoal() + "' has not be assigned to a section"); + } + String sectionId = goalSection + "." + mojo.getGoal() + "-goal"; + return sectionId; + } + private void writeParametersTable(PrintWriter writer, String detailsSectionId, List parameters) { writer.println("[cols=\"3,2,3\"]"); writer.println("|==="); @@ -139,7 +160,7 @@ public class DocumentPluginGoals extends DefaultTask { writer.println(); for (Parameter parameter : parameters) { String name = parameter.getName(); - writer.printf("| <<%s-%s,%s>>%n", detailsSectionId, name, name); + writer.printf("| <<%s.%s,%s>>%n", detailsSectionId, parameterId(name), name); writer.printf("| `%s`%n", typeNameToJavadocLink(shortTypeName(parameter.getType()), parameter.getType())); String defaultValue = parameter.getDefaultValue(); if (defaultValue != null) { @@ -158,7 +179,7 @@ public class DocumentPluginGoals extends DefaultTask { String name = parameter.getName(); writer.println(); writer.println(); - writer.printf("[[%s-%s]]%n", sectionId, name); + writer.printf("[[%s.%s]]%n", sectionId, parameterId(name)); writer.printf("=== `%s`%n", name); writer.println(parameter.getDescription()); writer.println(); @@ -174,6 +195,20 @@ public class DocumentPluginGoals extends DefaultTask { } } + private String parameterId(String name) { + StringBuilder id = new StringBuilder(name.length() + 4); + for (char c : name.toCharArray()) { + if (Character.isLowerCase(c)) { + id.append(c); + } + else { + id.append("-"); + id.append(Character.toLowerCase(c)); + } + } + return id.toString(); + } + private void writeDetail(PrintWriter writer, String name, String value) { writer.printf("| %s%n", name); writer.printf("| `%s`%n", value); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/build.gradle index 00c9b2106d..29fd71f4cd 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/build.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/build.gradle @@ -13,6 +13,8 @@ configurations { } dependencies { + asciidoctorExtensions("io.spring.asciidoctor:spring-asciidoctor-extensions-section-ids") + compileOnly("org.apache.maven.plugin-tools:maven-plugin-annotations") compileOnly("org.sonatype.plexus:plexus-build-api") compileOnly("org.apache.maven.shared:maven-common-artifact-filters") { @@ -142,3 +144,15 @@ prepareMavenBinaries { artifacts { "documentation" zip } + +tasks.named("documentPluginGoals") { + goalSections = [ + "build-image": "build-image", + "build-info": "build-info", + "help": "help", + "repackage": "packaging", + "run": "run", + "start": "integration-tests", + "stop": "integration-tests" + ] +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/anchor-rewrite.properties b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/anchor-rewrite.properties index 0cea3c652e..9ca1b6971e 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/anchor-rewrite.properties +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/anchor-rewrite.properties @@ -33,3 +33,117 @@ run-example-active-profiles=run.examples.specify-active-profiles using-parent-pom=using.parent-pom using-import=using.import using-overriding-command-line=using.overriding-command-line + +# Consistent section IDs for goals +goals-build-image=build-image.build-image-goal +goals-build-image-parameters-details=build-image.build-image-goal.parameter-details +goals-build-image-parameters-details-classifier=build-image.build-image-goal.parameter-details.classifier +goals-build-image-parameters-details-docker=build-image.build-image-goal.parameter-details.docker +goals-build-image-parameters-details-excludeDevtools=build-image.build-image-goal.parameter-details.exclude-devtools +goals-build-image-parameters-details-excludeGroupIds=build-image.build-image-goal.parameter-details.exclude-group-ids +goals-build-image-parameters-details-excludes=build-image.build-image-goal.parameter-details.excludes +goals-build-image-parameters-details-image=build-image.build-image-goal.parameter-details.image +goals-build-image-parameters-details-includeSystemScope=build-image.build-image-goal.parameter-details.include-system-scope +goals-build-image-parameters-details-includes=build-image.build-image-goal.parameter-details.includes +goals-build-image-parameters-details-layers=build-image.build-image-goal.parameter-details.layers +goals-build-image-parameters-details-layout=build-image.build-image-goal.parameter-details.layout +goals-build-image-parameters-details-layoutFactory=build-image.build-image-goal.parameter-details.layout-factory +goals-build-image-parameters-details-mainClass=build-image.build-image-goal.parameter-details.main-class +goals-build-image-parameters-details-skip=build-image.build-image-goal.parameter-details.skip +goals-build-image-parameters-details-sourceDirectory=build-image.build-image-goal.parameter-details.source-directory +goals-build-image-parameters-optional=build-image.build-image-goal.optional-parameters +goals-build-image-parameters-required=build-image.build-image-goal.required-parameters +goals-build-info=build-info.build-info-goal +goals-build-info-parameters-details=build-info.build-info-goal.parameter-details +goals-build-info-parameters-details-additionalProperties=build-info.build-info-goal.parameter-details.additional-properties +goals-build-info-parameters-details-excludeInfoProperties=build-info.build-info-goal.parameter-details.exclude-info-properties +goals-build-info-parameters-details-outputFile=build-info.build-info-goal.parameter-details.output-file +goals-build-info-parameters-details-time=build-info.build-info-goal.parameter-details.time +goals-build-info-parameters-optional=build-info.build-info-goal.optional-parameters +goals-help=help.help-goal +goals-help-parameters-details=help.help-goal.parameter-details +goals-help-parameters-details-detail=help.help-goal.parameter-details.detail +goals-help-parameters-details-goal=help.help-goal.parameter-details.goal +goals-help-parameters-details-indentSize=help.help-goal.parameter-details.indent-size +goals-help-parameters-details-lineLength=help.help-goal.parameter-details.line-length +goals-help-parameters-optional=help.help-goal.optional-parameters +goals-repackage=packaging.repackage-goal +goals-repackage-parameters-details=packaging.repackage-goal.parameter-details +goals-repackage-parameters-details-attach=packaging.repackage-goal.parameter-details.attach +goals-repackage-parameters-details-classifier=packaging.repackage-goal.parameter-details.classifier +goals-repackage-parameters-details-embeddedLaunchScript=packaging.repackage-goal.parameter-details.embedded-launch-script +goals-repackage-parameters-details-embeddedLaunchScriptProperties=packaging.repackage-goal.parameter-details.embedded-launch-script-properties +goals-repackage-parameters-details-excludeDevtools=packaging.repackage-goal.parameter-details.exclude-devtools +goals-repackage-parameters-details-excludeGroupIds=packaging.repackage-goal.parameter-details.exclude-group-ids +goals-repackage-parameters-details-excludes=packaging.repackage-goal.parameter-details.excludes +goals-repackage-parameters-details-executable=packaging.repackage-goal.parameter-details.executable +goals-repackage-parameters-details-includeSystemScope=packaging.repackage-goal.parameter-details.include-system-scope +goals-repackage-parameters-details-includes=packaging.repackage-goal.parameter-details.includes +goals-repackage-parameters-details-layers=packaging.repackage-goal.parameter-details.layers +goals-repackage-parameters-details-layout=packaging.repackage-goal.parameter-details.layout +goals-repackage-parameters-details-layoutFactory=packaging.repackage-goal.parameter-details.layout-factory +goals-repackage-parameters-details-mainClass=packaging.repackage-goal.parameter-details.main-class +goals-repackage-parameters-details-outputDirectory=packaging.repackage-goal.parameter-details.output-directory +goals-repackage-parameters-details-outputTimestamp=packaging.repackage-goal.parameter-details.output-timestamp +goals-repackage-parameters-details-requiresUnpack=packaging.repackage-goal.parameter-details.requires-unpack +goals-repackage-parameters-details-skip=packaging.repackage-goal.parameter-details.skip +goals-repackage-parameters-optional=packaging.repackage-goal.optional-parameters +goals-repackage-parameters-required=packaging.repackage-goal.required-parameters +goals-run=run.run-goal +goals-run-parameters-details=run.run-goal.parameter-details +goals-run-parameters-details-addResources=run.run-goal.parameter-details.add-resources +goals-run-parameters-details-agents=run.run-goal.parameter-details.agents +goals-run-parameters-details-arguments=run.run-goal.parameter-details.arguments +goals-run-parameters-details-classesDirectory=run.run-goal.parameter-details.classes-directory +goals-run-parameters-details-commandlineArguments=run.run-goal.parameter-details.commandline-arguments +goals-run-parameters-details-directories=run.run-goal.parameter-details.directories +goals-run-parameters-details-environmentVariables=run.run-goal.parameter-details.environment-variables +goals-run-parameters-details-excludeGroupIds=run.run-goal.parameter-details.exclude-group-ids +goals-run-parameters-details-excludes=run.run-goal.parameter-details.excludes +goals-run-parameters-details-fork=run.run-goal.parameter-details.fork +goals-run-parameters-details-includes=run.run-goal.parameter-details.includes +goals-run-parameters-details-jvmArguments=run.run-goal.parameter-details.jvm-arguments +goals-run-parameters-details-mainClass=run.run-goal.parameter-details.main-class +goals-run-parameters-details-noverify=run.run-goal.parameter-details.noverify +goals-run-parameters-details-optimizedLaunch=run.run-goal.parameter-details.optimized-launch +goals-run-parameters-details-profiles=run.run-goal.parameter-details.profiles +goals-run-parameters-details-skip=run.run-goal.parameter-details.skip +goals-run-parameters-details-systemPropertyVariables=run.run-goal.parameter-details.system-property-variables +goals-run-parameters-details-useTestClasspath=run.run-goal.parameter-details.use-test-classpath +goals-run-parameters-details-workingDirectory=run.run-goal.parameter-details.working-directory +goals-run-parameters-optional=run.run-goal.optional-parameters +goals-run-parameters-required=run.run-goal.required-parameters +goals-start=integration-tests.start-goal +goals-start-parameters-details=integration-tests.start-goal.parameter-details +goals-start-parameters-details-addResources=integration-tests.start-goal.parameter-details.add-resources +goals-start-parameters-details-agents=integration-tests.start-goal.parameter-details.agents +goals-start-parameters-details-arguments=integration-tests.start-goal.parameter-details.arguments +goals-start-parameters-details-classesDirectory=integration-tests.start-goal.parameter-details.classes-directory +goals-start-parameters-details-commandlineArguments=integration-tests.start-goal.parameter-details.commandline-arguments +goals-start-parameters-details-directories=integration-tests.start-goal.parameter-details.directories +goals-start-parameters-details-environmentVariables=integration-tests.start-goal.parameter-details.environment-variables +goals-start-parameters-details-excludeGroupIds=integration-tests.start-goal.parameter-details.exclude-group-ids +goals-start-parameters-details-excludes=integration-tests.start-goal.parameter-details.excludes +goals-start-parameters-details-fork=integration-tests.start-goal.parameter-details.fork +goals-start-parameters-details-includes=integration-tests.start-goal.parameter-details.includes +goals-start-parameters-details-jmxName=integration-tests.start-goal.parameter-details.jmx-name +goals-start-parameters-details-jmxPort=integration-tests.start-goal.parameter-details.jmx-port +goals-start-parameters-details-jvmArguments=integration-tests.start-goal.parameter-details.jvm-arguments +goals-start-parameters-details-mainClass=integration-tests.start-goal.parameter-details.main-class +goals-start-parameters-details-maxAttempts=integration-tests.start-goal.parameter-details.max-attempts +goals-start-parameters-details-noverify=integration-tests.start-goal.parameter-details.noverify +goals-start-parameters-details-profiles=integration-tests.start-goal.parameter-details.profiles +goals-start-parameters-details-skip=integration-tests.start-goal.parameter-details.skip +goals-start-parameters-details-systemPropertyVariables=integration-tests.start-goal.parameter-details.system-property-variables +goals-start-parameters-details-useTestClasspath=integration-tests.start-goal.parameter-details.use-test-classpath +goals-start-parameters-details-wait=integration-tests.start-goal.parameter-details.wait +goals-start-parameters-details-workingDirectory=integration-tests.start-goal.parameter-details.working-directory +goals-start-parameters-optional=integration-tests.start-goal.optional-parameters +goals-start-parameters-required=integration-tests.start-goal.required-parameters +goals-stop=integration-tests.stop-goal +goals-stop-parameters-details=integration-tests.stop-goal.parameter-details +goals-stop-parameters-details-fork=integration-tests.stop-goal.parameter-details.fork +goals-stop-parameters-details-jmxName=integration-tests.stop-goal.parameter-details.jmx-name +goals-stop-parameters-details-jmxPort=integration-tests.stop-goal.parameter-details.jmx-port +goals-stop-parameters-details-skip=integration-tests.stop-goal.parameter-details.skip +goals-stop-parameters-optional=integration-tests.stop-goal.optional-parameters \ No newline at end of file diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging.adoc b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging.adoc index e126727095..37f25f16e8 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging.adoc +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging.adoc @@ -210,7 +210,7 @@ include::../maven/packaging/custom-layout-pom.xml[tags=custom-layout] The layout factory is provided as an implementation of `LayoutFactory` (from `spring-boot-loader-tools`) explicitly specified in the pom. If there is only one custom `LayoutFactory` on the plugin classpath and it is listed in `META-INF/spring.factories` then it is unnecessary to explicitly set it in the plugin configuration. -Layout factories are always ignored if an explicit <> is set. +Layout factories are always ignored if an explicit <> is set. diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/using.adoc b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/using.adoc index 58d13bae7b..69a2023dd7 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/using.adoc +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/using.adoc @@ -8,7 +8,7 @@ The parent project provides the following features: * Compilation with `-parameters`. * A dependency management section, inherited from the `spring-boot-dependencies` POM, that manages the versions of common dependencies. This dependency management lets you omit `` tags for those dependencies when used in your own POM. -* An execution of the <> with a `repackage` execution id. +* An execution of the <> with a `repackage` execution id. * Sensible https://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html[resource filtering]. * Sensible plugin configuration (https://github.com/ktoso/maven-git-commit-id-plugin[Git commit ID], and https://maven.apache.org/plugins/maven-shade-plugin/[shade]). * Sensible resource filtering for `application.properties` and `application.yml` including profile-specific files (for example, `application-dev.properties` and `application-dev.yml`)