191: Uast: making KotlinUObjectLiteralExpression provide a proper referenceNameElement (KT-30534)
This commit is contained in:
@@ -121,9 +121,7 @@ class KotlinUAnnotation(
|
|||||||
override val uastAnchor by lazy {
|
override val uastAnchor by lazy {
|
||||||
KotlinUIdentifier(
|
KotlinUIdentifier(
|
||||||
javaPsi?.nameReferenceElement,
|
javaPsi?.nameReferenceElement,
|
||||||
annotationEntry.typeReference?.typeElement?.let {
|
annotationEntry.typeReference?.nameElement,
|
||||||
(it as? KtUserType)?.referenceExpression?.getReferencedNameElement() ?: it.navigationElement
|
|
||||||
},
|
|
||||||
this
|
this
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-3
@@ -117,9 +117,7 @@ class KotlinUAnnotation(
|
|||||||
override val uastAnchor by lazy {
|
override val uastAnchor by lazy {
|
||||||
KotlinUIdentifier(
|
KotlinUIdentifier(
|
||||||
javaPsi?.nameReferenceElement,
|
javaPsi?.nameReferenceElement,
|
||||||
annotationEntry.typeReference?.typeElement?.let {
|
annotationEntry.typeReference?.nameElement,
|
||||||
(it as? KtUserType)?.referenceExpression?.getReferencedNameElement() ?: it.navigationElement
|
|
||||||
},
|
|
||||||
this
|
this
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+92
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.uast.kotlin
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiMethod
|
||||||
|
import com.intellij.psi.PsiType
|
||||||
|
import org.jetbrains.kotlin.asJava.toLightClass
|
||||||
|
import org.jetbrains.kotlin.psi.KtObjectLiteralExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
|
import org.jetbrains.uast.*
|
||||||
|
import org.jetbrains.uast.kotlin.declarations.KotlinUIdentifier
|
||||||
|
import org.jetbrains.uast.kotlin.internal.DelegatedMultiResolve
|
||||||
|
|
||||||
|
class KotlinUObjectLiteralExpression(
|
||||||
|
override val psi: KtObjectLiteralExpression,
|
||||||
|
givenParent: UElement?
|
||||||
|
) : KotlinAbstractUExpression(givenParent), UObjectLiteralExpression, UCallExpressionEx, DelegatedMultiResolve, KotlinUElementWithType {
|
||||||
|
|
||||||
|
override val declaration: UClass by lz {
|
||||||
|
psi.objectDeclaration.toLightClass()
|
||||||
|
?.let { getLanguagePlugin().convert<UClass>(it, this) }
|
||||||
|
?: KotlinInvalidUClass("<invalid object code>", psi, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getExpressionType() = psi.objectDeclaration.toPsiType()
|
||||||
|
|
||||||
|
private val superClassConstructorCall by lz {
|
||||||
|
psi.objectDeclaration.superTypeListEntries.firstOrNull { it is KtSuperTypeCallEntry } as? KtSuperTypeCallEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
override val classReference: UReferenceExpression? by lz { superClassConstructorCall?.let { ObjectLiteralClassReference(it, this) } }
|
||||||
|
|
||||||
|
override val valueArgumentCount: Int
|
||||||
|
get() = superClassConstructorCall?.valueArguments?.size ?: 0
|
||||||
|
|
||||||
|
override val valueArguments by lz {
|
||||||
|
val psi = superClassConstructorCall ?: return@lz emptyList<UExpression>()
|
||||||
|
psi.valueArguments.map { KotlinConverter.convertOrEmpty(it.getArgumentExpression(), this) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override val typeArgumentCount: Int
|
||||||
|
get() = superClassConstructorCall?.typeArguments?.size ?: 0
|
||||||
|
|
||||||
|
override val typeArguments by lz {
|
||||||
|
val psi = superClassConstructorCall ?: return@lz emptyList<PsiType>()
|
||||||
|
psi.typeArguments.map { it.typeReference.toPsiType(this, boxed = true) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resolve() = superClassConstructorCall?.resolveCallToDeclaration() as? PsiMethod
|
||||||
|
|
||||||
|
override fun getArgumentForParameter(i: Int): UExpression? =
|
||||||
|
superClassConstructorCall?.let { it.getResolvedCall(it.analyze()) }?.let { getArgumentExpressionByIndex(i, it, this) }
|
||||||
|
|
||||||
|
private class ObjectLiteralClassReference(
|
||||||
|
override val psi: KtSuperTypeCallEntry,
|
||||||
|
givenParent: UElement?
|
||||||
|
) : KotlinAbstractUElement(givenParent), USimpleNameReferenceExpression {
|
||||||
|
|
||||||
|
override val javaPsi = null
|
||||||
|
override val sourcePsi = psi
|
||||||
|
|
||||||
|
override fun resolve() = (psi.resolveCallToDeclaration() as? PsiMethod)?.containingClass
|
||||||
|
|
||||||
|
override val annotations: List<UAnnotation>
|
||||||
|
get() = emptyList()
|
||||||
|
|
||||||
|
override val resolvedName: String?
|
||||||
|
get() = identifier
|
||||||
|
|
||||||
|
override val identifier: String
|
||||||
|
get() = psi.name ?: referenceNameElement.sourcePsi?.text ?: "<error>"
|
||||||
|
|
||||||
|
override val referenceNameElement: UElement
|
||||||
|
get() = KotlinUIdentifier(psi.typeReference?.nameElement, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -326,6 +326,11 @@ internal fun KtExpression.getExpectedType(): KotlinType? = analyze()[BindingCont
|
|||||||
|
|
||||||
internal fun KtTypeReference.getType(): KotlinType? = analyze()[BindingContext.TYPE, this]
|
internal fun KtTypeReference.getType(): KotlinType? = analyze()[BindingContext.TYPE, this]
|
||||||
|
|
||||||
|
internal val KtTypeReference.nameElement: PsiElement?
|
||||||
|
get() = this.typeElement?.let {
|
||||||
|
(it as? KtUserType)?.referenceExpression?.getReferencedNameElement() ?: it.navigationElement
|
||||||
|
}
|
||||||
|
|
||||||
internal fun KotlinType.getFunctionalInterfaceType(source: UElement, element: KtElement): PsiType? =
|
internal fun KotlinType.getFunctionalInterfaceType(source: UElement, element: KtElement): PsiType? =
|
||||||
takeIf { it.isInterface() && !it.isBuiltinFunctionalTypeOrSubtype }?.toPsiType(source, element, false)
|
takeIf { it.isInterface() && !it.isBuiltinFunctionalTypeOrSubtype }?.toPsiType(source, element, false)
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ runnable2 -> USimpleNameReferenceExpression (identifier = runnable2) from KtName
|
|||||||
run -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) from KtNameReferenceExpression
|
run -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) from KtNameReferenceExpression
|
||||||
Runnable -> USimpleNameReferenceExpression (identifier = Runnable) from KtNameReferenceExpression
|
Runnable -> USimpleNameReferenceExpression (identifier = Runnable) from KtNameReferenceExpression
|
||||||
Closeable -> USimpleNameReferenceExpression (identifier = Closeable) from KtNameReferenceExpression
|
Closeable -> USimpleNameReferenceExpression (identifier = Closeable) from KtNameReferenceExpression
|
||||||
|
InputStream -> USimpleNameReferenceExpression (identifier = InputStream) from KtObjectLiteralExpression
|
||||||
InputStream -> UObjectLiteralExpression from KtNameReferenceExpression
|
InputStream -> UObjectLiteralExpression from KtNameReferenceExpression
|
||||||
Runnable -> USimpleNameReferenceExpression (identifier = Runnable) from KtNameReferenceExpression
|
Runnable -> USimpleNameReferenceExpression (identifier = Runnable) from KtNameReferenceExpression
|
||||||
Int -> USimpleNameReferenceExpression (identifier = Int) from KtNameReferenceExpression
|
Int -> USimpleNameReferenceExpression (identifier = Int) from KtNameReferenceExpression
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
A -> UClass (name = A)
|
||||||
|
str -> UParameter (name = str)
|
||||||
|
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))
|
||||||
|
foo -> UAnnotationMethod (name = foo)
|
||||||
|
a -> UParameter (name = a)
|
||||||
|
Long -> USimpleNameReferenceExpression (identifier = Long)
|
||||||
|
B -> UClass (name = B)
|
||||||
|
param -> UParameter (name = param)
|
||||||
|
String -> USimpleNameReferenceExpression (identifier = String)
|
||||||
|
A -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1))
|
||||||
|
param -> USimpleNameReferenceExpression (identifier = param)
|
||||||
|
C -> UClass (name = C)
|
||||||
|
A -> USimpleNameReferenceExpression (identifier = A)
|
||||||
|
constructor -> UAnnotationMethod (name = C)
|
||||||
|
p -> UParameter (name = p)
|
||||||
|
String -> USimpleNameReferenceExpression (identifier = String)
|
||||||
|
super -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1))
|
||||||
|
p -> USimpleNameReferenceExpression (identifier = p)
|
||||||
|
constructor -> UAnnotationMethod (name = C)
|
||||||
|
i -> UParameter (name = i)
|
||||||
|
Int -> USimpleNameReferenceExpression (identifier = Int)
|
||||||
|
super -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1))
|
||||||
|
i -> USimpleNameReferenceExpression (identifier = i)
|
||||||
|
println -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
||||||
|
foo -> UAnnotationMethod (name = foo)
|
||||||
|
a -> UParameter (name = a)
|
||||||
|
Long -> USimpleNameReferenceExpression (identifier = Long)
|
||||||
|
super -> USimpleNameReferenceExpression (identifier = super)
|
||||||
|
foo -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
|
||||||
|
a -> USimpleNameReferenceExpression (identifier = a)
|
||||||
|
O -> UClass (name = O)
|
||||||
|
A -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1))
|
||||||
|
anon -> UField (name = anon)
|
||||||
|
object -> UClass (name = null)
|
||||||
|
A -> UObjectLiteralExpression
|
||||||
|
bar -> UAnnotationMethod (name = bar)
|
||||||
|
cons -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
|
||||||
|
object -> UClass (name = null)
|
||||||
|
A -> UObjectLiteralExpression
|
||||||
|
innerObject -> UClass (name = innerObject)
|
||||||
|
A -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1))
|
||||||
|
InnerClass -> UClass (name = InnerClass)
|
||||||
|
A -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1))
|
||||||
|
cons -> UAnnotationMethod (name = cons)
|
||||||
|
a -> UParameter (name = a)
|
||||||
|
A -> USimpleNameReferenceExpression (identifier = A)
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
String -> USimpleNameReferenceExpression (identifier = String) from KtNameReferenceExpression
|
||||||
|
Int -> USimpleNameReferenceExpression (identifier = Int) 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
|
||||||
|
Long -> USimpleNameReferenceExpression (identifier = Long) from KtNameReferenceExpression
|
||||||
|
String -> USimpleNameReferenceExpression (identifier = String) from KtNameReferenceExpression
|
||||||
|
A -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) from KtNameReferenceExpression
|
||||||
|
param -> USimpleNameReferenceExpression (identifier = param) from KtNameReferenceExpression
|
||||||
|
A -> USimpleNameReferenceExpression (identifier = A) from KtNameReferenceExpression
|
||||||
|
String -> USimpleNameReferenceExpression (identifier = String) from KtNameReferenceExpression
|
||||||
|
p -> USimpleNameReferenceExpression (identifier = p) from KtNameReferenceExpression
|
||||||
|
Int -> USimpleNameReferenceExpression (identifier = Int) from KtNameReferenceExpression
|
||||||
|
i -> USimpleNameReferenceExpression (identifier = i) from KtNameReferenceExpression
|
||||||
|
println -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) from KtNameReferenceExpression
|
||||||
|
Long -> USimpleNameReferenceExpression (identifier = Long) from KtNameReferenceExpression
|
||||||
|
foo -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) from KtDotQualifiedExpression
|
||||||
|
foo -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) from KtNameReferenceExpression
|
||||||
|
a -> USimpleNameReferenceExpression (identifier = a) from KtNameReferenceExpression
|
||||||
|
A -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) from KtNameReferenceExpression
|
||||||
|
A -> USimpleNameReferenceExpression (identifier = A) from KtObjectLiteralExpression
|
||||||
|
A -> UObjectLiteralExpression from KtNameReferenceExpression
|
||||||
|
cons -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) from KtNameReferenceExpression
|
||||||
|
A -> USimpleNameReferenceExpression (identifier = A) from KtObjectLiteralExpression
|
||||||
|
A -> UObjectLiteralExpression from KtNameReferenceExpression
|
||||||
|
A -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) from KtNameReferenceExpression
|
||||||
|
A -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) from KtNameReferenceExpression
|
||||||
|
A -> USimpleNameReferenceExpression (identifier = A) from KtNameReferenceExpression
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
package org.jetbrains.uast.test.kotlin
|
package org.jetbrains.uast.test.kotlin
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.uast.UFile
|
import org.jetbrains.uast.*
|
||||||
import org.jetbrains.uast.UReferenceExpression
|
|
||||||
import org.jetbrains.uast.test.common.UElementToParentMap
|
import org.jetbrains.uast.test.common.UElementToParentMap
|
||||||
import org.jetbrains.uast.test.common.kotlin.IdentifiersTestBase
|
import org.jetbrains.uast.test.common.kotlin.IdentifiersTestBase
|
||||||
import org.jetbrains.uast.test.env.assertEqualsToFile
|
import org.jetbrains.uast.test.env.assertEqualsToFile
|
||||||
import org.jetbrains.uast.toUElementOfType
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import kotlin.test.assertNotNull
|
||||||
|
|
||||||
|
|
||||||
abstract class AbstractKotlinIdentifiersTest : AbstractKotlinUastTest(), IdentifiersTestBase {
|
abstract class AbstractKotlinIdentifiersTest : AbstractKotlinUastTest(), IdentifiersTestBase {
|
||||||
@@ -23,6 +22,15 @@ abstract class AbstractKotlinIdentifiersTest : AbstractKotlinUastTest(), Identif
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun UFile.asRefNames() = object : UElementToParentMap({ it.toUElementOfType<UReferenceExpression>()?.referenceNameElement }) {
|
private fun refNameRetriever(psiElement: PsiElement): UElement? =
|
||||||
|
when (val uElement = psiElement.toUElementOfExpectedTypes(UCallExpression::class.java, UReferenceExpression::class.java)) {
|
||||||
|
is UReferenceExpression -> uElement.referenceNameElement
|
||||||
|
is UCallExpression -> uElement.classReference?.referenceNameElement
|
||||||
|
else -> null
|
||||||
|
}?.also {
|
||||||
|
assertNotNull(it.sourcePsi, "referenceNameElement should have physical source, origin = $psiElement")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun UFile.asRefNames() = object : UElementToParentMap(::refNameRetriever) {
|
||||||
override fun renderSource(element: PsiElement): String = element.javaClass.simpleName
|
override fun renderSource(element: PsiElement): String = element.javaClass.simpleName
|
||||||
}.visitUFileAndGetResult(this)
|
}.visitUFileAndGetResult(this)
|
||||||
@@ -24,4 +24,7 @@ class KotlinUastIdentifiersTest : AbstractKotlinIdentifiersTest() {
|
|||||||
@Test
|
@Test
|
||||||
fun testAnonymous() = doTest("Anonymous")
|
fun testAnonymous() = doTest("Anonymous")
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSuperCalls() = doTest("SuperCalls")
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user