diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightIdentifier.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightIdentifier.kt index f2da6bd37fb..a2afe07ae83 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightIdentifier.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightIdentifier.kt @@ -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 { 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 diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt index b61aa84bb18..d75999e697a 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt @@ -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?, diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt index 8d422b778ad..cd927c974cc 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt @@ -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 = run ktDeclarations@{ diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt index 97dc4aa5e50..85fbd148fce 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt @@ -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 get() = super.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 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<*>) { diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt.191 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt.191 index ef0c52de1e4..d4f11d6f361 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt.191 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt.191 @@ -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 get() = super.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 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<*>) { diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt index 842415d826a..a90a01b67a1 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt @@ -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) diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/UastLightIdentifier.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/UastLightIdentifier.kt index 0b33ab4fed2..d7e74ebe48e 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/UastLightIdentifier.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/UastLightIdentifier.kt @@ -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()) } diff --git a/plugins/uast-kotlin/testData/ParameterPropertyWithAnnotation.altlog.txt b/plugins/uast-kotlin/testData/ParameterPropertyWithAnnotation.altlog.txt index 594d3be75d5..928abf9f4a6 100644 --- a/plugins/uast-kotlin/testData/ParameterPropertyWithAnnotation.altlog.txt +++ b/plugins/uast-kotlin/testData/ParameterPropertyWithAnnotation.altlog.txt @@ -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)] diff --git a/plugins/uast-kotlin/testData/PropertyInitializer.identifiers.txt b/plugins/uast-kotlin/testData/PropertyInitializer.identifiers.txt new file mode 100644 index 00000000000..8601dedced4 --- /dev/null +++ b/plugins/uast-kotlin/testData/PropertyInitializer.identifiers.txt @@ -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) diff --git a/plugins/uast-kotlin/testData/PropertyInitializer.refNames.txt b/plugins/uast-kotlin/testData/PropertyInitializer.refNames.txt new file mode 100644 index 00000000000..e8fceeca040 --- /dev/null +++ b/plugins/uast-kotlin/testData/PropertyInitializer.refNames.txt @@ -0,0 +1,3 @@ +field -> USimpleNameReferenceExpression (identifier = field) from KtNameReferenceExpression +field -> USimpleNameReferenceExpression (identifier = field) from KtNameReferenceExpression +p -> USimpleNameReferenceExpression (identifier = p) from KtNameReferenceExpression diff --git a/plugins/uast-kotlin/tests/KotlinUastIdentifiersTest.kt b/plugins/uast-kotlin/tests/KotlinUastIdentifiersTest.kt index 798061028e5..4e2870f5240 100644 --- a/plugins/uast-kotlin/tests/KotlinUastIdentifiersTest.kt +++ b/plugins/uast-kotlin/tests/KotlinUastIdentifiersTest.kt @@ -30,6 +30,9 @@ class KotlinUastIdentifiersTest : AbstractKotlinIdentifiersTest() { @Test fun testSuperCalls() = doTest("SuperCalls") + @Test + fun testPropertyInitializer() = doTest("PropertyInitializer") + @Test fun testEnumValuesConstructors() = doTest("EnumValuesConstructors")