Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FileAlreadyExistsException after adding a KSP processor to a Gradle module with anvil-utils plugin enabled #4

Open
arkivanov opened this issue Nov 25, 2024 · 10 comments · Fixed by #5

Comments

@arkivanov
Copy link

The anvil-utils plugin throws FileAlreadyExistsException when I add a KSP processor to a Gradle module with the plugin enabled.

> Task :<redacted>:kspDebugKotlin FAILED
e: [ksp] kotlin.io.FileAlreadyExistsException: /Users/arkivanov/workspace/<redacted>/build/generated/ksp/debug/kotlin/<redacted>/<redacted>Component_AssistedFactory.kt
        at com.google.devtools.ksp.common.impl.CodeGeneratorImpl.createNewFile(CodeGeneratorImpl.kt:154)
        at com.google.devtools.ksp.common.impl.CodeGeneratorImpl.createNewFile(CodeGeneratorImpl.kt:69)
        at com.google.devtools.ksp.processing.CodeGenerator.createNewFile$default(CodeGenerator.kt:59)
        at com.squareup.kotlinpoet.ksp.OriginatingKSFilesKt.writeTo(OriginatingKSFiles.kt:128)
        at me.gulya.anvil.utils.ksp.ContributesAssistedFactorySymbolProcessor.processChecked(ContributesAssistedFactorySymbolProcessor.kt:59)
        at me.gulya.anvil.utils.ksp.internal.ErrorLoggingSymbolProcessor.process(ErrorLoggingSymbolProcessor.kt:14)
        at com.google.devtools.ksp.AbstractKotlinSymbolProcessingExtension$doAnalysis$8$1.invoke(KotlinSymbolProcessingExtension.kt:310)
        at com.google.devtools.ksp.AbstractKotlinSymbolProcessingExtension$doAnalysis$8$1.invoke(KotlinSymbolProcessingExtension.kt:308)
        at com.google.devtools.ksp.AbstractKotlinSymbolProcessingExtension.handleException(KotlinSymbolProcessingExtension.kt:414)
        at com.google.devtools.ksp.AbstractKotlinSymbolProcessingExtension.doAnalysis(KotlinSymbolProcessingExtension.kt:308)
        at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:112)
        at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:77)
        at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:256)
        at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:247)
        at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:115)
        at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:247)
        at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.repeatAnalysisIfNeeded(KotlinToJVMBytecodeCompiler.kt:181)
        at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:87)
        at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli$default(KotlinToJVMBytecodeCompiler.kt:43)
        at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:165)
        at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:50)
        at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:104)
        at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:48)
        at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101)
        at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1523)
        at jdk.internal.reflect.GeneratedMethodAccessor92.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.base/java.lang.reflect.Method.invoke(Unknown Source)
        at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
        at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
        at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
        at java.base/java.security.AccessController.doPrivileged(Unknown Source)
        at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source)
        at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
        at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
        at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source)
        at java.base/java.security.AccessController.doPrivileged(Unknown Source)
        at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.base/java.lang.Thread.run(Unknown Source)


@IlyaGulya
Copy link
Owner

@arkivanov could you please give me a bit more context?
Anvil version, KSP version, kotlin version, possibly example of a Component and its factory, how does your anvil configuration look like?

@arkivanov
Copy link
Author

arkivanov commented Nov 28, 2024

Sure!

Kotlin: 1.9.24
Dagger: 2.52
ksp: 1.9.24-1.0.20
dev.zacsweers.anvil: 0.4.0
anvil-utils: 0.3.0-beta01

After further investigation it appears that the error happens when the component depends on a class that's generated by another KSP processor.

@MyAnnotation // This annotation generates MyGeneratedClass under the same package
interface MyComponent {

    fun interface Factory {
        operator fun invoke(): MyComponent
    }
}

@ContributesAssistedFactory(UserScope::class, MyComponent.Factory::class)
class DefaultMyComponent @AssistedInject constructor(
    myGeneratedClass: MyGeneratedClass, // If I remove this dependency then the error disappears
) : MyComponent

I'm not sure, but it looks like anvil-utils is being executed second time (which may happen) and it tries to generate the same file second time.

@IlyaGulya
Copy link
Owner

Thanks!
I will take a look this weekend

@arkivanov
Copy link
Author

Also this error happens if the component's class contains a dependency from an unresolved import.

