Skip to content

Commit 3c42494

Browse files
authored
Merge pull request #34 from tobrun/kdz-revisit-default-annotation
Use another approach for default annotation
2 parents 37349dd + 375000c commit 3c42494

File tree

3 files changed

+57
-18
lines changed

3 files changed

+57
-18
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ And you will have to include the required dependencies:
2828

2929
```groovy
3030
dependencies {
31-
implementation 'com.github.tobrun.kotlin-data-compat:annotation:0.4.0'
32-
ksp 'com.github.tobrun.kotlin-data-compat:processor:0.4.0'
31+
implementation 'com.github.tobrun.kotlin-data-compat:annotation:0.4.1'
32+
ksp 'com.github.tobrun.kotlin-data-compat:processor:0.4.1'
3333
}
3434
```
3535

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists

processor/src/main/kotlin/com/tobrun/datacompat/DataCompatProcessor.kt

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import com.google.devtools.ksp.processing.SymbolProcessor
88
import com.google.devtools.ksp.symbol.ClassKind
99
import com.google.devtools.ksp.symbol.KSAnnotated
1010
import com.google.devtools.ksp.symbol.KSClassDeclaration
11+
import com.google.devtools.ksp.symbol.KSNode
1112
import com.google.devtools.ksp.symbol.KSPropertyDeclaration
13+
import com.google.devtools.ksp.symbol.KSValueParameter
1214
import com.google.devtools.ksp.symbol.KSVisitorVoid
1315
import com.google.devtools.ksp.symbol.Modifier
1416
import com.google.devtools.ksp.validate
@@ -45,19 +47,63 @@ class DataCompatProcessor(
4547

4648
override fun process(resolver: Resolver): List<KSAnnotated> {
4749
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) {
5052
logger.info("DataCompat: No DataCompat annotations found for processing")
5153
return emptyList()
5254
}
5355

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) }
5789
return unableToProcess.toList()
5890
}
5991

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() {
61107

62108
@Suppress("LongMethod", "MaxLineLength", "ComplexMethod")
63109
override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: Unit) {
@@ -77,7 +123,6 @@ class DataCompatProcessor(
77123
val implementedInterfaces = classDeclaration
78124
.superTypes
79125
.filter { (it.resolve().declaration as? KSClassDeclaration)?.classKind == ClassKind.INTERFACE }
80-
val imports = ArrayList<String>()
81126

82127
// Map KSP properties with KoltinPoet TypeNames
83128
val propertyMap = mutableMapOf<KSPropertyDeclaration, TypeName>()
@@ -220,19 +265,13 @@ class DataCompatProcessor(
220265
val builderBuilder = TypeSpec.classBuilder("Builder")
221266
for (property in propertyMap) {
222267
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+
230269
val nullableType = property.value.copy(nullable = true)
231270
builderBuilder.addProperty(
232271
PropertySpec.builder(propertyName, nullableType)
233272
.initializer(
234273
CodeBlock.builder()
235-
.add((defaultValue?.value as? String?) ?: "null")
274+
.add(defaultValuesMap[classDeclaration]?.get(propertyName) ?: "null")
236275
.build()
237276
)
238277
.addAnnotation(

0 commit comments

Comments
 (0)