Skip to content

Add optional ecosystem parameter to ChangeType#7833

Draft
Jenson3210 wants to merge 1 commit into
mainfrom
changetype-ecosystem-option
Draft

Add optional ecosystem parameter to ChangeType#7833
Jenson3210 wants to merge 1 commit into
mainfrom
changetype-ecosystem-option

Conversation

@Jenson3210
Copy link
Copy Markdown
Contributor

@Jenson3210 Jenson3210 commented May 29, 2026

  • Draft for discussion — opening this to gather maintainer feedback on the approach before polishing. Resolves moderneinc/customer-requests#2463.

Problem

org.openrewrite.java.ChangeType applies to every JavaSourceFile:

public boolean isAcceptable(SourceFile sourceFile, ExecutionContext ctx) {
    return sourceFile instanceof JavaSourceFile || sourceFile instanceof SourceFileWithReferences;
}

Python and JavaScript reuse the Java LST model — Py.CompilationUnit and JS.CompilationUnit both implement JavaSourceFile. So a JVM-targeted ChangeType accepts every Python/JS file and runs its UsesType precondition, walking the entire AST looking for a JVM fully-qualified type that can never appear there.

In telemetry from a single recipe run (see issue for the full table), ChangeType spent 423 s on finos/symphony-bdk-python — which has zero Java files — and changed nothing. On Python-heavy repos this is enough to push recipe runs past the timeout.

Proposal

Add an optional ecosystem option (jvm, python, javascript) that scopes the change to a single ecosystem:

  • Default (null) — unchanged behavior: the recipe runs on all source files.
  • When set, files whose compilation unit belongs to a different ecosystem are skipped before the UsesType scan.
  • Reference-based files (XML, properties, …) are always processed, since they may carry type references.

The new constructor is annotated @JsonCreator; the prior 3-arg constructor is preserved for backward compatibility.

Open questions for discussion

  • Detection mechanism — the current draft infers a file's ecosystem from its implementing class package (org.openrewrite.python.*, org.openrewrite.javascript.*, else jvm). Is there a cleaner / more robust signal we'd prefer (e.g. a marker or a SourceFile-level capability)?
  • Scope — the issue notes this affects other JVM type/usage recipes too (ChangeMethodName, UsesType-based recipes, …). Should this live on ChangeType alone, or be lifted into a shared precondition/utility so every affected recipe benefits?
  • Option shape — single ecosystem string vs. a more general include/exclude list? Naming (jvm vs java)?

Changes

  • ChangeType: new optional ecosystem option + ecosystem-skip logic, backward-compatible constructor.
  • Tests in ChangeTypeTest (jvm applies / non-jvm skips Java files) and ChangeTypeIntegTest (jvm scope skips Python files).

Possible follow-up: roll this out broadly via a best-practices recipe

The per-recipe option above is only worthwhile if it actually gets set across the large meta-recipes that drive the cost (Spring Boot upgrades, migrate-java, etc.), where hundreds of ChangeType steps each scan every Python/JS file.

Rather than hand-editing each declarative recipe, we could add a recipe to rewrite best practices that infers the right ecosystem for an existing ChangeType step from indicators already present in the declarative YAML — e.g. the package of the changed class (org.springframework.*, javax.*, … → jvm) — and fills in the ecosystem option automatically.

Run across rewrite-migrate-java, rewrite-spring, and the other recipe libraries, that would scope every ChangeType (and ideally the other UsesType-based steps) to jvm in one sweep — turning this from a single-recipe opt-in into a broad win, where the biggest savings land precisely on the Python/JS-heavy repos that pay the most today.

`ChangeType` applies to every `JavaSourceFile`. Because Python and
JavaScript reuse the Java LST model (their compilation units implement
`JavaSourceFile`), a JVM-targeted type change still runs its full
`UsesType` precondition scan over every Python/JS file, even though those
languages can never reference a JVM type.

Add an optional `ecosystem` option (`jvm`, `python`, `javascript`) that
scopes the change to a single ecosystem. Default (null) is unchanged:
the recipe runs on all source files. Reference-based files (XML,
properties) are always processed since they may carry type references.
Comment thread rewrite-java/src/main/java/org/openrewrite/java/ChangeType.java
Comment on lines +129 to +132
case "js":
return "javascript";
case "py":
return "python";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the alternatives also be in the valid set at that point?

@steve-aom-elliott
Copy link
Copy Markdown
Contributor

I think really a core of the problem is that yes, this really would affect all the UsesType scenarios as well, as any of those are still going to traverse all those files. When we have a change on a recipe like this, yeah, in order to actually optimize, there'd be a lot of other changes.

One suggestion I saw proposed was related to having a Language property on SourceFile (could be provided via overridden method on the various source file types) that would allow you to detect which language the file represents without needing to do package matching. That of course only would help so much and wouldn't be backwards compatible either.

Additionally the posibility of having an applicable languages property on a recipe generically might allow you to scope things through that rather than having to pass it as an option: declarative recipes could be scoped in yaml and imperative could be scoped via overriding a method. That too changes the exposed api for a recipe, which gets messy in different ways.

Not sure how I feel about all these yet, as it's a not-insubstantial change for any path here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

2 participants