Files
werkcrappit/docs/adr/0002-method-inventory.md
miandmhoennig aea74c2c6f
werkator build succeeded after 00:34
Step 3 of 8: method inventory and reliable bytecode access (#4)
Step 3 of 8 from section 8.3 of the specification.

- Classes are read only from PIT's code roots (PIT's own code-path rule, never dependency JARs); differing copies are ambiguous, a missing class makes the scope incomplete.
- JaCoCo's analysis is matched against the methods the class file declares (ASM): methods JaCoCo filtered are EXCLUDED with proof (`jacoco-filtered:bridge|synthetic|generated-annotation|other`), abstract/native methods get no complexity.
- PIT's `excludedMethods` → EXCLUDED with `pit-excluded-method:<glob>`.
- Every method of the selected classes appears in the provisional report (schemaVersion 0) with a score or a reason.
- ADR 0002, feature 03, MC-008 to MC-012 mapped; MC-013 open.

CI on werkator.javagil.de: green (52 s), 66 unit and 8 functional tests.

PR-doc: `docs/prs/2026-10-01-PR#4-method-inventory.md`

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: mhoennig <michael@hoennig.de>
Reviewed-on: #4
2026-10-01 15:53:27 +02:00

47 lines
2.7 KiB
Markdown

# ADR 0002: Method Inventory
- Status: accepted
- Date: 2026-10-01
- PR: #4
## Context
A result listener only sees methods that have mutation results.
The specification (4.4) demands that methods without results stay visible and that a report never claims a completeness it cannot prove.
It also demands an unambiguous origin of the analysed bytes (3.4) and no invented complexity (5.3).
## Decision
**Scope.** The classes PIT selected for mutation, `ReportOptions.getMutationClassPaths().code()`.
They already respect `targetClasses` and `excludedClasses`.
**Code roots.** A class is read only from the code roots, by PIT's own rule: the classpath elements matching `codePaths` if configured, otherwise every directory that is not a test output.
Dependency archives are never code roots.
This replaces ADR 0001's "first classpath element", which could read a selected class from a dependency JAR.
**Origin.** A class is read from every code root that holds it.
Identical copies are one origin; differing copies are `ambiguous-class-file`, since nobody can tell which one PIT mutated.
A selected class that cannot be read is `class-file-not-found`.
Either makes the scope incomplete.
**Inventory.** Every method with a body of every readable selected class.
Abstract and native methods have no body and are left out; they get no complexity.
**Methods JaCoCo filters.** JaCoCo analyses every method with code and drops only what its filters remove.
A declared method with code that JaCoCo does not report on the very same bytes has therefore been filtered — proven, not guessed.
It is `EXCLUDED` with the reason `jacoco-filtered:<hint>`, the hint read from the class file: `bridge`, `synthetic`, `generated-annotation`, or `other` (for example enum `values()` or record accessors).
**Methods PIT does not mutate.** A method whose name matches PIT's `excludedMethods` lies outside the selection of the run.
It is `EXCLUDED` with the reason `pit-excluded-method:<glob>` and keeps its complexity.
**Joining.** Only by `MethodId` (class, JVM name, descriptor), never by name or line.
Results whose class is unreadable carry that class's reason; results without inventory method carry `method-not-in-inventory`.
Both are `COMPLEXITY_UNAVAILABLE` and never dropped.
## Consequences
- Every selected method appears in the report exactly once, with a score or a reason.
- A strict gate (step 6) can fail on an incomplete scope and on unavailable complexity as analysis errors.
- `jacoco-filtered:other` covers several JaCoCo filters; the report names no finer reason for them.
A wrong exclusion would need JaCoCo to report a method it should have filtered, which a JaCoCo upgrade with changed filters could do; the JaCoCo version is in every report.