You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Applies the adversarially-verified findings of the skill review (13-agent
Opus panel over the stacked #1453+#1461 state; 25 confirmed findings):
Cuts: duplicate string-decision list in 00-decisions; duplicated
commit-message fence in multi-file-batch; four known-pitfalls rows that
were verbatim checklist echoes; copyright restatements reduced to
pointers (formatting-and-commit stays canonical).
Staleness/contradictions: one-file-conversion step 8 and the checklist
final invariant now teach the two-step rename+translate scheme; stale
hard-coded rule counts dropped; overview slice branch now based on
upstream/master; import order stated once (java.* -> org.* -> com.*,
junit inside org, static block separate) and aligned in rule 11 and the
pitfalls row; == equality rule gains the primitive-operand carve-out
(enums stay object-form); rollback recipe corrected for two-step slices
(reset --hard HEAD~N / revert both shas, never -m 1) and stated once;
SKILL.md lambda cheat-sheet aligned with 07 (expression form); Pairs
guidance defers to the no-xbase.lib pitfall; dead "ledger's Method 1"
pointer removed.
Small additions: trailing-\s trap noted at point of use in 4.3;
stable-rule-ID legend in the checklist header; overview Step 0 leads
with the bash listing; examples no longer claim their whitespace WAS
verified (they illustrate; real migrations must verify) and use the
PMD-safe explicit StringBuilder capacity.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ANGM7L3BaEGfGUmPVKRt4
Copy file name to clipboardExpand all lines: .agents/skills/xtend-to-java/examples/00-basic-generator.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -101,4 +101,4 @@ public class MyGenerator {
101
101
-**Template → StringBuilder** (tier 4) because the template has `«IF»` and `«FOR»` control flow.
102
102
-**`it` parameter renamed** to `model` (descriptive name).
103
103
-**`Iterables.filter(iter, Type.class)`** kept as Guava — genuinely more concise for type-safe filtering.
104
-
-**Whitespace verified against `xtend-gen/`** — the template output was confirmed by reading the generated code.
104
+
-**Whitespace must be verified against `xtend-gen/`** — for a real migration, confirm the template output by reading the generated code (this example illustrates the shape).
@@ -52,4 +52,4 @@ public CharSequence renderArgs(final List<Argument> args) {
52
52
- The `«FOR … SEPARATOR ", "»` block became either a stream with `Collectors.joining(", ")` or a boolean flag.
53
53
- The `«a.type»` and `«a.name»` interpolations became `a.getType()` and `a.getName()`.
54
54
- The trailing newline (implicit `\n` at end of template `'''`) is preserved by explicit `"\n"`.
55
-
-**Whitespace was verified against `xtend-gen/`** — the template starts with `(` directly (no leading newline because the first `'''` line has content after the opening mark).
55
+
-**Whitespace must be verified against `xtend-gen/`** — note the template starts with `(` directly (no leading newline because the first `'''` line has content after the opening mark).
Copy file name to clipboardExpand all lines: .agents/skills/xtend-to-java/rules/00-decisions.md
+1-7Lines changed: 1 addition & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -44,7 +44,7 @@ Use Java standard library for collections and streams. Keep Guava only where it
44
44
45
45
## String building — 4-tier decision tree
46
46
47
-
Choose the most readable Java idiom based on the template pattern:
47
+
Choose the most readable Java idiom based on the template pattern (evaluate top-down, first match wins):
48
48
49
49
| # | Template pattern | Java idiom |
50
50
|---|---|---|
@@ -53,12 +53,6 @@ Choose the most readable Java idiom based on the template pattern:
53
53
| 3 | Interpolation, no control flow |`.formatted()` (text block if multi-line, literal if single-line) |
54
54
| 4 | Control flow (`«IF»`, `«FOR»`) |`StringBuilder` with explicit `if`/`for`|
55
55
56
-
**Decision rules — in order:**
57
-
1.**No interpolation, single line** → string literal
58
-
2.**No interpolation, multi-line** → text block
59
-
3.**Interpolation, no control flow** → `.formatted()` (on text block if multi-line, on literal if single-line)
60
-
4.**Control flow** → `StringBuilder` — always
61
-
62
56
**`.formatted()` limitations — fall back to concatenation ONLY when:**
63
57
- The interpolated expression is glued to adjacent text with no whitespace/delimiter boundary, making `%s` ambiguous (e.g., `"pre" + expr + "suf"` where `"pre%ssuf"` is confusing)
64
58
- The template contains literal `%` characters (would need escaping as `%%`)
Copy file name to clipboardExpand all lines: .agents/skills/xtend-to-java/rules/08-operator-overloads.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,6 +5,7 @@
5
5
-`===` (Xtend identity-equals) → `==` (Java)
6
6
-`!==` (Xtend identity-not-equals) → `!=` (Java)
7
7
-`==` in Xtend is `.equals()` — convert to `.equals()` or `Objects.equals()` (use `Objects.equals()` when either operand could be null).
8
+
-**Applies to object/boxed operands.**`==`/`!=` between primitive-typed operands (int, long, short, byte, char, float, double, boolean) compile to Java `==`/`!=`, not `.equals()` — check operand types in `xtend-gen/` first. (Enums are NOT primitives: enum `==` follows the object form shown in `xtend-gen/`.)
Copy file name to clipboardExpand all lines: .agents/skills/xtend-to-java/rules/09-misc-syntax.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -155,7 +155,7 @@ Rules:
155
155
-**Multiple return paths**: Xtend implicitly returns the last expression. Add explicit `return` on **every** non-void path.
156
156
-**`class` keyword as literal**: `SomeClass` used as a class literal → `SomeClass.class`.
157
157
-**Static method reference `::`**: `ClassName::methodName` → `ClassName.methodName()` (or keep as a Java method reference where the receiving API accepts one).
-**Pairs**: `key -> value`compiles to `org.eclipse.xtext.xbase.lib.Pair` — never keep it in migrated Java. Use a small `private record` (nulls OK) or `Map.entry` (rejects null); see [`workflow/known-pitfalls.md`](../workflow/known-pitfalls.md) (xbase.lib row).
159
159
-**`^keyword`** (escaped reserved word in Xtend): Drop the `^` — most Xtend escapes aren't Java keywords.
Copy file name to clipboardExpand all lines: .agents/skills/xtend-to-java/workflow/known-pitfalls.md
+4-8Lines changed: 4 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,27 +11,23 @@ Consolidated table of common mistakes and their fixes. Review before and after e
11
11
|**Implicit returns**| Xtend methods return the last expression. The compiler catches missing returns but not wrong ones. |
12
12
|**Property access vs getter**| Xtend `obj.name` may call `getName()`. In Java, write `obj.getName()` explicitly. Check `xtend-gen/` if unsure. |
13
13
|**`CoreException` handling**| Xtend silently wraps checked exceptions. Java doesn't. Add explicit `try/catch` — the `xtend-gen/` file shows what was generated. |
14
-
|**`val` leaks**| Never use `var`. Use the explicit type. |
15
14
|**Invented Javadoc**| Never add **class/member Javadoc** that wasn't in the original. This is a migration, not a rewrite. (The file copyright header is the one exception — see next row — it is always normalised, not preserved.) |
16
15
|**Generated supertypes live in `src-gen/`, not `xtend-gen/`**| When the class extends/overrides a generated `Abstract*` base (Module/Setup/runtime/UI), read that base in `src-gen/` (committed, present without a build — unlike `xtend-gen/`) for inherited constructor signatures, the real `@Override` targets, and the return types Xtend inferred. Don't guess the supertype API. |
17
-
|**Copyright header ≠ "preserve original"**| The file MUST start with the Avaloq banner header, **replacing** whatever the source had — including a `/* generated by Xtext x.y */` stub marker or a `/** … */` Javadoc-style copyright block (these are the easy ones to wrongly "preserve", especially on IDE module/setup stubs). Normalising to the banner is required, not inventing. Match a sibling `.java` in the module. |
18
-
|**Missing `@throws` tags**| When Java migration adds `throws` and method already has Javadoc, Checkstyle requires `@throws`. Add it; don't create Javadoc just for the tag. |
19
-
|**Duplicate string literals**| Checkstyle flags strings appearing 2+ times. In tests, extract to constants. In generators, use `CHECKSTYLE:CONSTANTS-OFF/ON`. |
16
+
|**Copyright header ≠ "preserve original"**| Always normalise to the Avaloq banner, replacing whatever the source had — see [`formatting-and-commit.md`](./formatting-and-commit.md) §Copyright header. |
20
17
|**`@Data` / `@Accessors`**| These generate code at compile time. The `xtend-gen/` output shows exactly what — copy equals/hashCode/toString/getters from there. |
21
18
|**`@Tag` fields must not be `final`**|`TagExtension` assigns tag values via `Field.setInt()` at runtime. `Field.setInt()` on a `final` field fails on Java 9+ even after `setAccessible(true)`. IDE formatters and save-actions silently add `final` to `int` fields — always strip it from `@Tag` fields. See [`rules/09-misc-syntax.md`](../rules/09-misc-syntax.md) §9.6. |
22
19
|**`BasicEList` in generic code**| Needs explicit type parameter — `new BasicEList<X>()`. |
23
20
|**StringBuilder in `xtend-gen/`**| If `xtend-gen/` has `StringConcatenation` but Xtend has a template, that's the signal to use text block or `.formatted()` (tier 1–3) or `StringBuilder` (tier 4). |
24
21
|**Non-parameterized logging**| Xtend files often have `"msg" + x` in log calls. Fix to `{}` placeholders. |
25
22
|**PMD missing type-resolution**| Always `compile` before `pmd:check` or you'll miss `MissingOverride`, `LooseCoupling` etc. |
26
23
|**`--fail-at-end` hides failures**| Check the final BUILD line, not intermediate output. |
27
-
|**Dispatch method names**| Keep underscores. Suppress with `@SuppressWarnings`. Never rename. |
28
24
|**IDE save actions**| "Organize Imports" in Eclipse may trigger save actions that auto-convert string concatenation to text blocks. Auto-conversion produces wrong results. Review `git diff` after any IDE action. |
29
-
|**Import order**|Two groups (blank line between, no wildcards): framework (`java.*`/`javax.*`/`org.*`) first, then `com.*` alphabetically — so `com.avaloq.*` precedes `com.google.*`. Not enforced by checkstyle (no `ImportOrder` module); wrong order is diff churn only. |
25
+
|**Import order**|See [`rules/01-imports-and-package.md`](../rules/01-imports-and-package.md) for the canonical order. Not enforced by checkstyle (no `ImportOrder` module); wrong order is diff churn only — `com.avaloq.*` precedes `com.google.*`. |
30
26
|**Eclipse CLI formatter**| Does NOT organize imports — only code formatting. Import order must be correct from the start. |
31
27
|**IllegalCatch / IllegalThrows**| checkstyle `IllegalCatch` bans `catch (Exception/Throwable/RuntimeException)` — use the specific type, or a multi-catch (`catch (BadLocationException \| TemplateException e)`) re-thrown as `new IllegalStateException(e)`. `IllegalThrows` bans `throws Throwable/RuntimeException/Error` (plain `throws Exception` IS allowed — acceptable on a `@Test` when the JUnit-invoked API declares it; otherwise narrow to the actual checked type). Don't suppress `PMD.AvoidCatchingGenericException`. |
32
-
|**Rollback**|If already pushed: `git revert -m 1 <sha>`. If local only: `git reset --hard HEAD~1`. After reverting, build and test. |
28
+
|**Rollback**|A slice is 2-3 commits — plain `HEAD~1` strands the rename commit. Use the recipe in [`formatting-and-commit.md`](./formatting-and-commit.md) §Rollback. After reverting, build and test. |
33
29
|**`ByteArrayInputStream.close()`**| It's a no-op. Safe to remove entirely. |
34
-
|**`==` in Xtend**| Xtend `==` is `.equals()`, not identity. Convert to `.equals()` or `Objects.equals()`. Only`===`/`!==` are identity. |
30
+
|**`==` in Xtend**|On object/boxed operands, Xtend `==` is `.equals()` — convert to `.equals()`/`Objects.equals()`; only`===`/`!==` are identity. Between primitive-typed operands it compiles to Java `==` — check operand types in `xtend-gen/` (see [`rules/08-operator-overloads.md`](../rules/08-operator-overloads.md) §8.1). |
35
31
36
32
## Learnings from the per-module migration campaign
0 commit comments