307 lines
11 KiB
Kotlin
307 lines
11 KiB
Kotlin
/*
|
|
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
* 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 com.intellij.psi.PsiClassType
|
|
import com.intellij.psi.PsiType
|
|
import com.intellij.psi.PsiVariable
|
|
import com.intellij.testFramework.LightProjectDescriptor
|
|
import junit.framework.TestCase
|
|
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
|
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
|
import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner
|
|
import org.jetbrains.uast.*
|
|
import org.jetbrains.uast.kotlin.KotlinUFunctionCallExpression
|
|
import org.jetbrains.uast.test.env.kotlin.findElementByText
|
|
import org.jetbrains.uast.test.env.kotlin.findElementByTextFromPsi
|
|
import org.jetbrains.uast.test.env.kotlin.findUElementByTextFromPsi
|
|
import org.junit.runner.RunWith
|
|
|
|
@RunWith(JUnit3WithIdeaConfigurationRunner::class)
|
|
class KotlinUastResolveApiTest : KotlinLightCodeInsightFixtureTestCase() {
|
|
|
|
override fun getProjectDescriptor(): LightProjectDescriptor =
|
|
KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
|
|
|
|
|
|
fun testResolveStringFromUast() {
|
|
val file = myFixture.addFileToProject(
|
|
"s.kt", """fun foo(){
|
|
val s = "abc"
|
|
s.toUpperCase()
|
|
}
|
|
""${'"'}"""
|
|
)
|
|
|
|
val refs = file.findUElementByTextFromPsi<UQualifiedReferenceExpression>("s.toUpperCase()")
|
|
TestCase.assertNotNull((refs.receiver.getExpressionType() as PsiClassType).resolve())
|
|
}
|
|
|
|
fun testMultiResolve() {
|
|
val file = myFixture.configureByText(
|
|
"s.kt", """
|
|
fun foo(): Int = TODO()
|
|
fun foo(a: Int): Int = TODO()
|
|
fun foo(a: Int, b: Int): Int = TODO()
|
|
|
|
|
|
fun main(args: Array<String>) {
|
|
foo(1<caret>
|
|
}"""
|
|
)
|
|
|
|
val main = file.toUElement()!!.findElementByTextFromPsi<UElement>("main").getContainingUMethod()!!
|
|
val functionCall =
|
|
main.findElementByText<UElement>("foo").uastParent as KotlinUFunctionCallExpression
|
|
|
|
val resolvedDeclaration = functionCall.multiResolve()
|
|
val resolvedDeclarationsStrings = resolvedDeclaration.map { it.element.text ?: "<null>" }
|
|
assertContainsElements(
|
|
resolvedDeclarationsStrings,
|
|
"fun foo(): Int = TODO()",
|
|
"fun foo(a: Int): Int = TODO()",
|
|
"fun foo(a: Int, b: Int): Int = TODO()"
|
|
)
|
|
|
|
TestCase.assertEquals(PsiType.INT, functionCall.getExpressionType())
|
|
|
|
val firstArgument = main.findElementByText<UElement>("1")
|
|
val firstParameter = functionCall.getArgumentForParameter(0)
|
|
TestCase.assertEquals(firstArgument, firstParameter)
|
|
|
|
}
|
|
|
|
fun testMultiResolveJava() {
|
|
val file = myFixture.configureByText(
|
|
"s.kt", """
|
|
|
|
fun main(args: Array<String>) {
|
|
System.out.print(""
|
|
}
|
|
"""
|
|
)
|
|
|
|
val main = file.toUElement()!!.findElementByTextFromPsi<UElement>("main").getContainingUMethod()!!
|
|
val functionCall = main.findElementByText<UElement>("print").uastParent as KotlinUFunctionCallExpression
|
|
|
|
val resolvedDeclaration = functionCall.multiResolve()
|
|
val resolvedDeclarationsStrings = resolvedDeclaration.map { it.element.text ?: "<null>" }
|
|
assertContainsElements(
|
|
resolvedDeclarationsStrings,
|
|
"public void print(char c) { /* compiled code */ }",
|
|
"public void print(int i) { /* compiled code */ }",
|
|
"public void print(long l) { /* compiled code */ }",
|
|
"public void print(float f) { /* compiled code */ }",
|
|
"public void print(double d) { /* compiled code */ }",
|
|
"public void print(char[] s) { /* compiled code */ }",
|
|
"public void print(java.lang.String s) { /* compiled code */ }",
|
|
"public void print(java.lang.Object obj) { /* compiled code */ }"
|
|
)
|
|
|
|
TestCase.assertEquals(PsiType.VOID, functionCall.getExpressionType())
|
|
|
|
val firstArgument = main.findElementByText<UElement>("\"\"")
|
|
val firstParameter = functionCall.getArgumentForParameter(0)
|
|
TestCase.assertEquals(firstArgument, firstParameter)
|
|
}
|
|
|
|
fun testMultiResolveJavaAmbiguous() {
|
|
myFixture.addClass(
|
|
"""
|
|
public class JavaClass {
|
|
|
|
public void setParameter(String name, int value){}
|
|
public void setParameter(String name, double value){}
|
|
public void setParameter(String name, String value){}
|
|
|
|
}
|
|
"""
|
|
)
|
|
val file = myFixture.configureByText(
|
|
"s.kt", """
|
|
|
|
fun main(args: Array<String>) {
|
|
JavaClass().setParameter(""
|
|
}
|
|
"""
|
|
)
|
|
|
|
val main = file.toUElement()!!.findElementByTextFromPsi<UElement>("main").getContainingUMethod()!!
|
|
val functionCall = main.findElementByText<UElement>("setParameter").uastParent as KotlinUFunctionCallExpression
|
|
|
|
val resolvedDeclaration = functionCall.multiResolve()
|
|
val resolvedDeclarationsStrings = resolvedDeclaration.map { it.element.text ?: "<null>" }
|
|
assertContainsElements(
|
|
resolvedDeclarationsStrings,
|
|
"public void setParameter(String name, int value){}",
|
|
"public void setParameter(String name, double value){}",
|
|
"public void setParameter(String name, String value){}"
|
|
|
|
)
|
|
|
|
TestCase.assertEquals(PsiType.VOID, functionCall.getExpressionType())
|
|
|
|
val firstArgument = main.findElementByText<UElement>("\"\"")
|
|
val firstParameter = functionCall.getArgumentForParameter(0)
|
|
TestCase.assertEquals(firstArgument, firstParameter)
|
|
}
|
|
|
|
fun testMultiResolveInClass() {
|
|
val file = myFixture.configureByText(
|
|
"s.kt", """
|
|
class MyClass {
|
|
|
|
fun foo(): Int = TODO()
|
|
fun foo(a: Int): Int = TODO()
|
|
fun foo(a: Int, b: Int): Int = TODO()
|
|
|
|
}
|
|
|
|
fun foo(string: String) = TODO()
|
|
|
|
|
|
fun main(args: Array<String>) {
|
|
MyClass().foo(
|
|
}
|
|
"""
|
|
)
|
|
|
|
|
|
val functionCall =
|
|
file.toUElement()!!.findElementByTextFromPsi<UElement>("main").getContainingUMethod()!!
|
|
.findElementByText<UElement>("foo").uastParent as KotlinUFunctionCallExpression
|
|
|
|
val resolvedDeclaration = functionCall.multiResolve()
|
|
val resolvedDeclarationsStrings = resolvedDeclaration.map { it.element.text ?: "<null>" }
|
|
assertContainsElements(
|
|
resolvedDeclarationsStrings,
|
|
"fun foo(): Int = TODO()",
|
|
"fun foo(a: Int): Int = TODO()",
|
|
"fun foo(a: Int, b: Int): Int = TODO()"
|
|
)
|
|
assertDoesntContain(resolvedDeclarationsStrings, "fun foo(string: String) = TODO()")
|
|
TestCase.assertEquals(PsiType.INT, functionCall.getExpressionType())
|
|
}
|
|
|
|
fun testMultiConstructorResolve() {
|
|
val file = myFixture.configureByText(
|
|
"s.kt", """
|
|
class MyClass(int: Int) {
|
|
|
|
constructor(int: Int, int1: Int) : this(int + int1)
|
|
|
|
fun foo(): Int = TODO()
|
|
|
|
}
|
|
|
|
fun MyClass(string: String): MyClass = MyClass(1)
|
|
|
|
|
|
fun main(args: Array<String>) {
|
|
MyClass(
|
|
}
|
|
"""
|
|
)
|
|
|
|
|
|
val functionCall =
|
|
file.toUElement()!!.findElementByTextFromPsi<UElement>("main").getContainingUMethod()!!
|
|
.findElementByText<UElement>("MyClass").uastParent as KotlinUFunctionCallExpression
|
|
|
|
val resolvedDeclaration = functionCall.multiResolve()
|
|
val resolvedDeclarationsStrings = resolvedDeclaration.map { it.element.text ?: "<null>" }
|
|
assertContainsElements(
|
|
resolvedDeclarationsStrings,
|
|
"(int: Int)",
|
|
"constructor(int: Int, int1: Int) : this(int + int1)",
|
|
"fun MyClass(string: String): MyClass = MyClass(1)"
|
|
)
|
|
assertDoesntContain(resolvedDeclarationsStrings, "fun foo(): Int = TODO()")
|
|
TestCase.assertEquals(PsiType.getTypeByName("MyClass", project, file.resolveScope), functionCall.getExpressionType())
|
|
}
|
|
|
|
|
|
fun testMultiInvokableObjectResolve() {
|
|
val file = myFixture.configureByText(
|
|
"s.kt", """
|
|
object Foo {
|
|
|
|
operator fun invoke(i: Int): Int = TODO()
|
|
operator fun invoke(i1: Int, i2: Int): Int = TODO()
|
|
operator fun invoke(i1: Int, i2: Int, i3: Int): Int = TODO()
|
|
|
|
}
|
|
|
|
fun main(args: Array<String>) {
|
|
Foo(
|
|
}
|
|
"""
|
|
)
|
|
|
|
val functionCall =
|
|
file.toUElement()!!.findElementByTextFromPsi<UElement>("main").getContainingUMethod()!!
|
|
.findElementByText<UElement>("Foo").uastParent as KotlinUFunctionCallExpression
|
|
|
|
val resolvedDeclaration = functionCall.multiResolve()
|
|
val resolvedDeclarationsStrings = resolvedDeclaration.map { it.element.text ?: "<null>" }
|
|
assertContainsElements(
|
|
resolvedDeclarationsStrings,
|
|
"operator fun invoke(i: Int): Int = TODO()",
|
|
"operator fun invoke(i1: Int, i2: Int): Int = TODO()",
|
|
"operator fun invoke(i1: Int, i2: Int, i3: Int): Int = TODO()"
|
|
)
|
|
TestCase.assertEquals(PsiType.INT, functionCall.getExpressionType())
|
|
}
|
|
|
|
fun testMultiResolveJvmOverloads() {
|
|
val file = myFixture.configureByText(
|
|
"s.kt", """
|
|
|
|
class MyClass {
|
|
|
|
@JvmOverloads
|
|
fun foo(i1: Int = 1, i2: Int = 2): Int = TODO()
|
|
|
|
}
|
|
|
|
fun main(args: Array<String>) {
|
|
MyClass().foo(
|
|
}"""
|
|
)
|
|
|
|
val functionCall =
|
|
file.toUElement()!!.findElementByTextFromPsi<UElement>("main").getContainingUMethod()!!
|
|
.findElementByText<UElement>("foo").uastParent as KotlinUFunctionCallExpression
|
|
|
|
val resolvedDeclaration = functionCall.multiResolve()
|
|
val resolvedDeclarationsStrings = resolvedDeclaration.map { it.element.text ?: "<null>" }
|
|
assertContainsElements(
|
|
resolvedDeclarationsStrings,
|
|
"@JvmOverloads\n fun foo(i1: Int = 1, i2: Int = 2): Int = TODO()"
|
|
)
|
|
TestCase.assertEquals(PsiType.INT, functionCall.getExpressionType())
|
|
}
|
|
|
|
fun testLocalResolve() {
|
|
|
|
myFixture.configureByText(
|
|
"MyClass.kt", """
|
|
fun foo() {
|
|
fun bar() {}
|
|
|
|
ba<caret>r()
|
|
}
|
|
"""
|
|
)
|
|
|
|
val uCallExpression = myFixture.file.findElementAt(myFixture.caretOffset).toUElement().getUCallExpression().orFail("cant convert to UCallExpression")
|
|
val resolved = uCallExpression.resolve().orFail("cant resolve from $uCallExpression")
|
|
TestCase.assertEquals("bar", resolved.name)
|
|
}
|
|
|
|
}
|
|
|