UseTextBlocks: Added support for converting string concatenations with variables using .formatted(...) by jbessels · Pull Request #1301 · openrewrite/rewrite-migrate-java · GitHub
Skip to content

UseTextBlocks: Added support for converting string concatenations with variables using .formatted(...) - #1301

Open
jbessels wants to merge 1 commit into
openrewrite:mainfrom
jbessels:feature/use-text-blocks-format-variables
Open

jbessels wants to merge 1 commit into
openrewrite:mainfrom
jbessels:feature/use-text-blocks-format-variables

Conversation

@jbessels

@jbessels jbessels commented Oct 17, 2026 •

Copy link
Copy Markdown

Finally!! After all these years, I finally got to scratch that itch! 😄
UseTextBlocks: Support converting string concatenations with variables using .formatted(...)

Tbh its AI generated. I checked out all relevant OpenRewrite repo's, fed the AI with existing recipe name and a very careful description. Antigravity with Vertex / Gemini was then tasked to create it. I ordered it to test it all and create edge case tests - tests first, implementation later. Also to check and follow the OpenRewrite naming convention, test convertion etc. The result is shown beneath.

I'm very curious if this is decent code or AI slop. I used AI cause not knowledgable enough to code this OpenRewrite stuff my self (limited free time), the honest truth.

Summary

Extends the UseTextBlocks recipe with an opt-in formatVariables configuration option. When enabled, multi-line string concatenations that contain variable references or expressions (e.g. "SELECT * FROM\n" + table + " WHERE id = " + id) are migrated into a Java 15+ text block combined with .formatted(...).

Motivation

Developers migrating legacy Java code to modern Java often encounter multi-line SQL queries, JSON/XML templates, and messages that mix multi-line string literals with variables. Currently, UseTextBlocks only migrates pure string literals. Converting concatenated variables into text blocks with .formatted(...) by hand is tedious and error-prone.

Before & After

Before:

String query = "SELECT * FROM\n" +
        table + "\n" +
        "WHERE id = " + id;

After (formatVariables = true):

String query = """
        SELECT * FROM
        %s
        WHERE id = %d""".formatted(table, id);

Implementation Details

  1. Strict Backward Compatibility:

    • Added @Option boolean formatVariables (defaults to false).
    • When formatVariables = false, the recipe strictly follows existing behavior with zero changes to existing migrations.
  2. Format Specifier Resolution:

    • Integers, longs, shorts, and bytes (primitive and boxed) -> %d
    • Booleans (primitive and boxed) -> %b
    • Characters (primitive and boxed) -> %c
    • Floats and doubles intentionally map to %s (rather than %f) to prevent locale-dependent comma vs. dot decimal formatting issues.
    • Strings and general objects -> %s
  3. Escaping & Formatting:

    • Literal % characters inside string segments are safely escaped to %%.
    • Preserves trailing whitespace escapes (\s) and line continuations (\) consistent with existing text block formatting rules.
  4. AST Type Attribution:

    • Attaches fully resolved JavaType.Method for java.lang.String.formatted(Object... args) to both J.Identifier and J.MethodInvocation to satisfy FindMissingTypes static analysis.
  5. Runtime Compatibility:

    • Built and tested against Java 8 bytecode targets (-source 8 -target 8).

Verification

  • Ran ./gradlew check -x test (all license checks, jar manifests, and recipe CSV validations passed).
  • Ran ./gradlew test --tests org.openrewrite.java.migrate.lang.UseTextBlocksTest (all 52 tests passed, including edge cases for adjacent variables, escaped quotes, trailing spaces, and method/field arguments).

@github-project-automation github-project-automation Bot moved this to In Progress in OpenRewrite Oct 17, 2026
@jbessels jbessels changed the title feat(UseTextBlocks): support converting string concatenations with variables using .formatted(...) UseTextBlocks: Added support for converting string concatenations with variables using .formatted(...) Oct 17, 2026
@jbessels

Copy link
Copy Markdown
Author

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.

1 participant