https://kotlinlang.org logo
Title
e

elihart

02/22/2021, 5:07 PM
Is there any equivalent in KSP for
javax.lang.model.element.PackageElement
? As far as I can tell there isn’t a
KSAnnotated
representation of a package (potentially because package-info.java is not used in kotlin?) I have a javac processor that looks up annotations on package elements and am wondering how KSP handles that. Similarly, does KSP provide any way to resolve the package by name? In javac we can do
Elements.getPackageElement(CharSequence)
to get a package, which then provides access to all elements in that package (including elements from other modules). We have used this to enable a single module to aggregate the generated files of other modules, by putting them all in the same package. I’m trying to figure out how to translate this to KSP
j

Jiaxiang

02/22/2021, 8:29 PM
See docs/reference.md. There isn’t such thing in KSP directly, you can still inspect package names, but there is no KSP representation for package itself.
for your use case it might be impractical to do so, let me think about how to deal with this case.
e

elihart

02/22/2021, 9:54 PM
Thanks, I should have checked there first 😅 But yes, I think that leaves the question of how to support existing javac processors that heavily rely on these APIs. I started working on adding KSP support to the handful of libraries we own with annotation processors, and this is a bit of a blocker for them. Curious to hear what you can think of 🙏
j

Jiaxiang

02/23/2021, 1:39 AM
I am thinking about providing some API to return a list of symbols given a package name, in that case no package level symbols is introduced but should still serve your purpose (I feel this should be sufficient for practical use cases looking at PackageElement)
e

elihart

02/23/2021, 2:26 AM
I think that would be great, and would cover our only use case of it. (And this would return symbols outside of the currently compiling module, correct?)
What does KSP do if a java package element is annotated and processed with KSP? Does it skip it, or represent it with a different symbol type, maybe KSFile? (I can also try this out to see, but asking in case you happen to know off the top of your head)
well, I tried it out and it seems like
resolver.getSymbolsWithAnnotation
completely skips any annotated packages (I suppose kotlin just doesn’t even compile those?) That’s fine, I can work around that at least, but I think the documentation could be a little clearer that the package annotation target in java is not supported (it says the package element doesn’t exist, but kind of implies KSFile is the closest alternative)
j

Jiaxiang

02/23/2021, 2:55 AM
Sounds good, I’ll take a note on this.
And yes, my proposed API will return symbols from binaries as well, that’s why it will require some effort on KSP side, otherwise one can simply use
getAllFiles()
to iterate through all files and find the files with desired package name.
e

elihart

02/23/2021, 3:32 AM
great, I was thinking the same, just double checking. Thank you very much! 🙏
j

Jiaxiang

02/25/2021, 11:59 PM
Hi, some follow up here. From what you asked in original thread, it looks like it is not involving annotations, and we can achieve same thing with a byte code visitor that visits byte code in classpath, which can also be more efficient without intermediate wrapping of KSP and kotlin compiler. Is your project open source? if so may I take a look at the code to see what’s the exact use case and evaluate?
e

elihart

02/26/2021, 4:19 AM
That’s right, it doesn’t involve annotations, so visiting byte code sounds reasonable if it is able to be supported. Here’s an example in Showkase which generates a gallery of @Composable UI views. Data about each composable is written to a file in a hardcoded package: https://github.com/airbnb/Showkase/blob/master/showkase-processor/src/main/java/co[…]roid/showkase/processor/writer/ShowkaseCodegenMetadataWriter.kt Then a single module can read the generated files from all other modules to gather them together into the gallery it displays: https://github.com/airbnb/Showkase/blob/master/showkase-processor/src/main/java/com/airbnb/android/showkase/processor/ShowkaseProcessor.kt#L235 This allows us to write composables in many modules, and then have our single application module that depends on all library modules aggregate files together and further process all of them
Alternatively another approach could work by looking up annotated symbols in any binary on the classpath, but since javac doesn’t support that we use this approach.
j

Jiaxiang

02/26/2021, 10:55 PM
KSP is unlikely to provide a byte code visitor since it seems out of scope for an annotation processor. I wonder how feasible it will be for you to write a byte code visitor to load the classes, and once you get the classes (just names will work) you still have full access to other KSP APIs, like checking annotations you did in the code you linked.
e

elihart

02/26/2021, 11:37 PM
I could try writing a byte code visitor if you’re able to point me in the right direction to get started. A general purpose byte code visitor does seem out of scope, but since the root of our use case is to allow a module to access files generated by KSP in other modules that use case seems in scope. Or put another way, it could be in scope to be able to process annotations from binaries
j

Jiaxiang

02/26/2021, 11:42 PM
It is possible to process annotations from binaries, but the limitation is that you can’t call
getSymbolsAnnotatedWith
to get the symbols from binaries, this can be hard to implement and also expensive. I am trying to explore alternate options before I can make a commitment on whether KSP will provide such API for getting symbols from a package, since a package symbol is most likely for Java rather than for Kotlin.
e

elihart

02/27/2021, 6:11 PM
thank you for continuing to think it through 🙏
since a package symbol is most likely for Java rather than for Kotlin
I don’t think a package symbol is important, and it is fine that KSP doesn’t have it. But it is useful for both Java and Kotlin to look up either all symbols with the same package name, or process annotations in another binary. If KSP took a package name and returned a list of symbols within that package that would work great too, without any need for a package symbol
g

gabrielfv

02/27/2021, 11:02 PM
I’m also processing many modules and generating intermediate classes so that once I hit the aggregating module I could just access them through their package. Now, for that use-case in particular, what is interesting is not exactly to be able to fetch symbols within a package from dependency modules, but more specifically to have a way we can pre-process each module and finish processing of all of these symbols once we reach the bottom module that will aggregate everything. Doing so through package was just the way found to do it through javaAP, but in terms of API idk if that’s the optimal path, It’s what we get used to and good to port javaAP code to KSP, but that’s it.
IMO, there’s some quirkiness to the end user of those processors that perhaps we could avoid with KSP, like for example having to define some kind of
@Root<…>
annotation just to tell the processor “Hey, this is the module we should generate the aggregating code!“. Granted I don’t see no other way to do this in a nice API other than rely on flags that could be triggered from a custom gradle plugin and that’s not exactly better either.
e

elihart

03/25/2021, 6:48 PM
Hi @Jiaxiang I’m wondering if you have any updates to share on this at all. Would it be helpful if I created an issue on Github so this work could be tracked easier?
j

Jiaxiang

03/25/2021, 7:03 PM
Oops sorry for the long wait, I thought I’ve updated here. KSP itself is unlikely to provide package symbols directly, but we do plan to support it either as an experimental API like
getJvmName()
, or support it in another module, potentially Room’s abstraction layer. Yes please file an issue on Github.
👍 1
e

elihart

04/02/2021, 4:23 PM
Created the issue, https://github.com/google/ksp/issues/372, thanks!