# OpenRewrite

> List, preview and apply OpenRewrite recipes to Java sources with elide rewrite, add recipe dependencies, and use the code index to select files before parsing.

`elide rewrite` runs OpenRewrite recipes against an Elide project's main Java sources. Use it to automate source
changes, preview the diff, and apply the same recipe from the terminal or CI.

Experimental in 1.6.0; recipe compatibility hardening is planned for 1.6.1.

## Preview and apply a recipe

Run these commands from a project with an `elide.pkl` and Java sources:

```bash
elide rewrite --list
elide rewrite org.openrewrite.java.RemoveUnusedImports --dry-run
elide rewrite org.openrewrite.java.RemoveUnusedImports
elide test
```

`--list` prints available recipe names and display names. `--dry-run` prints the proposed diff without changing
source files. Omit it to apply the changes, then run your tests. Dependency resolution, indexing, and compilation
can still write build state during a dry run.

For a minimal project, create `elide.pkl`:

```pkl
amends "elide:project.pkl"

name = "rewrite-demo"
```

And `src/main/java/demo/Main.java`:

```java
package demo;

import java.util.List;

public class Main {
  public static void main(String[] args) {
    System.out.println("Hello");
  }
}
```

The `RemoveUnusedImports` recipe removes the unused `List` import. The preview leaves the file unchanged; after
applying it, a second run has no changes to make.

## Add recipe modules

Declare recipe JARs in `dependencies.maven.devPackages`. Replace the illustrative coordinate below with your
recipe module's published coordinate and version:

```pkl
dependencies {
  maven {
    devPackages {
      "com.example:rewrite-recipes:1.0.0"
    }
  }
}
```

Run `elide rewrite --list` again to discover the module's recipes. Elide discovers recipe classes and declarative
YAML recipes packaged under `META-INF/rewrite/` in those JARs. Select a declarative recipe by its declared name;
there is no CLI option to load a loose YAML file from the project directory.

Recipes run in the order named on the command line:

```bash
elide rewrite org.openrewrite.java.RemoveUnusedImports org.openrewrite.java.format.AutoFormat --dry-run
```

Elide resolves the recipe libraries separately from the project's application dependencies. Choose recipe modules
compatible with the bundled OpenRewrite 8.90.4; declaring a module that requests a newer core does not upgrade the
runner's core version.

## How the index is used

Elide's [code index](https://elide.help/docs/toolchain/jvm/code-index) supplies dependency type and member information to the Java parser
and the catalog used to discover recipes. A rewrite builds the needed dependency index layers automatically.

Before rewriting, Elide compiles the main Java and Kotlin sources and indexes their references. For supported
explicit type and method preconditions, it uses those references and source tokens to select candidate Java files
before OpenRewrite parses them. OpenRewrite still evaluates the recipe's preconditions on the selected files.

Filtering supports literal type and method searches in declarative preconditions and optional precondition
metadata supplied by recipe modules. Unsupported patterns or incomplete index data retain the full source set.
Recipes that need a project-wide scan also parse the full source set. A smaller candidate set reduces parsing
work, but compilation and indexing have their own cost.

To skip the compilation and filtering step:

```bash
elide rewrite org.openrewrite.java.RemoveUnusedImports --dry-run --no-prefilter
```

This parses every main Java source and still uses the dependency index for type information. It is useful when
comparing a filtered run or attempting a repair on sources that do not compile. `--list` also skips main-source
compilation.

## Options

| Option | Effect |
| --- | --- |
| `--list` | List available recipes and exit. |
| `--dry-run` | Print diffs without applying source changes. |
| `--no-prefilter` | Skip main-source compilation and candidate filtering. |
| `--offline` | Use locally available dependencies; fail if required artifacts are missing. |

The first run can download both project dependencies and recipe libraries. Prepare them with an online run before
using `--offline`. An unknown recipe exits `1`; invalid command usage exits `2`.

## Scope and limits

- Input files come from the main Java source set. Kotlin sources contribute compiled references, but are not
  rewritten; test source sets are not rewrite inputs.
- Recipes that read annotation values on dependency types are unsupported. Dependency type information also omits
  annotation defaults and parameter/type annotations.
- Workspace sibling JARs and dependencies supplied as filesystem paths are not included in the indexed dependency
  type information used by the parser.
- Recipe compatibility varies. Inspect the dry-run diff and run tests after applying changes.

## Maven, Gradle and Bazel projects

These commands use an `elide.pkl` project definition. The [Maven, Gradle and Bazel integrations](https://elide.help/docs/build-tools)
select compilers and other tools inside those builds; they do not import their dependency graphs into
`elide rewrite` or add a rewrite goal, task, or rule.

To use this workflow alongside an existing build, define the relevant source sets, target version, repositories,
and dependencies in an `elide.pkl`, or use [Adopt an existing project](https://elide.help/docs/toolchain/usage/adopt). Keep that definition in
sync with the build you use to test the result.

For code inspection without modifying sources, see [Dependency code index](https://elide.help/docs/toolchain/jvm/code-index).
