https://kotlinlang.org logo
#compiler
Title
# compiler
j

Jonathan Gerrish

12/28/2020, 6:10 PM
Hi all. I'm trying to write a compiler plugin that tracks which jars dependencies are loaded from. Is an `AnalysisHandlerExtension`the right kind of extension to do this? I'm having trouble finding an API that is able to tied a KtType back to the jar it was loaded from. Any pointers appreciated 🙂
s

shikasd

12/28/2020, 6:57 PM
Hey, I would try to track the ClassDescriptors to ModuleDescriptor they are associated with, this may provide some info related to this
j

Jonathan Gerrish

12/28/2020, 8:09 PM
Hey @shikasd - thanks, ya, I'm trying this but anything that looks useful on `ModuleDescriptor`seems to be null e.g: `ModuleDescriptor.moduleInfo`and calling `ModuleDescriptor.kotlinLibrary`which looks interesting throws an NPE. Should that information just be there or do I need to load it from somewhere?
s

shikasd

12/28/2020, 8:18 PM
Hm, do you try to resolve module descriptor for the current module or dependency one? AFAIK
kotlinLibrary
should be for
klib
dependencies rather than jars :)
j

Jonathan Gerrish

12/28/2020, 8:41 PM
Trying to resolve for a dependency, so if I have
Copy code
class Foo {
  var bar = Bar()
}
Foo + Bar are in different modules. I can get the `ClassDescriptor`for `Bar`but then
classDescriptor.module.name
==
<dependencies of foo>
and
ModuleDescriptor.moduleInfo == null
.
s

shikasd

12/29/2020, 5:50 PM
Interesting, maybe it is only populated in some builds I will maybe dig a little more into this, but not sure myself where else you could find this information
j

Jonathan Gerrish

12/30/2020, 5:19 PM
Hey @shikasd - We've found a way to do this using a
RemappingClassBuilder
and are able to write out dependencies for most usages. One thing we can't track though is stuff that has already been inlined by the compiler such as references to `const val FOO = 42`since `FOO`has already been replaced with `42`at this stage. Can you suggest a way to capture this information before the inlining occurs? Is this something we need to parse in
AnalysisHandlerExtension.doAnalysis(...)
s

shikasd

12/30/2020, 5:30 PM
Did you check if RemappingClassBuilder works with IR compiler? I remember some changes in there, but not sure if they have affected this extension point. Otherwise, if you only need to find the descriptors of the current module as an entry point, I think you could achieve the same enumerating the descriptors of the current module from BindingTrace in analysisCompleted or using DeclarationChecker. To track calls to the inline functions/properties, you can create your CallChecker, which will be called for each function/field reference inside function body. Class/FunctionDescriptors only contain info about the "abi" of the declaration, so you'll need to go through PSI tree there for sure.
j

Jonathan Gerrish

12/30/2020, 5:34 PM
Thanks Andrei, that's a lot to parse 🙂 .... I'll play around with your suggestions and let you know how I get on.
s

shikasd

12/30/2020, 5:59 PM
No worries, it is just random stream of everything I thought about while looking at your code :D
Let me know if something is unclear :)
j

Jonathan Gerrish

01/02/2021, 5:33 PM
Happy New Year @shikasd - I didn't find a way to get the descriptors from the
BindingTrace
- is there something I'm missing? Instead I just enumerated over the Files and pulled the import declarations. Obviously that's not complete (it will miss FQN usages) but it gets us started. I haven't taken a look at using `DeclarationChecker`/
CallChecker
- needing to check the PSI - would that be expensive?
Also, do you know who I should speak to re: JvmAbiPlugin? I'm not sure if this is used in Gradle yet, but its very important for compile avoidance in Bazel. I reported a few bugs and it also doesn't look fully complete so wondering when it might get some love? In particular I'd really like to find a way to run just the ABI generation and skip full compilation. Assuming that ABI generation is much faster than full compilation this would be enable us to to remove full compilation from the critical path and speed up builds significantly.
s

shikasd

01/02/2021, 5:55 PM
Declaration/CallCheckers are quite cheap, as they are called for any declaration/call anyways You get all declared/referenced descriptors there including fqn ones :) To pull descriptors out of BindingTrace, you need to reference a slice. BindingTrace is essentially
Map<Slice<Key, Value>, Map<Key, Value>>
Slices here is used to retrieve that inner map which you can iterate on (e.g. BindingContext.CLASS, which provides connection between KtClass and ClassDescriptors). This info is provided by DeclarationCheckers anyway, so I probably wouldn't bother.
For abi plugin, I am not sure, it was created by someone from JB, so I am not sure exactly who is responsible You can find a related tracking issue, probably the person who created it has comments there
j

Jonathan Gerrish

01/02/2021, 6:07 PM
Awesome, thank you! 🙂
19 Views