ProjectBuildStage

open class ProjectBuildStage(logger: RunnerLogger, processTimeout: Duration = ToolConfigDefaults.SUBPROCESS_RUN_TIMEOUT, gradleProjectDataCollector: (Path) -> Map<String, GradleProjectData>? = { null }) : ClasspathStage(source)

Stage 1 of the LST classpath-resolution pipeline: extract the project's compile classpath by invoking its own build tool (Maven or Gradle).

Why Stage 1? The most accurate way to obtain the exact JAR set the project actually compiles against is to ask the build tool itself. This accounts for BOM imports, version catalogs, dependency management, and plugin-contributed dependencies that are difficult to reproduce by static parsing alone.

Build unit discovery: Root descriptors keep the historical single-root invocation for that tool. If a tool has no root descriptor, top-most subdirectory descriptors become build units, so root-less monorepos can still use build-tool classpaths. Maven and Gradle units are non-exclusive and their results are merged. Root-level wrappers are reused when subdirectory units do not have their own wrappers.

Maven: Runs mvnw dependency:build-classpath (using the Maven wrapper if present, otherwise mvn). The classpath is written to a temp file via -Dmdep.outputFile and then parsed. The test scope is included (-DincludeScope=test) so test-only dependencies are available when recipes analyse test sources.

Gradle: Injects a temporary Gradle init script that registers a printClasspathForOpenRewrite task. The task resolves the project's testRuntimeClasspath (falling back through runtimeClasspath, testCompileClasspath, compileClasspath, and default in that order) and prints each JAR path to stdout. The Gradle wrapper (gradlew) is used when present; otherwise the system gradle command is used.

Failure behaviour: Per-unit failures — non-zero exit code, process timeout, missing build tool, unexpected exception, or capped discovery — are logged as warnings. extractClasspath returns the merged classpath only when every discovered unit completes. Partial coverage returns null so the pipeline falls through to DependencyResolutionStage (Stage 2).

Compilation: After a successful Stage 1, tryCompile is called if the project has no pre-compiled class directories. LstBuilder appends compiled .class directories once after the winning stage is selected so that intra-project type references resolve correctly.

Extensibility: The class is open with open methods so tests can subclass it to inject a fake classpath without spawning real processes.

Constructors

Link copied to clipboard
constructor(logger: RunnerLogger, processTimeout: Duration = ToolConfigDefaults.SUBPROCESS_RUN_TIMEOUT, gradleProjectDataCollector: (Path) -> Map<String, GradleProjectData>? = { null })

Types

Link copied to clipboard
object Companion

Functions

Link copied to clipboard
open override fun resolve(projectDir: Path, parseFailures: MutableList<ParseFailure>): ClasspathResolutionResult?

Returns null to fall through to the next stage; non-null terminates resolution.