Switch to 181 platform
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
package org.jetbrains.uast.test.kotlin
|
||||
|
||||
import org.jetbrains.uast.test.common.IdentifiersTestBase
|
||||
import java.io.File
|
||||
|
||||
|
||||
abstract class AbstractKotlinIdentifiersTest : AbstractKotlinUastTest(), IdentifiersTestBase {
|
||||
|
||||
private fun getTestFile(testName: String, ext: String) =
|
||||
File(File(AbstractKotlinUastTest.TEST_KOTLIN_MODEL_DIR, testName).canonicalPath + '.' + ext)
|
||||
|
||||
override fun getIdentifiersFile(testName: String): File = getTestFile(testName, "identifiers.txt")
|
||||
|
||||
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
|
||||
import org.jetbrains.uast.JvmDeclarationUElement
|
||||
import org.jetbrains.uast.UDeclaration
|
||||
import org.jetbrains.uast.UAnchorOwner
|
||||
import org.jetbrains.uast.UElement
|
||||
import org.jetbrains.uast.UFile
|
||||
import org.jetbrains.uast.kotlin.KOTLIN_CACHED_UELEMENT_KEY
|
||||
@@ -90,7 +90,7 @@ abstract class AbstractKotlinRenderLogTest : AbstractKotlinUastTest(), RenderLog
|
||||
node.containingFile.assertedCast<KtFile> { "containingFile should be KtFile for ${node.asLogString()}" }
|
||||
}
|
||||
|
||||
val anchorPsi = (node as? UDeclaration)?.uastAnchor?.psi
|
||||
val anchorPsi = (node as? UAnchorOwner)?.uastAnchor?.sourcePsi
|
||||
if (anchorPsi != null) {
|
||||
anchorPsi.containingFile.assertedCast<KtFile> { "uastAnchor.containingFile should be KtFile for ${node.asLogString()}" }
|
||||
}
|
||||
@@ -104,14 +104,16 @@ abstract class AbstractKotlinRenderLogTest : AbstractKotlinUastTest(), RenderLog
|
||||
accept(object : UastVisitor {
|
||||
override fun visitElement(node: UElement): Boolean {
|
||||
|
||||
if (node is UAnchorOwner) {
|
||||
node.uastAnchor?.let { visitElement(it) }
|
||||
}
|
||||
|
||||
val jvmDeclaration = node as? JvmDeclarationUElement
|
||||
?: throw AssertionError("${node.javaClass} should implement 'JvmDeclarationUElement'")
|
||||
|
||||
jvmDeclaration.sourcePsi?.let {
|
||||
assertTrue("sourcePsi should be physical but ${it.javaClass} found for [${it.text}] " +
|
||||
"for ${jvmDeclaration.javaClass}->${jvmDeclaration.uastParent?.javaClass}",
|
||||
it is KtElement || it is LeafPsiElement
|
||||
)
|
||||
"for ${jvmDeclaration.javaClass}->${jvmDeclaration.uastParent?.javaClass}",it is LeafPsiElement || it is KtElement|| it is LeafPsiElement)
|
||||
}
|
||||
jvmDeclaration.javaPsi?.let {
|
||||
assertTrue("javaPsi should be light but ${it.javaClass} found for [${it.text}] " +
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
package org.jetbrains.uast.test.kotlin
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiRecursiveElementVisitor
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
|
||||
import org.jetbrains.uast.JvmDeclarationUElement
|
||||
import org.jetbrains.uast.UDeclaration
|
||||
import org.jetbrains.uast.UElement
|
||||
import org.jetbrains.uast.UFile
|
||||
import org.jetbrains.uast.kotlin.KOTLIN_CACHED_UELEMENT_KEY
|
||||
import org.jetbrains.uast.kotlin.KotlinUastLanguagePlugin
|
||||
import org.jetbrains.uast.test.common.RenderLogTestBase
|
||||
import org.jetbrains.uast.visitor.UastVisitor
|
||||
import org.junit.Assert
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
abstract class AbstractKotlinRenderLogTest : AbstractKotlinUastTest(), RenderLogTestBase {
|
||||
override fun getTestFile(testName: String, ext: String) =
|
||||
File(File(TEST_KOTLIN_MODEL_DIR, testName).canonicalPath + '.' + ext)
|
||||
|
||||
override fun check(testName: String, file: UFile) {
|
||||
check(testName, file, true)
|
||||
}
|
||||
|
||||
fun check(testName: String, file: UFile, checkParentConsistency: Boolean) {
|
||||
super.check(testName, file)
|
||||
|
||||
if (checkParentConsistency) {
|
||||
checkParentConsistency(file)
|
||||
}
|
||||
|
||||
file.checkContainingFileForAllElements()
|
||||
file.checkJvmDeclarationsImplementations()
|
||||
}
|
||||
|
||||
private fun checkParentConsistency(file: UFile) {
|
||||
val parentMap = mutableMapOf<PsiElement, String>()
|
||||
|
||||
file.accept(object : UastVisitor {
|
||||
private val parentStack = Stack<UElement>()
|
||||
|
||||
override fun visitElement(node: UElement): Boolean {
|
||||
val parent = node.uastParent
|
||||
if (parent == null) {
|
||||
Assert.assertTrue("Wrong parent of $node", parentStack.empty())
|
||||
}
|
||||
else {
|
||||
Assert.assertEquals("Wrong parent of $node", parentStack.peek(), parent)
|
||||
}
|
||||
node.psi?.let {
|
||||
if (it !in parentMap) {
|
||||
parentMap[it] = parentStack.reversed().joinToString { it.asLogString() }
|
||||
}
|
||||
}
|
||||
parentStack.push(node)
|
||||
return false
|
||||
}
|
||||
|
||||
override fun afterVisitElement(node: UElement) {
|
||||
super.afterVisitElement(node)
|
||||
parentStack.pop()
|
||||
}
|
||||
})
|
||||
|
||||
file.psi.clearUastCaches()
|
||||
|
||||
file.psi.accept(object : PsiRecursiveElementVisitor() {
|
||||
override fun visitElement(element: PsiElement) {
|
||||
val uElement = KotlinUastLanguagePlugin().convertElementWithParent(element, null)
|
||||
val expectedParents = parentMap[element]
|
||||
if (expectedParents != null) {
|
||||
assertNotNull("Expected to be able to convert PSI element $element", uElement)
|
||||
val parents = generateSequence(uElement!!.uastParent) { it.uastParent }.joinToString { it.asLogString() }
|
||||
assertEquals("Inconsistent parents for ${uElement.asRenderString()}(${uElement.asLogString()})(${uElement.javaClass}) (converted from $element[${element.text}])", expectedParents, parents)
|
||||
}
|
||||
super.visitElement(element)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun UFile.checkContainingFileForAllElements() {
|
||||
accept(object : UastVisitor {
|
||||
override fun visitElement(node: UElement): Boolean {
|
||||
if (node is PsiElement) {
|
||||
node.containingFile.assertedCast<KtFile> { "containingFile should be KtFile for ${node.asLogString()}" }
|
||||
}
|
||||
|
||||
val anchorPsi = (node as? UDeclaration)?.uastAnchor?.psi
|
||||
if (anchorPsi != null) {
|
||||
anchorPsi.containingFile.assertedCast<KtFile> { "uastAnchor.containingFile should be KtFile for ${node.asLogString()}" }
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun UFile.checkJvmDeclarationsImplementations() {
|
||||
accept(object : UastVisitor {
|
||||
override fun visitElement(node: UElement): Boolean {
|
||||
|
||||
val jvmDeclaration = node as? JvmDeclarationUElement
|
||||
?: throw AssertionError("${node.javaClass} should implement 'JvmDeclarationUElement'")
|
||||
|
||||
jvmDeclaration.sourcePsi?.let {
|
||||
assertTrue("sourcePsi should be physical but ${it.javaClass} found for [${it.text}] " +
|
||||
"for ${jvmDeclaration.javaClass}->${jvmDeclaration.uastParent?.javaClass}",
|
||||
it is KtElement || it is LeafPsiElement
|
||||
)
|
||||
}
|
||||
jvmDeclaration.javaPsi?.let {
|
||||
assertTrue("javaPsi should be light but ${it.javaClass} found for [${it.text}] " +
|
||||
"for ${jvmDeclaration.javaClass}->${jvmDeclaration.uastParent?.javaClass}", it !is KtElement)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun PsiFile.clearUastCaches() {
|
||||
accept(object : PsiRecursiveElementVisitor() {
|
||||
override fun visitElement(element: PsiElement) {
|
||||
super.visitElement(element)
|
||||
element.putUserData(KOTLIN_CACHED_UELEMENT_KEY, null)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -6,7 +6,6 @@ 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.getValueParameterList
|
||||
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
import org.jetbrains.uast.*
|
||||
@@ -219,9 +218,10 @@ class KotlinUastApiTest : AbstractKotlinUastTest() {
|
||||
@Test
|
||||
fun testSimpleAnnotated() {
|
||||
doTest("SimpleAnnotated") { _, file ->
|
||||
file.findElementByTextFromPsi<UField>("@SinceKotlin(\"1.0\")\n val property: String = \"Mary\"").let { field ->
|
||||
file.findElementByTextFromPsi<UField>("@kotlin.SinceKotlin(\"1.0\")\n val property: String = \"Mary\"").let { field ->
|
||||
val annotation = field.annotations.assertedFind("kotlin.SinceKotlin") { it.qualifiedName }
|
||||
Assert.assertEquals(annotation.findDeclaredAttributeValue("version")?.evaluateString(), "1.0")
|
||||
Assert.assertEquals("1.0", annotation.findDeclaredAttributeValue("version")?.evaluateString())
|
||||
Assert.assertEquals("SinceKotlin", annotation.cast<UAnchorOwner>().uastAnchor?.sourcePsi?.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -303,10 +303,44 @@ class KotlinUastApiTest : AbstractKotlinUastTest() {
|
||||
val lightAnnotation = convertedUAnnotation.getAsJavaPsiElement(PsiAnnotation::class.java)
|
||||
?: throw AssertionError("can't get lightAnnotation from $convertedUAnnotation")
|
||||
assertEquals("Annotation", lightAnnotation.qualifiedName)
|
||||
assertEquals("Annotation", (convertedUAnnotation as UAnchorOwner).uastAnchor?.sourcePsi?.text)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun testParametersDisorder() = doTest("ParametersDisorder") { _, file ->
|
||||
|
||||
fun assertArguments(argumentsInPositionalOrder: List<String?>?, refText: String) =
|
||||
file.findElementByTextFromPsi<UCallExpression>(refText).let { call ->
|
||||
if (call !is UCallExpressionEx) throw AssertionError("${call.javaClass} is not a UCallExpressionEx")
|
||||
Assert.assertEquals(
|
||||
argumentsInPositionalOrder,
|
||||
call.resolve()?.let { psiMethod ->
|
||||
(0 until psiMethod.parameterList.parametersCount).map {
|
||||
call.getArgumentForParameter(it)?.asRenderString()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
assertArguments(listOf("2", "2.2"), "global(b = 2.2F, a = 2)")
|
||||
assertArguments(listOf(null, "\"bbb\""), "withDefault(d = \"bbb\")")
|
||||
assertArguments(listOf("1.3", "3.4"), "atan2(1.3, 3.4)")
|
||||
assertArguments(null, "unresolvedMethod(\"param1\", \"param2\")")
|
||||
assertArguments(listOf("\"%i %i %i\"", "varargs 1 : 2 : 3"), "format(\"%i %i %i\", 1, 2, 3)")
|
||||
assertArguments(listOf("\"%i %i %i\"", "varargs arrayOf(1, 2, 3)"), "format(\"%i %i %i\", arrayOf(1, 2, 3))")
|
||||
assertArguments(
|
||||
listOf("\"%i %i %i\"", "varargs arrayOf(1, 2, 3) : arrayOf(4, 5, 6)"),
|
||||
"format(\"%i %i %i\", arrayOf(1, 2, 3), arrayOf(4, 5, 6))"
|
||||
)
|
||||
assertArguments(listOf("\"%i %i %i\"", "\"\".chunked(2).toTypedArray()"), "format(\"%i %i %i\", *\"\".chunked(2).toTypedArray())")
|
||||
assertArguments(listOf("\"def\"", "8", "7.0"), "with2Receivers(8, 7.0F)")
|
||||
assertArguments(listOf("\"foo\"", "1"), "object : Parent(b = 1, a = \"foo\")\n")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun <T, R> Iterable<T>.assertedFind(value: R, transform: (T) -> R): T = find { transform(it) == value } ?: throw AssertionError("'$value' not found, only ${this.joinToString { transform(it).toString() }}")
|
||||
fun <T, R> Iterable<T>.assertedFind(value: R, transform: (T) -> R): T =
|
||||
find { transform(it) == value } ?: throw AssertionError("'$value' not found, only ${this.joinToString { transform(it).toString() }}")
|
||||
|
||||
@@ -0,0 +1,312 @@
|
||||
package org.jetbrains.uast.test.kotlin
|
||||
|
||||
import com.intellij.psi.PsiAnnotation
|
||||
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.getValueParameterList
|
||||
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
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 testSAM() {
|
||||
doTest("SAM") { _, file ->
|
||||
assertNull(file.findElementByText<ULambdaExpression>("{ /* Not SAM */ }").functionalInterfaceType)
|
||||
|
||||
assertEquals("java.lang.Runnable",
|
||||
file.findElementByText<ULambdaExpression>("{/* Variable */}").functionalInterfaceType?.canonicalText)
|
||||
|
||||
assertEquals("java.lang.Runnable",
|
||||
file.findElementByText<ULambdaExpression>("{/* Assignment */}").functionalInterfaceType?.canonicalText)
|
||||
|
||||
assertEquals("java.lang.Runnable",
|
||||
file.findElementByText<ULambdaExpression>("{/* Type Cast */}").functionalInterfaceType?.canonicalText)
|
||||
|
||||
assertEquals("java.lang.Runnable",
|
||||
file.findElementByText<ULambdaExpression>("{/* Argument */}").functionalInterfaceType?.canonicalText)
|
||||
|
||||
assertEquals("java.lang.Runnable",
|
||||
file.findElementByText<ULambdaExpression>("{/* Return */}").functionalInterfaceType?.canonicalText)
|
||||
}
|
||||
}
|
||||
|
||||
@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 testConvertTypeInAnnotation() {
|
||||
doTest("TypeInAnnotation") { _, file ->
|
||||
val index = file.psi.text.indexOf("Test")
|
||||
val element = file.psi.findElementAt(index)!!.getParentOfType<KtUserType>(false)!!
|
||||
assertNotNull(element.getUastParentOfType(UAnnotation::class.java))
|
||||
}
|
||||
}
|
||||
|
||||
@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 testSimpleAnnotated() {
|
||||
doTest("SimpleAnnotated") { _, file ->
|
||||
file.findElementByTextFromPsi<UField>("@SinceKotlin(\"1.0\")\n val property: String = \"Mary\"").let { field ->
|
||||
val annotation = field.annotations.assertedFind("kotlin.SinceKotlin") { it.qualifiedName }
|
||||
Assert.assertEquals(annotation.findDeclaredAttributeValue("version")?.evaluateString(), "1.0")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun UFile.checkUastSuperTypes(refText: String, superTypes: List<String>) {
|
||||
findElementByTextFromPsi<UClass>(refText, false).let {
|
||||
assertEquals("base classes", superTypes, it.uastSuperTypes.map { it.getQualifiedName() })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun testSuperTypes() {
|
||||
doTest("SuperCalls") { _, file ->
|
||||
file.checkUastSuperTypes("B", listOf("A"))
|
||||
file.checkUastSuperTypes("O", listOf("A"))
|
||||
file.checkUastSuperTypes("innerObject ", listOf("A"))
|
||||
file.checkUastSuperTypes("InnerClass", listOf("A"))
|
||||
file.checkUastSuperTypes("object : A(\"textForAnon\")", listOf("A"))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAnonymousSuperTypes() {
|
||||
doTest("Anonymous") { _, file ->
|
||||
file.checkUastSuperTypes("object : Runnable { override fun run() {} }", listOf("java.lang.Runnable"))
|
||||
file.checkUastSuperTypes(
|
||||
"object : Runnable, Closeable { override fun close() {} override fun run() {} }",
|
||||
listOf("java.lang.Runnable", "java.io.Closeable")
|
||||
)
|
||||
file.checkUastSuperTypes(
|
||||
"object : InputStream(), Runnable { override fun read(): Int = 0; override fun run() {} }",
|
||||
listOf("java.io.InputStream", "java.lang.Runnable")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLiteralArraysTypes() {
|
||||
doTest("AnnotationParameters") { _, file ->
|
||||
file.findElementByTextFromPsi<UCallExpression>("intArrayOf(1, 2, 3)").let { field ->
|
||||
Assert.assertEquals("PsiType:int[]", field.returnType.toString())
|
||||
}
|
||||
file.findElementByTextFromPsi<UCallExpression>("[1, 2, 3]").let { field ->
|
||||
Assert.assertEquals("PsiType:int[]", field.returnType.toString())
|
||||
Assert.assertEquals("PsiType:int", field.typeArguments.single().toString())
|
||||
}
|
||||
file.findElementByTextFromPsi<UCallExpression>("[\"a\", \"b\", \"c\"]").let { field ->
|
||||
Assert.assertEquals("PsiType:String[]", field.returnType.toString())
|
||||
Assert.assertEquals("PsiType:String", field.typeArguments.single().toString())
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@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 testNestedAnnotation() = doTest("AnnotationComplex") { _, file ->
|
||||
file.findElementByTextFromPsi<UElement>("@AnnotationArray(value = Annotation())")
|
||||
.findElementByTextFromPsi<UElement>("Annotation()")
|
||||
.sourcePsiElement
|
||||
.let { referenceExpression ->
|
||||
val convertedUAnnotation = referenceExpression
|
||||
.cast<KtReferenceExpression>()
|
||||
.toUElementOfType<UAnnotation>()
|
||||
?: throw AssertionError("haven't got annotation from $referenceExpression(${referenceExpression?.javaClass})")
|
||||
|
||||
assertEquals("Annotation", convertedUAnnotation.qualifiedName)
|
||||
val lightAnnotation = convertedUAnnotation.getAsJavaPsiElement(PsiAnnotation::class.java)
|
||||
?: throw AssertionError("can't get lightAnnotation from $convertedUAnnotation")
|
||||
assertEquals("Annotation", lightAnnotation.qualifiedName)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
fun <T, R> Iterable<T>.assertedFind(value: R, transform: (T) -> R): T = find { transform(it) == value } ?: throw AssertionError("'$value' not found, only ${this.joinToString { transform(it).toString() }}")
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.uast.test.kotlin
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
class KotlinUastIdentifiersTest : AbstractKotlinIdentifiersTest() {
|
||||
|
||||
@Test
|
||||
fun testClassAnnotation() = doTest("ClassAnnotation")
|
||||
|
||||
@Test
|
||||
fun testLocalDeclarations() = doTest("LocalDeclarations")
|
||||
|
||||
@Test
|
||||
fun testConstructors() = doTest("Constructors")
|
||||
|
||||
@Test
|
||||
fun testSimpleAnnotated() = doTest("SimpleAnnotated")
|
||||
|
||||
@Test
|
||||
fun testAnonymous() = doTest("Anonymous")
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.uast.test.common
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.uast.*
|
||||
import org.jetbrains.uast.test.env.assertEqualsToFile
|
||||
import org.jetbrains.uast.visitor.AbstractUastVisitor
|
||||
import org.junit.ComparisonFailure
|
||||
import java.io.File
|
||||
|
||||
interface IdentifiersTestBase {
|
||||
fun getIdentifiersFile(testName: String): File
|
||||
|
||||
private fun UFile.asIdentifiersWithParents(): String {
|
||||
val builder = StringBuilder()
|
||||
var level = 0
|
||||
(this.psi as KtFile).accept(object : PsiElementVisitor() {
|
||||
override fun visitElement(element: PsiElement) {
|
||||
val uIdentifier = element.toUElementOfType<UIdentifier>()
|
||||
if (uIdentifier != null) {
|
||||
builder.append(" ".repeat(level))
|
||||
builder.append(uIdentifier.sourcePsiElement!!.text)
|
||||
builder.append(" -> ")
|
||||
builder.append(uIdentifier.uastParent?.asLogString())
|
||||
builder.appendln()
|
||||
}
|
||||
if (element is KtBlockExpression) level++
|
||||
element.acceptChildren(this)
|
||||
if (element is KtBlockExpression) level--
|
||||
}
|
||||
})
|
||||
return builder.toString()
|
||||
}
|
||||
|
||||
private fun UFile.testIdentifiersParents() {
|
||||
accept(object : AbstractUastVisitor() {
|
||||
override fun visitElement(node: UElement): Boolean {
|
||||
if (node is UAnchorOwner) {
|
||||
val uastAnchor = node.uastAnchor ?: return false
|
||||
assertParents(node, uastAnchor)
|
||||
val uastAnchorFromSource = (uastAnchor.sourcePsi ?: return false).toUElementOfType<UIdentifier>()
|
||||
assertParents(node, uastAnchorFromSource)
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun assertParents(node: UAnchorOwner, uastAnchor: UIdentifier?) {
|
||||
//skipping such elements because they are ambiguous (properties and getters for instance)
|
||||
if (node.sourcePsi.toUElement() != node) return
|
||||
if (uastAnchor == null)
|
||||
throw AssertionError("no uast anchor for ${node.uastAnchor?.sourcePsi}(${node.uastAnchor?.sourcePsi?.javaClass}) for node = $node")
|
||||
val nodeParents = node.withContainingElements.log()
|
||||
val anchorParentParents = uastAnchor.uastParent?.withContainingElements?.log() ?: ""
|
||||
// dropping node itself because we allow children to share identifiers with parents (primary constructor for instance)
|
||||
val parentsSuffix = node.withContainingElements.drop(1).log()
|
||||
if (!anchorParentParents.endsWith(parentsSuffix))
|
||||
throw ComparisonFailure(
|
||||
"wrong parents for '${uastAnchor.sourcePsi?.text}' owner: $node[${node.sourcePsi}[${node.sourcePsi?.text}]]",
|
||||
nodeParents,
|
||||
anchorParentParents
|
||||
)
|
||||
}
|
||||
|
||||
private fun Sequence<UElement>.log() = this.joinToString { it.asLogString() }
|
||||
|
||||
fun check(testName: String, file: UFile) {
|
||||
val valuesFile = getIdentifiersFile(testName)
|
||||
|
||||
assertEqualsToFile("Identifiers", valuesFile, file.asIdentifiersWithParents())
|
||||
file.testIdentifiersParents()
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user