Create deep descriptors copy for Change signature
It's needed to prevent accesses to invalid PSI after changes has been applied
This commit is contained in:
+1
-1
@@ -831,7 +831,7 @@ class KotlinChangeSignatureUsageProcessor : ChangeSignatureUsageProcessor {
|
|||||||
val descriptorWrapper = usages.firstIsInstanceOrNull<OriginalJavaMethodDescriptorWrapper>()
|
val descriptorWrapper = usages.firstIsInstanceOrNull<OriginalJavaMethodDescriptorWrapper>()
|
||||||
if (descriptorWrapper == null || descriptorWrapper.originalJavaMethodDescriptor != null) return true
|
if (descriptorWrapper == null || descriptorWrapper.originalJavaMethodDescriptor != null) return true
|
||||||
|
|
||||||
val methodDescriptor = method.getJavaMethodDescriptor() ?: return false
|
val methodDescriptor = method.getJavaMethodDescriptor()?.createDeepCopy() ?: return false
|
||||||
descriptorWrapper.originalJavaMethodDescriptor = KotlinChangeSignatureData(methodDescriptor, method, listOf(methodDescriptor))
|
descriptorWrapper.originalJavaMethodDescriptor = KotlinChangeSignatureData(methodDescriptor, method, listOf(methodDescriptor))
|
||||||
|
|
||||||
// This change info is used as a placeholder before primary method update
|
// This change info is used as a placeholder before primary method update
|
||||||
|
|||||||
+19
-4
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement
|
|||||||
import com.intellij.refactoring.changeSignature.CallerUsageInfo
|
import com.intellij.refactoring.changeSignature.CallerUsageInfo
|
||||||
import com.intellij.refactoring.changeSignature.OverriderUsageInfo
|
import com.intellij.refactoring.changeSignature.OverriderUsageInfo
|
||||||
import com.intellij.usageView.UsageInfo
|
import com.intellij.usageView.UsageInfo
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.DeferredJavaMethodKotlinCallerUsage
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.DeferredJavaMethodKotlinCallerUsage
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JavaMethodKotlinUsageWithDelegate
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JavaMethodKotlinUsageWithDelegate
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.KotlinCallableDefinitionUsage
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.KotlinCallableDefinitionUsage
|
||||||
@@ -27,10 +28,9 @@ import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.KotlinCaller
|
|||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
|
||||||
import org.jetbrains.kotlin.types.Variance
|
|
||||||
import org.jetbrains.kotlin.types.substitutions.getCallableSubstitutor
|
import org.jetbrains.kotlin.types.substitutions.getCallableSubstitutor
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||||
|
|
||||||
fun KtNamedDeclaration.getDeclarationBody(): KtElement? {
|
fun KtNamedDeclaration.getDeclarationBody(): KtElement? {
|
||||||
return when {
|
return when {
|
||||||
@@ -77,4 +77,19 @@ fun KotlinType.renderTypeWithSubstitution(substitutor: TypeSubstitutor?, default
|
|||||||
val newType = substitutor?.substitute(this, Variance.INVARIANT) ?: return defaultText
|
val newType = substitutor?.substitute(this, Variance.INVARIANT) ?: return defaultText
|
||||||
val renderer = if (inArgumentPosition) IdeDescriptorRenderers.SOURCE_CODE_FOR_TYPE_ARGUMENTS else IdeDescriptorRenderers.SOURCE_CODE
|
val renderer = if (inArgumentPosition) IdeDescriptorRenderers.SOURCE_CODE_FOR_TYPE_ARGUMENTS else IdeDescriptorRenderers.SOURCE_CODE
|
||||||
return renderer.renderType(newType)
|
return renderer.renderType(newType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This method is used to create full copies of functions (including copies of all types)
|
||||||
|
// It's needed to prevent accesses to PSI (e.g. using LazyJavaClassifierType properties) when Change signature invalidates it
|
||||||
|
// See KotlinChangeSignatureTest.testSAMChangeMethodReturnType
|
||||||
|
fun FunctionDescriptor.createDeepCopy() = substitute(TypeSubstitutor.create(ForceTypeCopySubstitution))
|
||||||
|
|
||||||
|
private object ForceTypeCopySubstitution : TypeSubstitution() {
|
||||||
|
override fun get(key: KotlinType) =
|
||||||
|
with(key) {
|
||||||
|
KotlinTypeImpl.create(
|
||||||
|
annotations, constructor, isMarkedNullable, arguments, substitution, memberScope, capabilities).asTypeProjection()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isEmpty() = false
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user