DEADSOFTWARE

cfaa3a590393d3478e34994c39174da0db93a147
[cavedroid.git] / dagger-multibind-ksp / src / main / kotlin / ru / fredboy / cavedroid / ksp / processor / GenerateMapMultibindingsSymbolProcessor.kt
1 package ru.fredboy.cavedroid.ksp.processor
3 import com.google.devtools.ksp.processing.*
4 import com.google.devtools.ksp.symbol.KSAnnotated
5 import com.google.devtools.ksp.symbol.KSClassDeclaration
6 import com.google.devtools.ksp.symbol.KSType
7 import com.squareup.kotlinpoet.*
8 import com.squareup.kotlinpoet.ksp.toClassName
9 import com.squareup.kotlinpoet.ksp.writeTo
10 import ru.fredboy.cavedroid.ksp.annotations.GenerateMapMultibindingsModule
12 class GenerateMapMultibindingsSymbolProcessor(
13 private val codeGenerator: CodeGenerator,
14 private val logger: KSPLogger,
15 ) : SymbolProcessor {
17 private fun generateModule(
18 annotationName: String,
19 interfaceName: ClassName,
20 moduleName: ClassName,
21 classes: List<KSClassDeclaration>
22 ): FileSpec? {
23 if (classes.isEmpty()) {
24 return null
25 }
27 val bindings = classes.map { decl ->
28 val stringKey = decl.annotations.first { declAnn ->
29 declAnn.shortName.getShortName() == annotationName
30 }.arguments.firstOrNull { arg ->
31 arg.name!!.getShortName() == "stringKey"
32 }?.value as? String ?: run {
33 logger.error("@${annotationName} must include stringKey parameter for key selection in generated module")
34 throw IllegalArgumentException()
35 }
37 val clazz = decl.toClassName()
39 FunSpec.builder("bind${clazz.simpleName}")
40 .addAnnotation(ClassName("dagger", "Binds"))
41 .addAnnotation(ClassName("dagger.multibindings", "IntoMap"))
42 .addAnnotation(
43 AnnotationSpec.builder(ClassName("dagger.multibindings", "StringKey"))
44 .addMember("\"$stringKey\"")
45 .build()
46 )
47 .addParameter(ParameterSpec("impl", clazz))
48 .returns(interfaceName)
49 .addCode("return impl")
50 .build()
51 }
53 val moduleObject = TypeSpec.objectBuilder(moduleName)
54 .addAnnotation(ClassName("dagger", "Module"))
55 .addFunctions(bindings)
56 .build()
58 return FileSpec.builder(moduleName)
59 .addType(moduleObject)
60 .build()
62 }
64 private fun processAnnotation(resolver: Resolver, annotation: KSClassDeclaration) {
65 val args = annotation.annotations.first {
66 it.shortName.getShortName() == "GenerateMapMultibindingsModule"
67 }.arguments.takeIf { it.size == 3 } ?: run {
68 logger.error("GenerateMapMultibindingsModule should have 3 arguments")
69 throw IllegalArgumentException()
70 }
72 val interfaceName = args.first { it.name?.getShortName() == "interfaceClass" }.value as KSType
73 val modulePackage = args.first { it.name?.getShortName() == "modulePackage" }.value as String
74 val moduleName = args.first { it.name?.getShortName() == "moduleName" }.value as String
76 val moduleClassName = ClassName(modulePackage, moduleName)
77 val elements = resolver.getSymbolsWithAnnotation(annotation.qualifiedName!!.asString())
78 .filterIsInstance<KSClassDeclaration>()
79 .toList()
81 logger.info("Found elements: ${elements.joinToString()}")
83 generateModule(
84 annotationName = annotation.qualifiedName!!.getShortName(),
85 interfaceName = interfaceName.toClassName(),
86 moduleName = moduleClassName,
87 classes = elements
88 )?.writeTo(codeGenerator, Dependencies(true))
89 }
91 override fun process(resolver: Resolver): List<KSAnnotated> {
92 val annotations = resolver.getAnnotatedClasses(GenerateMapMultibindingsModule::class.qualifiedName!!, logger)
93 logger.info("Found annotations: ${annotations.joinToString { it.qualifiedName!!.asString() }}")
94 annotations.forEach { processAnnotation(resolver, it) }
95 return emptyList()
96 }
98 }