Omit version when annotation processor is managed by parent POM#7392
Omit version when annotation processor is managed by parent POM#7392
Conversation
Modern `maven-compiler-plugin` (3.12+) resolves annotation processor path versions from effective `dependencyManagement`. When the target coordinate is already managed, adding a hardcoded `<version>` conflicts with the parent POM's managed version (e.g. Spring Boot's). Fixes #7384
| if (!child.getChildValue("version").isPresent()) { | ||
| // No explicit version: the path intentionally defers to | ||
| // the effective POM's dependencyManagement. Leave it alone. | ||
| return tg; | ||
| } |
There was a problem hiding this comment.
I suppose I wasn't aware that the annotation processor paths could defer to the POM's dependencyManagement to begin with, as I've. generally only seen explicit versions in the past.
There was a problem hiding this comment.
Yeah, I only recently learned about this too. Maven Compiler Plugin 3.12+ falls back to effective <dependencyManagement> when a <path> has no version — see MCOMPILER-391.
| // Not found, so we add it | ||
| return tg.withContent(ListUtils.concat(tg.getChildren(), Xml.Tag.build(String.format( | ||
| "<path>\n<groupId>%s</groupId>\n<artifactId>%s</artifactId>\n<version>%s</version>\n</path>", | ||
| groupId, artifactId, version)))); | ||
| // Not found, so we add it. Omit <version> when the effective POM's | ||
| // dependencyManagement already manages this coordinate — modern | ||
| // maven-compiler-plugin (3.12+) resolves annotation processor path | ||
| // versions from dependencyManagement automatically. | ||
| String managedVersion = currentMrr.getPom().getManagedVersion(groupId, artifactId, null, null); | ||
| String pathXml = managedVersion != null ? | ||
| String.format("<path>\n<groupId>%s</groupId>\n<artifactId>%s</artifactId>\n</path>", | ||
| groupId, artifactId) : | ||
| String.format("<path>\n<groupId>%s</groupId>\n<artifactId>%s</artifactId>\n<version>%s</version>\n</path>", | ||
| groupId, artifactId, version); | ||
| return tg.withContent(ListUtils.concat(tg.getChildren(), Xml.Tag.build(pathXml))); |
There was a problem hiding this comment.
Does any of the logic need to be guarded by actually using maven-compiler-plugin 3.12+? If this ended up being called and they were on a lower version of the plugin than 3.12, might it not end up potentially adding the annotation processor path without a version tag, breaking compilation?
There was a problem hiding this comment.
Great catch! I've just pushed a guard: compilerPluginSupportsManagedVersions() looks up the effective maven-compiler-plugin version from ResolvedPom.getPlugins() / getPluginManagement() and only omits <version> when it's >= 3.12.0. For older plugin versions (or when the version can't be determined), we still emit the explicit <version> as before. Added keepVersionWhenCompilerPluginIsOlderThan312 to pin that behavior.
Only maven-compiler-plugin 3.12.0 and newer resolve annotation processor path versions from effective dependencyManagement. For older plugin versions, a missing <version> would break compilation, so keep emitting it explicitly.
|
Going to try adding tests for just a few more scenarios shortly to add a bit more coverage. |
Adds tests exercising three additional paths through the
compilerPluginSupportsManagedVersions guard that the existing pair of
tests (which inline the plugin version) does not reach:
- Property substitution: <version>${maven.compiler.plugin.version}</version>
- Same-POM <pluginManagement> supplies the version
- Parent-POM <pluginManagement> supplies the version (mirrors #7384)
Also adds a test for the conservative-false fallback when the compiler
plugin version cannot be determined anywhere in the effective POM.
Summary
AddAnnotationProcessornow checksResolvedPom.getManagedVersion()before adding a new<path>; when the coordinate is already managed via effective<dependencyManagement>(e.g. inherited fromspring-boot-starter-parent), the<version>is omitted so modernmaven-compiler-plugin(3.12+) resolves it fromdependencyManagement.<path>entry is left untouched on subsequent runs.Test plan
New
omitVersionWhenManagedByParenttest covers a parent POM with<dependencyManagement>and a reactor child, asserting the added<path>has no<version>../gradlew :rewrite-maven:test --tests "org.openrewrite.maven.AddAnnotationProcessorTest"— 24/24 pass.Fixes Lombok Plugin Version is added, even when managed by Spring Boot #7384