diff --git a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinCodeBlockModificationListener.kt b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinCodeBlockModificationListener.kt index b7e64b85f2d..fcaf8499b79 100644 --- a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinCodeBlockModificationListener.kt +++ b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinCodeBlockModificationListener.kt @@ -107,81 +107,41 @@ public class KotlinCodeBlockModificationListener(modificationTracker: PsiModific if (element is PsiFileSystemItem) return false if (element == null || element.getParent() == null) return true - var parent = element - while (parent !is PsiFile && parent !is PsiDirectory && parent != null) { - if (parent is JetClass) return false // anonymous or local class + val blockDeclarationCandidate = JetPsiUtil.getTopmostParentOfTypes( + element, + javaClass(), + javaClass()) - if (parent is JetBlockExpression) { - if (!shouldChangeModificationCount(element)) { - return true; - } - } - - parent = parent!!.getParent() - } - - return false - } - - public fun shouldChangeModificationCount(place: PsiElement): Boolean { - // false -> inside code block - // true -> means nothing, parent will be checked - - val declaration = PsiTreeUtil.getParentOfType(place, javaClass(), true) - if (declaration == null) return true - - return when (declaration) { + when (blockDeclarationCandidate) { is JetNamedFunction -> { - val function: JetNamedFunction = declaration - if (function.hasDeclaredReturnType() || function.hasBlockBody()) { - takePartInDeclarationTypeInference(function) + val function = blockDeclarationCandidate : JetNamedFunction + if (function.hasBlockBody() && function.getBodyExpression().isAncestorOf(element)) { + return true } - else { - shouldChangeModificationCount(function) + + if (function.hasDeclaredReturnType() && function.getInitializer().isAncestorOf(element)) { + return true } } - is JetPropertyAccessor -> { - takePartInDeclarationTypeInference(declaration) - } is JetProperty -> { - val property = declaration as JetProperty - if (property.getTypeReference() != null) { - takePartInDeclarationTypeInference(property) - } - else { - shouldChangeModificationCount(property) - } - } - is JetMultiDeclaration, is JetMultiDeclarationEntry, is JetFunctionLiteral -> { - shouldChangeModificationCount(declaration) - } - else -> { - true - } - } - } - - private fun takePartInDeclarationTypeInference(place: PsiElement): Boolean { - val declaration = PsiTreeUtil.getParentOfType(place, javaClass(), true) - if (declaration != null) { - if (declaration is JetNamedFunction) { - val function = declaration as JetNamedFunction - if (!function.hasDeclaredReturnType() && !function.hasBlockBody()) { + val property = blockDeclarationCandidate : JetProperty + val typeReference = property.getTypeReference() + if (typeReference != null && property.getInitializer().isAncestorOf(element)) { return true } - } - else if (declaration is JetProperty) { - val property = declaration as JetProperty - if (property.getTypeReference() == null) { - return true + + for (accessor in property.getAccessors()) { + when { + accessor.getInitializer().isAncestorOf(element) -> return true + accessor.getBodyExpression().isAncestorOf(element) -> return true + } } } - - return takePartInDeclarationTypeInference(declaration) } return false } + + private fun PsiElement?.isAncestorOf(element: PsiElement) = PsiTreeUtil.isAncestor(this, element, false) } } - diff --git a/idea/testData/codeInsight/outOfBlock/Class_Class_FunNoType_Block.kt b/idea/testData/codeInsight/outOfBlock/Class_Class_FunNoType_Block.kt new file mode 100644 index 00000000000..b9848899881 --- /dev/null +++ b/idea/testData/codeInsight/outOfBlock/Class_Class_FunNoType_Block.kt @@ -0,0 +1,9 @@ +// FALSE + +class Test { + class Other { + fun test() { + + } + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/Class_Class_FunNoType_Block_Expression.kt b/idea/testData/codeInsight/outOfBlock/Class_Class_FunNoType_Block_Expression.kt new file mode 100644 index 00000000000..14b4dbed0b5 --- /dev/null +++ b/idea/testData/codeInsight/outOfBlock/Class_Class_FunNoType_Block_Expression.kt @@ -0,0 +1,9 @@ +// FALSE + +class Test { + class Other { + fun test() { + val a + } + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/FunNoType_Block_Class.kt b/idea/testData/codeInsight/outOfBlock/FunNoType_Block_Class.kt new file mode 100644 index 00000000000..993740c1f3a --- /dev/null +++ b/idea/testData/codeInsight/outOfBlock/FunNoType_Block_Class.kt @@ -0,0 +1,6 @@ +// FALSE +fun test() { + class Test { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/FunWithType_Initializer.kt b/idea/testData/codeInsight/outOfBlock/FunWithType_Initializer.kt new file mode 100644 index 00000000000..9b402c40350 --- /dev/null +++ b/idea/testData/codeInsight/outOfBlock/FunWithType_Initializer.kt @@ -0,0 +1,4 @@ +// TRUE +// (Investigation starts from parent) + +fun test() : Int = 12 \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/FunWithType_Initializer_Expression.kt b/idea/testData/codeInsight/outOfBlock/FunWithType_Initializer_Expression.kt new file mode 100644 index 00000000000..5b46c5502b3 --- /dev/null +++ b/idea/testData/codeInsight/outOfBlock/FunWithType_Initializer_Expression.kt @@ -0,0 +1,3 @@ +// FALSE + +fun test() : Int = 12 + 12 \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/InClassInClass.kt b/idea/testData/codeInsight/outOfBlock/InClassInClass.kt new file mode 100644 index 00000000000..8365185537f --- /dev/null +++ b/idea/testData/codeInsight/outOfBlock/InClassInClass.kt @@ -0,0 +1,6 @@ +// TRUE +class Test { + class Other { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/InFunInFunctionInitializerInFun.kt b/idea/testData/codeInsight/outOfBlock/InFunInFunctionInitializerInFun.kt new file mode 100644 index 00000000000..9e48681bfc9 --- /dev/null +++ b/idea/testData/codeInsight/outOfBlock/InFunInFunctionInitializerInFun.kt @@ -0,0 +1,11 @@ +// TRUE + +val a = 1 +fun test() = if (a) { + fun hello() { + + } +} +else { + +} \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/InFunInProperty.kt b/idea/testData/codeInsight/outOfBlock/InFunInProperty.kt new file mode 100644 index 00000000000..bd55a45a5d5 --- /dev/null +++ b/idea/testData/codeInsight/outOfBlock/InFunInProperty.kt @@ -0,0 +1,11 @@ +// FALSE +fun test() { + val some = if () { + fun other() { + + } + } + else { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/InFunInPropertyInObjectLiteral.kt b/idea/testData/codeInsight/outOfBlock/InFunInPropertyInObjectLiteral.kt new file mode 100644 index 00000000000..b64af660cd3 --- /dev/null +++ b/idea/testData/codeInsight/outOfBlock/InFunInPropertyInObjectLiteral.kt @@ -0,0 +1,8 @@ +// FALSE +trait Some + +fun test() { + val foo = object: Some { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/InFunObjectLiteral.kt b/idea/testData/codeInsight/outOfBlock/InFunObjectLiteral.kt new file mode 100644 index 00000000000..82d8c9c12e4 --- /dev/null +++ b/idea/testData/codeInsight/outOfBlock/InFunObjectLiteral.kt @@ -0,0 +1,10 @@ +// FALSE +trait Some + +fun test() { + object : Some { + fun test() { + + } + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/Object_FunNoType_Block.kt b/idea/testData/codeInsight/outOfBlock/Object_FunNoType_Block.kt new file mode 100644 index 00000000000..5a72266cb3c --- /dev/null +++ b/idea/testData/codeInsight/outOfBlock/Object_FunNoType_Block.kt @@ -0,0 +1,6 @@ +// FALSE +object Some { + fun test() { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/Object_FunNoType_Block_Expression.kt b/idea/testData/codeInsight/outOfBlock/Object_FunNoType_Block_Expression.kt new file mode 100644 index 00000000000..af583024d26 --- /dev/null +++ b/idea/testData/codeInsight/outOfBlock/Object_FunNoType_Block_Expression.kt @@ -0,0 +1,7 @@ +// FALSE + +object Some { + fun test() { + if () + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/PropertyNoType_Initializer_String.kt b/idea/testData/codeInsight/outOfBlock/PropertyNoType_Initializer_String.kt new file mode 100644 index 00000000000..aa541ff3b65 --- /dev/null +++ b/idea/testData/codeInsight/outOfBlock/PropertyNoType_Initializer_String.kt @@ -0,0 +1,5 @@ +// TRUE + +// TODO: Investigate + +val test = "some" \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/PropertyWithType_Initializer_String.kt b/idea/testData/codeInsight/outOfBlock/PropertyWithType_Initializer_String.kt new file mode 100644 index 00000000000..259979a5210 --- /dev/null +++ b/idea/testData/codeInsight/outOfBlock/PropertyWithType_Initializer_String.kt @@ -0,0 +1,3 @@ +// FALSE + +val test: String = "" \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/codeInsight/OutOfBlockModificationTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/codeInsight/OutOfBlockModificationTestGenerated.java index e6ab99dd954..0c65ab5d331 100644 --- a/idea/tests/org/jetbrains/jet/plugin/codeInsight/OutOfBlockModificationTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/codeInsight/OutOfBlockModificationTestGenerated.java @@ -36,6 +36,18 @@ public class OutOfBlockModificationTestGenerated extends AbstractOutOfBlockModif JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/codeInsight/outOfBlock"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("Class_Class_FunNoType_Block.kt") + public void testClass_Class_FunNoType_Block() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/Class_Class_FunNoType_Block.kt"); + doTest(fileName); + } + + @TestMetadata("Class_Class_FunNoType_Block_Expression.kt") + public void testClass_Class_FunNoType_Block_Expression() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/Class_Class_FunNoType_Block_Expression.kt"); + doTest(fileName); + } + @TestMetadata("FunInFun.kt") public void testFunInFun() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/FunInFun.kt"); @@ -48,6 +60,24 @@ public class OutOfBlockModificationTestGenerated extends AbstractOutOfBlockModif doTest(fileName); } + @TestMetadata("FunNoType_Block_Class.kt") + public void testFunNoType_Block_Class() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/FunNoType_Block_Class.kt"); + doTest(fileName); + } + + @TestMetadata("FunWithType_Initializer.kt") + public void testFunWithType_Initializer() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/FunWithType_Initializer.kt"); + doTest(fileName); + } + + @TestMetadata("FunWithType_Initializer_Expression.kt") + public void testFunWithType_Initializer_Expression() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/FunWithType_Initializer_Expression.kt"); + doTest(fileName); + } + @TestMetadata("InAntonymsObjectDeclaration.kt") public void testInAntonymsObjectDeclaration() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/InAntonymsObjectDeclaration.kt"); @@ -60,6 +90,12 @@ public class OutOfBlockModificationTestGenerated extends AbstractOutOfBlockModif doTest(fileName); } + @TestMetadata("InClassInClass.kt") + public void testInClassInClass() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/InClassInClass.kt"); + doTest(fileName); + } + @TestMetadata("InClassPropertyAccessor.kt") public void testInClassPropertyAccessor() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/InClassPropertyAccessor.kt"); @@ -72,12 +108,36 @@ public class OutOfBlockModificationTestGenerated extends AbstractOutOfBlockModif doTest(fileName); } + @TestMetadata("InFunInFunctionInitializerInFun.kt") + public void testInFunInFunctionInitializerInFun() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/InFunInFunctionInitializerInFun.kt"); + doTest(fileName); + } + @TestMetadata("InFunInMultiDeclaration.kt") public void testInFunInMultiDeclaration() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/InFunInMultiDeclaration.kt"); doTest(fileName); } + @TestMetadata("InFunInProperty.kt") + public void testInFunInProperty() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/InFunInProperty.kt"); + doTest(fileName); + } + + @TestMetadata("InFunInPropertyInObjectLiteral.kt") + public void testInFunInPropertyInObjectLiteral() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/InFunInPropertyInObjectLiteral.kt"); + doTest(fileName); + } + + @TestMetadata("InFunObjectLiteral.kt") + public void testInFunObjectLiteral() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/InFunObjectLiteral.kt"); + doTest(fileName); + } + @TestMetadata("InFunWithInference.kt") public void testInFunWithInference() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/InFunWithInference.kt"); @@ -119,4 +179,28 @@ public class OutOfBlockModificationTestGenerated extends AbstractOutOfBlockModif String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/InPropertyWithInference.kt"); doTest(fileName); } + + @TestMetadata("Object_FunNoType_Block.kt") + public void testObject_FunNoType_Block() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/Object_FunNoType_Block.kt"); + doTest(fileName); + } + + @TestMetadata("Object_FunNoType_Block_Expression.kt") + public void testObject_FunNoType_Block_Expression() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/Object_FunNoType_Block_Expression.kt"); + doTest(fileName); + } + + @TestMetadata("PropertyNoType_Initializer_String.kt") + public void testPropertyNoType_Initializer_String() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/PropertyNoType_Initializer_String.kt"); + doTest(fileName); + } + + @TestMetadata("PropertyWithType_Initializer_String.kt") + public void testPropertyWithType_Initializer_String() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/outOfBlock/PropertyWithType_Initializer_String.kt"); + doTest(fileName); + } }