Skip to content

Commit d453417

Browse files
yigitneetopia
authored andcommitted
FIx findOverridee for properties
This CL updates KSPropertyDecl.findOverridee to use the same infra that is used by KSFunctionDeclaration. Fixes: #174
1 parent 06eab3b commit d453417

File tree

6 files changed

+93
-11
lines changed

6 files changed

+93
-11
lines changed

api/src/main/kotlin/com/google/devtools/ksp/symbol/KSPropertyDeclaration.kt

+24-2
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,30 @@ interface KSPropertyDeclaration : KSDeclaration {
5858
fun isDelegated(): Boolean
5959

6060
/**
61-
* Find the original overridee of this property, if overriding.
62-
* @return [KSPropertyDeclaration] for the original property, if overriding, otherwise null.
61+
* Find the closest overridee of this property, if overriding.
62+
*
63+
* For the following input:
64+
* ```
65+
* abstract class A {
66+
* open val x:Int
67+
* open val y:Int
68+
* }
69+
* abstract class B : A() {
70+
* override val x:Int
71+
* }
72+
* abstract class C : B() {
73+
* override val x:Int
74+
* override val y:Int
75+
* }
76+
* ```
77+
* Calling `findOverridee` on `C.x` will return `B.x`.
78+
* Calling `findOverridee` on `C.y` will return `A.y`.
79+
*
80+
* When there are multiple super classes / interfaces with the property, the closest declaration
81+
* to the current containing declaration is selected. If they are in the same level, the
82+
* property of the first specified interface (in source) will be returned.
83+
*
84+
* @return [KSPropertyDeclaration] for the overridden property, if overriding, otherwise null.
6385
* Calling [findOverridee] is expensive and should be avoided if possible.
6486
*/
6587
fun findOverridee(): KSPropertyDeclaration?

compiler-plugin/src/main/kotlin/com/google/devtools/ksp/processor/OverrideeProcessor.kt

+16
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import com.google.devtools.ksp.getClassDeclarationByName
2222
import com.google.devtools.ksp.processing.Resolver
2323
import com.google.devtools.ksp.symbol.KSClassDeclaration
2424
import com.google.devtools.ksp.symbol.KSFunctionDeclaration
25+
import com.google.devtools.ksp.symbol.KSPropertyDeclaration
2526

2627
@Suppress("unused") // used by tests
2728
class OverrideeProcessor: AbstractTestProcessor() {
@@ -51,6 +52,12 @@ class OverrideeProcessor: AbstractTestProcessor() {
5152
}
5253

5354
private fun logClass(subject: KSClassDeclaration) {
55+
subject.declarations.filterIsInstance<KSPropertyDeclaration>()
56+
.forEach {
57+
val signature = it.toSignature()
58+
val overrideeSignature = it.findOverridee()?.toSignature()
59+
results.add("$signature -> $overrideeSignature")
60+
}
5461
subject.declarations.filterIsInstance<KSFunctionDeclaration>()
5562
.filterNot { it.simpleName.asString() in IGNORED_METHOD_NAMES }
5663
.forEach {
@@ -74,6 +81,15 @@ class OverrideeProcessor: AbstractTestProcessor() {
7481
}
7582
}
7683

84+
private fun KSPropertyDeclaration.toSignature(): String {
85+
val self = this
86+
return buildString {
87+
append(self.closestClassDeclaration()?.simpleName?.asString())
88+
append(".")
89+
append(self.simpleName.asString())
90+
}
91+
}
92+
7793
companion object {
7894
// ignore these methods as we receive syntetics of it from compiled code
7995
private val IGNORED_METHOD_NAMES = listOf("equals", "hashCode", "toString")

compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSPropertyDeclarationDescriptorImpl.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ class KSPropertyDeclarationDescriptorImpl private constructor(val descriptor: Pr
8686
}
8787

8888
override fun findOverridee(): KSPropertyDeclaration? {
89-
return ResolverImpl.instance.resolvePropertyDeclaration(this)?.original?.overriddenDescriptors?.single { it.overriddenDescriptors.isEmpty() }
90-
?.toKSPropertyDeclaration()
89+
val propertyDescriptor = ResolverImpl.instance.resolvePropertyDeclaration(this)
90+
return propertyDescriptor?.findClosestOverridee()?.toKSPropertyDeclaration()
9191
}
9292

9393
override fun isDelegated(): Boolean {

compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyDeclarationImpl.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ class KSPropertyDeclarationImpl private constructor(val ktProperty: KtProperty)
104104
override fun isDelegated(): Boolean = ktProperty.hasDelegate()
105105

106106
override fun findOverridee(): KSPropertyDeclaration? {
107-
return ResolverImpl.instance.resolvePropertyDeclaration(this)?.original?.overriddenDescriptors?.single { it.overriddenDescriptors.isEmpty() }
108-
?.toKSPropertyDeclaration()
107+
val propertyDescriptor = ResolverImpl.instance.resolvePropertyDeclaration(this)
108+
return propertyDescriptor?.findClosestOverridee()?.toKSPropertyDeclaration()
109109
}
110110

111111
override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {

compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/utils.kt

+5-5
Original file line numberDiff line numberDiff line change
@@ -285,9 +285,9 @@ internal fun DeclarationDescriptor.findPsi(): PsiElement? {
285285
}
286286

287287
/**
288-
* @see KSFunctionDeclaration.findOverridee for docs.
288+
* @see KSFunctionDeclaration.findOverridee / [KSPropertyDeclaration.findOverridee] for docs.
289289
*/
290-
internal fun FunctionDescriptor.findClosestOverridee(): FunctionDescriptor? {
290+
internal inline fun <reified T : CallableMemberDescriptor> T.findClosestOverridee(): T? {
291291
// When there is an intermediate class between the overridden and our function, we might receive
292292
// a FAKE_OVERRIDE function which is not desired as we are trying to find the actual
293293
// declared method.
@@ -296,16 +296,16 @@ internal fun FunctionDescriptor.findClosestOverridee(): FunctionDescriptor? {
296296
// class / interface method OR in case of equal distance (e.g. diamon dinheritance), pick the
297297
// one declared first in the code.
298298

299-
val queue = ArrayDeque<FunctionDescriptor>()
299+
val queue = ArrayDeque<T>()
300300
queue.add(this)
301301

302302
while (queue.isNotEmpty()) {
303303
val current = queue.removeFirst()
304-
val overriddenDescriptors = current.original.overriddenDescriptors
304+
val overriddenDescriptors: Collection<T> = current.original.overriddenDescriptors.filterIsInstance<T>()
305305
overriddenDescriptors.firstOrNull {
306306
it.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE
307307
}?.let {
308-
return it.original
308+
return it.original as T?
309309
}
310310
// if all methods are fake, add them to the queue
311311
queue.addAll(overriddenDescriptors)

compiler-plugin/testData/api/overridee.kt

+44
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020
// EXPECTED:
2121
// Subject:
2222
// Companion.companionMethod() -> null
23+
// Subject.notOverridingProp -> null
24+
// Subject.overriddenBaseProp -> Base.overriddenBaseProp
25+
// Subject.overriddenAbstractBaseProp -> Base.overriddenAbstractBaseProp
26+
// Subject.openGrandBaseProp -> GrandBase.openGrandBaseProp
27+
// Subject.abstractGrandBaseProp -> GrandBase.abstractGrandBaseProp
28+
// Subject.overriddenGrandBaseProp -> Base.overriddenGrandBaseProp
29+
// Subject.overriddenAbstractGrandBaseProp -> Base.overriddenAbstractGrandBaseProp
2330
// Subject.openFun() -> Base.openFun()
2431
// Subject.abstractFun() -> Base.abstractFun()
2532
// Subject.openFunWithGenericArg(t:String) -> Base.openFunWithGenericArg(t:T)
@@ -42,6 +49,13 @@
4249
// Subject.staticMethod() -> null
4350
// lib.Subject:
4451
// Companion.companionMethod() -> null
52+
// Subject.abstractGrandBaseProp -> GrandBase.abstractGrandBaseProp
53+
// Subject.notOverridingProp -> null
54+
// Subject.openGrandBaseProp -> GrandBase.openGrandBaseProp
55+
// Subject.overriddenAbstractBaseProp -> Base.overriddenAbstractBaseProp
56+
// Subject.overriddenAbstractGrandBaseProp -> Base.overriddenAbstractGrandBaseProp
57+
// Subject.overriddenBaseProp -> Base.overriddenBaseProp
58+
// Subject.overriddenGrandBaseProp -> Base.overriddenGrandBaseProp
4559
// Subject.abstractFun() -> Base.abstractFun()
4660
// Subject.abstractFunWithGenericArg(t:String) -> Base.abstractFunWithGenericArg(t:T)
4761
// Subject.abstractGrandBaseFun() -> GrandBase.abstractGrandBaseFun()
@@ -68,12 +82,20 @@
6882
// FILE: lib.kt
6983
package lib;
7084
abstract class GrandBase {
85+
open var openGrandBaseProp: Int = 0
86+
abstract var abstractGrandBaseProp: Int
87+
open var overriddenGrandBaseProp: Int = 0
88+
abstract var overriddenAbstractGrandBaseProp: Int
7189
open fun openGrandBaseFun() {}
7290
abstract fun abstractGrandBaseFun()
7391
open fun overriddenGrandBaseFun() {}
7492
abstract fun overriddenAbstractGrandBaseFun()
7593
}
7694
abstract class Base<T> : GrandBase() {
95+
open var overriddenBaseProp: Int = 0
96+
abstract var overriddenAbstractBaseProp: Int
97+
override var overriddenGrandBaseProp:Int = 0
98+
override var overriddenAbstractGrandBaseProp: Int = 0
7799
open fun openFun() {}
78100
abstract fun abstractFun():Unit
79101
open fun openFunWithGenericArg(t:T):T = TODO()
@@ -83,6 +105,13 @@ abstract class Base<T> : GrandBase() {
83105
}
84106

85107
abstract class Subject: Base<String>() {
108+
var notOverridingProp: Int = 0
109+
override open var overriddenBaseProp: Int = 0
110+
override var overriddenAbstractBaseProp: Int = 0
111+
override open var openGrandBaseProp: Int = 0
112+
override var abstractGrandBaseProp: Int = 0
113+
override var overriddenGrandBaseProp:Int = 0
114+
override var overriddenAbstractGrandBaseProp: Int = 0
86115
override fun openFun() {}
87116
override fun abstractFun() {}
88117
override fun openFunWithGenericArg(t:String):String = TODO()
@@ -99,12 +128,20 @@ abstract class Subject: Base<String>() {
99128
// MODULE: main(lib)
100129
// FILE: a.kt
101130
abstract class GrandBase {
131+
open var openGrandBaseProp: Int = 0
132+
abstract var abstractGrandBaseProp: Int = 0
133+
open var overriddenGrandBaseProp: Int = 0
134+
abstract var overriddenAbstractGrandBaseProp: Int = 0
102135
open fun openGrandBaseFun() {}
103136
abstract fun abstractGrandBaseFun()
104137
open fun overriddenGrandBaseFun() {}
105138
abstract fun overriddenAbstractGrandBaseFun()
106139
}
107140
abstract class Base<T> : GrandBase() {
141+
open var overriddenBaseProp: Int = 0
142+
var overriddenAbstractBaseProp: Int = 0
143+
override var overriddenGrandBaseProp:Int = 0
144+
override var overriddenAbstractGrandBaseProp: Int = 0
108145
open fun openFun() {}
109146
abstract fun abstractFun():Unit
110147
open fun openFunWithGenericArg(t:T):T = TODO()
@@ -114,6 +151,13 @@ abstract class Base<T> : GrandBase() {
114151
}
115152

116153
abstract class Subject: Base<String>() {
154+
var notOverridingProp: Int = 0
155+
override open var overriddenBaseProp: Int = 0
156+
override var overriddenAbstractBaseProp: Int = 0
157+
override open var openGrandBaseProp: Int = 0
158+
override var abstractGrandBaseProp: Int = 0
159+
override var overriddenGrandBaseProp:Int = 0
160+
override var overriddenAbstractGrandBaseProp: Int = 0
117161
override fun openFun() {}
118162
override fun abstractFun() {}
119163
override fun openFunWithGenericArg(t:String):String = TODO()

0 commit comments

Comments
 (0)