Make property initializer modification is OutOfBlock change

Fixed #KT-38762
This commit is contained in:
Igor Yakovlev
2020-06-26 22:27:57 +03:00
parent 507a718632
commit a32f901ab9
4 changed files with 34 additions and 23 deletions
@@ -29,6 +29,7 @@ import com.intellij.psi.util.PsiModificationTracker
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.kdoc.psi.api.KDoc
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
import org.jetbrains.kotlin.psi.psiUtil.getTopmostParentOfType
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
@@ -220,32 +221,27 @@ abstract class KotlinCodeBlockModificationListenerCompat(protected val project:
// return BlockModificationScopeElement(it, it)
// }
// }
if (blockDeclaration.typeReference != null) {
val accessors =
blockDeclaration.accessors.map { it.initializer ?: it.bodyExpression }
val accessorList = if (blockDeclaration.initializer.isAncestor(element) &&
// call expression changes in property initializer are OCB, see KT-38443
KtPsiUtil.getTopmostParentOfTypes(element, KtCallExpression::class.java) == null
) {
accessors + blockDeclaration.initializer
} else {
accessors
}
// adding annotations to accessor is the same as change contract of property
if (element !is KtAnnotated || element.annotationEntries.isEmpty()) {
for (accessor in accessorList) {
accessor?.takeIf {
it.isAncestor(element) &&
// adding annotations to accessor is the same as change contract of property
(element !is KtAnnotated || element.annotationEntries.isEmpty())
}
?.let { expression ->
val declaration =
KtPsiUtil.getTopmostParentOfTypes(blockDeclaration, KtClassOrObject::class.java) as? KtElement ?:
// ktFile to check top level property declarations
return null
return BlockModificationScopeElement(declaration, expression)
val properExpression = blockDeclaration.accessors
.firstOrNull { (it.initializer ?: it.bodyExpression).isAncestor(element) }
?: blockDeclaration.initializer?.takeIf {
// name references changes in property initializer are OCB, see KT-38443, KT-38762
it.isAncestor(element) && !it.anyDescendantOfType<KtNameReferenceExpression>()
}
if (properExpression != null) {
val declaration =
KtPsiUtil.getTopmostParentOfTypes(blockDeclaration, KtClassOrObject::class.java) as? KtElement
if (declaration != null) {
return BlockModificationScopeElement(declaration, properExpression)
}
}
}
}
}
@@ -0,0 +1,9 @@
// OUT_OF_CODE_BLOCK: TRUE
// TYPE: 'A'
// SKIP_ANALYZE_CHECK
class SomeClass(val paramA: Int) {
val someProperty: Int = param<caret>
}
// TODO: it has to be non OCB !
@@ -1,5 +1,6 @@
// OUT_OF_CODE_BLOCK: FALSE
// OUT_OF_CODE_BLOCK: TRUE
// ERROR: Unresolved reference: apri
// SKIP_ANALYZE_CHECK
class Test {
val a : () -> Int = { <caret>pri }
@@ -118,6 +118,11 @@ public class OutOfBlockModificationTestGenerated extends AbstractOutOfBlockModif
runTest("idea/testData/codeInsight/outOfBlock/InClassPropertyInitializer.kt");
}
@TestMetadata("InClassPropertyInitializer2.kt")
public void testInClassPropertyInitializer2() throws Exception {
runTest("idea/testData/codeInsight/outOfBlock/InClassPropertyInitializer2.kt");
}
@TestMetadata("InClassPropertyInitializerWithoutInference.kt")
public void testInClassPropertyInitializerWithoutInference() throws Exception {
runTest("idea/testData/codeInsight/outOfBlock/InClassPropertyInitializerWithoutInference.kt");