This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
RefactorFirst is a Java static analysis tool that scans Git repositories, detects code disharmonies (God Classes, Brain Classes, highly coupled classes, circular dependencies), and produces prioritized refactoring recommendations in HTML/CSV/JSON reports. The core insight is combining code-quality metrics with Git change history so the most painful classes surface first.
# Full build (compile + test + package)
mvn clean install
# Skip tests for faster iteration
mvn clean install -DskipTests
# Run all tests
mvn clean test
# Run tests in a single module
mvn clean test -pl effort-ranker
# Run a single test class
mvn clean test -pl effort-ranker -Dtest=BrainClassTest
# Format code (Palantir Java format via Spotless)
mvn spotless:apply
# Check formatting without modifying
mvn spotless:check
# Build with OWASP dependency check (slow)
mvn clean install -PlocalThe CLI fat jar is produced at cli/target/refactor-first-cli-*.jar via the Maven Shade plugin.
11-module Maven build. Data flows left-to-right:
codebase-graph-builder ──→ cost-benefit-calculator ──→ graph-data-generator
graph-algorithms ──→ │ ──→ report
change-proneness-ranker ──→ │ ──→ cli
effort-ranker ──→ ──────┘ ──→ refactor-first-maven-plugin
test-resources (shared fixtures)
coverage (JaCoCo aggregation)
codebase-graph-builder — The most complex module. Uses OpenRewrite to parse Java source across versions (11/17/21, and 25 when running on a Java 25+ runtime — see "Java 25 analysis" below), builds class and package dependency graphs with JGraphT, detects cycle-breaking candidates using two graph algorithms, and returns everything in CodebaseGraphDTO. Entry point: JavaGraphBuilder.getCodebaseGraphDTO().
graph-algorithms — Two cycle-decomposition algorithms used by JavaGraphBuilder:
- Directed Feedback Vertex Set (
org.hjug.feedback.vertex.kernelized) — kernelized algorithm; identifies the minimum vertex set to remove to break all cycles. - Feedback Arc Set with PageRank (
org.hjug.feedback.arc.pageRank) — identifies edges to remove; uses PageRank on the line digraph. Based on Geladaris et al. - See
DIAGRAM.mdfiles in each algorithm package for pseudocode diagrams.
effort-ranker — Runs PMD rules (category/java/design.xml + custom CBORule) to detect God Classes (ATFD, WMC, TCC) and highly coupled classes (CBO). Also detects Brain Classes, Data Classes, Feature Envy, and several other disharmonies in DisharmonyDetector.
change-proneness-ranker — Uses JGit to read Git commit history and assign change-frequency scores to classes.
cost-benefit-calculator — Orchestrates the full pipeline: runs effort-ranker and change-proneness-ranker, combines scores into RankedDisharmony objects. Main orchestration class: CostBenefitCalculator.
report — Generates HTML (with embedded bubble charts), CSV, and JSON output. Reports with >4000 classes switch to a simplified 3D viewer.
cli — PicoCLI-based executable. Entry: org.hjug.refactorfirst.Main → ReportCommand.
refactor-first-maven-plugin — Maven plugin wrapper; key config options: showDetails, backEdgeAnalysisCount (default 50; set 0 for all), analyzeCycles, excludeTests.
CodebaseGraphDTO is the central transfer object passed between modules. It holds:
- JGraphT directed graphs for class and package dependencies
- Detected disharmony lists (God Classes, Brain Classes, etc.)
- Metrics per class (ATFD, WMC, TCC, CBO)
RankedDisharmony carries the final prioritized output consumed by report generators.
- Visitor —
JavaVisitor(OpenRewrite) walks the AST to collect class dependencies. - Pipeline —
CostBenefitCalculatorchains multiple independent rankers then merges results. - DTO —
CodebaseGraphDTOdecouples parsing from ranking and reporting. - Lombok
@Data/@Builderis used extensively; avoid adding boilerplate that Lombok already removes.
JUnit 5 (Jupiter) with parameterized tests. Test fixtures live in test-resources/src/test/resources. When adding or modifying graph-algorithm behavior, check JavaGraphBuilderTest and CircularReferenceCheckerTests for integration-level coverage.
Mutation testing via PIT (pitest-maven) is configured but not part of the default build; run explicitly if needed.
- Source/target: Java 17 minimum; OpenRewrite parser supports 11, 17, 21 — plus 25 when running on a Java 25+ runtime.
- Logging: SLF4J; use
log.debug()for verbose per-class output,log.info()sparingly. - Spotless enforces Palantir Java format — run
mvn spotless:applybefore committing.
rewrite-java-25 is a required compile dependency of codebase-graph-builder and ships in every distribution (Maven plugin, CLI fat jar). Its class files are compiled for class-file version 69 but are inert on Java 17/21 classpaths (no META-INF/services entries, no base-level references). Activation uses a JEP 238 multi-release jar rather than reflection or runtime-version detection: codebase-graph-builder declares Multi-Release: true and carries two variants of org.hjug.graphbuilder.graphbuilder.Java25ParserFactory — the base variant (release 17, returns Optional.empty()) and a Java 25 variant compiled from src/main/java25 into META-INF/versions/25 (directly constructs Java25Parser, with a catch (Throwable) graceful-degradation guard). On JDK 25+ runtimes the JVM's versioned jar lookup shadows the base variant, so JavaSourceFileGraphBuilder.createJavaParser(config) is just Java25ParserFactory.createJava25Parser().orElseGet(JavaParser::fromJavaVersion...). OpenRewrite's fromJavaVersion() additionally elevates to Java25Parser on its own when the runtime is 25+ and rewrite-java-25 is on the classpath (covering exploded-directory classpaths where jar shadowing does not apply). The former forceJava25Parser escape hatch has been removed everywhere; there is no configuration surface for parser selection. Build constraints: never reference class-file-69 code from base sources (only src/main/java25); the versioned class must keep the base's exact public API; release artifacts must be built with JDK 25 (release.yml asserts the versioned entries exist); JaCoCo excludes META-INF/versions/**; the CLI shade config re-adds Multi-Release: true to the fat jar manifest; refactor-first-maven-plugin requires maven-plugin-plugin/maven-plugin-annotations 3.16.0 (ASM 9.10.1) so descriptor generation can scan class-file-69 entries. See plans/jep-238-plan.md for the design record.