Skip to content

Commit dc8f9f5

Browse files
Improve preconditions documentation (#442)
* Improve preconditions documentation Fixes: #441 * Update docs/reference/yaml-format-reference.md Co-authored-by: Tim te Beek <tim@moderne.io> * Update docs/reference/yaml-format-reference.md Co-authored-by: Tim te Beek <tim@moderne.io> --------- Co-authored-by: team-moderne[bot] <mike-solomon@users.noreply.github.com> Co-authored-by: Tim te Beek <tim@moderne.io>
1 parent 8f2c4f8 commit dc8f9f5

File tree

1 file changed

+32
-6
lines changed

1 file changed

+32
-6
lines changed

docs/reference/yaml-format-reference.md

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Note that values passed to declarative recipes are subject to YAML interpretatio
1616

1717
There are two places where you can define an OpenRewrite YAML file:
1818

19-
1. Within the `rewrite.yml` file of a project that applies rewrite recipes via the [rewrite-gradle-plugin](gradle-plugin-configuration.md) or [rewrite-maven-plugin](rewrite-maven-plugin.md)
19+
1. Within the `rewrite.yml` file of a project that applies rewrite recipes via the [rewrite-gradle-plugin](./gradle-plugin-configuration.md) or [rewrite-maven-plugin](./rewrite-maven-plugin.md)
2020
2. Inside the `META-INF/rewrite` folder of a JAR (such as in the [rewrite-testing-frameworks](https://github.com/openrewrite/rewrite-testing-frameworks/tree/main/src/main/resources/META-INF/rewrite))
2121

2222
If you define a recipe or style in the `rewrite.yml` file, they _will not_ be included in the JARs published from your project.
@@ -48,25 +48,32 @@ You can find the full recipe schema [here](https://github.com/openrewrite/rewrit
4848
| tags | array of strings | A list of strings that help categorize this recipe |
4949
| estimatedEffortPerOccurrence | [duration](https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html#parse-java.lang.CharSequence-) | The expected amount of time saved each time this recipe fixes something |
5050
| causesAnotherCycle | boolean | Whether or not this recipe can cause another cycle (defaults to false) |
51-
| [recipeList](yaml-format-reference.md#recipe-list) | array of recipes | The list of recipes which comprise this recipe |
51+
| [recipeList](#recipe-list) | array of recipes | The list of recipes which comprise this recipe |
5252

5353
### Preconditions
5454

55-
Preconditions are used to limit which source files a recipe is allowed to make edits to. In other words, they act as filters that allow you to target specific files, directories, or patterns.
55+
Preconditions are used to limit which source files a recipe is allowed to make edits to. In other words, they act as filters that allow you to target specific files, directories, or patterns.
5656

57-
This is particularly useful when you want a recipe to run only on a subset of the codebase.
57+
This is particularly useful when you want a recipe to run only on a subset of the codebase.
5858

5959
Technically, almost any recipe can serve as a precondition, but in practice, lightweight and fast recipes – often based on simple searches – are preferred. These ensure performance remains optimal during large-scale code transformations.
6060

6161
When a recipe is used as a precondition, it determines whether a source file should be considered eligible for transformation. In other words, preconditions don’t make changes themselves, they just decide if the targeted recipe(s) should be allowed to make changes to a file.
6262

6363
If a file does not satisfy the precondition, the recipe list is skipped for _that_ file entirely. When multiple recipes are used as preconditions, _all_ of them must make a change to the file for it to be considered to meet the precondition.
6464

65-
:::info
65+
:::info
6666
Changes made by preconditions are not included in the final result of the recipe.
6767
Changes made by preconditions are used _only_ to determine if the recipe should edit a particular source file.
6868
:::
6969

70+
It's important to understand that preconditions operate on **already-parsed** source files. OpenRewrite runs in two distinct phases:
71+
72+
1. **Parsing phase**: All source files (except those in `exclusions`) are parsed into LSTs
73+
2. **Recipe execution phase**: Preconditions determine which parsed files the recipe should modify
74+
75+
This means preconditions cannot prevent files from being parsed - they only control whether recipes apply to files that have already been successfully parsed.
76+
7077
:::warning
7178
Preconditions only apply to files that already exist in the source set. They cannot prevent the creation of new files.
7279

@@ -75,6 +82,25 @@ If a recipe generates files during the `generate` phase, those files will always
7582
To conditionally generate files, implement a custom scanning recipe. You can define logic in the scanning phase based on existing source files, and use that context in the generate phase to control whether a file should be created.
7683
:::
7784

85+
#### Preconditions vs. Exclusions
86+
87+
Since preconditions work on already-parsed files, they're not the right tool if you need to skip parsing certain files. Below is a table that should help you make an informed decision on when to use one feature over another:
88+
89+
| Feature | Purpose | When It Runs | Use Case |
90+
|-------------------|-----------------------------|----------------------|-----------------------------------------------------------------------|
91+
| **Exclusions** | Skip parsing files entirely | During parsing phase | Avoid parse errors, skip expensive directories, ignore generated code |
92+
| **Preconditions** | Control recipe application | After parsing phase | Apply recipes to specific subsets of successfully-parsed files |
93+
94+
**Example scenario:** If you have Groovy files that fail to parse in a Java project:
95+
96+
***Don't use preconditions** - the Groovy files will still be parsed and fail
97+
***Use exclusions** - skip parsing Groovy files: `exclusion("**/*.groovy")`
98+
99+
For information on how to configure each of these, please see:
100+
101+
* [Gradle plugin configuration](./gradle-plugin-configuration.md#configuring-the-rewrite-dsl)
102+
* [Maven plugin configuration](./rewrite-maven-plugin.md)
103+
78104
#### Adding preconditions to a YAML recipe
79105

80106
To create these top-level preconditions, you'll need to add the `preconditions` map to your declarative recipe's YAML. This object is a list of one or more recipes (formatted the same way as the [recipeList](#recipe-list)).
@@ -226,7 +252,7 @@ You can find the full style schema [here](https://github.com/openrewrite/rewrite
226252
:::
227253

228254
| Key | Type | Description |
229-
| ------------ | ---------------- | ----------------------------------------------------------------- |
255+
|--------------|------------------|-------------------------------------------------------------------|
230256
| type | const | A constant: `specs.openrewrite.org/v1beta/style` |
231257
| name | string | A fully qualified, unique name for this style |
232258
| displayName | string | A human-readable name for this style (does not end with a period) |

0 commit comments

Comments
 (0)