Uast: KT-40578: resolve Kotlin property writes to setters (#3597)
* KT-40578: resolve Kotlin property writes to setters * limit to non-constructor properties * Uast: `KotlinIDERenderLogTest.testConstructors` fix Co-authored-by: Nicolay Mitropolsky <nicolay.mitropolsky@jetbrains.com>
This commit is contained in:
+9
-7
@@ -26,12 +26,9 @@ import com.intellij.psi.impl.compiled.ClsTypeElementImpl
|
||||
import com.intellij.psi.impl.compiled.SignatureParsing
|
||||
import com.intellij.psi.impl.compiled.StubBuildingVisitor
|
||||
import com.intellij.psi.util.PsiTypesUtil
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||
import org.jetbrains.kotlin.asJava.*
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
|
||||
import org.jetbrains.kotlin.asJava.findFacadeClass
|
||||
import org.jetbrains.kotlin.asJava.toLightClass
|
||||
import org.jetbrains.kotlin.asJava.toLightElements
|
||||
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalTypeOrSubtype
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
@@ -334,7 +331,7 @@ internal fun resolveToDeclaration(sourcePsi: KtExpression): PsiElement? =
|
||||
}
|
||||
|
||||
internal fun resolveToDeclaration(sourcePsi: KtExpression, declarationDescriptor: DeclarationDescriptor): PsiElement? {
|
||||
declarationDescriptor.toSource()?.getMaybeLightElement()?.let { return it }
|
||||
declarationDescriptor.toSource()?.getMaybeLightElement(sourcePsi)?.let { return it }
|
||||
|
||||
var declarationDescriptor = declarationDescriptor
|
||||
if (declarationDescriptor is ImportedFromObjectCallableDescriptor<*>) {
|
||||
@@ -446,8 +443,8 @@ private fun resolveDeserialized(
|
||||
if (propertySignature != null) {
|
||||
with(propertySignature) {
|
||||
when {
|
||||
hasSetter() && accessHint?.isWrite == true -> setter // treat += etc. as write as was done elsewhere
|
||||
hasGetter() && accessHint?.isRead != false -> getter
|
||||
hasSetter() && accessHint?.isWrite != false -> setter
|
||||
else -> null // it should have been handled by the previous case
|
||||
}
|
||||
}?.let { methodSignature ->
|
||||
@@ -513,7 +510,12 @@ private fun KotlinType.containsLocalTypes(): Boolean {
|
||||
return arguments.any { !it.isStarProjection && it.type.containsLocalTypes() }
|
||||
}
|
||||
|
||||
private fun PsiElement.getMaybeLightElement(): PsiElement? {
|
||||
private fun PsiElement.getMaybeLightElement(sourcePsi: KtExpression? = null): PsiElement? {
|
||||
if (this is KtProperty && sourcePsi?.readWriteAccess()?.isWrite == true) {
|
||||
with(getAccessorLightMethods()) {
|
||||
(setter ?: backingField)?.let { return it } // backingField is for val property assignments in init blocks
|
||||
}
|
||||
}
|
||||
return when (this) {
|
||||
is KtDeclaration -> {
|
||||
val lightElement = toLightElements().firstOrNull()
|
||||
|
||||
@@ -69,3 +69,12 @@ String -> USimpleNameReferenceExpression (identifier = String)
|
||||
s -> USimpleNameReferenceExpression (identifier = s)
|
||||
local -> USimpleNameReferenceExpression (identifier = local)
|
||||
toString -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
||||
AWithFieldInit -> UClass (name = AWithFieldInit)
|
||||
i -> UParameter (name = i)
|
||||
Int -> USimpleNameReferenceExpression (identifier = Int)
|
||||
a -> UField (name = a)
|
||||
String -> USimpleNameReferenceExpression (identifier = String)
|
||||
a -> USimpleNameReferenceExpression (identifier = a)
|
||||
= -> USimpleNameReferenceExpression (identifier = =)
|
||||
i -> USimpleNameReferenceExpression (identifier = i)
|
||||
toString -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
||||
|
||||
+8
-1
@@ -71,4 +71,11 @@ class AWithSecondaryInit {
|
||||
local.toString()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class AWithFieldInit(i: Int) {
|
||||
val a: String
|
||||
init {
|
||||
a = i.toString()
|
||||
}
|
||||
}
|
||||
|
||||
+17
-1
@@ -158,4 +158,20 @@ UFile (package = )
|
||||
USimpleNameReferenceExpression (identifier = local)
|
||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
||||
UIdentifier (Identifier (toString))
|
||||
USimpleNameReferenceExpression (identifier = toString, resolvesTo = null)
|
||||
USimpleNameReferenceExpression (identifier = toString, resolvesTo = null)
|
||||
UClass (name = AWithFieldInit)
|
||||
UField (name = a)
|
||||
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
||||
UMethod (name = getA)
|
||||
UMethod (name = AWithFieldInit)
|
||||
UParameter (name = i)
|
||||
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
||||
UBlockExpression
|
||||
UBlockExpression
|
||||
UBinaryExpression (operator = =)
|
||||
USimpleNameReferenceExpression (identifier = a)
|
||||
UQualifiedReferenceExpression
|
||||
USimpleNameReferenceExpression (identifier = i)
|
||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
||||
UIdentifier (Identifier (toString))
|
||||
USimpleNameReferenceExpression (identifier = toString, resolvesTo = null)
|
||||
|
||||
@@ -159,3 +159,19 @@ UFile (package = )
|
||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
||||
UIdentifier (Identifier (toString))
|
||||
USimpleNameReferenceExpression (identifier = toString, resolvesTo = null)
|
||||
UClass (name = AWithFieldInit)
|
||||
UField (name = a)
|
||||
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
||||
UMethod (name = getA)
|
||||
UMethod (name = AWithFieldInit)
|
||||
UParameter (name = i)
|
||||
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
||||
UBlockExpression
|
||||
UBlockExpression
|
||||
UBinaryExpression (operator = =)
|
||||
USimpleNameReferenceExpression (identifier = a)
|
||||
UQualifiedReferenceExpression
|
||||
USimpleNameReferenceExpression (identifier = i)
|
||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
||||
UIdentifier (Identifier (toString))
|
||||
USimpleNameReferenceExpression (identifier = toString, resolvesTo = null)
|
||||
|
||||
@@ -42,3 +42,9 @@ s -> USimpleNameReferenceExpression (identifier = s) from KtNameReferenceExpress
|
||||
toString -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) from KtDotQualifiedExpression
|
||||
local -> USimpleNameReferenceExpression (identifier = local) from KtNameReferenceExpression
|
||||
toString -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) from KtNameReferenceExpression
|
||||
Int -> USimpleNameReferenceExpression (identifier = Int) from KtNameReferenceExpression
|
||||
String -> USimpleNameReferenceExpression (identifier = String) from KtNameReferenceExpression
|
||||
a -> USimpleNameReferenceExpression (identifier = a) from KtNameReferenceExpression
|
||||
toString -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) from KtDotQualifiedExpression
|
||||
i -> USimpleNameReferenceExpression (identifier = i) from KtNameReferenceExpression
|
||||
toString -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) from KtNameReferenceExpression
|
||||
|
||||
@@ -79,3 +79,13 @@ public final class AWithSecondaryInit {
|
||||
local.toString()
|
||||
}
|
||||
}
|
||||
|
||||
public final class AWithFieldInit {
|
||||
@org.jetbrains.annotations.NotNull private final var a: java.lang.String
|
||||
public final fun getA() : java.lang.String = UastEmptyExpression
|
||||
public fun AWithFieldInit(@org.jetbrains.annotations.NotNull i: int) {
|
||||
{
|
||||
a = i.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,3 +79,13 @@ public final class AWithSecondaryInit {
|
||||
local.toString()
|
||||
}
|
||||
}
|
||||
|
||||
public final class AWithFieldInit {
|
||||
@org.jetbrains.annotations.NotNull private final var a: java.lang.String
|
||||
public final fun getA() : java.lang.String = UastEmptyExpression
|
||||
public fun AWithFieldInit(@org.jetbrains.annotations.NotNull i: int) {
|
||||
{
|
||||
a = i.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-4
@@ -24,28 +24,28 @@ UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))(resolve
|
||||
UTypeReferenceExpression (name = java.lang.String) -> USimpleNameReferenceExpression (identifier = String) -> PsiClass:String: String
|
||||
UTypeReferenceExpression (name = int) -> USimpleNameReferenceExpression (identifier = Int) -> PsiClass:Integer: Integer
|
||||
UBlockExpression -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) -> PsiMethod:Object:
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = a) -> KtLightMethodImpl:getA: getA
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = a) -> KtLightMethodImpl:setA: setA
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = =) -> null: null
|
||||
UBinaryExpression (operator = =) -> UQualifiedReferenceExpression -> null: null
|
||||
UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = i) -> Light Parameter: i
|
||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))(resolves to null) -> USimpleNameReferenceExpression (identifier = toString) -> null: null
|
||||
UTypeReferenceExpression (name = java.lang.String) -> USimpleNameReferenceExpression (identifier = String) -> PsiClass:String: String
|
||||
UBlockExpression -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) -> PsiMethod:Object:
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = a) -> KtLightMethodImpl:getA: getA
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = a) -> KtLightMethodImpl:setA: setA
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = =) -> null: null
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = s) -> Light Parameter: s
|
||||
UTypeReferenceExpression (name = java.lang.String) -> USimpleNameReferenceExpression (identifier = String) -> PsiClass:String: String
|
||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))(resolves to PsiMethod:println) -> USimpleNameReferenceExpression (identifier = println) -> PsiMethod:println: println
|
||||
UTypeReferenceExpression (name = int) -> USimpleNameReferenceExpression (identifier = Int) -> PsiClass:Integer: Integer
|
||||
UBlockExpression -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) -> PsiMethod:Object:
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = a) -> KtLightMethodImpl:getA: getA
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = a) -> KtLightMethodImpl:setA: setA
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = =) -> null: null
|
||||
UBinaryExpression (operator = =) -> UQualifiedReferenceExpression -> null: null
|
||||
UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = i) -> Light Parameter: i
|
||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))(resolves to null) -> USimpleNameReferenceExpression (identifier = toString) -> null: null
|
||||
UTypeReferenceExpression (name = java.lang.String) -> USimpleNameReferenceExpression (identifier = String) -> PsiClass:String: String
|
||||
UBlockExpression -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) -> PsiMethod:Object:
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = a) -> KtLightMethodImpl:getA: getA
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = a) -> KtLightMethodImpl:setA: setA
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = =) -> null: null
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = s) -> Light Parameter: s
|
||||
UTypeReferenceExpression (name = java.lang.String) -> USimpleNameReferenceExpression (identifier = String) -> PsiClass:String: String
|
||||
@@ -53,3 +53,10 @@ UBlockExpression -> UCallExpression (kind = UastCallKind(name='constructor_call'
|
||||
UBlockExpression -> UQualifiedReferenceExpression -> PsiMethod:toString: toString
|
||||
UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = local) -> LightVariableBuilder:local: local
|
||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))(resolves to PsiMethod:toString) -> USimpleNameReferenceExpression (identifier = toString) -> PsiMethod:toString: toString
|
||||
UTypeReferenceExpression (name = int) -> USimpleNameReferenceExpression (identifier = Int) -> PsiClass:Integer: Integer
|
||||
UTypeReferenceExpression (name = java.lang.String) -> USimpleNameReferenceExpression (identifier = String) -> PsiClass:String: String
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = a) -> KtLightFieldForSourceDeclaration:a: a
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = =) -> null: null
|
||||
UBinaryExpression (operator = =) -> UQualifiedReferenceExpression -> null: null
|
||||
UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = i) -> Light Parameter: i
|
||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))(resolves to null) -> USimpleNameReferenceExpression (identifier = toString) -> null: null
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
class A(init: Int) {
|
||||
private var privateProp = 0 // accesses should be field accesses
|
||||
var mutableProp: Int
|
||||
init {
|
||||
mutableProp = init
|
||||
}
|
||||
|
||||
fun add(x: Int): Int {
|
||||
val result = privateProp
|
||||
privateProp = x
|
||||
return privateProp
|
||||
}
|
||||
}
|
||||
|
||||
fun properties() {
|
||||
val a = A(17)
|
||||
val x = -a.mutableProp
|
||||
a.mutableProp = 1
|
||||
a.mutableProp += x
|
||||
++a.mutableProp
|
||||
a.mutableProp--
|
||||
}
|
||||
|
||||
fun A.ext() {
|
||||
val x = -mutableProp
|
||||
mutableProp = 1
|
||||
mutableProp += x
|
||||
++mutableProp
|
||||
mutableProp--
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
UTypeReferenceExpression (name = int) -> USimpleNameReferenceExpression (identifier = Int) -> PsiClass:Integer: Integer
|
||||
UTypeReferenceExpression (name = int) -> USimpleNameReferenceExpression (identifier = Int) -> PsiClass:Integer: Integer
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = mutableProp) -> KtLightMethodImpl:setMutableProp: setMutableProp
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = =) -> null: null
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = init) -> Light Parameter: init
|
||||
UTypeReferenceExpression (name = int) -> USimpleNameReferenceExpression (identifier = Int) -> PsiClass:Integer: Integer
|
||||
UTypeReferenceExpression (name = int) -> USimpleNameReferenceExpression (identifier = Int) -> PsiClass:Integer: Integer
|
||||
ULocalVariable (name = result) -> USimpleNameReferenceExpression (identifier = privateProp) -> KtLightFieldForSourceDeclaration:privateProp: privateProp
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = privateProp) -> KtLightFieldForSourceDeclaration:privateProp: privateProp
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = =) -> null: null
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = x) -> Light Parameter: x
|
||||
UReturnExpression -> USimpleNameReferenceExpression (identifier = privateProp) -> KtLightFieldForSourceDeclaration:privateProp: privateProp
|
||||
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1))(resolves to KtLightMethodImpl:A) -> USimpleNameReferenceExpression (identifier = A) -> KtLightMethodImpl:A: A
|
||||
UPrefixExpression (operator = -) -> USimpleNameReferenceExpression (identifier = -) -> null: null
|
||||
UPrefixExpression (operator = -) -> UQualifiedReferenceExpression -> KtLightMethodImpl:getMutableProp: getMutableProp
|
||||
UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = a) -> LightVariableBuilder:a: a
|
||||
UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = mutableProp) -> KtLightMethodImpl:getMutableProp: getMutableProp
|
||||
UBinaryExpression (operator = =) -> UQualifiedReferenceExpression -> KtLightMethodImpl:setMutableProp: setMutableProp
|
||||
UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = a) -> LightVariableBuilder:a: a
|
||||
UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = mutableProp) -> KtLightMethodImpl:setMutableProp: setMutableProp
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = =) -> null: null
|
||||
UBinaryExpression (operator = +=) -> UQualifiedReferenceExpression -> KtLightMethodImpl:setMutableProp: setMutableProp
|
||||
UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = a) -> LightVariableBuilder:a: a
|
||||
UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = mutableProp) -> KtLightMethodImpl:setMutableProp: setMutableProp
|
||||
UBinaryExpression (operator = +=) -> USimpleNameReferenceExpression (identifier = +=) -> null: null
|
||||
UBinaryExpression (operator = +=) -> USimpleNameReferenceExpression (identifier = x) -> LightVariableBuilder:x: x
|
||||
UPrefixExpression (operator = ++) -> USimpleNameReferenceExpression (identifier = ++) -> null: null
|
||||
UPrefixExpression (operator = ++) -> UQualifiedReferenceExpression -> KtLightMethodImpl:setMutableProp: setMutableProp
|
||||
UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = a) -> LightVariableBuilder:a: a
|
||||
UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = mutableProp) -> KtLightMethodImpl:setMutableProp: setMutableProp
|
||||
UPostfixExpression (operator = --) -> UQualifiedReferenceExpression -> KtLightMethodImpl:setMutableProp: setMutableProp
|
||||
UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = a) -> LightVariableBuilder:a: a
|
||||
UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = mutableProp) -> KtLightMethodImpl:setMutableProp: setMutableProp
|
||||
UPostfixExpression (operator = --) -> USimpleNameReferenceExpression (identifier = --) -> null: null
|
||||
UTypeReferenceExpression (name = A) -> USimpleNameReferenceExpression (identifier = A) -> KtLightClassImpl:class A(init: Int) {
|
||||
private var privateProp = 0 // accesses should be field accesses
|
||||
var mutableProp: Int
|
||||
init {
|
||||
mutableProp = init
|
||||
}
|
||||
|
||||
fun add(x: Int): Int {
|
||||
val result = privateProp
|
||||
privateProp = x
|
||||
return privateProp
|
||||
}
|
||||
}: A
|
||||
UPrefixExpression (operator = -) -> USimpleNameReferenceExpression (identifier = -) -> null: null
|
||||
UPrefixExpression (operator = -) -> USimpleNameReferenceExpression (identifier = mutableProp) -> KtLightMethodImpl:getMutableProp: getMutableProp
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = mutableProp) -> KtLightMethodImpl:setMutableProp: setMutableProp
|
||||
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = =) -> null: null
|
||||
UBinaryExpression (operator = +=) -> USimpleNameReferenceExpression (identifier = mutableProp) -> KtLightMethodImpl:setMutableProp: setMutableProp
|
||||
UBinaryExpression (operator = +=) -> USimpleNameReferenceExpression (identifier = +=) -> null: null
|
||||
UBinaryExpression (operator = +=) -> USimpleNameReferenceExpression (identifier = x) -> LightVariableBuilder:x: x
|
||||
UPrefixExpression (operator = ++) -> USimpleNameReferenceExpression (identifier = ++) -> null: null
|
||||
UPrefixExpression (operator = ++) -> USimpleNameReferenceExpression (identifier = mutableProp) -> KtLightMethodImpl:setMutableProp: setMutableProp
|
||||
UPostfixExpression (operator = --) -> USimpleNameReferenceExpression (identifier = mutableProp) -> KtLightMethodImpl:setMutableProp: setMutableProp
|
||||
UPostfixExpression (operator = --) -> USimpleNameReferenceExpression (identifier = --) -> null: null
|
||||
@@ -33,4 +33,7 @@ class KotlinUastResolveEverythingTest : AbstractKotlinResolveEverythingTest() {
|
||||
@Test
|
||||
fun testResolve() = doTest("Resolve")
|
||||
|
||||
@Test
|
||||
fun testPropertyReferences() = doTest("PropertyReferences")
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user