38e2d474b7
and provide appropriate functionalInterface
231 lines
10 KiB
Plaintext
231 lines
10 KiB
Plaintext
package org.jetbrains.uast.test.kotlin
|
|
|
|
import com.intellij.psi.PsiModifier
|
|
import com.intellij.testFramework.UsefulTestCase
|
|
import org.jetbrains.kotlin.asJava.toLightAnnotation
|
|
import org.jetbrains.kotlin.psi.*
|
|
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
|
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
|
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
|
import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
|
|
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
|
import org.jetbrains.kotlin.utils.sure
|
|
import org.jetbrains.uast.*
|
|
import org.jetbrains.uast.kotlin.KotlinUastLanguagePlugin
|
|
import org.jetbrains.uast.test.env.findElementByText
|
|
import org.jetbrains.uast.test.env.findElementByTextFromPsi
|
|
import org.jetbrains.uast.visitor.AbstractUastVisitor
|
|
import org.junit.Assert
|
|
import org.junit.Test
|
|
|
|
|
|
class KotlinUastApiTest : AbstractKotlinUastTest() {
|
|
override fun check(testName: String, file: UFile) {
|
|
}
|
|
|
|
@Test fun testAnnotationParameters() {
|
|
doTest("AnnotationParameters") { _, file ->
|
|
val annotation = file.findElementByText<UAnnotation>("@IntRange(from = 10, to = 0)")
|
|
assertEquals(annotation.findAttributeValue("from")?.evaluate(), 10)
|
|
val toAttribute = annotation.findAttributeValue("to")!!
|
|
assertEquals(toAttribute.evaluate(), 0)
|
|
KtUsefulTestCase.assertInstanceOf(annotation.psi.toUElement(), UAnnotation::class.java)
|
|
KtUsefulTestCase.assertInstanceOf(
|
|
annotation.psi.cast<KtAnnotationEntry>().toLightAnnotation().toUElement(),
|
|
UAnnotation::class.java
|
|
)
|
|
KtUsefulTestCase.assertInstanceOf(toAttribute.uastParent, UNamedExpression::class.java)
|
|
KtUsefulTestCase.assertInstanceOf(toAttribute.psi.toUElement()?.uastParent, UNamedExpression::class.java)
|
|
}
|
|
}
|
|
|
|
@Test fun testConvertStringTemplate() {
|
|
doTest("StringTemplateInClass") { _, file ->
|
|
val literalExpression = file.findElementByText<ULiteralExpression>("lorem")
|
|
val psi = literalExpression.psi!!
|
|
Assert.assertTrue(psi is KtLiteralStringTemplateEntry)
|
|
val literalExpressionAgain = psi.toUElement()
|
|
Assert.assertTrue(literalExpressionAgain is ULiteralExpression)
|
|
|
|
}
|
|
}
|
|
|
|
@Test fun testConvertStringTemplateWithExpectedType() {
|
|
doTest("StringTemplateWithVar") { _, file ->
|
|
val index = file.psi.text.indexOf("foo")
|
|
val stringTemplate = file.psi.findElementAt(index)!!.getParentOfType<KtStringTemplateExpression>(false)
|
|
val uLiteral = stringTemplate.toUElementOfType<ULiteralExpression>()
|
|
assertNull(uLiteral)
|
|
}
|
|
}
|
|
|
|
@Test fun testNameContainingFile() {
|
|
doTest("NameContainingFile") { _, file ->
|
|
val foo = file.findElementByText<UClass>("class Foo")
|
|
assertEquals(file.psi, foo.nameIdentifier!!.containingFile)
|
|
|
|
val bar = file.findElementByText<UMethod>("fun bar() {}")
|
|
assertEquals(file.psi, bar.nameIdentifier!!.containingFile)
|
|
|
|
val xyzzy = file.findElementByText<UVariable>("val xyzzy: Int = 0")
|
|
assertEquals(file.psi, xyzzy.nameIdentifier!!.containingFile)
|
|
}
|
|
}
|
|
|
|
@Test fun testInterfaceMethodWithBody() {
|
|
doTest("DefaultImpls") { _, file ->
|
|
val bar = file.findElementByText<UMethod>("fun bar() = \"Hello!\"")
|
|
assertFalse(bar.containingFile.text!!, bar.psi.modifierList.hasExplicitModifier(PsiModifier.DEFAULT))
|
|
assertTrue(bar.containingFile.text!!, bar.psi.modifierList.hasModifierProperty(PsiModifier.DEFAULT))
|
|
}
|
|
}
|
|
|
|
@Test fun testParameterPropertyWithAnnotation() {
|
|
doTest("ParameterPropertyWithAnnotation") { _, file ->
|
|
val test1 = file.classes.find { it.name == "Test1" }!!
|
|
|
|
val constructor1 = test1.methods.find { it.name == "Test1" }!!
|
|
assertTrue(constructor1.uastParameters.first().annotations.any { it.qualifiedName == "MyAnnotation" })
|
|
|
|
val getter1 = test1.methods.find { it.name == "getBar" }!!
|
|
assertFalse(getter1.annotations.any { it.qualifiedName == "MyAnnotation" })
|
|
|
|
val setter1 = test1.methods.find { it.name == "setBar" }!!
|
|
assertFalse(setter1.annotations.any { it.qualifiedName == "MyAnnotation" })
|
|
assertFalse(setter1.uastParameters.first().annotations.any { it.qualifiedName == "MyAnnotation" })
|
|
|
|
|
|
val test2 = file.classes.find { it.name == "Test2" }!!
|
|
val constructor2 = test2.methods.find { it.name == "Test2" }!!
|
|
assertFalse(constructor2.uastParameters.first().annotations.any { it.qualifiedName?.startsWith("MyAnnotation") ?: false })
|
|
|
|
val getter2 = test2.methods.find { it.name == "getBar" }!!
|
|
getter2.annotations.single { it.qualifiedName == "MyAnnotation" }
|
|
|
|
val setter2 = test2.methods.find { it.name == "setBar" }!!
|
|
setter2.annotations.single { it.qualifiedName == "MyAnnotation2" }
|
|
setter2.uastParameters.first().annotations.single { it.qualifiedName == "MyAnnotation3" }
|
|
|
|
test2.fields.find { it.name == "bar" }!!.annotations.single { it.qualifiedName == "MyAnnotation5" }
|
|
}
|
|
}
|
|
|
|
@Test fun testElvisType() {
|
|
doTest("ElvisType") { _, file ->
|
|
val elvisExpression = file.findElementByText<UExpression>("text ?: return")
|
|
assertEquals("String", elvisExpression.getExpressionType()!!.presentableText)
|
|
}
|
|
}
|
|
|
|
@Test fun testFindAttributeDefaultValue() {
|
|
doTest("AnnotationParameters") { _, file ->
|
|
val witDefaultValue = file.findElementByText<UAnnotation>("@WithDefaultValue")
|
|
assertEquals(42, witDefaultValue.findAttributeValue("value")!!.evaluate())
|
|
assertEquals(42, witDefaultValue.findAttributeValue(null)!!.evaluate())
|
|
}
|
|
}
|
|
|
|
@Test fun testIfCondition() {
|
|
doTest("IfStatement") { _, file ->
|
|
val psiFile = file.psi
|
|
val element = psiFile.findElementAt(psiFile.text.indexOf("\"abc\""))!!
|
|
val binaryExpression = element.getParentOfType<KtBinaryExpression>(false)!!
|
|
val uBinaryExpression = KotlinUastLanguagePlugin().convertElementWithParent(binaryExpression, null)!!
|
|
UsefulTestCase.assertInstanceOf(uBinaryExpression.uastParent, UIfExpression::class.java)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun testWhenStringLiteral() {
|
|
doTest("WhenStringLiteral") { _, file ->
|
|
|
|
file.findElementByTextFromPsi<ULiteralExpression>("abc").let { literalExpression ->
|
|
val psi = literalExpression.psi!!
|
|
Assert.assertTrue(psi is KtLiteralStringTemplateEntry)
|
|
UsefulTestCase.assertInstanceOf(literalExpression.uastParent, USwitchClauseExpressionWithBody::class.java)
|
|
}
|
|
|
|
file.findElementByTextFromPsi<ULiteralExpression>("def").let { literalExpression ->
|
|
val psi = literalExpression.psi!!
|
|
Assert.assertTrue(psi is KtLiteralStringTemplateEntry)
|
|
UsefulTestCase.assertInstanceOf(literalExpression.uastParent, USwitchClauseExpressionWithBody::class.java)
|
|
}
|
|
|
|
file.findElementByTextFromPsi<ULiteralExpression>("def1").let { literalExpression ->
|
|
val psi = literalExpression.psi!!
|
|
Assert.assertTrue(psi is KtLiteralStringTemplateEntry)
|
|
UsefulTestCase.assertInstanceOf(literalExpression.uastParent, UBlockExpression::class.java)
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun testWhenAndDestructing() {
|
|
doTest("WhenAndDestructing") { _, file ->
|
|
|
|
file.findElementByTextFromPsi<UExpression>("val (bindingContext, statementFilter) = arr").let { e ->
|
|
val uBlockExpression = e.getParentOfType<UBlockExpression>()
|
|
Assert.assertNotNull(uBlockExpression)
|
|
val uMethod = uBlockExpression!!.getParentOfType<UMethod>()
|
|
Assert.assertNotNull(uMethod)
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun testBrokenMethodTypeResolve() {
|
|
doTest("BrokenMethod") { _, file ->
|
|
|
|
file.accept(object : AbstractUastVisitor() {
|
|
override fun visitCallExpression(node: UCallExpression): Boolean {
|
|
node.returnType
|
|
return false
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun testTypeAliases() {
|
|
doTest("TypeAliases") { _, file ->
|
|
val g = (file.psi as KtFile).declarations.single { it.name == "G" } as KtTypeAlias
|
|
val originalType = g.getTypeReference()!!.typeElement as KtFunctionType
|
|
val originalTypeParameters = originalType.parameterList.toUElement() as UDeclarationsExpression
|
|
Assert.assertTrue((originalTypeParameters.declarations.single() as UParameter).type.isValid)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun testResolvedDeserializedMethod() = doTest("Resolve") { _, file ->
|
|
val barMethod = file.psi.findElementAt(file.psi.text.indexOf("bar")).sure { "sourceElement" }
|
|
.parentsWithSelf.mapNotNull { it.toUElementOfType<UMethod>() }.firstOrNull().sure { "parent UMethod" }
|
|
|
|
fun UElement.assertResolveCall(callText: String, methodName: String = callText.substringBefore("(")) {
|
|
this.findElementByTextFromPsi<UCallExpression>(callText).let {
|
|
val resolve = it.resolve().sure { "resolving '$callText'" }
|
|
assertEquals(methodName, resolve.name)
|
|
}
|
|
}
|
|
barMethod.assertResolveCall("foo()")
|
|
barMethod.assertResolveCall("inlineFoo()")
|
|
barMethod.assertResolveCall("forEach { println(it) }", "forEach")
|
|
barMethod.assertResolveCall("joinToString()")
|
|
barMethod.assertResolveCall("last()")
|
|
}
|
|
|
|
@Test
|
|
fun testUtilsStreamLambda() {
|
|
doTest("Lambdas") { _, file ->
|
|
val lambda = file.findElementByTextFromPsi<ULambdaExpression>("{ it.isEmpty() }")
|
|
assertEquals(
|
|
"kotlin.jvm.functions.Function1<? super java.lang.String,? extends java.lang.Boolean>",
|
|
lambda.getExpressionType()?.canonicalText
|
|
)
|
|
val uCallExpression = lambda.uastParent.assertedCast<UCallExpression> { "UCallExpression expected" }
|
|
assertTrue(uCallExpression.valueArguments.contains(lambda))
|
|
}
|
|
}
|