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
2.7 KiB
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:othercovers 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.