Uast-java: JavaUAnonymousClass.uastSuperTypes returns implementing class

This commit is contained in:
Nicolay Mitropolsky
2018-01-18 21:13:10 +03:00
parent 64b12cc421
commit f08f1c2d15
4 changed files with 57 additions and 10 deletions
@@ -38,17 +38,16 @@ abstract class AbstractJavaUClass(givenParent: UElement?) : JavaAbstractUElement
}
}
override val uastSuperTypes: List<UTypeReferenceExpression>
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<UTypeReferenceExpression> 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<UAnonymousClass, PsiAnonymousClass>(psi)
override val uastSuperTypes: List<UTypeReferenceExpression> by lazy {
listOf(createJavaUTypeReferenceExpression(psi.baseClassReference)) + super.uastSuperTypes
}
override fun getSuperClass(): UClass? = super<AbstractJavaUClass>.getSuperClass()
override fun getFields(): Array<UField> = super<AbstractJavaUClass>.getFields()
override fun getInitializers(): Array<UClassInitializer> = super<AbstractJavaUClass>.getInitializers()
@@ -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
@@ -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 <T> UElement.findElementByText(refText: String, cls: Class<T>): T {
}
inline fun <reified T : Any> UElement.findElementByText(refText: String): T = findElementByText(refText, T::class.java)
inline fun <reified T : UElement> UElement.findElementByTextFromPsi(refText: String, strict: Boolean = true): T =
(this.psi ?: throw AssertionError("no psi for $this")).findUElementByTextFromPsi(refText, strict)
inline fun <reified T : UElement> 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<T>() }.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;
}
@@ -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<UCallExpression>("barBase(7)").receiverType?.canonicalText)
}
}
@Test
fun testSuperTypes() {
doTest("Simple/SuperTypes.java") { name, file ->
val testClass = file.findElementByTextFromPsi<UIdentifier>("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<UElement>("""Runnable() {
public void run() {
int variable = 24;
variable++;
}
}""") as UAnonymousClass
assertEquals("base classes", listOf("java.lang.Runnable"), testClass.uastSuperTypes.map { it.getQualifiedName() })
}
}
}