Make section IDs consistent in Maven Plugin docs and enforce it

Closes gh-26619
This commit is contained in:
Andy Wilkinson 2023-08-09 08:06:38 +01:00
parent 032d92a9fb
commit 68baa6e7df
5 changed files with 173 additions and 10 deletions

View File

@ -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<String, String> goalSections;
@OutputDirectory
public File getOutputDir() {
return this.outputDir;
@ -55,6 +59,15 @@ public class DocumentPluginGoals extends DefaultTask {
this.outputDir = outputDir;
}
@Input
public Map<String, String> getGoalSections() {
return this.goalSections;
}
public void setGoalSections(Map<String, String> 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("| <<goals-%s,%s:%s>>%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<Parameter> 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<Parameter> 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);

View File

@ -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"
]
}

View File

@ -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

View File

@ -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 <<goals-repackage-parameters-details-layoutFactory,layout>> is set.
Layout factories are always ignored if an explicit <<packaging.repackage-goal.parameter-details.layout-factory,layout>> is set.

View File

@ -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 `<version>` tags for those dependencies when used in your own POM.
* An execution of the <<goals.adoc#goals-repackage, `repackage` goal>> with a `repackage` execution id.
* An execution of the <<goals.adoc#packaging.repackage-goal, `repackage` goal>> 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`)