diff --git a/.agents/skills/xtend-to-java/SKILL.md b/.agents/skills/xtend-to-java/SKILL.md index 2703e81652..6773ea2723 100644 --- a/.agents/skills/xtend-to-java/SKILL.md +++ b/.agents/skills/xtend-to-java/SKILL.md @@ -23,9 +23,13 @@ the `xtend-gen/` output — what Xtend compiled to Java before the migration. ## Hard Rules — Non-Negotiable -> **Hard rule — read BOTH `.xtend` source AND `xtend-gen/` output in full before writing ANY Java.** +> **Hard rule — read BOTH `.xtend` source AND a behavioural ground truth in full before writing ANY Java.** > No exceptions regardless of file size. A 5-line file with one template expression can have > surprising whitespace behavior. See [`workflow/overview.md`](./workflow/overview.md) for the full rationale. +> +> The ground truth is the `xtend-gen/` compiled output. **`xtend-gen/` is gitignored and only exists after a build** — if it is absent you must still obtain a ground truth before writing Java: either (a) build the module to generate `xtend-gen/`, or (b) if a pre-converted reference branch exists, read its `.java` (it was produced from `xtend-gen/` and encodes the same behavior). **Never write Java from the `.xtend` source alone.** +> +> Separately, if the class extends/overrides a **generated supertype** (`Abstract…Module`, `…Setup`, runtime/UI bases), read that supertype under `src-gen/` (committed, present without a build) — it is the authoritative source for inherited constructor signatures, real `@Override` targets, and Xtend-inferred return types. See [`workflow/overview.md`](./workflow/overview.md) §3b-also. > **Template whitespace is the #1 source of migration bugs.** > Xtend strips indentation relative to control structures. The only reliable way to know what diff --git a/.agents/skills/xtend-to-java/workflow/formatting-and-commit.md b/.agents/skills/xtend-to-java/workflow/formatting-and-commit.md index 6b4c672d46..c364710e92 100644 --- a/.agents/skills/xtend-to-java/workflow/formatting-and-commit.md +++ b/.agents/skills/xtend-to-java/workflow/formatting-and-commit.md @@ -2,7 +2,7 @@ ## Copyright headers -Every `.java` file must include the Avaloq copyright header. Files must start with: +Every `.java` file must start with the exact Avaloq banner header below: ```java /******************************************************************************* * Copyright (c) 2016 Avaloq Group AG and others. @@ -16,6 +16,20 @@ Every `.java` file must include the Avaloq copyright header. Files must start wi *******************************************************************************/ ``` +> **This banner REPLACES whatever header the source carried — it is not "preserve the original".** +> The `.xtend` source (or its `xtend-gen/` output) commonly starts with a different header, e.g. +> a generated stub marker `/* generated by Xtext 2.x */`, or a `/** ... */` Javadoc-style copyright +> block without the asterisk banner. **Normalise all of these to the banner above**, matching the +> existing hand-written `.java` files in the same module (check a sibling like `Activator.java`). +> +> The "never invent / preserve Javadoc exactly" rule (Step 3d, validation rule 1, the *Invented +> Javadoc* pitfall) applies to **class and member Javadoc and to behaviour** — it does **not** apply +> to the file-level copyright header, which is always normalised to this banner. Swapping in the +> required banner is not "inventing". +> +> This holds even for files that look generated (IDE module/setup stubs): once migrated to +> hand-maintained Java they get the standard banner like every other `.java` in the repo. + Verify before committing. ## Format in Eclipse before pushing diff --git a/.agents/skills/xtend-to-java/workflow/known-pitfalls.md b/.agents/skills/xtend-to-java/workflow/known-pitfalls.md index b4088314ca..63579751eb 100644 --- a/.agents/skills/xtend-to-java/workflow/known-pitfalls.md +++ b/.agents/skills/xtend-to-java/workflow/known-pitfalls.md @@ -12,7 +12,9 @@ Consolidated table of common mistakes and their fixes. Review before and after e | **Property access vs getter** | Xtend `obj.name` may call `getName()`. In Java, write `obj.getName()` explicitly. Check `xtend-gen/` if unsure. | | **`CoreException` handling** | Xtend silently wraps checked exceptions. Java doesn't. Add explicit `try/catch` — the `xtend-gen/` file shows what was generated. | | **`val` leaks** | Never use `var`. Use the explicit type. | -| **Invented Javadoc** | Never add Javadoc that wasn't in the original. This is a migration, not a rewrite. | +| **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.) | +| **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. | +| **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. | | **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. | | **Duplicate string literals** | Checkstyle flags strings appearing 2+ times. In tests, extract to constants. In generators, use `CHECKSTYLE:CONSTANTS-OFF/ON`. | | **`@Data` / `@Accessors`** | These generate code at compile time. The `xtend-gen/` output shows exactly what — copy equals/hashCode/toString/getters from there. | diff --git a/.agents/skills/xtend-to-java/workflow/overview.md b/.agents/skills/xtend-to-java/workflow/overview.md index ffc5024e6b..a483570e09 100644 --- a/.agents/skills/xtend-to-java/workflow/overview.md +++ b/.agents/skills/xtend-to-java/workflow/overview.md @@ -99,6 +99,12 @@ Do not write the Java file first and then vet it — read the references first, > to read what the Xtend compiler produced in `xtend-gen/`. > > **There is no file small enough to skip this step.** +> +> **If `xtend-gen/` is not present:** it is gitignored and only exists after a build, so a fresh +> checkout often has none. You may NOT skip the ground truth — obtain it one of two ways: +> (a) build the module to generate `xtend-gen/`, or (b) if a pre-converted reference branch exists, +> read its `.java` for this file (it was produced from `xtend-gen/` and encodes the same behavior). +> Wherever this document says "read `xtend-gen/`", that reference `.java` is the equivalent ground truth. ### 3a. Read the Xtend source — understand intent and structure @@ -117,6 +123,20 @@ Find the corresponding generated file under `xtend-gen/` (same package, same cla - The precise exception handling Xtend generated - Which implicit null checks, type casts, and conversions Xtend inserted +### 3b-also. Read `src-gen/` for any generated supertype + +`xtend-gen/` is the Xtend *compiler* output for the file's own logic. It is **not** the same as +`src-gen/`, the MWE2/Xtext *generator* output that holds the `AbstractModule`, +`Abstract…Setup`, runtime/UI module bases, etc. that the migrated class `extends`/`override`s. + +If the class extends or overrides a generated type, read that supertype under `src-gen/` (same +module). Unlike `xtend-gen/`, **`src-gen/` is committed**, so it is present without a build. It is +the authoritative source for: +- inherited **constructor signatures** (an `@FinalFieldsConstructor` must call the right `super(...)`) +- which methods are genuinely `@Override`s (vs new methods) and their **exact return types** — Xtend + often infers a return type from the override target that you must restate explicitly in Java +- the binding methods a `*Module` is expected to provide + ### 3c. Template whitespace — verify against `xtend-gen/` Xtend's template whitespace rules: @@ -135,7 +155,7 @@ Xtend's template whitespace rules: After reading both references, write Java that: 1. **Matches the `xtend-gen/` behavior exactly** for all string outputs, method signatures, and control flow 2. **Uses idiomatic Java** (text blocks, `.formatted()`, concatenation) instead of `StringConcatenation` -3. **Preserves the original Javadoc exactly** — never invent +3. **Preserves the original class/member Javadoc exactly** — never invent. (The file copyright header is the exception: always normalise it to the Avaloq banner per [`formatting-and-commit.md`](./formatting-and-commit.md) — replacing any generated-stub or Javadoc-style header — which is not "inventing".) 4. **Follows the quality checklist** in [`workflow/validation-checklist.md`](./validation-checklist.md) --- diff --git a/.agents/skills/xtend-to-java/workflow/validation-checklist.md b/.agents/skills/xtend-to-java/workflow/validation-checklist.md index 4a353b1ece..5e217419fc 100644 --- a/.agents/skills/xtend-to-java/workflow/validation-checklist.md +++ b/.agents/skills/xtend-to-java/workflow/validation-checklist.md @@ -10,7 +10,7 @@ Run through this list before declaring a conversion done. Every item is a hard g | # | Rule | Requirement | |---|------|-------------| -| 1 | Javadoc preservation | Copy Javadoc from Xtend source verbatim. Never generate/guess Javadoc that wasn't in the original. | +| 1 | Javadoc preservation | Copy **class and member Javadoc** from Xtend source verbatim. Never generate/guess Javadoc that wasn't in the original. (Does **not** cover the file copyright header — see rule 21, which always normalises it.) | | 2 | `@throws` tags | Only add when method already has Javadoc AND migrated signature declares `throws`. Don't create Javadoc just for the tag. | ### Types and variables @@ -82,7 +82,7 @@ Run through this list before declaring a conversion done. Every item is a hard g | # | Rule | Requirement | |---|------|-------------| -| 21 | Copyright headers | File starts with `/* Copyright (c) Avaloq Group AG ...` block. | +| 21 | Copyright headers | File starts with the exact Avaloq `/**…**/` banner header (see [`formatting-and-commit.md`](./formatting-and-commit.md)). This **replaces** any header the source carried — a `/* generated by Xtext x.y */` stub marker or a `/** … */` Javadoc-style copyright block. Normalising to the banner is **not** "inventing" (rule 1 does not apply to the copyright header). Match a sibling `.java` in the module. | | 22 | Commit format | `refactor: migrate Xtend to Java - `. Single commit. | | 28 | Infrastructure cleanup | Remove Xtend from MANIFEST.MF, build.properties, .classpath, .project; delete `xtend-gen/` directory (when module fully off Xtend). | @@ -114,8 +114,8 @@ Run through this list before declaring a conversion done. Every item is a hard g - [ ] Semicolons added to every statement. - [ ] Explicit visibility on every class, method, and field. - [ ] All imports updated (no wildcards, no unused, correct order). -- [ ] All comments and Javadoc preserved exactly. -- [ ] Copyright header preserved/added. +- [ ] All comments and class/member Javadoc preserved exactly. +- [ ] Copyright header is the exact Avaloq banner — **replacing** any generated-stub or Javadoc-style header the source had (not preserved from source). - [ ] Checked exceptions handled (`throws` clause or `try`/`catch` with specific types). - [ ] The `.xtend` file is deleted; the `.java` file is added; both never coexist. @@ -131,4 +131,4 @@ Run through this list before declaring a conversion done. Every item is a hard g ## Behaviour parity -- [ ] Diff against the `xtend-gen/` output. The hand-converted version should be materially equivalent (often shorter, always more idiomatic). Any behaviour-shifting deviation must be intentional and called out in the commit message. +- [ ] Diff against the behavioural ground truth — the `xtend-gen/` output, or the pre-converted reference branch's `.java` when `xtend-gen/` is not built (see [`overview.md`](./overview.md) Step 3b). The hand-converted version should be materially equivalent (often shorter, always more idiomatic). Any behaviour-shifting deviation must be intentional and called out in the commit message.