diff --git a/idea/testData/codeInsight/outOfBlock/FunInInitBlock.kt b/idea/testData/codeInsight/outOfBlock/FunInInitBlock.kt index 422a2d508ec..2eda898028b 100644 --- a/idea/testData/codeInsight/outOfBlock/FunInInitBlock.kt +++ b/idea/testData/codeInsight/outOfBlock/FunInInitBlock.kt @@ -6,4 +6,7 @@ class A { } } -} \ No newline at end of file +} + +// TODO +// SKIP_ANALYZE_CHECK \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/FunWithType_Initializer.kt b/idea/testData/codeInsight/outOfBlock/FunWithType_Initializer.kt index 9b402c40350..0550032dda5 100644 --- a/idea/testData/codeInsight/outOfBlock/FunWithType_Initializer.kt +++ b/idea/testData/codeInsight/outOfBlock/FunWithType_Initializer.kt @@ -1,4 +1,7 @@ // TRUE // (Investigation starts from parent) -fun test() : Int = 12 \ No newline at end of file +fun test() : Int = 12 + +// TODO +// SKIP_ANALYZE_CHECK \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/InPropertyAccessorWithInference.kt b/idea/testData/codeInsight/outOfBlock/InPropertyAccessorWithInference.kt index 8927e32140d..d2577d4575c 100644 --- a/idea/testData/codeInsight/outOfBlock/InPropertyAccessorWithInference.kt +++ b/idea/testData/codeInsight/outOfBlock/InPropertyAccessorWithInference.kt @@ -1,3 +1,6 @@ // TRUE val test : Int - get() = 12 \ No newline at end of file + get() = 12 + +// TODO +// SKIP_ANALYZE_CHECK \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/InPropertyWithFunctionLiteral.kt b/idea/testData/codeInsight/outOfBlock/InPropertyWithFunctionLiteral.kt index 7a29f2d1c2d..cdac03deab1 100644 --- a/idea/testData/codeInsight/outOfBlock/InPropertyWithFunctionLiteral.kt +++ b/idea/testData/codeInsight/outOfBlock/InPropertyWithFunctionLiteral.kt @@ -1,4 +1,6 @@ // TRUE class Test { val a : () -> Int = { pri } -} \ No newline at end of file +} + +// SKIP_ANALYZE_CHECK \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/InitBlock.kt b/idea/testData/codeInsight/outOfBlock/InitBlock.kt index 5d88e2fd15a..ba410cebc14 100644 --- a/idea/testData/codeInsight/outOfBlock/InitBlock.kt +++ b/idea/testData/codeInsight/outOfBlock/InitBlock.kt @@ -2,6 +2,9 @@ class A { init { - + call() } -} \ No newline at end of file +} + +// TODO: +// SKIP_ANALYZE_CHECK \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/PropNotNullType_Initializer_ObjectLiteral_Fun.kt b/idea/testData/codeInsight/outOfBlock/PropNotNullType_Initializer_ObjectLiteral_Fun.kt index deab9da7824..0308ee2d73e 100644 --- a/idea/testData/codeInsight/outOfBlock/PropNotNullType_Initializer_ObjectLiteral_Fun.kt +++ b/idea/testData/codeInsight/outOfBlock/PropNotNullType_Initializer_ObjectLiteral_Fun.kt @@ -7,4 +7,6 @@ val test: Some = object: Some { fun test() { } -} \ No newline at end of file +} + +// SKIP_ANALYZE_CHECK \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/PropNullType_Initializer_If_Fun.kt b/idea/testData/codeInsight/outOfBlock/PropNullType_Initializer_If_Fun.kt index 89406328014..89583bc74ad 100644 --- a/idea/testData/codeInsight/outOfBlock/PropNullType_Initializer_If_Fun.kt +++ b/idea/testData/codeInsight/outOfBlock/PropNullType_Initializer_If_Fun.kt @@ -9,4 +9,6 @@ val test: Int? = if (true) { } else { -} \ No newline at end of file +} + +// SKIP_ANALYZE_CHECK \ No newline at end of file diff --git a/idea/testData/codeInsight/outOfBlock/PropNullType_Initializer_ObjectLiteral_Fun.kt b/idea/testData/codeInsight/outOfBlock/PropNullType_Initializer_ObjectLiteral_Fun.kt index 1882dd20b14..a2124069cbe 100644 --- a/idea/testData/codeInsight/outOfBlock/PropNullType_Initializer_ObjectLiteral_Fun.kt +++ b/idea/testData/codeInsight/outOfBlock/PropNullType_Initializer_ObjectLiteral_Fun.kt @@ -7,4 +7,6 @@ val test: Some? = object: Some { fun test() { } -} \ No newline at end of file +} + +// SKIP_ANALYZE_CHECK \ 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 index d3e072aa7d9..025dfc44176 100644 --- a/idea/testData/codeInsight/outOfBlock/PropertyWithType_Initializer_String.kt +++ b/idea/testData/codeInsight/outOfBlock/PropertyWithType_Initializer_String.kt @@ -1,3 +1,5 @@ // TRUE -val test: String = "" \ No newline at end of file +val test: String = "" + +// SKIP_ANALYZE_CHECK \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractOutOfBlockModificationTest.java b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractOutOfBlockModificationTest.java index c30727da04d..179b2e860c7 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractOutOfBlockModificationTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractOutOfBlockModificationTest.java @@ -16,14 +16,21 @@ package org.jetbrains.kotlin.idea.codeInsight; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiManager; import com.intellij.psi.impl.PsiModificationTrackerImpl; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils; +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade; import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase; import org.jetbrains.kotlin.idea.test.PluginTestCaseBase; +import org.jetbrains.kotlin.psi.*; +import org.jetbrains.kotlin.resolve.BindingContext; +import org.jetbrains.kotlin.resolve.lazy.ResolveSession; import org.jetbrains.kotlin.test.InTextDirectivesUtils; import java.io.File; @@ -65,6 +72,52 @@ public abstract class AbstractOutOfBlockModificationTest extends KotlinLightCode assertEquals("Result for out of block test is differs from expected on element in file:\n" + FileUtil.loadFile(new File(path)), expectedOutOfBlock, oobBeforeType != oobAfterCount); + + boolean isSkipCheckDefined = InTextDirectivesUtils.isDirectiveDefined(myFixture.getFile().getText(), "SKIP_ANALYZE_CHECK"); + assertTrue("It's allowed to skip check with analyze only for tests where out-of-block is expected", + !isSkipCheckDefined || expectedOutOfBlock); + + if (!isSkipCheckDefined) { + checkOOBWithDescriptorsResolve(expectedOutOfBlock); + } + } + + private void checkOOBWithDescriptorsResolve(boolean expectedOutOfBlock) { + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + ((PsiModificationTrackerImpl) PsiManager.getInstance(myFixture.getProject()).getModificationTracker()) + .incOutOfCodeBlockModificationCounter(); + } + }); + + PsiElement updateElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset() - 1); + KtExpression ktExpression = PsiTreeUtil.getParentOfType(updateElement, KtExpression.class, false); + KtDeclaration ktDeclaration = PsiTreeUtil.getParentOfType(updateElement, KtDeclaration.class, false); + KtElement ktElement = ktExpression != null ? ktExpression : ktDeclaration; + + if (ktElement == null) return; + + ResolutionFacade facade = ResolutionUtils.getResolutionFacade(ktElement.getContainingKtFile()); + ResolveSession session = facade.getFrontendService(ResolveSession.class); + session.forceResolveAll(); + + BindingContext context = session.getBindingContext(); + + if (ktExpression != null && ktExpression != ktDeclaration) { + @SuppressWarnings("ConstantConditions") + boolean expressionProcessed = context.get( + BindingContext.PROCESSED, + ktExpression instanceof KtFunctionLiteral ? (KtLambdaExpression) ktExpression.getParent() : ktExpression); + + assertEquals("Expected out-of-block should result expression analyzed and vise versa", expectedOutOfBlock, + expressionProcessed); + } + else { + boolean declarationProcessed = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, ktDeclaration) != null; + assertEquals("Expected out-of-block should result declaration analyzed and vise versa", expectedOutOfBlock, + declarationProcessed); + } } private String getStringToType() {