Skip to content

Fix incremental factory generation - #189

Merged
matejsemancik merged 4 commits into
6.xfrom
fix/generator-file-already-exists-error
May 13, 2026
Merged

Fix incremental factory generation#189
matejsemancik merged 4 commits into
6.xfrom
fix/generator-file-already-exists-error

Conversation

@matejsemancik

@matejsemancik matejsemancik commented May 6, 2026

Copy link
Copy Markdown
Member

Summary

This PR fixes unstable incremental KSP generation in decompose-processor. The processor generates one *ComponentFactory.kt file per @GenerateFactory component, but the generated files were not explicitly associated with the source file that produced them. Although the files were marked as isolating, KSP had no originating KSFile metadata for the outputs, so incremental builds could lose the relationship between an annotated component and its generated factory.

In a consuming KMP project this showed up as nondeterministic rebuild failures. A clean build generated all factories, but subsequent incremental runs could pass only a subset of annotated components to the processor. KSP then regenerated only that subset and removed the factories for unchanged components, causing unresolved references such as FirstComponentFactory or LoginComponentFactory until a clean build was run again.

Fix

Each generated factory is now explicitly registered with the annotated component's containing source file via addOriginatingKSFile(factoryComponent.containingFile). The generated file remains isolating (aggregating = false), which matches the actual dependency model: one factory depends on one component source file.

The previous one-shot invoked guard was removed so the processor can participate correctly in KSP rounds. With proper originating-file metadata, KSP can safely decide which factories to keep, remove, or regenerate during incremental processing instead of relying on skipping later rounds.

Test plan

  • ./gradlew :decompose-processor:compileKotlinJvm
  • Verified in a consuming KMP project with :shared:feature:clean :shared:feature:compileCommonMainKotlinMetadata --refresh-dependencies --no-build-cache --no-configuration-cache
  • Verified subsequent :shared:feature:compileCommonMainKotlinMetadata rebuild keeps all generated factories
  • Confirmed KSP cache maps each component source file to its corresponding generated factory output

KSP can invoke process() in multiple rounds within a single build when
another aggregating processor (e.g. Koin compiler) generates files that
trigger a new round. Without a guard, ComponentFactoryProcessor attempted
to recreate already-generated factory files in round 2+, causing
FileAlreadyExistsException.

Fix 1: Add invoked guard so the processor exits early on subsequent rounds.
Fix 2: Change aggregating=true to aggregating=false — each *ComponentFactory
is derived solely from its own source class, so treating it as an aggregating
output was semantically incorrect and caused unnecessary full regeneration on
every incremental build.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@matejsemancik
matejsemancik requested review from Syntey and okalman May 6, 2026 07:50
@matejsemancik
matejsemancik marked this pull request as draft May 6, 2026 08:03
@matejsemancik matejsemancik changed the title Fix FileAlreadyExistsException in ComponentFactoryProcessor Fix incremental factory generation May 11, 2026
Fixes KSP-based koin annotations bug with component validation related to context parameters execution
@matejsemancik
matejsemancik marked this pull request as ready for review May 11, 2026 18:05
@matejsemancik
matejsemancik merged commit dcf5f0d into 6.x May 13, 2026
1 check passed
@matejsemancik
matejsemancik deleted the fix/generator-file-already-exists-error branch May 13, 2026 15:15
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.

2 participants