@@ -8,7 +8,9 @@ import com.google.devtools.ksp.processing.SymbolProcessor
8
8
import com.google.devtools.ksp.symbol.ClassKind
9
9
import com.google.devtools.ksp.symbol.KSAnnotated
10
10
import com.google.devtools.ksp.symbol.KSClassDeclaration
11
+ import com.google.devtools.ksp.symbol.KSNode
11
12
import com.google.devtools.ksp.symbol.KSPropertyDeclaration
13
+ import com.google.devtools.ksp.symbol.KSValueParameter
12
14
import com.google.devtools.ksp.symbol.KSVisitorVoid
13
15
import com.google.devtools.ksp.symbol.Modifier
14
16
import com.google.devtools.ksp.validate
@@ -45,19 +47,63 @@ class DataCompatProcessor(
45
47
46
48
override fun process (resolver : Resolver ): List <KSAnnotated > {
47
49
logger.info(" DataCompat: process" )
48
- val annotated = resolver.getSymbolsWithAnnotation(DataCompat ::class .qualifiedName!! , true )
49
- if (annotated .count() == 0 ) {
50
+ val dataCompatAnnotated = resolver.getSymbolsWithAnnotation(DataCompat ::class .qualifiedName!! , true )
51
+ if (dataCompatAnnotated .count() == 0 ) {
50
52
logger.info(" DataCompat: No DataCompat annotations found for processing" )
51
53
return emptyList()
52
54
}
53
55
54
- val unableToProcess = annotated.filterNot { it.validate() }
55
- annotated.filter { it is KSClassDeclaration && it.validate() }
56
- .forEach { it.accept(Visitor (), Unit ) }
56
+ // symbols returned by
57
+ // resolver.getSymbolsWithAnnotation(DataCompat::class.qualifiedName!!, true)
58
+ // don't expose their annotations.
59
+ // Therefore we can't access the @Default annotation required to build the code
60
+ // for default values.
61
+ val classToDefaultValuesMap =
62
+ mutableMapOf<KSClassDeclaration , MutableMap <String , String ?>>()
63
+ val imports = ArrayList <String >()
64
+ val symbolsWithDefaultAnnotation =
65
+ resolver.getSymbolsWithAnnotation(Default ::class .qualifiedName!! , true )
66
+ symbolsWithDefaultAnnotation.forEach { annotatedProperty ->
67
+ // since KSP 1.8.10-1.0.9 annotatedProperty are returned ONLY as KSValueParameter;
68
+ // for previous KSP versions they were also returned as KSPropertyDeclaration
69
+ if (annotatedProperty is KSValueParameter ) {
70
+ val parentClass = annotatedProperty.findParentClass()!!
71
+ var defaultValueMap = classToDefaultValuesMap[parentClass]
72
+ if (defaultValueMap == null ) {
73
+ defaultValueMap = mutableMapOf ()
74
+ }
75
+ val defaultAnnotationsParams = annotatedProperty.annotations.firstOrNull()?.arguments
76
+ val defaultValue = defaultAnnotationsParams?.first()
77
+ defaultValueMap[annotatedProperty.name!! .getShortName()] =
78
+ defaultValue?.value as ? String?
79
+ defaultAnnotationsParams?.getOrNull(1 )?.value?.let {
80
+ imports.addAll(it as ArrayList <String >)
81
+ }
82
+ classToDefaultValuesMap[parentClass] = defaultValueMap
83
+ }
84
+ }
85
+
86
+ val unableToProcess = dataCompatAnnotated.filterNot { it.validate() }
87
+ dataCompatAnnotated.filter { it is KSClassDeclaration && it.validate() }
88
+ .forEach { it.accept(Visitor (classToDefaultValuesMap, imports), Unit ) }
57
89
return unableToProcess.toList()
58
90
}
59
91
60
- private inner class Visitor : KSVisitorVoid () {
92
+ private fun KSNode.findParentClass (): KSClassDeclaration ? {
93
+ var currentParent: KSNode ? = parent
94
+ while (currentParent !is KSClassDeclaration ) {
95
+ currentParent = parent?.parent
96
+ if (currentParent == null ) {
97
+ return null
98
+ }
99
+ }
100
+ return currentParent
101
+ }
102
+
103
+ private inner class Visitor (
104
+ private val defaultValuesMap : Map <KSClassDeclaration , MutableMap <String , String ?>>,
105
+ private val imports : List <String >
106
+ ) : KSVisitorVoid() {
61
107
62
108
@Suppress(" LongMethod" , " MaxLineLength" , " ComplexMethod" )
63
109
override fun visitClassDeclaration (classDeclaration : KSClassDeclaration , data : Unit ) {
@@ -77,7 +123,6 @@ class DataCompatProcessor(
77
123
val implementedInterfaces = classDeclaration
78
124
.superTypes
79
125
.filter { (it.resolve().declaration as ? KSClassDeclaration )?.classKind == ClassKind .INTERFACE }
80
- val imports = ArrayList <String >()
81
126
82
127
// Map KSP properties with KoltinPoet TypeNames
83
128
val propertyMap = mutableMapOf<KSPropertyDeclaration , TypeName >()
@@ -220,19 +265,13 @@ class DataCompatProcessor(
220
265
val builderBuilder = TypeSpec .classBuilder(" Builder" )
221
266
for (property in propertyMap) {
222
267
val propertyName = property.key.toString()
223
- val defaultAnnotationsParams = property.key.annotations
224
- .firstOrNull { it.annotationType.resolve().toString() == Default ::class .simpleName }
225
- ?.arguments
226
- val defaultValue = defaultAnnotationsParams?.first()
227
- defaultAnnotationsParams?.getOrNull(1 )?.value?.let {
228
- imports.addAll(it as ArrayList <String >)
229
- }
268
+
230
269
val nullableType = property.value.copy(nullable = true )
231
270
builderBuilder.addProperty(
232
271
PropertySpec .builder(propertyName, nullableType)
233
272
.initializer(
234
273
CodeBlock .builder()
235
- .add((defaultValue?.value as ? String? ) ? : " null" )
274
+ .add(defaultValuesMap[classDeclaration]?.get(propertyName ) ? : " null" )
236
275
.build()
237
276
)
238
277
.addAnnotation(
0 commit comments