EA-214662: Support property accessors in UastLightIdentifier

This commit is contained in:
Yan Zhulanow
2020-01-14 21:21:27 +09:00
parent be99f44c4f
commit b1414fa477
11 changed files with 55 additions and 16 deletions
@@ -21,14 +21,12 @@ import com.intellij.psi.PsiCompiledElement
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiNameIdentifierOwner
import com.intellij.psi.impl.light.LightIdentifier
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.KtPrimaryConstructor
import org.jetbrains.kotlin.psi.KtSecondaryConstructor
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
open class KtLightIdentifier(
private val lightOwner: PsiElement,
private val ktDeclaration: KtNamedDeclaration?
private val ktDeclaration: KtDeclaration?
) : LightIdentifier(lightOwner.manager, ktDeclaration?.name ?: ""), PsiCompiledElement,
PsiElementWithOrigin<PsiElement> {
override val origin: PsiElement?
@@ -37,7 +35,9 @@ open class KtLightIdentifier(
is KtPrimaryConstructor -> ktDeclaration.getConstructorKeyword()
?: ktDeclaration.valueParameterList
?: ktDeclaration.containingClassOrObject?.nameIdentifier
else -> ktDeclaration?.nameIdentifier
is KtPropertyAccessor -> ktDeclaration.namePlaceholder
is KtNamedDeclaration -> ktDeclaration.nameIdentifier
else -> null
}
override fun getMirror() = ((lightOwner as? KtLightElement<*, *>)?.clsDelegate as? PsiNameIdentifierOwner)?.nameIdentifier
@@ -197,8 +197,11 @@ internal object KotlinConverter {
else -> element
}
private val identifiersTokens =
setOf(KtTokens.IDENTIFIER, KtTokens.CONSTRUCTOR_KEYWORD, KtTokens.THIS_KEYWORD, KtTokens.SUPER_KEYWORD, KtTokens.OBJECT_KEYWORD)
private val identifiersTokens = setOf(
KtTokens.IDENTIFIER, KtTokens.CONSTRUCTOR_KEYWORD, KtTokens.OBJECT_KEYWORD,
KtTokens.THIS_KEYWORD, KtTokens.SUPER_KEYWORD,
KtTokens.GET_KEYWORD, KtTokens.SET_KEYWORD
)
internal fun convertPsiElement(element: PsiElement?,
givenParent: UElement?,
@@ -165,7 +165,10 @@ open class KotlinUClass private constructor(
if (isDelegatedMethod(lightMethod)) continue
val uMethod = createUMethod(lightMethod)
result.add(uMethod)
handledKtDeclarations.addIfNotNull(uMethod.sourcePsi)
// Ensure we pick the main Kotlin origin, not the auxiliary one
val kotlinOrigin = (lightMethod as? KtLightMethod)?.kotlinOrigin ?: uMethod.sourcePsi
handledKtDeclarations.addIfNotNull(kotlinOrigin)
}
val ktDeclarations: List<KtDeclaration> = run ktDeclarations@{
@@ -39,7 +39,7 @@ open class KotlinUMethod(
givenParent: UElement?
) : KotlinAbstractUElement(givenParent), UMethodTypeSpecific, UAnchorOwner, JavaUElementWithComments, PsiMethod by psi {
constructor(psi: KtLightMethod, givenParent: UElement?) : this(psi, psi.kotlinOrigin, givenParent)
constructor(psi: KtLightMethod, givenParent: UElement?) : this(psi, getKotlinMemberOrigin(psi), givenParent)
override val comments: List<UComment>
get() = super<KotlinAbstractUElement>.comments
@@ -50,14 +50,14 @@ open class KotlinUMethod(
override fun getSourceElement() = sourcePsi ?: this
private val kotlinOrigin = (psi.originalElement as? KtLightElement<*, *>)?.kotlinOrigin ?: sourcePsi
private val kotlinOrigin = getKotlinMemberOrigin(psi.originalElement) ?: sourcePsi
override fun getContainingFile(): PsiFile? {
kotlinOrigin?.containingFile?.let { return it }
return unwrapFakeFileForLightClass(psi.containingFile)
}
override fun getNameIdentifier() = UastLightIdentifier(psi, kotlinOrigin as KtNamedDeclaration?)
override fun getNameIdentifier() = UastLightIdentifier(psi, kotlinOrigin as? KtDeclaration)
override val annotations: List<UAnnotation> by lz {
psi.annotations
@@ -85,6 +85,7 @@ open class KotlinUMethod(
when (sourcePsi) {
is PsiNameIdentifierOwner -> sourcePsi.nameIdentifier
is KtObjectDeclaration -> sourcePsi.getObjectKeyword()
is KtPropertyAccessor -> sourcePsi.namePlaceholder
else -> sourcePsi?.navigationElement
}
},
@@ -97,6 +98,7 @@ open class KotlinUMethod(
if (kotlinOrigin?.canAnalyze() != true) return@lz null // EA-137193
val bodyExpression = when (kotlinOrigin) {
is KtFunction -> kotlinOrigin.bodyExpression
is KtPropertyAccessor -> kotlinOrigin.bodyExpression
is KtProperty -> when {
psi is KtLightMethod && psi.isGetter -> kotlinOrigin.getter?.bodyExpression
psi is KtLightMethod && psi.isSetter -> kotlinOrigin.setter?.bodyExpression
@@ -118,6 +120,12 @@ open class KotlinUMethod(
override fun equals(other: Any?) = other is KotlinUMethod && psi == other.psi
companion object {
private fun getKotlinMemberOrigin(element: PsiElement?): KtDeclaration? {
(element as? KtLightMember<*>)?.lightMemberOrigin?.auxiliaryOriginalElement?.let { return it }
(element as? KtLightElement<*, *>)?.kotlinOrigin?.let { return it as? KtDeclaration }
return null
}
fun create(psi: KtLightMethod, containingElement: UElement?): KotlinUMethod {
val kotlinOrigin = psi.kotlinOrigin
return if (kotlinOrigin is KtConstructor<*>) {
@@ -40,7 +40,7 @@ open class KotlinUMethod(
givenParent: UElement?
) : KotlinAbstractUElement(givenParent), UMethodTypeSpecific, UAnchorOwner, JavaUElementWithComments, PsiMethod by psi {
constructor(psi: KtLightMethod, givenParent: UElement?) : this(psi, psi.kotlinOrigin, givenParent)
constructor(psi: KtLightMethod, givenParent: UElement?) : this(psi, getKotlinMemberOrigin(psi), givenParent)
override val comments: List<UComment>
get() = super<KotlinAbstractUElement>.comments
@@ -51,14 +51,14 @@ open class KotlinUMethod(
override fun getSourceElement() = sourcePsi ?: this
private val kotlinOrigin = (psi.originalElement as? KtLightElement<*, *>)?.kotlinOrigin ?: sourcePsi
private val kotlinOrigin = getKotlinMemberOrigin(psi.originalElement) ?: sourcePsi
override fun getContainingFile(): PsiFile? {
kotlinOrigin?.containingFile?.let { return it }
return unwrapFakeFileForLightClass(psi.containingFile)
}
override fun getNameIdentifier() = UastLightIdentifier(psi, kotlinOrigin as KtNamedDeclaration?)
override fun getNameIdentifier() = UastLightIdentifier(psi, kotlinOrigin as? KtDeclaration)
override val annotations: List<UAnnotation> by lz {
psi.annotations
@@ -86,6 +86,7 @@ open class KotlinUMethod(
when (sourcePsi) {
is PsiNameIdentifierOwner -> sourcePsi.nameIdentifier
is KtObjectDeclaration -> sourcePsi.getObjectKeyword()
is KtPropertyAccessor -> sourcePsi.namePlaceholder
else -> sourcePsi?.navigationElement
}
},
@@ -98,6 +99,7 @@ open class KotlinUMethod(
if (kotlinOrigin?.canAnalyze() != true) return@lz null // EA-137193
val bodyExpression = when (kotlinOrigin) {
is KtFunction -> kotlinOrigin.bodyExpression
is KtPropertyAccessor -> kotlinOrigin.bodyExpression
is KtProperty -> when {
psi is KtLightMethod && psi.isGetter -> kotlinOrigin.getter?.bodyExpression
psi is KtLightMethod && psi.isSetter -> kotlinOrigin.setter?.bodyExpression
@@ -121,6 +123,12 @@ open class KotlinUMethod(
override fun equals(other: Any?) = other is KotlinUMethod && psi == other.psi
companion object {
private fun getKotlinMemberOrigin(element: PsiElement?): KtDeclaration? {
(element as? KtLightMember<*>)?.lightMemberOrigin?.auxiliaryOriginalElement?.let { return it }
(element as? KtLightElement<*, *>)?.kotlinOrigin?.let { return it as? KtDeclaration }
return null
}
fun create(psi: KtLightMethod, containingElement: UElement?): KotlinUMethod {
val kotlinOrigin = psi.kotlinOrigin
return if (kotlinOrigin is KtConstructor<*>) {
@@ -75,7 +75,7 @@ abstract class AbstractKotlinUVariable(givenParent: UElement?) : KotlinAbstractU
override fun getNameIdentifier(): PsiIdentifier {
val kotlinOrigin = (psi as? KtLightElement<*, *>)?.kotlinOrigin
return UastLightIdentifier(psi, kotlinOrigin as KtNamedDeclaration?)
return UastLightIdentifier(psi, kotlinOrigin as? KtDeclaration)
}
override fun getContainingFile(): PsiFile = unwrapFakeFileForLightClass(psi.containingFile)
@@ -29,7 +29,7 @@ import org.jetbrains.uast.UIdentifier
import org.jetbrains.uast.kotlin.unwrapFakeFileForLightClass
import org.jetbrains.uast.toUElement
class UastLightIdentifier(lightOwner: PsiNameIdentifierOwner, ktDeclaration: KtNamedDeclaration?) :
class UastLightIdentifier(lightOwner: PsiNameIdentifierOwner, ktDeclaration: KtDeclaration?) :
KtLightIdentifier(lightOwner, ktDeclaration) {
override fun getContainingFile(): PsiFile = unwrapFakeFileForLightClass(super.getContainingFile())
}
@@ -29,11 +29,13 @@
[1]:[UDeclarationsExpression]
[4]:[UParameter (name = bar), UField (name = bar), UMethod (name = getBar), UMethod (name = setBar)]
[1]:[UAnnotation (fqName = MyAnnotation)]
[1]:[UIdentifier (Identifier (get))]
[1]:[[!] UnknownKotlinExpression (CONSTRUCTOR_CALLEE)]
[1]:[UTypeReferenceExpression (name = MyAnnotation)]
[1]:[USimpleNameReferenceExpression (identifier = MyAnnotation)]
[1]:[UIdentifier (Identifier (MyAnnotation))]
[1]:[UAnnotation (fqName = MyAnnotation2)]
[1]:[UIdentifier (Identifier (set))]
[1]:[[!] UnknownKotlinExpression (CONSTRUCTOR_CALLEE)]
[1]:[UTypeReferenceExpression (name = MyAnnotation2)]
[1]:[USimpleNameReferenceExpression (identifier = MyAnnotation2)]
@@ -0,0 +1,9 @@
TestPropertyInitializer -> UClass (name = TestPropertyInitializer)
withSetter -> UField (name = withSetter)
get -> UMethod (name = getWithSetter)
field -> USimpleNameReferenceExpression (identifier = field)
set -> UMethod (name = setWithSetter)
p -> UParameter (name = p)
field -> USimpleNameReferenceExpression (identifier = field)
= -> USimpleNameReferenceExpression (identifier = =)
p -> USimpleNameReferenceExpression (identifier = p)
@@ -0,0 +1,3 @@
field -> USimpleNameReferenceExpression (identifier = field) from KtNameReferenceExpression
field -> USimpleNameReferenceExpression (identifier = field) from KtNameReferenceExpression
p -> USimpleNameReferenceExpression (identifier = p) from KtNameReferenceExpression
@@ -30,6 +30,9 @@ class KotlinUastIdentifiersTest : AbstractKotlinIdentifiersTest() {
@Test
fun testSuperCalls() = doTest("SuperCalls")
@Test
fun testPropertyInitializer() = doTest("PropertyInitializer")
@Test
fun testEnumValuesConstructors() = doTest("EnumValuesConstructors")