Skip to content

Commit 0318ba3

Browse files
committed
Introduce static field-level analysis for migration fixes
- Add `MigrationAnalyzer#analyzeFieldOperations` to introspect field-level operations without executing fixes. - Extend testkit with assertions for field-aware rewrite rules. - Add unit tests for `FieldAwareRule` and enhanced diagnostics. - Update schema tools test coverage for field-level analysis. Signed-off-by: Erik Pförtner <splatcrafter@splatgames.de>
1 parent 5d13ef1 commit 0318ba3

13 files changed

Lines changed: 2404 additions & 1 deletion

File tree

aether-datafixers-core/src/main/java/de/splatgames/aether/datafixers/core/fix/DataFixRegistry.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.util.List;
3535
import java.util.Map;
3636
import java.util.NavigableMap;
37+
import java.util.Set;
3738
import java.util.TreeMap;
3839

3940
/**
@@ -208,6 +209,22 @@ public boolean hasFixesInRange(
208209
return !fixesByVersion.subMap(fromExclusive, false, toInclusive, true).isEmpty();
209210
}
210211

212+
/**
213+
* Returns the set of all type references that have at least one registered fix.
214+
*
215+
* <p>This method enables enumeration of all types known to the registry,
216+
* which is useful for analyzers that need to walk every fix regardless of
217+
* schema changes (e.g., field-level diagnostic analyzers in
218+
* {@link de.splatgames.aether.datafixers.schematools schema-tools}).</p>
219+
*
220+
* @return an unmodifiable snapshot of the registered type references, never {@code null}
221+
* @since 1.0.0
222+
*/
223+
@NotNull
224+
public Set<TypeReference> registeredTypes() {
225+
return Set.copyOf(this.fixesByType.keySet());
226+
}
227+
211228
/**
212229
* Freezes this registry, making it immutable.
213230
*

aether-datafixers-core/src/main/java/de/splatgames/aether/datafixers/core/fix/SchemaDataFix.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,58 @@ protected SchemaDataFix(
145145
@NotNull Schema outputSchema
146146
);
147147

148+
/**
149+
* Introspects the rule produced by this fix without executing a migration.
150+
*
151+
* <p>This method exposes the {@link TypeRewriteRule} that this fix would apply
152+
* for the given input and output schemas. It is intended for static analysis
153+
* tools (e.g.,
154+
* {@link de.splatgames.aether.datafixers.api.rewrite.FieldAwareRule field-level
155+
* diagnostic analyzers}) that need to inspect what a fix does without actually
156+
* running it on data.</p>
157+
*
158+
* <p>Unlike {@link #apply(TypeReference, Dynamic, DataFixerContext)}, this method:</p>
159+
* <ul>
160+
* <li>Does not require any input data</li>
161+
* <li>Does not invoke {@code rule.apply()}</li>
162+
* <li>Does not wrap the rule with diagnostic instrumentation</li>
163+
* <li>Returns the unmodified result of {@link #makeRule(Schema, Schema)}</li>
164+
* </ul>
165+
*
166+
* <h4>Usage Example</h4>
167+
* <pre>{@code
168+
* Schema inputSchema = registry.require(new DataVersion(100));
169+
* Schema outputSchema = registry.require(new DataVersion(200));
170+
* TypeRewriteRule rule = fix.introspectRule(inputSchema, outputSchema);
171+
*
172+
* if (rule instanceof FieldAwareRule fieldAware) {
173+
* for (FieldOperation op : fieldAware.fieldOperations()) {
174+
* System.out.println(op.toSummary());
175+
* }
176+
* }
177+
* }</pre>
178+
*
179+
* <p>Callers are responsible for providing schemas consistent with the fix's
180+
* declared {@link #fromVersion()} and {@link #toVersion()}; passing mismatched
181+
* schemas may yield rules that reference unknown types.</p>
182+
*
183+
* @param inputSchema the schema for the source version, must not be {@code null}
184+
* @param outputSchema the schema for the target version, must not be {@code null}
185+
* @return the rewrite rule that this fix would apply, never {@code null}
186+
* @throws NullPointerException if any argument is {@code null}
187+
* @see #makeRule(Schema, Schema)
188+
* @see de.splatgames.aether.datafixers.api.rewrite.FieldAwareRule
189+
* @since 1.0.0
190+
*/
191+
public final @NotNull TypeRewriteRule introspectRule(
192+
@NotNull final Schema inputSchema,
193+
@NotNull final Schema outputSchema
194+
) {
195+
Preconditions.checkNotNull(inputSchema, "inputSchema must not be null");
196+
Preconditions.checkNotNull(outputSchema, "outputSchema must not be null");
197+
return this.makeRule(inputSchema, outputSchema);
198+
}
199+
148200
@Override
149201
public final @NotNull Dynamic<Object> apply(
150202
@NotNull final TypeReference type,

0 commit comments

Comments
 (0)