Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
895b56d
feat: migrate check.core Xtend files to Java 21
joaodinissf Feb 27, 2026
668482a
fix: handle checked CoreException in CheckGeneratorExtensions
joaodinissf Feb 27, 2026
e416bb7
chore: add migration docs and update project files
joaodinissf Feb 28, 2026
9be7c86
feat: migrate Batch 2+3 Xtend files to Java 21 (28 files)
joaodinissf Feb 28, 2026
13e0fd9
feat: migrate Batch 4 Xtend files to Java 21 (13 files)
joaodinissf Feb 28, 2026
0a49642
feat: migrate Batch 5 Xtend files to Java 21 (9 files)
joaodinissf Feb 28, 2026
49e886e
feat: migrate Batch 6 Xtend files to Java 21 (10 files)
joaodinissf Feb 28, 2026
716c813
feat: migrate Batch 7 Xtend files to Java 21 (6 files)
joaodinissf Feb 28, 2026
7d6afad
feat: migrate Batch 8 Xtend files to Java 21 (17 files)
joaodinissf Feb 28, 2026
b6f36bb
feat: migrate Batch 9 Xtend files to Java 21 (5 files) — migration co…
joaodinissf Mar 1, 2026
b377176
chore: remove Xtend build infrastructure after migration
joaodinissf Mar 1, 2026
13cdb52
style: resolve all PMD and checkstyle warnings in migrated code
joaodinissf Mar 1, 2026
cfbd1f4
style: fix remaining CI violations (SpotBugs, PMD)
joaodinissf Mar 1, 2026
3d34c1b
style: resolve all PMD and checkstyle warnings in generator, scope, a…
joaodinissf Mar 1, 2026
3b3f888
style: fix UnnecessaryBoxing in AnnotationAwareAntlrGrammarGenerator
joaodinissf Mar 1, 2026
a15f188
style: fix all remaining PMD and checkstyle violations in migrated code
joaodinissf Mar 1, 2026
9b443d0
style: fix remaining PMD violations (StringToString, UnnecessaryCast,…
joaodinissf Mar 1, 2026
ba4ed9f
style: fix UseCollectionIsEmpty in PropertiesInferenceHelper
joaodinissf Mar 1, 2026
9eaf951
fix: resolve BasicEList compilation error in XbaseGeneratorFragmentTest
joaodinissf Mar 1, 2026
51d439d
docs: add handover summary for Xtend-to-Java migration session
joaodinissf Mar 1, 2026
b26386d
refactor: replace StringBuilder patterns with String.format() and tex…
joaodinissf Mar 2, 2026
76087e2
refactor: convert string concatenation to text blocks in test DSL sou…
joaodinissf Mar 3, 2026
7194985
refactor: convert remaining StringBuilder patterns to text blocks and…
joaodinissf Mar 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,3 @@
*.java._trace
*.smap
*.checkbin
*.xtendbin
/*/xtend-gen/*
!/*/xtend-gen/.gitignore
11 changes: 4 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ This document helps AI coding agents work effectively with the DSL DevKit codeba
- **Java**: 21+
- **Maven**: 3.9+
- **Tycho**
- **Xtext/Xtend**
- **Xtext**

## Key Directories

Expand Down Expand Up @@ -50,7 +50,7 @@ export WORKSPACE=$(pwd)

### PMD
- **Ruleset**: `ddk-configuration/pmd/ruleset.xml`
- Excludes: `src-gen/`, `src-model/`, `xtend-gen/`
- Excludes: `src-gen/`, `src-model/`

### Checkstyle
- **Config**: `ddk-configuration/checkstyle/avaloq.xml`
Expand Down Expand Up @@ -79,10 +79,6 @@ Tests are disabled by default and activated only in test bundles.
These directories contain generated code - do not edit manually:
- `src-gen/` - Xtext generated sources
- `src-model/` - EMF model generated sources
- `xtend-gen/` - Xtend transpiled Java sources

### Xtend
- `.xtend` files in `src/` compile to Java in `xtend-gen/`

## Common Tasks

Expand All @@ -95,7 +91,7 @@ These directories contain generated code - do not edit manually:

### Fixing PMD Violations
1. Check ruleset at `ddk-configuration/pmd/ruleset.xml`
2. Violations in generated code (`src-gen/`, `xtend-gen/`) are excluded
2. Violations in generated code (`src-gen/`) are excluded
3. Run `mvn pmd:check -f ./ddk-parent/pom.xml` to verify fixes

### Fixing Checkstyle Violations
Expand All @@ -116,3 +112,4 @@ xvfb-run mvn verify -f ./ddk-parent/pom.xml -pl :com.avaloq.tools.ddk.xtext.test
- **Platform**: GitHub Actions
- **Workflow**: `.github/workflows/verify.yml`
- Triggers on: push to master, pull requests

118 changes: 118 additions & 0 deletions HANDOVER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Handover — Fix All PMD & Checkstyle Violations for Xtend-to-Java Migration

*Generated: Sun Mar 1 23:26 CET 2026*
*Branch: feature/xtend-to-java-migration*
*Last commit: 645407dd5 — fix: resolve BasicEList compilation error in XbaseGeneratorFragmentTest*

## What We Were Working On

Resolving all PMD and Checkstyle violations introduced by the Xtend-to-Java migration on the `feature/xtend-to-java-migration` branch. The migration converted ~90 Xtend files to Java 21 across the entire dsl-devkit project, and the auto-generated Java code had widespread style violations that failed CI.

The initial plan estimated ~542 violations across 12 files in 4 modules. In practice, violations were discovered iteratively across **10+ modules and 36 files**, totaling roughly 600+ violations.

## What Got Done

- [x] Fixed all PMD and Checkstyle violations — CI is fully green (all 3 jobs: maven-verify, pmd, checkstyle)
- [x] 4 commits covering the fixes:
- `18fb5a34e` — bulk fix across 33 files in 10 modules
- `8d4d826d7` — StringToString, UnnecessaryCast, MissingOverride, LooseCoupling
- `ab0d6df10` — UseCollectionIsEmpty in PropertiesInferenceHelper
- `645407dd5` — BasicEList compilation error in XbaseGeneratorFragmentTest
- [x] All pushed and CI confirmed green (run 22551555855)

### Modules touched:
- `check.core` (8 files) — largest module, ~510 violations
- `check.core.test` (10 files) — ~150 violations
- `check.ui` (2 files)
- `check.ui.test` (1 file)
- `checkcfg.core` (4 files)
- `checkcfg.core.test` (4 files)
- `xtext.format.generator` (1 file)
- `xtext.export.generator` (1 file)
- `xtext.generator.test` (1 file)
- `xtext.generator` (1 file)

### Fix categories applied:
- **FinalParams** (~354): Added `final` to method parameters
- **UnnecessaryReturn** (~53): Removed trailing `return;` in void dispatch methods
- **MethodName** (~27): Class-level `@SuppressWarnings({"checkstyle:MethodName"})` for dispatch methods (`_format()`, `_scope()`, etc.)
- **AppendCharacterWithChar** (~20): `.append("x")` → `.append('x')`
- **MultipleStringLiterals** (~32): `CHECKSTYLE:CONSTANTS-OFF/ON` wrappers
- **MemberName** (~6): Renamed `_fieldName` → `fieldName`
- **MissingOverride**: Added `@Override` annotations
- **LooseCoupling**: Changed implementation types to interfaces (`BasicEList` → `EList`, `TreeMap` → `Map`, `ArrayList` → `List`)
- **InsufficientStringBufferDeclaration**: Increased `StringBuilder` capacities
- **Various others**: IllegalCatch suppression, JavadocMethod tags, UseIndexOfChar, ExhaustiveSwitchHasDefault, etc.

## What Worked

- **Parallel team agents** for the initial bulk work — two agents handled `check.core` (8 files) and the smaller modules (4 files) simultaneously, getting the majority of mechanical fixes done quickly.
- **Iterative verification loop** — running `mvn checkstyle:check pmd:check` after each round of fixes, then fixing what remained. This was essential because new modules kept appearing as CI checks expanded beyond the initial plan.
- **Suppression patterns** for rules that couldn't be fixed (dispatch method names, intentional exception catching):
- `// CHECKSTYLE:CONSTANTS-OFF` / `// CHECKSTYLE:CONSTANTS-ON`
- `// CHECKSTYLE:CHECK-OFF <Rule>` / `// CHECKSTYLE:CHECK-ON <Rule>`
- `@SuppressWarnings({"checkstyle:MethodName", "PMD.UnusedFormalParameter"})`

## What Didn't Work

- **Local PMD checks without `compile`** — Running `mvn checkstyle:check pmd:check` without a prior `compile` phase misses PMD rules that require type resolution (MissingOverride, UnnecessaryCast, LooseCoupling, UseCollectionIsEmpty). This caused violations to slip through local verification and only appear in CI.
- **Grepping build output with `head -30`** — When verifying with `--fail-at-end`, the first 30 lines were all `0 Checkstyle violations` messages, hiding the actual `BUILD FAILURE` at the bottom. A compilation error was missed because of this.
- **Initial scope estimation** — The plan identified 4 modules but violations existed in 10+. Each CI run surfaced new modules we hadn't checked locally.
- **Agent-generated fixes sometimes incomplete** — Agents fixed the obvious cases but missed edge cases (e.g., expanding a star import but not checking all usages, changing an import without updating all references).

## Key Decisions & Rationale

1. **Suppress vs fix for MethodName violations**: Dispatch methods like `_format()`, `_scope()`, `_computeTypes()` must keep underscore prefixes (Xtext dispatch pattern). Used class-level `@SuppressWarnings` rather than renaming.

2. **CHECKSTYLE:CONSTANTS-OFF for MultipleStringLiterals**: Template-generating methods that build Java source code via StringBuilder inherently have repeated string literals. Extracting constants would hurt readability.

3. **CHECKSTYLE:CHECK-OFF for IllegalCatch**: Some methods intentionally catch `Exception` (e.g., in code generation utilities). Suppressed rather than changed.

4. **Switch to `mvn clean compile pmd:check` for local verification**: After discovering that PMD needs compiled classes for type-resolution rules, this became the correct local verification command.

## Lessons Learned & Gotchas

1. **PMD type-resolution rules need compiled code**: `MissingOverride`, `UnnecessaryCast`, `LooseCoupling`, `UseCollectionIsEmpty` all need class files. Always run `mvn clean compile pmd:check` locally, not just `pmd:check`.

2. **Checkstyle does NOT need compilation** — it works purely on source files.

3. **`--fail-at-end` hides early failures** — When grepping output, always check the final `BUILD SUCCESS/FAILURE` line, not just intermediate results.

4. **Xtend dispatch methods produce underscore-prefixed Java methods** — These are a known pattern (`_methodName`) that Xtext's dispatch resolution depends on. They cannot be renamed.

5. **CI modules are discovered incrementally** — The Maven reactor with `--fail-at-end` skips downstream modules when an upstream module fails. Fixing one module can unblock compilation of others, revealing their violations.

6. **`ByteArrayInputStream.close()` is a no-op** — When simplifying try-finally around BAIS, safe to just remove the close call entirely.

7. **PMD's InsufficientStringBufferDeclaration calculates actual string sizes** — A StringBuilder(512) may still trigger if the appended content totals >512 bytes. Some methods needed 2048.

## Next Steps

1. **Consider squashing the 4 style-fix commits** before merging to master — they're all part of the same logical change. The commits are `18fb5a34e`, `8d4d826d7`, `ab0d6df10`, `645407dd5`.

2. **Clean up untracked `xtend-gen/` directories** — 25 untracked `xtend-gen/` directories remain from the migration. These should either be `.gitignore`d or removed.

3. **Consider adding `mvn clean compile pmd:check` to the local dev workflow** — Document that `pmd:check` alone misses type-resolution rules.

4. **PR is ready for review** — CI is green. The PR is #1274 on the dsl-devkit repo.

## Key Files & Locations

| File | Purpose |
|------|---------|
| `check.core/.../formatting2/CheckFormatter.java` | Largest single file fix (~143 violations). Dispatch-based formatter. |
| `check.core/.../jvmmodel/CheckJvmModelInferrer.java` | JVM model inference with dispatch methods. Had LooseCoupling, UnnecessaryCast, MissingOverride. |
| `check.core/.../generator/CheckGeneratorExtensions.java` | Code generation utilities. Star import expansion, JavadocMethod, IllegalCatch. |
| `check.core/.../generator/CheckGenerator.java` | Main code generator. AppendCharWithChar, InsufficientStringBufferDeclaration. |
| `check.core/.../generator/CheckGeneratorNaming.java` | Naming conventions. StringToString fix (getLastSegment().toString() redundant). |
| `check.core/.../scoping/CheckScopeProvider.java` | Scoping with dispatch methods. UnusedFormalParameter, UseIndexOfChar. |
| `xtext.generator.test/.../XbaseGeneratorFragmentTest.java` | Test file. LooseCoupling (BasicEList→EList), ConstantName renames, ImmutableField. |
| `xtext.generator/.../AnnotationAwareAntlrContentAssistGrammarGenerator.java` | Grammar generator. MissingOverride, UnnecessaryBoxing fixes. |
| `checkcfg.core/.../PropertiesInferenceHelper.java` | Properties inference. ExhaustiveSwitchHasDefault (switch expression), UseCollectionIsEmpty. |
| `check.core.test/.../util/CheckModelUtil.java` | Test model utilities. JavadocMethod, VariableDeclarationUsageDistance, AppendCharWithChar. |

## Additional Notes

- The `xtend-gen/` directories in the untracked files list are leftover from the Xtend build infrastructure that was removed in commit `41edd59ab`. They should be added to `.gitignore` or deleted.
- The worktree branches (`worktree-agent-*`) visible in `git branch` are leftovers from agent execution. They can be cleaned up with `git branch -D`.
- You may want to add `HANDOVER.md` to `.gitignore`.
5 changes: 0 additions & 5 deletions com.avaloq.tools.ddk.check.core.test/.classpath
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@
<attribute name="ignore_optional_problems" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="xtend-gen">
<attributes>
<attribute name="ignore_optional_problems" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="resource"/>
<classpathentry kind="output" path="bin"/>
</classpath>
1 change: 0 additions & 1 deletion com.avaloq.tools.ddk.check.core.test/build.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
source.. = src/,\
src-gen/,\
xtend-gen/,\
resource/
output.. = bin/
bin.includes = META-INF/,\
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*******************************************************************************
* Copyright (c) 2016 Avaloq Group AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Avaloq Evolution AG - initial API and implementation
*******************************************************************************/

package com.avaloq.tools.ddk.check.core.generator;

import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

import org.eclipse.xtext.testing.InjectWith;
import org.eclipse.xtext.testing.extensions.InjectionExtension;
import org.eclipse.xtext.xbase.testing.JavaSource;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import com.avaloq.tools.ddk.check.CheckInjectorProvider;
import com.avaloq.tools.ddk.check.core.test.AbstractCheckGenerationTestCase;

import static org.junit.jupiter.api.Assertions.assertTrue;

@InjectWith(CheckInjectorProvider.class)
@ExtendWith(InjectionExtension.class)
public class IssueCodeValueTest extends AbstractCheckGenerationTestCase {

private static final String PACKAGE_NAME = "mypackage";
private static final String CATALOG_NAME = "MyCatalog";

/**
* Test the map generated from a catalog with checks.
*/
@Test
public void testIssueCodeValue() throws Exception {
// ARRANGE
// @Format-Off
String source = String.format("""
package %s

import com.avaloq.tools.ddk.check.check.Check
import com.avaloq.tools.ddk.check.check.Context
import com.avaloq.tools.ddk.check.check.Documented

catalog %s
for grammar com.avaloq.tools.ddk.check.Check {

live error MyCheck1 "Label 1"
message "Message 1" {
for Documented elem {
switch elem {
Context : issue on elem
Check : issue on elem
}
}
}

live error MyCheck_2 "Label 2"
message "Message 2" {
for Documented elem {
switch elem {
Context : issue on elem
Check : issue on elem
}
}
}

live error MYCheck3 "Label 3"
message "Message 3" {
for Documented elem {
switch elem {
Context : issue on elem
Check : issue on elem
}
}
}
}
""", PACKAGE_NAME, CATALOG_NAME);
// @Format-On

Map<String, String> expectedIssueCodeValues = Map.of(
"MY_CHECK_1", "MyCheck1",
"MY_CHECK_2", "MyCheck2",
"MY_CHECK_3", "MyCheck3");

// ACT
List<JavaSource> compiledClassesList;
ByteArrayInputStream sourceStream = new ByteArrayInputStream(source.getBytes(StandardCharsets.UTF_8));
try {
compiledClassesList = generateAndCompile(sourceStream);
} finally {
sourceStream.close();
}

// ASSERT
String issueCodesClassName = CATALOG_NAME + ISSUE_CODES_SUFFIX;

String issueCodesClass = compiledClassesList.stream()
.filter(s -> s.getFileName().equals(issueCodesClassName))
.findFirst()
.orElse(null)
.getCode();

for (Map.Entry<String, String> issueCode : expectedIssueCodeValues.entrySet()) {
String expectedIssueCodeAssignment = "public static final String " + issueCode.getKey()
+ " = \"" + PACKAGE_NAME + "." + CATALOG_NAME + ISSUE_CODES_SUFFIX + "." + issueCode.getValue() + "\";";
assertTrue(issueCodesClass.contains(expectedIssueCodeAssignment),
issueCodesClassName + " contains correct initialization of " + issueCode.getKey());
}
}

}
Loading