Extract AbstractResolveElementCacheTest to use in FIR cache testing
This commit is contained in:
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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.kotlin.idea
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||||
|
import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
|
||||||
|
abstract class AbstractResolveElementCacheTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||||
|
override fun getProjectDescriptor(): KotlinLightProjectDescriptor = KotlinLightProjectDescriptor.INSTANCE
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
//language=kotlin
|
||||||
|
const val FILE_TEXT =
|
||||||
|
"""
|
||||||
|
class C(param1: String = "", param2: Int = 0) {
|
||||||
|
fun a(p: Int = 0) {
|
||||||
|
b(1, 2)
|
||||||
|
val x = c()
|
||||||
|
d(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun b() {
|
||||||
|
x(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun c() {
|
||||||
|
x(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
protected data class Data(
|
||||||
|
val file: KtFile,
|
||||||
|
val klass: KtClass,
|
||||||
|
val members: List<KtDeclaration>,
|
||||||
|
val statements: List<KtExpression>,
|
||||||
|
val factory: KtPsiFactory
|
||||||
|
)
|
||||||
|
|
||||||
|
protected fun doTest(handler: Data.() -> Unit) {
|
||||||
|
val file = myFixture.configureByText("Test.kt", FILE_TEXT) as KtFile
|
||||||
|
val data = extractData(file)
|
||||||
|
myFixture.project.executeWriteCommand("") { data.handler() }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun extractData(file: KtFile): Data {
|
||||||
|
val klass = file.declarations.single() as KtClass
|
||||||
|
val members = klass.declarations
|
||||||
|
val function = members.first() as KtNamedFunction
|
||||||
|
val statements = function.bodyBlockExpression!!.statements
|
||||||
|
return Data(file, klass, members, statements, KtPsiFactory(project))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,8 +14,6 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithAllCompilerChecks
|
|||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
||||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
|
||||||
import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor
|
|
||||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -31,51 +29,7 @@ import org.jetbrains.kotlin.types.typeUtil.containsError
|
|||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
@RunWith(JUnit3WithIdeaConfigurationRunner::class)
|
@RunWith(JUnit3WithIdeaConfigurationRunner::class)
|
||||||
class ResolveElementCacheTest : KotlinLightCodeInsightFixtureTestCase() {
|
class ResolveElementCacheTest : AbstractResolveElementCacheTest() {
|
||||||
override fun getProjectDescriptor() = KotlinLightProjectDescriptor.INSTANCE
|
|
||||||
|
|
||||||
//language=kotlin
|
|
||||||
private val FILE_TEXT =
|
|
||||||
"""
|
|
||||||
class C(param1: String = "", param2: Int = 0) {
|
|
||||||
fun a(p: Int = 0) {
|
|
||||||
b(1, 2)
|
|
||||||
val x = c()
|
|
||||||
d(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun b() {
|
|
||||||
x(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun c() {
|
|
||||||
x(2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
private data class Data(
|
|
||||||
val file: KtFile,
|
|
||||||
val klass: KtClass,
|
|
||||||
val members: List<KtDeclaration>,
|
|
||||||
val statements: List<KtExpression>,
|
|
||||||
val factory: KtPsiFactory
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun doTest(handler: Data.() -> Unit) {
|
|
||||||
val file = myFixture.configureByText("Test.kt", FILE_TEXT) as KtFile
|
|
||||||
val data = extractData(file)
|
|
||||||
myFixture.project.executeWriteCommand("") { data.handler() }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun extractData(file: KtFile): Data {
|
|
||||||
val klass = file.declarations.single() as KtClass
|
|
||||||
val members = klass.declarations
|
|
||||||
val function = members.first() as KtNamedFunction
|
|
||||||
val statements = function.bodyBlockExpression!!.statements
|
|
||||||
return Data(file, klass, members, statements, KtPsiFactory(project))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun testFullResolveCaching() {
|
fun testFullResolveCaching() {
|
||||||
doTest { this.testResolveCaching() }
|
doTest { this.testResolveCaching() }
|
||||||
}
|
}
|
||||||
@@ -149,7 +103,7 @@ class C(param1: String = "", param2: Int = 0) {
|
|||||||
val statement = statements[0]
|
val statement = statements[0]
|
||||||
val bindingContext1 = statement.analyze(BodyResolveMode.FULL)
|
val bindingContext1 = statement.analyze(BodyResolveMode.FULL)
|
||||||
|
|
||||||
val classConstructorParamTypeRef = klass.getPrimaryConstructor()!!.valueParameters.first().typeReference!!
|
val classConstructorParamTypeRef = klass.primaryConstructor!!.valueParameters.first().typeReference!!
|
||||||
val bindingContext2 = classConstructorParamTypeRef.analyze(BodyResolveMode.FULL)
|
val bindingContext2 = classConstructorParamTypeRef.analyze(BodyResolveMode.FULL)
|
||||||
|
|
||||||
val documentManager = PsiDocumentManager.getInstance(project)
|
val documentManager = PsiDocumentManager.getInstance(project)
|
||||||
@@ -249,8 +203,10 @@ class C(param1: String = "", param2: Int = 0) {
|
|||||||
|
|
||||||
fun testPartialResolveCachedForAllStatementsResolved() {
|
fun testPartialResolveCachedForAllStatementsResolved() {
|
||||||
doTest {
|
doTest {
|
||||||
val bindingContext1 = statements[2].analyze(BodyResolveMode.PARTIAL) // resolve 'd(x)'
|
// resolve 'd(x)'
|
||||||
val bindingContext2 = (statements[1] as KtVariableDeclaration).initializer!!.analyze(BodyResolveMode.PARTIAL) // resolve initializer in 'val x = c()' - it required for resolved 'd(x)' and should be already resolved
|
val bindingContext1 = statements[2].analyze(BodyResolveMode.PARTIAL)
|
||||||
|
// resolve initializer in 'val x = c()' - it required for resolved 'd(x)' and should be already resolved
|
||||||
|
val bindingContext2 = (statements[1] as KtVariableDeclaration).initializer!!.analyze(BodyResolveMode.PARTIAL)
|
||||||
assert(bindingContext1 === bindingContext2)
|
assert(bindingContext1 === bindingContext2)
|
||||||
|
|
||||||
val bindingContext3 = statements[0].analyze(BodyResolveMode.PARTIAL)
|
val bindingContext3 = statements[0].analyze(BodyResolveMode.PARTIAL)
|
||||||
@@ -306,10 +262,11 @@ class C(param1: String = "", param2: Int = 0) {
|
|||||||
|
|
||||||
fun testAnnotationEntry() {
|
fun testAnnotationEntry() {
|
||||||
val file = configureWithKotlin(
|
val file = configureWithKotlin(
|
||||||
"""
|
"""
|
||||||
annotation class A
|
annotation class A
|
||||||
@A class B {}
|
@A class B {}
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
val klass = file.declarations[1] as KtClass
|
val klass = file.declarations[1] as KtClass
|
||||||
val annotationEntry = klass.annotationEntries.single()
|
val annotationEntry = klass.annotationEntries.single()
|
||||||
@@ -320,10 +277,11 @@ class C(param1: String = "", param2: Int = 0) {
|
|||||||
|
|
||||||
fun testFileAnnotationList() {
|
fun testFileAnnotationList() {
|
||||||
val file = configureWithKotlin(
|
val file = configureWithKotlin(
|
||||||
"""
|
"""
|
||||||
@file:Suppress("Some")
|
@file:Suppress("Some")
|
||||||
@file:JvmName("Hi")
|
@file:JvmName("Hi")
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
val fileAnnotationList = file.fileAnnotationList!!
|
val fileAnnotationList = file.fileAnnotationList!!
|
||||||
val context = fileAnnotationList.analyze(BodyResolveMode.PARTIAL)
|
val context = fileAnnotationList.analyze(BodyResolveMode.PARTIAL)
|
||||||
@@ -332,10 +290,12 @@ class C(param1: String = "", param2: Int = 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun testIncompleteFileAnnotationList() {
|
fun testIncompleteFileAnnotationList() {
|
||||||
val file = myFixture.configureByText("Test.kt", """
|
val file = myFixture.configureByText(
|
||||||
|
"Test.kt", """
|
||||||
@file
|
@file
|
||||||
import some.hello
|
import some.hello
|
||||||
""") as KtFile
|
"""
|
||||||
|
) as KtFile
|
||||||
|
|
||||||
val fileAnnotationList = file.fileAnnotationList!!
|
val fileAnnotationList = file.fileAnnotationList!!
|
||||||
fileAnnotationList.analyze(BodyResolveMode.PARTIAL)
|
fileAnnotationList.analyze(BodyResolveMode.PARTIAL)
|
||||||
@@ -343,27 +303,29 @@ class C(param1: String = "", param2: Int = 0) {
|
|||||||
|
|
||||||
fun testNamedParametersInFunctionType() {
|
fun testNamedParametersInFunctionType() {
|
||||||
val file = configureWithKotlin(
|
val file = configureWithKotlin(
|
||||||
"""
|
"""
|
||||||
fun <K, V> intercept(block: (key: K, next: (K) -> V, K) -> V) {}
|
fun <K, V> intercept(block: (key: K, next: (K) -> V, K) -> V) {}
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
val function = file.declarations[0] as KtNamedFunction
|
val function = file.declarations[0] as KtNamedFunction
|
||||||
val functionType = function.valueParameters.first().typeReference!!.typeElement as KtFunctionType
|
val functionType = function.valueParameters.first().typeReference!!.typeElement as KtFunctionType
|
||||||
val descriptorsForParameters = functionType.parameters.map { it.unsafeResolveToDescriptor() }
|
val descriptorsForParameters = functionType.parameters.map { it.unsafeResolveToDescriptor() }
|
||||||
|
|
||||||
assert(
|
assert(
|
||||||
listOf("key", "next", SpecialNames.NO_NAME_PROVIDED.asString()) ==
|
listOf("key", "next", SpecialNames.NO_NAME_PROVIDED.asString()) ==
|
||||||
descriptorsForParameters.map { it.name.asString() }
|
descriptorsForParameters.map { it.name.asString() }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testNoBodyResolveOnFunctionParameterAnalyze() {
|
fun testNoBodyResolveOnFunctionParameterAnalyze() {
|
||||||
val file = configureWithKotlin(
|
val file = configureWithKotlin(
|
||||||
"""
|
"""
|
||||||
fun test(a: String) {
|
fun test(a: String) {
|
||||||
unresolved // Check diagnostics is empty even in FULL mode when starting analyzing for parameter
|
unresolved // Check diagnostics is empty even in FULL mode when starting analyzing for parameter
|
||||||
}
|
}
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
val function = file.declarations[0] as KtNamedFunction
|
val function = file.declarations[0] as KtNamedFunction
|
||||||
val functionParameter = function.valueParameters.first()
|
val functionParameter = function.valueParameters.first()
|
||||||
@@ -378,9 +340,11 @@ class C(param1: String = "", param2: Int = 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun testPrimaryConstructorParameterFullAnalysis() {
|
fun testPrimaryConstructorParameterFullAnalysis() {
|
||||||
myFixture.configureByText("Test.kt", """
|
myFixture.configureByText(
|
||||||
|
"Test.kt", """
|
||||||
class My(param: Int = <caret>0)
|
class My(param: Int = <caret>0)
|
||||||
""") as KtFile
|
"""
|
||||||
|
) as KtFile
|
||||||
|
|
||||||
val defaultValue = myFixture.elementByOffset.getParentOfType<KtExpression>(true)!!
|
val defaultValue = myFixture.elementByOffset.getParentOfType<KtExpression>(true)!!
|
||||||
// Kept to preserve correct behaviour of analyzeFully() on class internal elements
|
// Kept to preserve correct behaviour of analyzeFully() on class internal elements
|
||||||
@@ -403,12 +367,14 @@ class C(param1: String = "", param2: Int = 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun testFunctionParameterAnnotation() {
|
fun testFunctionParameterAnnotation() {
|
||||||
val file = myFixture.configureByText("Test.kt", """
|
val file = myFixture.configureByText(
|
||||||
|
"Test.kt", """
|
||||||
annotation class Ann
|
annotation class Ann
|
||||||
fun foo(@<caret>Ann p: Int) {
|
fun foo(@<caret>Ann p: Int) {
|
||||||
bar()
|
bar()
|
||||||
}
|
}
|
||||||
""") as KtFile
|
"""
|
||||||
|
) as KtFile
|
||||||
|
|
||||||
val function = (file.declarations[1]) as KtFunction
|
val function = (file.declarations[1]) as KtFunction
|
||||||
val typeRef = myFixture.elementByOffset.getParentOfType<KtTypeReference>(true)!!
|
val typeRef = myFixture.elementByOffset.getParentOfType<KtTypeReference>(true)!!
|
||||||
@@ -424,10 +390,12 @@ class C(param1: String = "", param2: Int = 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun testPrimaryConstructorParameterAnnotation() {
|
fun testPrimaryConstructorParameterAnnotation() {
|
||||||
myFixture.configureByText("Test.kt", """
|
myFixture.configureByText(
|
||||||
|
"Test.kt", """
|
||||||
annotation class Ann
|
annotation class Ann
|
||||||
class X(@set:<caret>Ann var p: Int)
|
class X(@set:<caret>Ann var p: Int)
|
||||||
""") as KtFile
|
"""
|
||||||
|
) as KtFile
|
||||||
|
|
||||||
val typeRef = myFixture.elementByOffset.getParentOfType<KtTypeReference>(true)!!
|
val typeRef = myFixture.elementByOffset.getParentOfType<KtTypeReference>(true)!!
|
||||||
|
|
||||||
@@ -439,16 +407,18 @@ class C(param1: String = "", param2: Int = 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun testSecondaryConstructorParameterAnnotation() {
|
fun testSecondaryConstructorParameterAnnotation() {
|
||||||
val file = myFixture.configureByText("Test.kt", """
|
val file = myFixture.configureByText(
|
||||||
|
"Test.kt", """
|
||||||
annotation class Ann
|
annotation class Ann
|
||||||
class X {
|
class X {
|
||||||
constructor(@<caret>Ann p: Int) {
|
constructor(@<caret>Ann p: Int) {
|
||||||
foo()
|
foo()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""") as KtFile
|
"""
|
||||||
|
) as KtFile
|
||||||
|
|
||||||
val constructor = ((file.declarations[1]) as KtClass).getSecondaryConstructors()[0]
|
val constructor = ((file.declarations[1]) as KtClass).secondaryConstructors[0]
|
||||||
val typeRef = myFixture.elementByOffset.getParentOfType<KtTypeReference>(true)!!
|
val typeRef = myFixture.elementByOffset.getParentOfType<KtTypeReference>(true)!!
|
||||||
|
|
||||||
val bindingContext = typeRef.analyze(BodyResolveMode.PARTIAL)
|
val bindingContext = typeRef.analyze(BodyResolveMode.PARTIAL)
|
||||||
@@ -482,10 +452,12 @@ class C(param1: String = "", param2: Int = 0) {
|
|||||||
val statement1InFunA = aBody.statements[0]
|
val statement1InFunA = aBody.statements[0]
|
||||||
val statement2InFunA = aBody.statements[1]
|
val statement2InFunA = aBody.statements[1]
|
||||||
val statementInFunB = ((members[1] as KtFunction).bodyBlockExpression)!!.statements[0]
|
val statementInFunB = ((members[1] as KtFunction).bodyBlockExpression)!!.statements[0]
|
||||||
val constructorParameterDefault = klass.getPrimaryConstructor()!!.valueParameters[1].defaultValue!!
|
val constructorParameterDefault = klass.primaryConstructor!!.valueParameters[1].defaultValue!!
|
||||||
val funC = members[2]
|
val funC = members[2]
|
||||||
|
|
||||||
checkResolveMultiple(BodyResolveMode.PARTIAL, statement1InFunA, statement2InFunA, statementInFunB, constructorParameterDefault, funC)
|
checkResolveMultiple(
|
||||||
|
BodyResolveMode.PARTIAL, statement1InFunA, statement2InFunA, statementInFunB, constructorParameterDefault, funC
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,7 +482,8 @@ class C(param1: String = "", param2: Int = 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun testResolveDefaultValueInPrimaryConstructor() {
|
fun testResolveDefaultValueInPrimaryConstructor() {
|
||||||
myFixture.configureByText("Test.kt", """
|
myFixture.configureByText(
|
||||||
|
"Test.kt", """
|
||||||
class ClassA<N> (
|
class ClassA<N> (
|
||||||
messenger: ClassB<N> = object : ClassB<N> {
|
messenger: ClassB<N> = object : ClassB<N> {
|
||||||
override fun methodOne<caret>(param: List<N>) {
|
override fun methodOne<caret>(param: List<N>) {
|
||||||
@@ -521,7 +494,8 @@ class C(param1: String = "", param2: Int = 0) {
|
|||||||
interface ClassB<N> {
|
interface ClassB<N> {
|
||||||
fun methodOne(param: List<N>)
|
fun methodOne(param: List<N>)
|
||||||
}
|
}
|
||||||
""") as KtFile
|
"""
|
||||||
|
) as KtFile
|
||||||
|
|
||||||
val methodOne = myFixture.elementByOffset.getParentOfType<KtFunction>(true)!!
|
val methodOne = myFixture.elementByOffset.getParentOfType<KtFunction>(true)!!
|
||||||
|
|
||||||
@@ -574,8 +548,7 @@ class C(param1: String = "", param2: Int = 0) {
|
|||||||
expressions.forEach {
|
expressions.forEach {
|
||||||
if (it !is KtDeclaration) {
|
if (it !is KtDeclaration) {
|
||||||
TestCase.assertEquals(true, bindingContext[BindingContext.PROCESSED, it])
|
TestCase.assertEquals(true, bindingContext[BindingContext.PROCESSED, it])
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
TestCase.assertNotNull(bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, it])
|
TestCase.assertNotNull(bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, it])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user