From a32f901ab93e89233b704a44bb2ef130e64bad49 Mon Sep 17 00:00:00 2001 From: Igor Yakovlev Date: Fri, 26 Jun 2020 22:27:57 +0300 Subject: [PATCH] Make property initializer modification is OutOfBlock change Fixed #KT-38762 --- ...tlinCodeBlockModificationListenerCompat.kt | 40 +++++++++---------- .../outOfBlock/InClassPropertyInitializer2.kt | 9 +++++ .../InPropertyWithFunctionLiteral.kt | 3 +- .../OutOfBlockModificationTestGenerated.java | 5 +++ 4 files changed, 34 insertions(+), 23 deletions(-) create mode 100644 idea/testData/codeInsight/outOfBlock/InClassPropertyInitializer2.kt diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/caches/trackers/KotlinCodeBlockModificationListenerCompat.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/caches/trackers/KotlinCodeBlockModificationListenerCompat.kt index cae3ce5b597..aacd0e69d70 100644 --- a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/caches/trackers/KotlinCodeBlockModificationListenerCompat.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/caches/trackers/KotlinCodeBlockModificationListenerCompat.kt @@ -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() } + + if (properExpression != null) { + val declaration = + KtPsiUtil.getTopmostParentOfTypes(blockDeclaration, KtClassOrObject::class.java) as? KtElement + + if (declaration != null) { + return BlockModificationScopeElement(declaration, properExpression) + } + } } } } diff --git a/idea/testData/codeInsight/outOfBlock/InClassPropertyInitializer2.kt b/idea/testData/codeInsight/outOfBlock/InClassPropertyInitializer2.kt new file mode 100644 index 00000000000..889a1b821ec --- /dev/null +++ b/idea/testData/codeInsight/outOfBlock/InClassPropertyInitializer2.kt @@ -0,0 +1,9 @@ +// OUT_OF_CODE_BLOCK: TRUE +// TYPE: 'A' +// SKIP_ANALYZE_CHECK + +class SomeClass(val paramA: Int) { + val someProperty: Int = param +} + +// TODO: it has to be non OCB ! \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/InPropertyWithFunctionLiteral.kt b/idea/testData/codeInsight/outOfBlock/InPropertyWithFunctionLiteral.kt index e37be40aa4f..5d41960afa6 100644 --- a/idea/testData/codeInsight/outOfBlock/InPropertyWithFunctionLiteral.kt +++ b/idea/testData/codeInsight/outOfBlock/InPropertyWithFunctionLiteral.kt @@ -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 = { pri } diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/OutOfBlockModificationTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/OutOfBlockModificationTestGenerated.java index cacbd20a4c1..5b7f50a2a89 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/OutOfBlockModificationTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/OutOfBlockModificationTestGenerated.java @@ -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");