Skip to content

JS AST templating and matching #5481

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 50 commits into from
May 27, 2025
Merged

JS AST templating and matching #5481

merged 50 commits into from
May 27, 2025

Conversation

knutwannheden
Copy link
Contributor

@knutwannheden knutwannheden commented May 22, 2025

This PR introduces a new templating system that provides a clean, TypeScript-friendly API for JavaScript AST pattern matching and code generation using tagged template literals.

pattern() - Pattern Matching

Create patterns to match against AST nodes and extract matched captures:

const addPattern = pattern`${"left"} + ${"right"}`;

const match = await addPattern.match(expression);
if (match) {
   const leftOperand = match.get("left");
   const rightOperand = match.get("right");
}

template() - AST Generation

Generate new AST nodes from templates:

// Direct value substitution
const newNode = template`${rightOperand} + ${leftOperand}`.apply(cursor, expression);

// Mix of captures, AST nodes, and primitives
const result = template`if (${condition}) return ${42};`.apply(cursor, statement);

capture() - Reusable Placeholders

Create placeholders for pattern matching and value reuse:

const expr = capture();

// Use same capture multiple times when requiring subtrees to be identical
const redundantOr = pattern`${expr} || ${expr}`;  // Matches: x || x

rewrite() - Transformation Rules

Combine patterns and templates into rewrite rules:

const swapOperands = rewrite(() => {
    return {
        before: pattern`${"left"} + ${"right"}`,
        after: template`${"right"} + ${"left"}`
    };
});
const updated = await swapOperands.tryOn(this.cursor, binary);

JohannisK and others added 27 commits May 23, 2025 14:13
…ds with escape characters (#5476)

* Added tests showing the issue

* Added check to skip escaped '$' signs in build.groovy files

* Added support for escaped $ in single quoted strings, added tests showing correct parsing, added test showing correct behavior
…th conjunctions (#5470)

ensuring EE10 migration recipes (e.g. JavaxXmlToJakartaXmlXJCBinding) reliably match intended elements, regardless of whitespace.

Co-authored-by: Torsten Liermann <[email protected]>
)

* Let `JavaParser#classpathFromResources()` first check type tables

The type tables are much quicker to load than the classpath (via ClassGraph) and should therefore be favored.

* Use `ConcurrentHashMap` with `CompletableFuture` in `TypeTable`
…if dependency is pulled in transitively (#5409)

* RemoveRedundantDependencyVersions recipe removes direct dependencies if dependency is pulled in transitively

* Polish

* Can handle several boms

* Added sorting to find highest dependency managed version

* cleanup

* extracted method out of loop

* improved name, removed unused option

* Added support for kotlin, added support for all dependency management methods.

* renamed method

* reverted temporary assignment for debug purposes

---------

Co-authored-by: Johan Kragt <[email protected]>
* Add initial xml LST, jsx test

* [wip]

* JS: extract JSX children mapping to dedicated method

Separate JSX-specific logic from the general-purpose `mapToRightPaddedList()`
method by creating a dedicated `mapJsxChildren()` method. This improves code
organization by keeping the general-purpose method clean and focused on its
original purpose, while moving JSX-specific logic to a dedicated method.

The change updates all JSX visitor methods (`visitJsxElement`,
`visitJsxSelfClosingElement`, and `visitJsxFragment`) to use the new method,
ensuring proper handling of JSX children and attributes. This approach makes
the code more maintainable and easier to understand.

All JSX tests now pass successfully.

* Start updating Java code

* Extend senders and receivers

* Wait with types for `JSX.Tag` and `JSX.NamespacedName`

* Polish JSX LST model

* Fix bugs in sender and receiver logic for JSX

* Adjust JSX LST model to account for member expressions

* Update rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JSX.java

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Update rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JSX.java

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Polish

---------

Co-authored-by: Jonathan Schneider <[email protected]>
Co-authored-by: Sam Snyder <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* Fixing spaces for type declarations

* Fixing spaces for type declarations
# Conflicts:
#	rewrite-javascript/rewrite/src/javascript/parser.ts
@knutwannheden knutwannheden changed the title Initial JS templating support JS templating support May 26, 2025
@knutwannheden knutwannheden changed the title JS templating support JS AST templating and matching May 26, 2025
Maybe we don't need that.
@knutwannheden knutwannheden marked this pull request as ready for review May 27, 2025 10:28
@knutwannheden knutwannheden merged commit 32e8ece into main May 27, 2025
2 checks passed
@knutwannheden knutwannheden deleted the js-templating branch May 27, 2025 10:29
@github-project-automation github-project-automation bot moved this from In Progress to Done in OpenRewrite May 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

6 participants