Context
PR #419 tightened the generated-source task wiring work from #418 and added honest coverage for Android-shaped task names such as kspDebugKotlin and kaptGenerateStubsDebugKotlin.
However, the KSP coverage in that PR is intentionally not full real KSP runtime coverage. The current fixtures verify task-name wiring, but they do not prove that a real KSP processor can see generated GraphQL symbols during KSP analysis.
This distinction matters for future consumers such as anitrend-v2, where data modules use KSP and generated GraphQL sources may need to be visible to symbol processors during the actual ksp*Kotlin execution phase.
Problem
The current KSP fixtures prove that the retrofit-graphql Gradle plugin wires GraphQL generation before tasks named like:
They do not prove that a real KSP processor can resolve generated symbols such as:
sample.generated.GeneratedGraphQLRegistry
through the KSP Resolver API.
A previous attempt at real KSP TestKit coverage failed with a classpath/runtime issue similar to:
NoClassDefFoundError: org.jetbrains.kotlin.gradle.plugin.KotlinCompilerPluginSupportPlugin
That appears to be a TestKit/KSP/Kotlin Gradle Plugin classloading problem, not direct evidence that retrofit-graphql generated-source wiring is wrong. Still, the coverage gap should be closed before relying on this path during downstream migrations.
Expected Behaviour
A repository-local fixture should prove end-to-end KSP runtime visibility:
generateGraphQLSources runs before real ksp*Kotlin tasks.
- A real KSP processor is loaded by the fixture build.
- The processor can resolve generated GraphQL source symbols through
Resolver.
- The fixture fails if generated GraphQL sources are not visible during KSP analysis.
- The fixture does not rely only on synthetic task names or
dependsOn assertions.
Recommended Implementation Direction
Prefer a published-consumer TestKit fixture rather than only withPluginClasspath().
The likely issue with the previous fixture is that withPluginClasspath() injects the plugin-under-test classpath, while KSP is an external compiler plugin that must resolve and load against the correct Kotlin Gradle Plugin APIs inside the nested fixture build.
A better fixture shape is:
- Publish retrofit-graphql Gradle plugin to
mavenLocal().
- Create a synthetic consumer project in TestKit.
- Resolve the retrofit-graphql plugin from
mavenLocal() using the Gradle plugins {} DSL.
- Apply the real KSP plugin.
- Add a real KSP processor module through the
ksp(...) configuration.
- Assert generated symbols are visible from the processor.
Example fixture plugin setup:
pluginManagement {
repositories {
mavenLocal()
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
kotlin("jvm") version "2.4.0"
id("com.google.devtools.ksp") version "2.3.9"
id("co.anitrend.retrofit.graphql.codegen") version "<local-version>"
}
Example processor dependency:
dependencies {
ksp(project(":processor"))
}
Example processor assertion:
val generatedRegistry = resolver.getClassDeclarationByName(
resolver.getKSNameFromString("sample.generated.GeneratedGraphQLRegistry"),
)
if (generatedRegistry == null) {
logger.error("GeneratedGraphQLRegistry was not visible to KSP")
}
Suggested Test Matrix
JVM KSP fixture
- Apply
kotlin("jvm").
- Apply real
com.google.devtools.ksp.
- Apply published retrofit-graphql codegen plugin from
mavenLocal().
- Generate a simple operation such as
GetViewer.graphql.
- Run:
Expected result:
generateGraphQLSources runs successfully before kspKotlin.
- Real KSP processor loads successfully.
- Processor resolves
GeneratedGraphQLRegistry.
Android KSP fixture
- Apply
com.android.library or com.android.application.
- Apply real
com.google.devtools.ksp.
- Apply published retrofit-graphql codegen plugin from
mavenLocal().
- Generate a simple operation such as
GetViewer.graphql.
- Run:
Expected result:
generateGraphQLSources runs successfully before kspDebugKotlin.
- Real KSP processor loads successfully.
- Processor resolves
GeneratedGraphQLRegistry.
Acceptance Criteria
- A real KSP processor fixture exists and is executed by a dedicated test task.
- The processor is registered through:
META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider
- The processor uses
Resolver.getClassDeclarationByName(...) to resolve GeneratedGraphQLRegistry.
- The test fails if generated GraphQL symbols are not visible during KSP processing.
- The fixture covers at least JVM
kspKotlin.
- The fixture covers Android
kspDebugKotlin if Android SDK/AGP fixture support is available in the executing environment.
- Synthetic task-name-only coverage remains allowed as a lightweight regression check, but it must not be the only KSP coverage.
- The issue documents any remaining TestKit/KSP classpath limitation if full Android KSP coverage cannot be stabilized in one pass.
Related Work
Context
PR #419 tightened the generated-source task wiring work from #418 and added honest coverage for Android-shaped task names such as
kspDebugKotlinandkaptGenerateStubsDebugKotlin.However, the KSP coverage in that PR is intentionally not full real KSP runtime coverage. The current fixtures verify task-name wiring, but they do not prove that a real KSP processor can see generated GraphQL symbols during KSP analysis.
This distinction matters for future consumers such as
anitrend-v2, where data modules use KSP and generated GraphQL sources may need to be visible to symbol processors during the actualksp*Kotlinexecution phase.Problem
The current KSP fixtures prove that the retrofit-graphql Gradle plugin wires GraphQL generation before tasks named like:
They do not prove that a real KSP processor can resolve generated symbols such as:
through the KSP
ResolverAPI.A previous attempt at real KSP TestKit coverage failed with a classpath/runtime issue similar to:
That appears to be a TestKit/KSP/Kotlin Gradle Plugin classloading problem, not direct evidence that retrofit-graphql generated-source wiring is wrong. Still, the coverage gap should be closed before relying on this path during downstream migrations.
Expected Behaviour
A repository-local fixture should prove end-to-end KSP runtime visibility:
generateGraphQLSourcesruns before realksp*Kotlintasks.Resolver.dependsOnassertions.Recommended Implementation Direction
Prefer a published-consumer TestKit fixture rather than only
withPluginClasspath().The likely issue with the previous fixture is that
withPluginClasspath()injects the plugin-under-test classpath, while KSP is an external compiler plugin that must resolve and load against the correct Kotlin Gradle Plugin APIs inside the nested fixture build.A better fixture shape is:
mavenLocal().mavenLocal()using the Gradleplugins {}DSL.ksp(...)configuration.Example fixture plugin setup:
pluginManagement { repositories { mavenLocal() google() mavenCentral() gradlePluginPortal() } } plugins { kotlin("jvm") version "2.4.0" id("com.google.devtools.ksp") version "2.3.9" id("co.anitrend.retrofit.graphql.codegen") version "<local-version>" }Example processor dependency:
dependencies { ksp(project(":processor")) }Example processor assertion:
Suggested Test Matrix
JVM KSP fixture
kotlin("jvm").com.google.devtools.ksp.mavenLocal().GetViewer.graphql.Expected result:
generateGraphQLSourcesruns successfully beforekspKotlin.GeneratedGraphQLRegistry.Android KSP fixture
com.android.libraryorcom.android.application.com.google.devtools.ksp.mavenLocal().GetViewer.graphql.Expected result:
generateGraphQLSourcesruns successfully beforekspDebugKotlin.GeneratedGraphQLRegistry.Acceptance Criteria
Resolver.getClassDeclarationByName(...)to resolveGeneratedGraphQLRegistry.kspKotlin.kspDebugKotlinif Android SDK/AGP fixture support is available in the executing environment.Related Work