diff --git a/uast/uast-java/src/org/jetbrains/uast/java/declarations/JavaUClass.kt b/uast/uast-java/src/org/jetbrains/uast/java/declarations/JavaUClass.kt index 1466f73129b8..a4cb44b99573 100644 --- a/uast/uast-java/src/org/jetbrains/uast/java/declarations/JavaUClass.kt +++ b/uast/uast-java/src/org/jetbrains/uast/java/declarations/JavaUClass.kt @@ -38,17 +38,16 @@ abstract class AbstractJavaUClass(givenParent: UElement?) : JavaAbstractUElement } } - override val uastSuperTypes: List - get() { - fun createJavaUTypeReferenceExpression(referenceElement: PsiJavaCodeReferenceElement) = - LazyJavaUTypeReferenceExpression(referenceElement, this) { - JavaPsiFacade.getElementFactory(referenceElement.project).createType(referenceElement) - } - - return psi.extendsList?.referenceElements?.map(::createJavaUTypeReferenceExpression).orEmpty() + - psi.implementsList?.referenceElements?.map(::createJavaUTypeReferenceExpression).orEmpty() + protected fun createJavaUTypeReferenceExpression(referenceElement: PsiJavaCodeReferenceElement) = + LazyJavaUTypeReferenceExpression(referenceElement, this) { + JavaPsiFacade.getElementFactory(referenceElement.project).createType(referenceElement) } + override val uastSuperTypes: List by lazy { + psi.extendsList?.referenceElements?.map { createJavaUTypeReferenceExpression(it) }.orEmpty() + + psi.implementsList?.referenceElements?.map { createJavaUTypeReferenceExpression(it) }.orEmpty() + } + override val uastAnchor: UElement? get() = UIdentifier(psi.nameIdentifier, this) @@ -92,6 +91,10 @@ class JavaUAnonymousClass( override val javaPsi: PsiAnonymousClass = unwrap(psi) + override val uastSuperTypes: List by lazy { + listOf(createJavaUTypeReferenceExpression(psi.baseClassReference)) + super.uastSuperTypes + } + override fun getSuperClass(): UClass? = super.getSuperClass() override fun getFields(): Array = super.getFields() override fun getInitializers(): Array = super.getInitializers() diff --git a/uast/uast-tests/java/Simple/Anonymous.values.txt b/uast/uast-tests/java/Simple/Anonymous.values.txt index 2b3cb21457a8..6132a98bce2a 100644 --- a/uast/uast-tests/java/Simple/Anonymous.values.txt +++ b/uast/uast-tests/java/Simple/Anonymous.values.txt @@ -8,7 +8,7 @@ UFile (package = ) [public class Anonymous {...] UDeclarationsExpression [var runnable: java.lang.Runnable = anonymous Runnable() {... }] = Undetermined ULocalVariable (name = runnable) [var runnable: java.lang.Runnable = anonymous Runnable() {... }] UObjectLiteralExpression [anonymous Runnable() {... }] = Undetermined - UClass (name = null) [final class null {...}] + UClass (name = null) [final class null : java.lang.Runnable {...}] UMethod (name = run) [public fun run() : void {...}] UBlockExpression [{...}] = (var variable = 24) UDeclarationsExpression [var variable: int = 24] = Undetermined diff --git a/uast/uast-tests/src/org/jetbrains/uast/test/env/AbstractUastTest.kt b/uast/uast-tests/src/org/jetbrains/uast/test/env/AbstractUastTest.kt index 9ba83ccd089f..9945fe5eb31c 100644 --- a/uast/uast-tests/src/org/jetbrains/uast/test/env/AbstractUastTest.kt +++ b/uast/uast-tests/src/org/jetbrains/uast/test/env/AbstractUastTest.kt @@ -17,10 +17,13 @@ package org.jetbrains.uast.test.env import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import org.jetbrains.uast.UElement import org.jetbrains.uast.UFile import org.jetbrains.uast.UastContext +import org.jetbrains.uast.toUElementOfType import org.jetbrains.uast.visitor.UastVisitor import java.io.File @@ -79,3 +82,19 @@ fun UElement.findElementByText(refText: String, cls: Class): T { } inline fun UElement.findElementByText(refText: String): T = findElementByText(refText, T::class.java) + +inline fun UElement.findElementByTextFromPsi(refText: String, strict: Boolean = true): T = + (this.psi ?: throw AssertionError("no psi for $this")).findUElementByTextFromPsi(refText, strict) + +inline fun PsiElement.findUElementByTextFromPsi(refText: String, strict: Boolean = true): T { + val elementAtStart = this.findElementAt(this.text.indexOf(refText)) + ?: throw AssertionError("requested text '$refText' was not found in $this") + val uElementContainingText = generateSequence(elementAtStart) { if (it is PsiFile) null else it.parent } + .let { + if (strict) it.dropWhile { !it.text.contains(refText) } else it + }.mapNotNull { it.toUElementOfType() }.firstOrNull() ?: throw AssertionError("requested text '$refText' not found as ${T::class.java}") + if (strict && uElementContainingText.psi != null && uElementContainingText.psi?.text != refText) { + throw AssertionError("requested text '$refText' found as '${uElementContainingText.psi?.text}' in $uElementContainingText") + } + return uElementContainingText; +} diff --git a/uast/uast-tests/test/org/jetbrains/uast/test/java/JavaUastApiTest.kt b/uast/uast-tests/test/org/jetbrains/uast/test/java/JavaUastApiTest.kt index d3528cb82f47..6e708892269e 100644 --- a/uast/uast-tests/test/org/jetbrains/uast/test/java/JavaUastApiTest.kt +++ b/uast/uast-tests/test/org/jetbrains/uast/test/java/JavaUastApiTest.kt @@ -22,6 +22,7 @@ import com.intellij.testFramework.UsefulTestCase import junit.framework.TestCase import org.jetbrains.uast.* import org.jetbrains.uast.test.env.findElementByText +import org.jetbrains.uast.test.env.findElementByTextFromPsi import org.junit.Test class JavaUastApiTest : AbstractJavaUastTest() { @@ -116,4 +117,28 @@ class JavaUastApiTest : AbstractJavaUastTest() { assertEquals("TestBase", file.findElementByText("barBase(7)").receiverType?.canonicalText) } } + + @Test + fun testSuperTypes() { + doTest("Simple/SuperTypes.java") { name, file -> + val testClass = file.findElementByTextFromPsi("Test").uastParent as UClass + assertEquals("base class", "A", testClass.superClass?.qualifiedName) + assertEquals("base classes", listOf("A", "B"), testClass.uastSuperTypes.map { it.getQualifiedName() }) + } + } + + @Test + fun testSuperTypesForAnonymous() { + doTest("Simple/Anonymous.java") { name, file -> + val testClass = file.findElementByTextFromPsi("""Runnable() { + + public void run() { + int variable = 24; + variable++; + } + }""") as UAnonymousClass + assertEquals("base classes", listOf("java.lang.Runnable"), testClass.uastSuperTypes.map { it.getQualifiedName() }) + } + } + }