From 036c0fd6a47937243970dc33177faa1d7bd31116 Mon Sep 17 00:00:00 2001 From: Nicolay Mitropolsky Date: Mon, 5 Feb 2018 11:20:19 +0300 Subject: [PATCH] 181: Uast: fixes for non-leaf identifiers --- .../kotlin/KotlinUastLanguagePlugin.kt.181 | 4 ++- .../declarations/KotlinUVariable.kt.181 | 15 +++++++++- .../declarations/UastLightIdentifier.kt.181 | 28 +++++++++++++------ .../KotlinUFunctionCallExpression.kt.181 | 8 +++++- .../ClassAnnotation.identifiers.txt.181 | 10 +++---- .../testData/Constructors.identifiers.txt.181 | 3 ++ .../SimpleAnnotated.identifiers.txt.181 | 4 +-- 7 files changed, 54 insertions(+), 18 deletions(-) diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.181 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.181 index 33485aecc81..33fc721e6ec 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.181 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.181 @@ -297,6 +297,8 @@ internal object KotlinConverter { else -> element } + private val identifiersTokens = setOf(KtTokens.IDENTIFIER, KtTokens.CONSTRUCTOR_KEYWORD, KtTokens.THIS_KEYWORD, KtTokens.SUPER_KEYWORD) + internal fun convertPsiElement(element: PsiElement?, givenParent: UElement?, requiredType: Class?): UElement? { @@ -354,7 +356,7 @@ internal object KotlinConverter { is KtImportDirective -> el(build(::KotlinUImportStatement)) else -> { if (element is LeafPsiElement) { - if (element.elementType == KtTokens.IDENTIFIER || element.elementType == KtTokens.CONSTRUCTOR_KEYWORD) + if (element.elementType in identifiersTokens) el(build(::KotlinUIdentifier)) else if (element.elementType == KtTokens.LBRACKET && element.parent is KtCollectionLiteralExpression) el { diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt.181 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt.181 index e576495becd..95d31bdd079 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt.181 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt.181 @@ -96,7 +96,20 @@ abstract class AbstractKotlinUVariable(givenParent: UElement?) : KotlinAbstractU override val typeReference by lz { getLanguagePlugin().convertOpt(psi.typeElement, this) } override val uastAnchor: UIdentifier? - get() = KotlinUIdentifier(nameIdentifier, (sourcePsi as? KtNamedDeclaration)?.nameIdentifier ?: sourcePsi, this) + get() { + val sourcePsi = sourcePsi + val identifierSourcePsi = when (sourcePsi) { + is KtNamedDeclaration -> sourcePsi.nameIdentifier + is KtTypeReference -> sourcePsi.typeElement?.let { + // receiver param in extension function + (it as? KtUserType)?.referenceExpression?.getIdentifier() ?: it + } ?: sourcePsi + is KtBinaryExpression, is KtCallExpression -> null // e.g. `foo("Lorem ipsum") ?: foo("dolor sit amet")` + is KtDestructuringDeclaration -> sourcePsi.valOrVarKeyword + else -> sourcePsi + } ?: return null + return KotlinUIdentifier(nameIdentifier, identifierSourcePsi, this) + } override fun equals(other: Any?) = other is AbstractKotlinUVariable && psi == other.psi diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/UastLightIdentifier.kt.181 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/UastLightIdentifier.kt.181 index 7af4a411b77..2de1f41e4bf 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/UastLightIdentifier.kt.181 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/UastLightIdentifier.kt.181 @@ -21,10 +21,9 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import com.intellij.psi.PsiNameIdentifierOwner import com.intellij.psi.impl.source.tree.LeafPsiElement +import com.intellij.psi.util.parents import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier -import org.jetbrains.kotlin.psi.KtCallElement -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtNamedDeclaration +import org.jetbrains.kotlin.psi.* import org.jetbrains.uast.UElement import org.jetbrains.uast.UIdentifier import org.jetbrains.uast.kotlin.unwrapFakeFileForLightClass @@ -43,19 +42,32 @@ class KotlinUIdentifier private constructor( ) : UIdentifier(psi, givenParent) { init { - if (ApplicationManager.getApplication().isUnitTestMode) - assert(sourcePsi == null || sourcePsi is LeafPsiElement || (sourcePsi is KtElement && sourcePsi.firstChild == null), - { "sourcePsi should be physical leaf element but got $sourcePsi of (${sourcePsi?.javaClass})" }) + if (ApplicationManager.getApplication().isUnitTestMode && !acceptableSourcePsi(sourcePsi)) + throw AssertionError("sourcePsi should be physical leaf element but got $sourcePsi of (${sourcePsi?.javaClass})") + } + + private fun acceptableSourcePsi(sourcePsi: PsiElement?): Boolean { + if (sourcePsi == null) return true + if (sourcePsi is LeafPsiElement) return true + if (sourcePsi is KtElement && sourcePsi.firstChild == null) return true + return false } override val uastParent: UElement? by lazy { if (givenParent != null) return@lazy givenParent val parent = sourcePsi?.parent ?: return@lazy null + getIdentifierParentForCall(parent) ?: parent.toUElement() + } + + private fun getIdentifierParentForCall(parent: PsiElement): UElement? { val parentParent = parent.parent if (parentParent is KtCallElement && parentParent.calleeExpression == parent) { // method identifiers in calls - return@lazy parentParent.toUElement() + return parentParent.toUElement() } - return@lazy parent.toUElement() + (parent.parents().take(3).find { it is KtTypeReference && it.parent is KtConstructorCalleeExpression })?.let { + return it.parent.parent.toUElement() + } + return null } constructor(javaPsi: PsiElement?, sourcePsi: PsiElement?, uastParent: UElement?) : this(javaPsi, sourcePsi, javaPsi, uastParent) diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt.181 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt.181 index c9e4ec3aabb..b1c7001ccc5 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt.181 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt.181 @@ -77,7 +77,13 @@ class KotlinUFunctionCallExpression( when (calleeExpression) { null -> null is KtNameReferenceExpression -> - KotlinUIdentifier(calleeExpression.getReferencedNameElement(), this /* ReferenceExpression will be the parent */) + KotlinUIdentifier(calleeExpression.getReferencedNameElement(), this) + is KtConstructorDelegationReferenceExpression -> + KotlinUIdentifier(calleeExpression.firstChild ?: calleeExpression, this) + is KtConstructorCalleeExpression -> + KotlinUIdentifier( + calleeExpression.constructorReferenceExpression?.getReferencedNameElement() ?: calleeExpression, this + ) else -> KotlinUIdentifier(calleeExpression, this) } } diff --git a/plugins/uast-kotlin/testData/ClassAnnotation.identifiers.txt.181 b/plugins/uast-kotlin/testData/ClassAnnotation.identifiers.txt.181 index 5ce47e5e597..70c4e02d27d 100644 --- a/plugins/uast-kotlin/testData/ClassAnnotation.identifiers.txt.181 +++ b/plugins/uast-kotlin/testData/ClassAnnotation.identifiers.txt.181 @@ -1,12 +1,12 @@ -Test -> USimpleNameReferenceExpression (identifier = Test) +Test -> UAnnotation (fqName = null) A -> UClass (name = A) MyAnnotation -> UClass (name = MyAnnotation) text -> [!] UnknownKotlinExpression (VALUE_PARAMETER) String -> USimpleNameReferenceExpression (identifier = String) -MyAnnotation -> USimpleNameReferenceExpression (identifier = MyAnnotation) +MyAnnotation -> UAnnotation (fqName = MyAnnotation) B -> UClass (name = B) -MyAnnotation -> USimpleNameReferenceExpression (identifier = MyAnnotation) +MyAnnotation -> UAnnotation (fqName = MyAnnotation) InB -> UClass (name = InB) -MyAnnotation -> USimpleNameReferenceExpression (identifier = MyAnnotation) -MyAnnotation -> USimpleNameReferenceExpression (identifier = MyAnnotation) +MyAnnotation -> UAnnotation (fqName = MyAnnotation) +MyAnnotation -> UAnnotation (fqName = MyAnnotation) Obj -> UClass (name = Obj) diff --git a/plugins/uast-kotlin/testData/Constructors.identifiers.txt.181 b/plugins/uast-kotlin/testData/Constructors.identifiers.txt.181 index 65201a4b034..560dd4fdad2 100644 --- a/plugins/uast-kotlin/testData/Constructors.identifiers.txt.181 +++ b/plugins/uast-kotlin/testData/Constructors.identifiers.txt.181 @@ -4,6 +4,7 @@ String -> USimpleNameReferenceExpression (identifier = String) constructor -> UAnnotationMethod (name = A) i -> UParameter (name = i) Int -> USimpleNameReferenceExpression (identifier = Int) +this -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) i -> USimpleNameReferenceExpression (identifier = i) toString -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) AWithInit -> UClass (name = AWithInit) @@ -13,6 +14,7 @@ String -> USimpleNameReferenceExpression (identifier = String) constructor -> UAnnotationMethod (name = AWithInit) i -> UParameter (name = i) Int -> USimpleNameReferenceExpression (identifier = Int) +this -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) i -> USimpleNameReferenceExpression (identifier = i) toString -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) AWith2Init -> UClass (name = AWith2Init) @@ -23,6 +25,7 @@ String -> USimpleNameReferenceExpression (identifier = String) constructor -> UAnnotationMethod (name = AWith2Init) i -> UParameter (name = i) Int -> USimpleNameReferenceExpression (identifier = Int) +this -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) i -> USimpleNameReferenceExpression (identifier = i) toString -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) AOnlyInit -> UClass (name = AOnlyInit) diff --git a/plugins/uast-kotlin/testData/SimpleAnnotated.identifiers.txt.181 b/plugins/uast-kotlin/testData/SimpleAnnotated.identifiers.txt.181 index f3c86634874..9e2cb188e0c 100644 --- a/plugins/uast-kotlin/testData/SimpleAnnotated.identifiers.txt.181 +++ b/plugins/uast-kotlin/testData/SimpleAnnotated.identifiers.txt.181 @@ -1,8 +1,8 @@ SimpleAnnotated -> UClass (name = SimpleAnnotated) -Suppress -> USimpleNameReferenceExpression (identifier = Suppress) +Suppress -> UAnnotation (fqName = kotlin.Suppress) method -> UAnnotationMethod (name = method) println -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) kotlin -> USimpleNameReferenceExpression (identifier = kotlin) -SinceKotlin -> USimpleNameReferenceExpression (identifier = SinceKotlin) +SinceKotlin -> UAnnotation (fqName = kotlin.SinceKotlin) property -> UField (name = property) String -> USimpleNameReferenceExpression (identifier = String)