diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUAnnotation.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUAnnotation.kt index 79fa884442a..fdc2a6a49fd 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUAnnotation.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUAnnotation.kt @@ -121,9 +121,7 @@ class KotlinUAnnotation( override val uastAnchor by lazy { KotlinUIdentifier( javaPsi?.nameReferenceElement, - annotationEntry.typeReference?.typeElement?.let { - (it as? KtUserType)?.referenceExpression?.getReferencedNameElement() ?: it.navigationElement - }, + annotationEntry.typeReference?.nameElement, this ) } diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUAnnotation.kt.182 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUAnnotation.kt.182 index 974cd127163..ed02195cbe3 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUAnnotation.kt.182 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUAnnotation.kt.182 @@ -117,9 +117,7 @@ class KotlinUAnnotation( override val uastAnchor by lazy { KotlinUIdentifier( javaPsi?.nameReferenceElement, - annotationEntry.typeReference?.typeElement?.let { - (it as? KtUserType)?.referenceExpression?.getReferencedNameElement() ?: it.navigationElement - }, + annotationEntry.typeReference?.nameElement, this ) } diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt.191 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt.191 new file mode 100644 index 00000000000..c06035e6ee1 --- /dev/null +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt.191 @@ -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(it, this) } + ?: KotlinInvalidUClass("", 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() + 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() + 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 + get() = emptyList() + + override val resolvedName: String? + get() = identifier + + override val identifier: String + get() = psi.name ?: referenceNameElement.sourcePsi?.text ?: "" + + override val referenceNameElement: UElement + get() = KotlinUIdentifier(psi.typeReference?.nameElement, this) + } + +} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt index 2918e2bfaa4..6c7fe2c582e 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt @@ -326,6 +326,11 @@ internal fun KtExpression.getExpectedType(): KotlinType? = analyze()[BindingCont 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? = takeIf { it.isInterface() && !it.isBuiltinFunctionalTypeOrSubtype }?.toPsiType(source, element, false) diff --git a/plugins/uast-kotlin/testData/Anonymous.refNames.txt.191 b/plugins/uast-kotlin/testData/Anonymous.refNames.txt.191 index 62efa9fed4e..9667b912c45 100644 --- a/plugins/uast-kotlin/testData/Anonymous.refNames.txt.191 +++ b/plugins/uast-kotlin/testData/Anonymous.refNames.txt.191 @@ -19,6 +19,7 @@ runnable2 -> USimpleNameReferenceExpression (identifier = runnable2) from KtName run -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) from KtNameReferenceExpression Runnable -> USimpleNameReferenceExpression (identifier = Runnable) from KtNameReferenceExpression Closeable -> USimpleNameReferenceExpression (identifier = Closeable) from KtNameReferenceExpression +InputStream -> USimpleNameReferenceExpression (identifier = InputStream) from KtObjectLiteralExpression InputStream -> UObjectLiteralExpression from KtNameReferenceExpression Runnable -> USimpleNameReferenceExpression (identifier = Runnable) from KtNameReferenceExpression Int -> USimpleNameReferenceExpression (identifier = Int) from KtNameReferenceExpression diff --git a/plugins/uast-kotlin/testData/SuperCalls.identifiers.txt b/plugins/uast-kotlin/testData/SuperCalls.identifiers.txt new file mode 100644 index 00000000000..f7cea817651 --- /dev/null +++ b/plugins/uast-kotlin/testData/SuperCalls.identifiers.txt @@ -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) diff --git a/plugins/uast-kotlin/testData/SuperCalls.refNames.txt.191 b/plugins/uast-kotlin/testData/SuperCalls.refNames.txt.191 new file mode 100644 index 00000000000..6b91e0eaf63 --- /dev/null +++ b/plugins/uast-kotlin/testData/SuperCalls.refNames.txt.191 @@ -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 diff --git a/plugins/uast-kotlin/tests/AbstractKotlinIdentifiersTest.kt.191 b/plugins/uast-kotlin/tests/AbstractKotlinIdentifiersTest.kt.191 index f09ac4a22f4..0262154ebf6 100644 --- a/plugins/uast-kotlin/tests/AbstractKotlinIdentifiersTest.kt.191 +++ b/plugins/uast-kotlin/tests/AbstractKotlinIdentifiersTest.kt.191 @@ -1,13 +1,12 @@ package org.jetbrains.uast.test.kotlin import com.intellij.psi.PsiElement -import org.jetbrains.uast.UFile -import org.jetbrains.uast.UReferenceExpression +import org.jetbrains.uast.* import org.jetbrains.uast.test.common.UElementToParentMap import org.jetbrains.uast.test.common.kotlin.IdentifiersTestBase import org.jetbrains.uast.test.env.assertEqualsToFile -import org.jetbrains.uast.toUElementOfType import java.io.File +import kotlin.test.assertNotNull abstract class AbstractKotlinIdentifiersTest : AbstractKotlinUastTest(), IdentifiersTestBase { @@ -23,6 +22,15 @@ abstract class AbstractKotlinIdentifiersTest : AbstractKotlinUastTest(), Identif } } -fun UFile.asRefNames() = object : UElementToParentMap({ it.toUElementOfType()?.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 }.visitUFileAndGetResult(this) \ No newline at end of file diff --git a/plugins/uast-kotlin/tests/KotlinUastIdentifiersTest.kt b/plugins/uast-kotlin/tests/KotlinUastIdentifiersTest.kt index d45325d1da4..ded8832c467 100644 --- a/plugins/uast-kotlin/tests/KotlinUastIdentifiersTest.kt +++ b/plugins/uast-kotlin/tests/KotlinUastIdentifiersTest.kt @@ -24,4 +24,7 @@ class KotlinUastIdentifiersTest : AbstractKotlinIdentifiersTest() { @Test fun testAnonymous() = doTest("Anonymous") + @Test + fun testSuperCalls() = doTest("SuperCalls") + } \ No newline at end of file