Uast: fake light method for uast is created only when containing class exists (KT-35310, EA-219604)
This commit is contained in:
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
@@ -517,8 +518,12 @@ internal object KotlinConverter {
|
||||
val lightMethod = LightClassUtil.getLightClassMethod(original)
|
||||
if (lightMethod != null)
|
||||
convertDeclaration(lightMethod, givenParent, expectedTypes)
|
||||
else
|
||||
KotlinUMethodWithFakeLightDelegate(original, givenParent)
|
||||
else {
|
||||
val ktLightClass = original.containingClassOrObject?.toLightClass()
|
||||
?: original.containingKtFile.findFacadeClass()
|
||||
?: return null
|
||||
KotlinUMethodWithFakeLightDelegate(original, ktLightClass, givenParent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,6 @@ import com.intellij.psi.impl.light.LightModifierList
|
||||
import com.intellij.psi.impl.light.LightParameterListBuilder
|
||||
import com.intellij.psi.impl.light.LightTypeParameterBuilder
|
||||
import org.jetbrains.kotlin.asJava.elements.*
|
||||
import org.jetbrains.kotlin.asJava.findFacadeClass
|
||||
import org.jetbrains.kotlin.asJava.toLightClass
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
@@ -152,14 +150,14 @@ open class KotlinUAnnotationMethod(
|
||||
|
||||
}
|
||||
|
||||
private fun buildLightMethodFake(original: KtFunction): PsiMethod = object : LightMethodBuilder(
|
||||
private class UastFakeLightMethod(private val original: KtFunction, containingClass: PsiClass) : LightMethodBuilder(
|
||||
original.manager, original.language, original.name,
|
||||
LightParameterListBuilder(original.manager, original.language),
|
||||
LightModifierList(original.manager)
|
||||
) {
|
||||
|
||||
init {
|
||||
containingClass = original.containingClassOrObject?.toLightClass() ?: original.containingKtFile.findFacadeClass()
|
||||
this.containingClass = containingClass
|
||||
}
|
||||
|
||||
private val _buildTypeParameterList by lazy {
|
||||
@@ -181,8 +179,8 @@ private fun buildLightMethodFake(original: KtFunction): PsiMethod = object : Lig
|
||||
override fun getParent(): PsiElement? = containingClass
|
||||
}
|
||||
|
||||
class KotlinUMethodWithFakeLightDelegate(val original: KtFunction, givenParent: UElement?) :
|
||||
KotlinUMethod(buildLightMethodFake(original), original, givenParent) {
|
||||
class KotlinUMethodWithFakeLightDelegate(val original: KtFunction, containingLightClass: PsiClass, givenParent: UElement?) :
|
||||
KotlinUMethod(UastFakeLightMethod(original, containingLightClass), original, givenParent) {
|
||||
override val annotations: List<UAnnotation>
|
||||
get() = original.annotationEntries.mapNotNull { it.toUElementOfType<UAnnotation>() }
|
||||
|
||||
|
||||
@@ -23,8 +23,6 @@ import com.intellij.psi.impl.light.LightParameterListBuilder
|
||||
import com.intellij.psi.impl.light.LightTypeParameterBuilder
|
||||
import org.jetbrains.kotlin.asJava.elements.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.asJava.findFacadeClass
|
||||
import org.jetbrains.kotlin.asJava.toLightClass
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
@@ -155,14 +153,14 @@ open class KotlinUAnnotationMethod(
|
||||
|
||||
}
|
||||
|
||||
private fun buildLightMethodFake(original: KtFunction): PsiMethod = object : LightMethodBuilder(
|
||||
private class UastFakeLightMethod(private val original: KtFunction, containingClass: PsiClass) : LightMethodBuilder(
|
||||
original.manager, original.language, original.name,
|
||||
LightParameterListBuilder(original.manager, original.language),
|
||||
LightModifierList(original.manager)
|
||||
) {
|
||||
|
||||
init {
|
||||
containingClass = original.containingClassOrObject?.toLightClass() ?: original.containingKtFile.findFacadeClass()
|
||||
this.containingClass = containingClass
|
||||
}
|
||||
|
||||
private val _buildTypeParameterList by lazy {
|
||||
@@ -184,8 +182,8 @@ private fun buildLightMethodFake(original: KtFunction): PsiMethod = object : Lig
|
||||
override fun getParent(): PsiElement? = containingClass
|
||||
}
|
||||
|
||||
class KotlinUMethodWithFakeLightDelegate(val original: KtFunction, givenParent: UElement?) :
|
||||
KotlinUMethod(buildLightMethodFake(original), original, givenParent) {
|
||||
class KotlinUMethodWithFakeLightDelegate(val original: KtFunction, containingLightClass: PsiClass, givenParent: UElement?) :
|
||||
KotlinUMethod(UastFakeLightMethod(original, containingLightClass), original, givenParent) {
|
||||
override val annotations: List<UAnnotation>
|
||||
get() = original.annotationEntries.mapNotNull { it.toUElementOfType<UAnnotation>() }
|
||||
|
||||
|
||||
+12
-1
@@ -66,6 +66,7 @@ import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.typeUtil.isInterface
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.uast.*
|
||||
import org.jetbrains.uast.kotlin.expressions.KotlinLocalFunctionUVariable
|
||||
import java.lang.ref.WeakReference
|
||||
@@ -294,7 +295,17 @@ internal fun KotlinType.toPsiType(lightDeclaration: PsiModifierListOwner?, conte
|
||||
val typeInfo = TypeInfo.fromString(javaType, false)
|
||||
val typeText = TypeInfo.createTypeText(typeInfo) ?: return UastErrorType
|
||||
|
||||
return ClsTypeElementImpl(lightDeclaration ?: context, typeText, '\u0000').type
|
||||
val parent: PsiElement = lightDeclaration ?: context
|
||||
if (parent.containingFile == null) {
|
||||
Logger.getInstance("org.jetbrains.uast.kotlin.KotlinInternalUastUtils")
|
||||
.error(
|
||||
"initialising ClsTypeElementImpl with null-file parent = $parent (of ${parent.javaClass}) " +
|
||||
"containing class = ${parent.safeAs<PsiMethod>()?.containingClass}, " +
|
||||
"lightDeclaration = $lightDeclaration (of ${lightDeclaration?.javaClass})," +
|
||||
" context = $context (of ${context.javaClass})"
|
||||
)
|
||||
}
|
||||
return ClsTypeElementImpl(parent, typeText, '\u0000').type
|
||||
}
|
||||
|
||||
private fun KotlinType.containsLocalTypes(): Boolean {
|
||||
|
||||
@@ -26,11 +26,14 @@ import org.jetbrains.kotlin.idea.core.copied
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.findFunctionByName
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner
|
||||
import org.jetbrains.kotlin.test.testFramework.runWriteAction
|
||||
import org.jetbrains.uast.*
|
||||
import org.jetbrains.uast.test.env.kotlin.findUElementByTextFromPsi
|
||||
import org.junit.runner.RunWith
|
||||
@@ -135,18 +138,38 @@ class KotlinDetachedUastTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||
|
||||
fun testAnonymousInnerClassWithIDELightClasses() {
|
||||
|
||||
val detachedClass = myFixture.configureByText("MyClass.kt","""
|
||||
val detachedClass = myFixture.configureByText(
|
||||
"MyClass.kt", """
|
||||
class MyClass() {
|
||||
private val obj = object : MyClass() {}
|
||||
}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
val anonymousClass = detachedClass.findUElementByTextFromPsi<UObjectLiteralExpression>("object : MyClass() {}")
|
||||
.let { uObjectLiteralExpression -> uObjectLiteralExpression.declaration }
|
||||
TestCase.assertEquals("UClass (name = null), UObjectLiteralExpression, UField (name = obj), UClass (name = MyClass), UFile (package = )", generateSequence<UElement>(anonymousClass, { it.uastParent }).joinToString { it.asLogString() })
|
||||
TestCase.assertEquals(
|
||||
"UClass (name = null), UObjectLiteralExpression, UField (name = obj), UClass (name = MyClass), UFile (package = )",
|
||||
generateSequence<UElement>(anonymousClass, { it.uastParent }).joinToString { it.asLogString() })
|
||||
|
||||
}
|
||||
|
||||
|
||||
fun testDontConvertDetachedFunctions() {
|
||||
val ktFile = myFixture.configureByText(
|
||||
"MyClass.kt", """
|
||||
class MyClass() {
|
||||
fun foo1() = 42
|
||||
}
|
||||
"""
|
||||
) as KtFile
|
||||
val ktClass = ktFile.declarations.filterIsInstance<KtClass>().single()//.copied()
|
||||
val ktFunctionDetached = ktClass.findFunctionByName("foo1")!!
|
||||
runWriteAction { ktClass.delete() }
|
||||
TestCase.assertNull(ktFunctionDetached.toUElementOfType<UMethod>())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
fun <T> T?.orFail(msg: String): T = this ?: error(msg)
|
||||
Reference in New Issue
Block a user