I’m trying to invoke KSP2 programmatically as a li...
# ksp
d
I’m trying to invoke KSP2 programmatically as a library function, and I get an error “cannot find KtModule”. So, I basically have a directory with one kotlin source file. I set up a
KSPJvmConfig
with all the paths and get an exception. (It’s in the 🧵) The exception is supposed to tell me that no module containing the kotlin file can be found. Unfortunately, it’s hard to debug how it’s searching for the module. But what I can see in the exception attachment, is that paths (of the file and search scope) seem to match. Has anybody have ideas what could be wrong here?
Copy code
Exception in thread "main" org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments: Cannot find KtModule; see the attachment for more details.
	at org.jetbrains.kotlin.analysis.project.structure.impl.KtModuleProviderImpl.getModule(KtModuleProviderImpl.kt:72)
	at org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider$Companion.getModule(ProjectStructureProvider.kt:55)
	at org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSessionKt.getModule(LLFirResolveSession.kt:90)
	at org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableResolveSession.getModuleComponentsForElement(LLFirResolvableResolveSession.kt:57)
	at org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableResolveSession.getOrBuildFirFile$low_level_api_fir(LLFirResolvableResolveSession.kt:52)
	at org.jetbrains.kotlin.analysis.low.level.api.fir.api.LowLevelFirApiFacadeKt.getOrBuildFirFile(LowLevelFirApiFacade.kt:129)
	at org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirSymbolProvider.getFileSymbol(KtFirSymbolProvider.kt:57)
	at org.jetbrains.kotlin.analysis.api.symbols.KtSymbolProviderMixIn.getFileSymbol(KtSymbolProvider.kt:137)
	at com.google.devtools.ksp.impl.KotlinSymbolProcessing.prepareAllKSFiles(KotlinSymbolProcessing.kt:365)
	at com.google.devtools.ksp.impl.KotlinSymbolProcessing.execute(KotlinSymbolProcessing.kt:415)
t
Could you share a mini reproduce case, or attach the debugger (now that KSP2 can be called programmatically 🙂 ) to see why
KtModuleProviderImpl.getModule
throws?
d
Oh, yes, I tried to debug it from the beginning, for sure. I wasn’t very clear when I said it’s hard to debug. What I meant, is that for some reason I can’t see the sources of
KtModuleProviderImpl
. In my project I can navigate to this class, but I can see only the Idea-docompiled version, and it says “_Implementation of methods is not available_”, so only signatures. In KSP sources I can’t find this class at all. I mean even in libraries, understanding that it’s not really part of KSP itself, rather of a compiler. And grepping for its name in KSP sources, I can’t find references either. I could provide a small code sample. But also, maybe you could give me advice on how to get hold of that class? So that I could look around myself as well. Also, just to check, are these the correct dependencies for calling KSP2 in the way described in the blog post? I.e. create
KSPJvmConfig
and then call
KotlinSymbolProcessing
Copy code
symbol-processing-aa
symbol-processing-common-deps
Small update: I’ve found the reference to class
KtModuleProviderImpl
in the right version of the sources. I was looking at the latest sources, where it has already been changed. The KSP version used is 1.0.15
Another intermediate update: in
KotlinSymbolProcessing:533
in version 1.9.21-1.0.15 on line
if (parent in directories) return true
I get
false
although the paths clearly match. Checked by
parent.path in directories.map { it.path }
(It’s the place where we check that file is in content scope) Classloader issue seems to be out of question, as the class instance (
CoreLocalVirtualFile
) is the same for
parent
and members of
directories
(not only class name but KClass itself) However, hash codes are different for instances of
parent
and members of
directories
. Exploring further…
Ok, seems that the problem is that
myIoFile
object inside
CoreLocalVirtualFile
contain absolute and relative paths for 1) the file being searched for and 2) directory in content scope, respectively. That must be the reason for different hash codes. I’ll check if I can workaround that in my KSP setup code. But looks like something to fix.
Seems like passing only absolute path based
io.File
objects to
KSPJvmConfig
solves the issue.
👍 1
t
Congrats on solving the issue! btw, when calling KSP2 programmatically: 1. It's easier to use
symbol-processing-aa-embeddable
than
symbol-processing-aa
. The former renames all the dependencies so that those classes won't conflict with anything else, e.g., another version of the Kotlin compiler or KSP1, in the classpath. 2. Now that KSP2 doesn't depend on any specific version of the Kotlin compiler in the runtime / classpath, feel free to update to the latest snapshots to get the latest fixes. It is usually only ~1 night behind the main branch. a. Recent builds embed sources from dependencies into the uber source jar, so that guessing the correct versions of sources of the dependencies is no longer required.
d
Thanks! I wanted to try
aa-embeddable
but seems like it’s built for a much smaller number of kotlin/ksp versions. Judging by https://mvnrepository.com/artifact/com.google.devtools.ksp/symbol-processing-aa-embeddable
t
The latest one (in 2.0.0-Beta3-1.0.18) should work. Although there is a
2.0.0-Beta3-
prefix, it doesn't really depend on Kotlin 2.0.0-Beta3. It's just the legacy naming scheme for KSP1.
thank you color 1