Fix change signature refactoring

Do not increase modification count for OutOfCodeBlockTracker when KtTypeCodeFragment is modified

KtTypeCodeFragment is used in UI for providing completion for types.
When OutOfCodeBlockModification happens it invalidates ModuleDescriptors
But change signature relies on them which causes InvalidModuleException

#KT-35903 fixed
#KT-35689 fixed
#KT-34415 fixed
#KT-34415 fixed
This commit is contained in:
Ilya Kirillov
2020-01-27 18:50:20 +03:00
parent ed5156ee83
commit 7a52cf103a
2 changed files with 14 additions and 5 deletions
@@ -103,7 +103,7 @@ class KotlinCodeBlockModificationListener(
if (inBlockElements.isEmpty()) {
messageBusConnection.deliverImmediately()
if (physical && !isReplLine(ktFile.virtualFile)) {
if (physical && !isReplLine(ktFile.virtualFile) && ktFile !is KtTypeCodeFragment) {
if (isLanguageTrackerEnabled) {
kotlinOutOfCodeBlockTrackerImpl.incModificationCount()
perModuleOutOfCodeBlockTrackerUpdater.onKotlinPhysicalFileOutOfBlockChange(ktFile, true)
@@ -332,7 +332,7 @@ class KotlinChangeSignatureDialog(
override fun validateAndCommitData(): String? {
if (myMethod.canChangeReturnType() == MethodDescriptor.ReadWriteOption.ReadWrite &&
myReturnTypeCodeFragment.getTypeInfo(isCovariant = true, forPreview = false).type == null
myReturnTypeCodeFragment.getTypeInfo(isCovariant = true, forPreview = false, reanalyse = true).type == null
) {
if (Messages.showOkCancelDialog(
myProject,
@@ -346,7 +346,7 @@ class KotlinChangeSignatureDialog(
}
for (item in parametersTableModel.items) {
if (item.typeCodeFragment.getTypeInfo(isCovariant = true, forPreview = false).type == null) {
if (item.typeCodeFragment.getTypeInfo(isCovariant = true, forPreview = false, reanalyse = true).type == null) {
val paramText = if (item.parameter != parametersTableModel.receiver) "parameter '${item.parameter.name}'" else "receiver"
if (Messages.showOkCancelDialog(
myProject,
@@ -455,10 +455,19 @@ class KotlinChangeSignatureDialog(
return KotlinChangeSignatureProcessor(project, changeInfo, commandName)
}
fun PsiCodeFragment?.getTypeInfo(isCovariant: Boolean, forPreview: Boolean): KotlinTypeInfo {
private fun KtTypeCodeFragment.createCopy() =
KtPsiFactory(this).createTypeCodeFragment(text, this)
fun PsiCodeFragment?.getTypeInfo(isCovariant: Boolean, forPreview: Boolean, reanalyse: Boolean = false): KotlinTypeInfo {
if (this !is KtTypeCodeFragment) return KotlinTypeInfo(isCovariant)
val typeRef = getContentElement()
/*
As we do not update our caches on every KtTypeCodeFragment change
Caches are old and we cannot resolve type for old KtTypeCodeFragment
*/
val codeFragment = if (reanalyse) createCopy() else this
val typeRef = codeFragment.getContentElement()
val type = typeRef?.analyze(BodyResolveMode.PARTIAL)?.get(BindingContext.TYPE, typeRef)
return when {
type != null && !type.isError -> KotlinTypeInfo(isCovariant, type, if (forPreview) typeRef.text else null)