From 02976cde0189f6ffbd51527bd7014d05cae80b42 Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Wed, 22 Apr 2020 21:41:38 +0200 Subject: [PATCH] Call expression changes in property initializer are OCB #KT-38443 Fixed Original commit: 1565fc0211dd0d970837afd1e4f7a7b2b1d371d5 GitOrigin-RevId: 92df0d83a4045b5d4eb45983c3f705adbdfe2155 --- ...tlinCodeBlockModificationListenerCompat.kt | 22 ++++++++++++++----- .../OutOfBlockModificationTestGenerated.java | 15 +++++++++++++ .../outOfBlock/InClassPropertyInitializer.kt | 10 +++++++++ ...lassPropertyInitializerWithoutInference.kt | 11 ++++++++++ ...assPropertyInitializerWithoutInference2.kt | 11 ++++++++++ 5 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 plugins/kotlin/idea/tests/testData/codeInsight/outOfBlock/InClassPropertyInitializer.kt create mode 100644 plugins/kotlin/idea/tests/testData/codeInsight/outOfBlock/InClassPropertyInitializerWithoutInference.kt create mode 100644 plugins/kotlin/idea/tests/testData/codeInsight/outOfBlock/InClassPropertyInitializerWithoutInference2.kt diff --git a/plugins/kotlin/analysis/src/org/jetbrains/kotlin/idea/caches/trackers/KotlinCodeBlockModificationListenerCompat.kt b/plugins/kotlin/analysis/src/org/jetbrains/kotlin/idea/caches/trackers/KotlinCodeBlockModificationListenerCompat.kt index 2270ecdb94f6..ba329487f660 100644 --- a/plugins/kotlin/analysis/src/org/jetbrains/kotlin/idea/caches/trackers/KotlinCodeBlockModificationListenerCompat.kt +++ b/plugins/kotlin/analysis/src/org/jetbrains/kotlin/idea/caches/trackers/KotlinCodeBlockModificationListenerCompat.kt @@ -222,13 +222,23 @@ abstract class KotlinCodeBlockModificationListenerCompat(protected val project: // } if (blockDeclaration.typeReference != null) { val accessors = - blockDeclaration.accessors.map { it.initializer ?: it.bodyExpression } + blockDeclaration.initializer - for (accessor in 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 + } + + 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()) - } + 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 ?: diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/codeInsight/OutOfBlockModificationTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/codeInsight/OutOfBlockModificationTestGenerated.java index 5e20aca1e735..cacbd20a4c16 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/codeInsight/OutOfBlockModificationTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/codeInsight/OutOfBlockModificationTestGenerated.java @@ -113,6 +113,21 @@ public class OutOfBlockModificationTestGenerated extends AbstractOutOfBlockModif runTest("idea/testData/codeInsight/outOfBlock/InClassPropertyAccessor.kt"); } + @TestMetadata("InClassPropertyInitializer.kt") + public void testInClassPropertyInitializer() throws Exception { + runTest("idea/testData/codeInsight/outOfBlock/InClassPropertyInitializer.kt"); + } + + @TestMetadata("InClassPropertyInitializerWithoutInference.kt") + public void testInClassPropertyInitializerWithoutInference() throws Exception { + runTest("idea/testData/codeInsight/outOfBlock/InClassPropertyInitializerWithoutInference.kt"); + } + + @TestMetadata("InClassPropertyInitializerWithoutInference2.kt") + public void testInClassPropertyInitializerWithoutInference2() throws Exception { + runTest("idea/testData/codeInsight/outOfBlock/InClassPropertyInitializerWithoutInference2.kt"); + } + @TestMetadata("InComment.kt") public void testInComment() throws Exception { runTest("idea/testData/codeInsight/outOfBlock/InComment.kt"); diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/outOfBlock/InClassPropertyInitializer.kt b/plugins/kotlin/idea/tests/testData/codeInsight/outOfBlock/InClassPropertyInitializer.kt new file mode 100644 index 000000000000..9f3d14731c65 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/codeInsight/outOfBlock/InClassPropertyInitializer.kt @@ -0,0 +1,10 @@ +// OUT_OF_CODE_BLOCK: TRUE +// ERROR: No value passed for parameter 'i2' +// TYPE: '\b\b' +class Test { + val foo = bar(1, 2) + + fun bar(i: Int, i2: Int) = "" +} + +// TODO: it has to be non OCB ! \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/outOfBlock/InClassPropertyInitializerWithoutInference.kt b/plugins/kotlin/idea/tests/testData/codeInsight/outOfBlock/InClassPropertyInitializerWithoutInference.kt new file mode 100644 index 000000000000..5f30432ccadd --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/codeInsight/outOfBlock/InClassPropertyInitializerWithoutInference.kt @@ -0,0 +1,11 @@ +// TODO: it has to be non OCB ! +// OUT_OF_CODE_BLOCK: TRUE +// ERROR: No value passed for parameter 'i2' +// TYPE: '\b\b' +class Test { + val foo: String? = "a" + bar(1, 2) + + fun bar(i: Int, i2: Int) = "" +} + +// SKIP_ANALYZE_CHECK diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/outOfBlock/InClassPropertyInitializerWithoutInference2.kt b/plugins/kotlin/idea/tests/testData/codeInsight/outOfBlock/InClassPropertyInitializerWithoutInference2.kt new file mode 100644 index 000000000000..c43483ecfca1 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/codeInsight/outOfBlock/InClassPropertyInitializerWithoutInference2.kt @@ -0,0 +1,11 @@ +// TODO: it has to be non OCB ! +// OUT_OF_CODE_BLOCK: TRUE +// ERROR: The integer literal does not conform to the expected type String? +// TYPE: '\b\b\b\b' +class Test { + val foo: String? = "a"+1 + + fun bar(i: Int, i2: Int) = "" +} + +// SKIP_ANALYZE_CHECK