Skip to content

[gradle] Fix external dependency resolution when KSP is applied to Android modules - #233

Open
kalin91 wants to merge 2 commits into
Kotlin:mainfrom
kalin91:fix/android-ksp-nested-components-sources
Open

[gradle] Fix external dependency resolution when KSP is applied to Android modules#233
kalin91 wants to merge 2 commits into
Kotlin:mainfrom
kalin91:fix/android-ksp-nested-components-sources

Conversation

@kalin91

@kalin91 kalin91 commented Jul 18, 2026

Copy link
Copy Markdown

Fix external dependency resolution when KSP is applied to Android modules

Fixes #225

Root cause

KSP registers its generated source directories on Android components as Providers backed by the producing KSP tasks. Querying such a provider before its task has run is illegal in Gradle.

The prepareKotlinIdeaImport task guards against this by declaring variant sources as task inputs (forcing the generator tasks to run before model building), but it only did so for main variants. Nested components (androidTest / unitTest) were not covered, so their KSP tasks (e.g. kspDebugAndroidTestKotlin) never ran. When ModuleSourceSetsModelBuilder later queried their sources, Gradle threw:

Querying the mapped value of provider(java.util.Set) before task ':app:kspDebugAndroidTestKotlin' has completed is not supported

The exception propagated out of resolveAndroidSourceSets, aborting the whole model builder. The module ended up with no source sets at all (IdeaProjectMapper - <module> has an empty set of source sets), and since library dependencies attach to source sets, every external .jar symbol became unresolvable in the editor — while the Gradle build itself kept working. Removing the KSP plugin removed the task-backed providers, which is why it "fixed" the problem.

Fix

Two layers:

  1. prepareKotlinIdeaImport.kt — declare the sources of nested components as task inputs too, so their generator tasks run before model building (root cause).
  2. resolveAndroidSourceSets.kt — resolve each component defensively: a component whose providers cannot be queried is skipped with a warning instead of discarding the source sets of the whole module (containment, so no future task-backed provider can empty a module again).

Verification

Reproduced with an Android app (AGP 9.2.1, Kotlin 2.3.21, KSP 2.3.9 with Hilt, Gradle 9.4.1) against extension 0.0.5 on Linux. With this patch compiled into workspace-import-gradle-plugin.jar:

  • kspDebugUnitTestKotlin / kspDebugAndroidTestKotlin now run during import.
  • The provider-query error is gone from the server log.
  • <module>.app has an empty set of source sets is gone; the workspace model cache grew from 56 K to 65 K (source sets + dependencies now present).
  • Semantic highlighting, hover, and Ctrl+Click navigation to external library symbols (decompiled stubs) work again.

Note for maintainers

I'm aware this repository is a read-only mirror and direct code contributions aren't integrated automatically — this PR is offered as a reference patch for the diagnosis in #225, to be integrated manually if useful.

Unrelated but observed while debugging on AGP 9.2.1: [IMPORT ERR]: Failed to call 'onVariants' in 'androidComponents' extension appears once during configuration (non-fatal; variants are still collected). May be worth a separate look.

🤖 Generated with Claude Code

…droid modules

KSP registers generated source directories on Android components as providers
backed by the producing KSP tasks. The 'prepareKotlinIdeaImport' task only
declared the sources of main variants as inputs, so KSP tasks of nested
components (androidTest/unitTest) never ran before model building. Querying
their source providers then failed with "Querying the mapped value of
provider(java.util.Set) before task ':app:kspDebugAndroidTestKotlin' has
completed is not supported", which aborted ModuleSourceSetsModelBuilder and
left the module with no source sets at all - and therefore no resolvable
external library dependencies in the editor.

Two-part fix:
- prepareKotlinIdeaImport now declares the sources of nested components as
  task inputs too, so their generator tasks run before model building.
- resolveAndroidSourceSets resolves each component defensively: a component
  whose providers cannot be queried is skipped with a warning instead of
  discarding the source sets of the whole module.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Kotlin ksp becomes unstable when using KSP Gradle plugin

1 participant