Kotlinify AbstractOutOfBlockModificationTest, p2

This commit is contained in:
Vladimir Dolzhenko
2019-11-27 11:51:26 +01:00
parent 8f8ed4dbcf
commit 144f721a44
@@ -3,121 +3,122 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.codeInsight;
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.caches.trackers.KotlinCodeBlockModificationListenerKt;
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade;
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase;
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.IOException;
public abstract class AbstractOutOfBlockModificationTest extends KotlinLightCodeInsightFixtureTestCase {
public static final String OUT_OF_CODE_BLOCK_DIRECTIVE = "OUT_OF_CODE_BLOCK:";
public static final String SKIP_ANALYZE_CHECK_DIRECTIVE = "SKIP_ANALYZE_CHECK";
public static final String TYPE_DIRECTIVE = "TYPE:";
protected void doTest(String unused) throws IOException {
myFixture.configureByFile(fileName());
boolean expectedOutOfBlock = getExpectedOutOfBlockResult();
boolean isSkipCheckDefined = InTextDirectivesUtils.isDirectiveDefined(myFixture.getFile().getText(), SKIP_ANALYZE_CHECK_DIRECTIVE);
assertTrue("It's allowed to skip check with analyze only for tests where out-of-block is expected",
!isSkipCheckDefined || expectedOutOfBlock);
PsiModificationTrackerImpl tracker =
(PsiModificationTrackerImpl) PsiManager.getInstance(myFixture.getProject()).getModificationTracker();
PsiElement element = myFixture.getFile().findElementAt(myFixture.getCaretOffset());
assertNotNull("Should be valid element", element);
KtFile file = (KtFile) getFile();
long oobBeforeType = KotlinCodeBlockModificationListenerKt.getOutOfBlockModificationCount(file);
long modificationCountBeforeType = tracker.getModificationCount();
myFixture.type(getStringToType());
PsiDocumentManager.getInstance(myFixture.getProject()).commitDocument(myFixture.getDocument(myFixture.getFile()));
long oobAfterCount = KotlinCodeBlockModificationListenerKt.getOutOfBlockModificationCount(file);
long modificationCountAfterType = tracker.getModificationCount();
assertTrue("Modification tracker should always be changed after type", modificationCountBeforeType != modificationCountAfterType);
assertEquals("Result for out of block test is differs from expected on element in file:\n"
+ FileUtil.loadFile(testDataFile()),
expectedOutOfBlock, oobBeforeType != oobAfterCount);
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.PsiManager
import com.intellij.psi.impl.PsiModificationTrackerImpl
import com.intellij.psi.util.PsiTreeUtil
import junit.framework.TestCase
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.caches.trackers.outOfBlockModificationCount
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.test.InTextDirectivesUtils
abstract class AbstractOutOfBlockModificationTest : KotlinLightCodeInsightFixtureTestCase() {
protected fun doTest(unused: String?) {
val ktFile = myFixture.configureByFile(fileName()) as KtFile
val expectedOutOfBlock = expectedOutOfBlockResult
val isSkipCheckDefined = InTextDirectivesUtils.isDirectiveDefined(
ktFile.text,
SKIP_ANALYZE_CHECK_DIRECTIVE
)
TestCase.assertTrue(
"It's allowed to skip check with analyze only for tests where out-of-block is expected",
!isSkipCheckDefined || expectedOutOfBlock
)
val tracker =
PsiManager.getInstance(myFixture.project).modificationTracker as PsiModificationTrackerImpl
val element = ktFile.findElementAt(myFixture.caretOffset)
TestCase.assertNotNull("Should be valid element", element)
val oobBeforeType = ktFile.outOfBlockModificationCount
val modificationCountBeforeType = tracker.modificationCount
myFixture.type(stringToType)
PsiDocumentManager.getInstance(myFixture.project).commitDocument(myFixture.getDocument(myFixture.file))
val oobAfterCount = ktFile.outOfBlockModificationCount
val modificationCountAfterType = tracker.modificationCount
TestCase.assertTrue(
"Modification tracker should always be changed after type",
modificationCountBeforeType != modificationCountAfterType
)
TestCase.assertEquals(
"Result for out of block test is differs from expected on element in file:\n"
+ FileUtil.loadFile(testDataFile()),
expectedOutOfBlock, oobBeforeType != oobAfterCount
)
if (!isSkipCheckDefined) {
checkOOBWithDescriptorsResolve(expectedOutOfBlock);
checkOOBWithDescriptorsResolve(expectedOutOfBlock)
}
}
private void checkOOBWithDescriptorsResolve(boolean expectedOutOfBlock) {
ApplicationManager.getApplication().runReadAction(
() -> ((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) == Boolean.TRUE;
assertEquals("Expected out-of-block should result expression analyzed and vise versa", expectedOutOfBlock,
expressionProcessed);
private fun checkOOBWithDescriptorsResolve(expectedOutOfBlock: Boolean) {
ApplicationManager.getApplication().runReadAction {
(PsiManager.getInstance(myFixture.project).modificationTracker as PsiModificationTrackerImpl)
.incOutOfCodeBlockModificationCounter()
}
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);
val updateElement = myFixture.file.findElementAt(myFixture.caretOffset - 1)
val ktExpression: KtExpression? = PsiTreeUtil.getParentOfType(updateElement, KtExpression::class.java, false)
val ktDeclaration: KtDeclaration? = PsiTreeUtil.getParentOfType(updateElement, KtDeclaration::class.java, false)
val ktElement = ktExpression ?: ktDeclaration ?: return
val facade = ktElement.containingKtFile.getResolutionFacade()
val session = facade.getFrontendService(ResolveSession::class.java)
session.forceResolveAll()
val context = session.bindingContext
if (ktExpression != null && ktExpression !== ktDeclaration) {
val expressionProcessed = context.get(
BindingContext.PROCESSED,
if (ktExpression is KtFunctionLiteral) ktExpression.getParent() as KtLambdaExpression else ktExpression
) === java.lang.Boolean.TRUE
TestCase.assertEquals(
"Expected out-of-block should result expression analyzed and vise versa", expectedOutOfBlock,
expressionProcessed
)
} else {
val declarationProcessed =
context.get(
BindingContext.DECLARATION_TO_DESCRIPTOR,
ktDeclaration
) != null
TestCase.assertEquals(
"Expected out-of-block should result declaration analyzed and vise versa", expectedOutOfBlock,
declarationProcessed
)
}
}
private String getStringToType() {
String text = myFixture.getDocument(myFixture.getFile()).getText();
String typeDirectives = InTextDirectivesUtils.findStringWithPrefixes(text, TYPE_DIRECTIVE);
private val stringToType: String
get() {
val text = myFixture.getDocument(myFixture.file).text
val typeDirectives =
InTextDirectivesUtils.findStringWithPrefixes(text, TYPE_DIRECTIVE)
return if (typeDirectives != null) StringUtil.unescapeStringCharacters(typeDirectives) else "a"
}
return typeDirectives != null ? StringUtil.unescapeStringCharacters(typeDirectives) : "a";
private val expectedOutOfBlockResult: Boolean
get() {
val text = myFixture.getDocument(myFixture.file).text
val outOfCodeBlockDirective = InTextDirectivesUtils.findStringWithPrefixes(
text,
OUT_OF_CODE_BLOCK_DIRECTIVE
)
assertNotNull(
"${fileName()}: Expectation of code block result test should be configured with " +
"\"// " + OUT_OF_CODE_BLOCK_DIRECTIVE + " TRUE\" or " +
"\"// " + OUT_OF_CODE_BLOCK_DIRECTIVE + " FALSE\" directive in the file",
outOfCodeBlockDirective
)
return outOfCodeBlockDirective?.toBoolean() ?: false
}
companion object {
const val OUT_OF_CODE_BLOCK_DIRECTIVE = "OUT_OF_CODE_BLOCK:"
const val SKIP_ANALYZE_CHECK_DIRECTIVE = "SKIP_ANALYZE_CHECK"
const val TYPE_DIRECTIVE = "TYPE:"
}
private boolean getExpectedOutOfBlockResult() {
String text = myFixture.getDocument(myFixture.getFile()).getText();
String outOfCodeBlockDirective = InTextDirectivesUtils.findStringWithPrefixes(text, OUT_OF_CODE_BLOCK_DIRECTIVE);
assertNotNull(fileName() +
": Expectation of code block result test should be configured with " +
"\"// " + OUT_OF_CODE_BLOCK_DIRECTIVE + " TRUE\" or " +
"\"// " + OUT_OF_CODE_BLOCK_DIRECTIVE + " FALSE\" directive in the file",
outOfCodeBlockDirective);
return Boolean.parseBoolean(outOfCodeBlockDirective);
}
}
}