181: Uast: fixes for non-leaf identifiers

This commit is contained in:
Nicolay Mitropolsky
2018-02-05 11:20:19 +03:00
committed by Nikolay Krasko
parent 8a4ef83b3d
commit 036c0fd6a4
7 changed files with 54 additions and 18 deletions
@@ -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<out UElement>?): UElement? {
@@ -354,7 +356,7 @@ internal object KotlinConverter {
is KtImportDirective -> el<UImportStatement>(build(::KotlinUImportStatement))
else -> {
if (element is LeafPsiElement) {
if (element.elementType == KtTokens.IDENTIFIER || element.elementType == KtTokens.CONSTRUCTOR_KEYWORD)
if (element.elementType in identifiersTokens)
el<UIdentifier>(build(::KotlinUIdentifier))
else if (element.elementType == KtTokens.LBRACKET && element.parent is KtCollectionLiteralExpression)
el<UIdentifier> {
@@ -96,7 +96,20 @@ abstract class AbstractKotlinUVariable(givenParent: UElement?) : KotlinAbstractU
override val typeReference by lz { getLanguagePlugin().convertOpt<UTypeReferenceExpression>(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
@@ -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)
@@ -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)
}
}
@@ -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)
@@ -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)
@@ -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)