import unresolved.package.name.MyClass

@ContributesAssistedFactory(UserScope::class, MyComponent.Factory::class)
class DefaultMyComponent @AssistedInject constructor(
    myClass: MyClass,
) : MyComponent

@IlyaGulya
Copy link
Owner

@arkivanov please test with this release and let me know if the issue is resolved
https://github.com/IlyaGulya/anvil-utils/releases/tag/v0.3.0-beta02

@arkivanov
Copy link
Author

I tried the new version, it looks like the issue with passing an unresolved dependency is now fixed, however the original issue still happens.

Here is the new stack trace:

[ksp] kotlin.io.FileAlreadyExistsException: /Users/arkivanov/workspace/<redacted>/build/generated/ksp/debug/kotlin/<redacted>/<redacted>Component_AssistedFactory.kt
	at com.google.devtools.ksp.common.impl.CodeGeneratorImpl.createNewFile(CodeGeneratorImpl.kt:154)
	at com.google.devtools.ksp.common.impl.CodeGeneratorImpl.createNewFile(CodeGeneratorImpl.kt:69)
	at com.google.devtools.ksp.processing.CodeGenerator.createNewFile$default(CodeGenerator.kt:59)
	at com.squareup.kotlinpoet.ksp.OriginatingKSFilesKt.writeTo(OriginatingKSFiles.kt:128)
	at me.gulya.anvil.utils.ksp.ContributesAssistedFactorySymbolProcessor.processChecked(ContributesAssistedFactorySymbolProcessor.kt:74)
	at me.gulya.anvil.utils.ksp.internal.ErrorLoggingSymbolProcessor.process(ErrorLoggingSymbolProcessor.kt:14)
	at com.google.devtools.ksp.AbstractKotlinSymbolProcessingExtension$doAnalysis$8$1.invoke(KotlinSymbolProcessingExtension.kt:310)
	at com.google.devtools.ksp.AbstractKotlinSymbolProcessingExtension$doAnalysis$8$1.invoke(KotlinSymbolProcessingExtension.kt:308)
	at com.google.devtools.ksp.AbstractKotlinSymbolProcessingExtension.handleException(KotlinSymbolProcessingExtension.kt:414)
	at com.google.devtools.ksp.AbstractKotlinSymbolProcessingExtension.doAnalysis(KotlinSymbolProcessingExtension.kt:308)
	at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:112)
	at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:77)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:256)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:247)
	at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:115)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:247)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.repeatAnalysisIfNeeded(KotlinToJVMBytecodeCompiler.kt:181)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:87)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli$default(KotlinToJVMBytecodeCompiler.kt:43)
	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:165)
	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:50)
	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:104)
	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:48)
	at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101)
	at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1523)
	at jdk.internal.reflect.GeneratedMethodAccessor91.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
	at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
	at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
	at java.base/java.security.AccessController.doPrivileged(Unknown Source)
	at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source)
	at java.base/java.security.AccessController.doPrivileged(Unknown Source)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.base/java.lang.Thread.run(Unknown Source)

@IlyaGulya
Copy link
Owner

@arkivanov thanks, I will take a look!

@IlyaGulya
Copy link
Owner

@arkivanov Unfortunately, I'm struggling to reproduce the issue 😅
Could you please give me more insights on your project structure?
Specifically, which modules contain which code and which other KSP processors being run in each of them?
I've tried to reproduce the issue with following project structure and had no luck:
https://github.com/IlyaGulya/anvil-utils/tree/reproducer/ksp-multi-round/compiler/src/test/fixtures/ksp-multi-round

I think I'm missing something 🙂

@arkivanov
Copy link
Author

No problem. I migrated my decompose-dagger-sample to Anvil and anvil-utils. And uploaded a reproducer for this issue to a separate branch. Just run ./gradlew :feature-list:kspDebugKotlin.

@IlyaGulya
Copy link
Owner

IlyaGulya commented Jan 14, 2025

@arkivanov Thanks for the reproducer!
I've fixed this issue in this release: https://github.com/IlyaGulya/anvil-utils/releases/tag/v0.3.0-beta03
However, I've found another issue in the Anvil itself which causes your reproducer to fail: ZacSweers/anvil#87
For now you can use Dagger KSP compiler instead of generateDaggerFactories, I suppose.

Let me know if there's something else left

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 a pull request may close this issue.

2 participants