From 91c86f7f56753e0bdba1a3667b27367adcca870b Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 20 Nov 2018 15:21:10 +0300 Subject: [PATCH] Fix refactorings that remove parameter based on ultra-light classes This commit fixes the exception attached to the bottom of the message The problem is that when creating ChangeSignatureProcessor for old PsiMethod that points to the parameter that is already removed from PSI, some pieces of platform code run resolution on the light PSI that eventually checks if the source element is valid. For KtUltraLightParameter, it inherits "isValid" from LightElement and the latter is defined as getNavigationElement().isValid(), while here navigationElement points to already removed parameter, and marked as invalid. The simplest solution was to define KtUltraLightParameter::isValid as it was before ultra-light classes, i.e. checking if parent is valid (see KtLightElementBase::isValid) com.intellij.psi.PsiInvalidElementAccessException: Element: class com.intellij.psi.impl.compiled.ClsJavaCodeReferenceElementImpl #JAVA because: File language:Language: JAVA != Provider base language:Language: kotlin invalidated at: no info at com.intellij.psi.util.PsiUtilCore.ensureValid(PsiUtilCore.java:482) at com.intellij.psi.impl.source.PsiClassReferenceType.resolveGenerics(PsiClassReferenceType.java:190) at com.intellij.psi.impl.source.PsiClassReferenceType.resolve(PsiClassReferenceType.java:138) at com.intellij.psi.util.PsiUtil.resolveClassInType(PsiUtil.java:445) at com.intellij.psi.util.PsiUtil.convertAnonymousToBaseType(PsiUtil.java:484) at com.intellij.psi.impl.light.LightTypeElement.(LightTypeElement.java:33) at com.intellij.psi.impl.PsiElementFactoryImpl.createTypeElement(PsiElementFactoryImpl.java:142) at com.intellij.refactoring.changeSignature.JavaChangeInfoImpl.fillOldParams(JavaChangeInfoImpl.java:218) at com.intellij.refactoring.changeSignature.JavaChangeInfoImpl.(JavaChangeInfoImpl.java:127) at com.intellij.refactoring.changeSignature.JavaChangeInfoImpl.(JavaChangeInfoImpl.java:86) at com.intellij.refactoring.changeSignature.ChangeSignatureProcessor.generateChangeInfo(ChangeSignatureProcessor.java:121) at com.intellij.refactoring.changeSignature.ChangeSignatureProcessor.(ChangeSignatureProcessor.java:88) at org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinChangeInfo$getOrCreateJavaChangeInfos$3.invoke(KotlinChangeInfo.kt:400) at org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinChangeInfo$getOrCreateJavaChangeInfos$5.invoke(KotlinChangeInfo.kt:469) at org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinChangeInfo.getOrCreateJavaChangeInfos(KotlinChangeInfo.kt:498) at org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinChangeSignatureUsageProcessor.processUsage(KotlinChangeSignatureUsageProcessor.kt:847) at com.intellij.refactoring.changeSignature.ChangeSignatureProcessorBase.doChangeSignature(ChangeSignatureProcessorBase.java:218) --- .../kotlin/asJava/classes/ultraLightPsi.kt | 2 ++ ...terToReceiverForMemberUltraLightAfter.1.java | 5 +++++ ...rameterToReceiverForMemberUltraLightAfter.kt | 17 +++++++++++++++++ ...erToReceiverForMemberUltraLightBefore.1.java | 5 +++++ ...ameterToReceiverForMemberUltraLightBefore.kt | 17 +++++++++++++++++ .../KotlinChangeSignatureTest.kt | 12 +++++++++--- 6 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 idea/testData/refactoring/changeSignature/ConvertParameterToReceiverForMemberUltraLightAfter.1.java create mode 100644 idea/testData/refactoring/changeSignature/ConvertParameterToReceiverForMemberUltraLightAfter.kt create mode 100644 idea/testData/refactoring/changeSignature/ConvertParameterToReceiverForMemberUltraLightBefore.1.java create mode 100644 idea/testData/refactoring/changeSignature/ConvertParameterToReceiverForMemberUltraLightBefore.kt diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightPsi.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightPsi.kt index daa8253767c..ae9c1d3201b 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightPsi.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightPsi.kt @@ -693,6 +693,8 @@ internal class KtUltraLightParameter( override fun getNavigationElement(): PsiElement = kotlinOrigin + override fun isValid() = parent.isValid + private val kotlinType: KotlinType? by lazyPub { when { receiver != null -> (kotlinOrigin.resolve() as? CallableMemberDescriptor)?.extensionReceiverParameter?.type diff --git a/idea/testData/refactoring/changeSignature/ConvertParameterToReceiverForMemberUltraLightAfter.1.java b/idea/testData/refactoring/changeSignature/ConvertParameterToReceiverForMemberUltraLightAfter.1.java new file mode 100644 index 00000000000..d789386f98b --- /dev/null +++ b/idea/testData/refactoring/changeSignature/ConvertParameterToReceiverForMemberUltraLightAfter.1.java @@ -0,0 +1,5 @@ +class J { + void test() { + new A(3).foo(new X(0), "1", 2); + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/ConvertParameterToReceiverForMemberUltraLightAfter.kt b/idea/testData/refactoring/changeSignature/ConvertParameterToReceiverForMemberUltraLightAfter.kt new file mode 100644 index 00000000000..94a8cb8f405 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/ConvertParameterToReceiverForMemberUltraLightAfter.kt @@ -0,0 +1,17 @@ +class A(val k: Int) { + fun X.foo(s: String, k: Int): Boolean { + return this.k + s.length - k + this@A.k/2 > 0 + } + + fun test() { + X(0).foo("1", 2) + } +} + +class X(val k: Int) + +fun test() { + with(A(3)) { + X(0).foo("1", 2) + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/ConvertParameterToReceiverForMemberUltraLightBefore.1.java b/idea/testData/refactoring/changeSignature/ConvertParameterToReceiverForMemberUltraLightBefore.1.java new file mode 100644 index 00000000000..d789386f98b --- /dev/null +++ b/idea/testData/refactoring/changeSignature/ConvertParameterToReceiverForMemberUltraLightBefore.1.java @@ -0,0 +1,5 @@ +class J { + void test() { + new A(3).foo(new X(0), "1", 2); + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/ConvertParameterToReceiverForMemberUltraLightBefore.kt b/idea/testData/refactoring/changeSignature/ConvertParameterToReceiverForMemberUltraLightBefore.kt new file mode 100644 index 00000000000..c2c9d2a5f7e --- /dev/null +++ b/idea/testData/refactoring/changeSignature/ConvertParameterToReceiverForMemberUltraLightBefore.kt @@ -0,0 +1,17 @@ +class A(val k: Int) { + fun foo(x: X, s: String, k: Int): Boolean { + return x.k + s.length - k + this.k/2 > 0 + } + + fun test() { + foo(X(0), "1", 2) + } +} + +class X(val k: Int) + +fun test() { + with(A(3)) { + foo(X(0), "1", 2) + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureTest.kt b/idea/tests/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureTest.kt index f26aaec1fb8..0c80bc7c79b 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureTest.kt @@ -37,9 +37,10 @@ import org.jetbrains.kotlin.asJava.toLightMethods import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.refactoring.changeSignature.ui.KotlinMethodNode -import org.jetbrains.kotlin.idea.refactoring.changeSignature.ui.KotlinChangeSignatureDialog.Companion.getTypeInfo +import org.jetbrains.kotlin.idea.perf.forceUsingUltraLightClassesForTest import org.jetbrains.kotlin.idea.refactoring.changeSignature.ui.KotlinChangeSignatureDialog.Companion.getTypeCodeFragmentContext +import org.jetbrains.kotlin.idea.refactoring.changeSignature.ui.KotlinChangeSignatureDialog.Companion.getTypeInfo +import org.jetbrains.kotlin.idea.refactoring.changeSignature.ui.KotlinMethodNode import org.jetbrains.kotlin.idea.search.allScope import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionFqnNameIndex @@ -575,6 +576,11 @@ class KotlinChangeSignatureTest : KotlinLightCodeInsightFixtureTestCase() { fun testConvertParameterToReceiverForMember1() = doTest { receiverParameterInfo = newParameters[0] } + fun testConvertParameterToReceiverForMemberUltraLight() { + forceUsingUltraLightClassesForTest() + doTest { receiverParameterInfo = newParameters[0] } + } + fun testConvertParameterToReceiverForMember2() = doTest { receiverParameterInfo = newParameters[1] } fun testConvertParameterToReceiverForMemberConflict() = doTestConflict { receiverParameterInfo = newParameters[0] } @@ -1012,4 +1018,4 @@ class KotlinChangeSignatureTest : KotlinLightCodeInsightFixtureTestCase() { fun testKotlinOverridingJavaWithDifferentParamName() = doJavaTest { newParameters.add(ParameterInfoImpl(-1, "n", PsiType.INT)) } -} \ No newline at end of file +}