Expand star imports in ChangePackage when they would create ambiguity#7202
Expand star imports in ChangePackage when they would create ambiguity#7202steve-aom-elliott wants to merge 9 commits intomainfrom
Conversation
When ChangePackage renames a star import (e.g. import origpkg.* to import newpkg.*), the new package may contain types whose simple names clash with types from other star imports in the same file. This creates ambiguous imports that fail to compile. This change converts ChangePackage to a ScanningRecipe so it can first collect which types exist in which packages across all source files, then use that information to detect ambiguity. When a changed star import would create ambiguity, it is expanded into explicit imports for only the types actually used from that package. Fixes moderneinc/customer-requests#1733
… classpath for ambiguity detection
a6ee247 to
c7942f8
Compare
Move annotation interface definitions out of source specs and into parser dependsOn, so the tests focus on the consumer file's import behavior rather than asserting changes to the definition files.
Replace synthetic test packages with real javax/jakarta/hibernate validation types from recipeDependencies. Use JavaSourceSet.build with classpath to populate the source set marker. Switch from typesInUse to AST identifier walking for collecting referenced types, since typesInUse does not include annotation types resolved through star imports.
- Use javax.validation:validation-api:1.1 (no NotBlank), jakarta.validation-api:2.0.2, and org.hibernate:hibernate-validator:5.4.3 (has NotBlank) so @notblank unambiguously resolves from org.hibernate.validator.constraints - Fix hasAmbiguity to also check the original (pre-rename) package on the classpath, since the classpath may not yet have types under the new package name - Regenerate type table for updated parserClasspath versions
Use classpathFromResources + srcMainJava + addTypesToSourceSet instead of manual JavaSourceSet.build and classpath. Move validation and hibernate deps to testParserClasspath since they're only needed by ChangePackageTest.
Future work: Recipe-level type table lookup (Option 1)A higher-level migration recipe (e.g., a javax-to-jakarta composite) could declare the target dependency as a ExampleA composite migration recipe already declares // In the migration recipe module's build.gradle.kts
recipeDependencies {
parserClasspath("jakarta.validation:jakarta.validation-api:3.0.2")
}Then at recipe runtime, What's needed
|
Future work: Worker-level dependency resolution (Option 2)When Inter-recipe signalingCurrently recipes are independent transforms — they modify source files but don't communicate side effects to the runner.
Dependency resolution in the workerThe worker would need to resolve a GAV to an actual JAR at recipe runtime. The Moderne worker already connects to artifact repositories (Artifactory, Maven Central) for LST retrieval, but that's a different code path. It would need:
JavaSourceSet rebuildAfter downloading the new JAR:
Ordering becomes load-bearingThis only works if Transitive dependenciesWhen Platform boundaryThis works naturally in the Moderne worker/CLI where there's infrastructure for artifact resolution. For the OSS plugins ( PerformanceResolving and scanning JARs adds latency per dependency change. For a large migration like javax → jakarta with dozens of Realistic v1 scopeA pragmatic first version could:
|
Summary
ChangePackagerenames a star import (e.g.,import javax.validation.constraints.*→import jakarta.validation.constraints.*), it now detects if the new package contains types whose simple names clash with types from other star imports (e.g.,org.hibernate.validator.constraints.*also hasNotBlank)JavaSourceSetclasspath to enumerate types in each package, then walks AST identifiers to determine which types are actually referencedTest plan
changePackageExpandsStarImportWhenItWouldCreateAmbiguity— uses realjavax.validation,jakarta.validation, andorg.hibernate.validatortypes; verifies star import is expanded to explicit imports when another star import contains a type with the same simple namechangePackagePreservesStarImportWhenNoAmbiguity— verifies star import is preserved when no ambiguity exists (no hibernate-validator on classpath)ChangePackageTestsuite passesFuture work
AddImporthas a related gap when star-import folding kicks in. If the import layout style folds multiple explicit imports from the same package into a star import (e.g., 3+jakarta.validation.constraintsimports fold tojakarta.validation.constraints.*), and another existing star import (org.hibernate.validator.constraints.*) contains a type with the same simple name, the result is ambiguous. A fix would check via classpath whether folding to a star import would create cross-package name collisions, and if so, keep the conflicting type as an explicit import.Example: