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

How to get list of contributed interfaces and modules #724

Open
mattinger opened this issue Jul 13, 2023 · 1 comment
Open

How to get list of contributed interfaces and modules #724

mattinger opened this issue Jul 13, 2023 · 1 comment

Comments

@mattinger
Copy link

mattinger commented Jul 13, 2023

I am trying to write a compiler plug-in, and as part of that, i want to get the generated components and the things included in them.

    override fun generateCode(
        codeGenDir: File,
        module: ModuleDescriptor,
        projectFiles: Collection<KtFile>
    ): Collection<GeneratedFile> {
        return projectFiles
            .classAndInnerClassReferences(module)
            .filter {
                it.isAnnotatedWith(FqName(MockableComponent::class.java.name))
            }
            .mapNotNull { clazz ->

                val packageName = clazz.packageFqName.asString()
                val className = clazz.shortName
                
                val scope = clazz.annotations.find {
                    it.fqName.asString() == MergeComponent::class.java.name
                }?.arguments?.find {
                    it.name == "scope"
                }?.value<ClassReference>()?.fqName?.asString()

So, knowing the class, and scope, I'm trying to figure out how to get the list of included modules and interfaces. I just can't seem to find much documentation on using the compiler api itself, and nothing is jumping out at me when i'm perusing the code.

Any pointers as to how to get started would be appreciated.

Basically my end goal is to take the generated component, and produce a version of it with a full Component.Factory with functions for each module. This would allow me to auto generate a component suitable for use with daggermock.

something like this:

@Component(modules = [ MyModule::class ])
public interface MyComponent_Mockable : MyAccessors {
  @Component.Factory
  public interface Factory {
    public fun create(myModule: MyModule): MyComponent_Mockable
  }
}

I'm able to gather all the contributed classes and interfaces and the basic example above, but it will get hairy dealing with things like "replaces" and "excludes". I'm hoping to re-use the logic in the existing compiler to do that work for me of assembling the list of modules and interfaces.

@mattinger
Copy link
Author

mattinger commented Jul 17, 2023

I had been hoping to use ClassScanner and perhaps FlushingCodeGenerator, but they are internal classes. And what i've done locally isn't picking up all my modules. It's only picking up ones in the current source tree:

    fun getContributedModulePsis(
        module: ModuleDescriptor,
        projectFiles: Collection<KtFile>,
        scope: String,
    ) = projectFiles
        .classAndInnerClassReferences(module)
        .filter {
            it.isContributesTo(scope) &&
                    !it.isInterface()
                    it.annotations.find { a -> a.fqName.asString() == Module::class.java.name } != null

        }
        .toList()

I suspect this is because the module hints and such are used for sort of keeping track across the different sourcepaths, and i'm not able to use the classes required for that because it all seems to be internal

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

No branches or pull requests

1 participant