|
| 1 | +# SortPom — Coding Guidelines for AI Agents |
| 2 | + |
| 3 | +## Project Overview |
| 4 | + |
| 5 | +SortPom is a Maven plugin that sorts `pom.xml` files. It is a two-module Maven project: |
| 6 | + |
| 7 | +- **`sorter/`** — Core sorting library (pure business logic, no Maven dependencies) |
| 8 | +- **`maven-plugin/`** — Maven plugin wrapper around the sorter |
| 9 | + |
| 10 | +## Build & Tooling |
| 11 | + |
| 12 | +```bash |
| 13 | +mvn verify # Full build: compile, test, integration tests |
| 14 | +mvn test # Unit tests only |
| 15 | +mvn fmt:format # Auto-format all Java source (Spotify fmt-maven-plugin) |
| 16 | +mvn fmt:check # Verify formatting without modifying files |
| 17 | +``` |
| 18 | + |
| 19 | +Always run `mvn fmt:format` before committing, or let it run as part of the build. Code that fails the format check will break CI. |
| 20 | + |
| 21 | +Integration tests live in `maven-plugin/src/it/` and are executed via `maven-invoker-plugin` during `verify`. |
| 22 | + |
| 23 | +## Java Version |
| 24 | + |
| 25 | +- Current target: **Java 17** (`maven.compiler.release=17`) |
| 26 | +- Use `var` for local variable type inference where it improves readability (it is widely used in this codebase) |
| 27 | +- Java 17 features are available: sealed classes, pattern matching for `instanceof`, records, text blocks |
| 28 | +- Do not use language features beyond Java 17 |
| 29 | + |
| 30 | +## Code Style |
| 31 | + |
| 32 | +Formatting is enforced automatically by `fmt-maven-plugin` (Google Java Format). Do not manually adjust whitespace or brace placement — just run `mvn fmt:format`. |
| 33 | + |
| 34 | +**Naming:** |
| 35 | +- Classes: `PascalCase` |
| 36 | +- Methods and fields: `camelCase` |
| 37 | +- Constants: `UPPER_SNAKE_CASE` |
| 38 | +- Packages: lowercase, e.g. `sortpom.wrapper.content` |
| 39 | + |
| 40 | +**Javadoc:** Add Javadoc to public classes and non-trivial public methods. Include `@author` on classes only where already present in the file. |
| 41 | + |
| 42 | +**Annotations:** Use `@SuppressWarnings` sparingly and only with justification. |
| 43 | + |
| 44 | +## Architecture |
| 45 | + |
| 46 | +The codebase is layered; keep concerns separated: |
| 47 | + |
| 48 | +| Layer | Location | Responsibility | |
| 49 | +|---|---|---| |
| 50 | +| Plugin (Mojo) | `maven-plugin/.../SortMojo`, `VerifyMojo`, `AbstractParentMojo` | Maven lifecycle, parameter wiring | |
| 51 | +| Application | `sorter/.../SortPomImpl`, `SortPomService` | Orchestration | |
| 52 | +| Domain | `sorter/.../wrapper/`, `sorter/.../verify/` | Sorting logic, XML structure | |
| 53 | +| Infrastructure | `sorter/.../util/`, `sorter/.../output/` | File I/O, XML serialisation | |
| 54 | + |
| 55 | +**Key patterns in use:** |
| 56 | +- **Builder** — `PluginParameters.Builder` for all configuration; use this pattern for new config objects |
| 57 | +- **Strategy / Wrapper hierarchy** — `Wrapper<T>` implementations define different sort behaviours; add new sorting strategies here |
| 58 | +- **Factory** — `WrapperFactory` / `WrapperFactoryImpl` creates wrappers; register new wrapper types here |
| 59 | +- **Template Method** — `HierarchyWrapperOperation` defines the tree traversal hooks |
| 60 | + |
| 61 | +Never mix Maven plugin concerns (Mojo annotations, `MavenProject`) into the `sorter` module. |
| 62 | + |
| 63 | +## Error Handling |
| 64 | + |
| 65 | +- Throw `FailureException` (extends `RuntimeException`) for unrecoverable errors in the sorter module |
| 66 | +- The plugin layer converts `FailureException` to `MojoFailureException` via `ExceptionConverter` |
| 67 | +- Do not propagate checked exceptions beyond module boundaries |
| 68 | + |
| 69 | +## Testing |
| 70 | + |
| 71 | +**Coverage requirement: 100%.** Every new production code path must have a corresponding test. |
| 72 | + |
| 73 | +### Test frameworks |
| 74 | +- JUnit 5 (Jupiter) — `@Test`, `@ParameterizedTest`, etc. |
| 75 | +- Mockito 5 — for mocking collaborators |
| 76 | +- Hamcrest 3 — preferred for assertions; use `assertThat(actual, matcher)` |
| 77 | +- JUnit `Assertions` — acceptable for simple equality (`assertEquals`, `assertTrue`, etc.) |
| 78 | + |
| 79 | +### Test structure |
| 80 | + |
| 81 | +Test classes mirror the production package structure and are named `{Subject}Test`. |
| 82 | + |
| 83 | +For XML sorting tests, use the fluent test utilities rather than constructing objects manually: |
| 84 | + |
| 85 | +```java |
| 86 | +// Sorting / round-trip XML tests |
| 87 | +XmlProcessorTestUtil.create() |
| 88 | + .predefinedSortOrder("recommended_2008_06") |
| 89 | + .testInputAndExpected("src/test/resources/MyFeature_input.xml", |
| 90 | + "src/test/resources/MyFeature_expected.xml"); |
| 91 | + |
| 92 | +// Full integration through SortPomImpl |
| 93 | +SortPomImplUtil.create() |
| 94 | + .sortDependencies("scope,groupId,artifactId") |
| 95 | + .testFiles("src/test/resources/MyFeature_input.xml", |
| 96 | + "src/test/resources/MyFeature_expected.xml"); |
| 97 | +``` |
| 98 | + |
| 99 | +XML fixture files live in `sorter/src/test/resources/`. Name them `<Feature>_input.xml` and `<Feature>_expected.xml`. |
| 100 | + |
| 101 | +### What to test |
| 102 | + |
| 103 | +- Normal (happy-path) cases with fixture XML files |
| 104 | +- Edge cases: empty elements, comments, processing instructions, special characters |
| 105 | +- Error cases: verify `FailureException` is thrown with the correct message |
| 106 | +- Parameter validation: invalid combinations should fail with a clear error |
| 107 | + |
| 108 | +### What not to do |
| 109 | + |
| 110 | +- Do not mock the file system or XML parser in integration-style tests; use real fixture files |
| 111 | +- Do not use `@BeforeEach` to share mutable state across unrelated tests |
| 112 | +- Do not test private methods directly; test through the public API |
| 113 | + |
| 114 | +## Adding New Features |
| 115 | + |
| 116 | +1. Add or update the parameter in `PluginParameters` (and its `Builder`) |
| 117 | +2. Wire the parameter through `AbstractParentMojo` if it is user-facing |
| 118 | +3. Implement the logic in the sorter module (typically a new `Wrapper` implementation or a new phase in an existing wrapper) |
| 119 | +4. Register the wrapper in `WrapperFactoryImpl` if needed |
| 120 | +5. Add fixture XML files and tests covering all branches |
| 121 | +6. Run `mvn verify` to confirm 100% coverage and passing integration tests |
0 commit comments