From da7b12f7e1013a128ae9a73db68c0786a618d760 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Tue, 3 Nov 2020 23:06:45 +0300 Subject: [PATCH] FIR IDE: introduce ProjectWideOutOfBlockKotlinModificationTrackerTest --- .../kotlin/generators/tests/GenerateTests.kt | 4 + .../api/element/builder/FirElementBuilder.kt | 13 +++ ...lockModificationTrackerConsistencyTest.kt} | 51 ++++------ ...cationTrackerConsistencyTestGenerated.java | 95 +++++++++++++++++++ ...StructureElementCreationTestGenerated.java | 50 ---------- ...OutOfBlockKotlinModificationTrackerTest.kt | 2 +- 6 files changed, 129 insertions(+), 86 deletions(-) rename idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/{AbstractReanalyzableFileStructureElementCreationTest.kt => AbstractFileStructureAndOutOfBlockModificationTrackerConsistencyTest.kt} (56%) create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructureAndOutOfBlockModificationTrackerConsistencyTestGenerated.java delete mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/ReanalyzableFileStructureElementCreationTestGenerated.java diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index ea49712ab5a..7163b3ef307 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -84,6 +84,7 @@ import org.jetbrains.kotlin.idea.fir.AbstractKtDeclarationAndFirDeclarationEqual import org.jetbrains.kotlin.idea.fir.low.level.api.AbstractFirLazyDeclarationResolveTest import org.jetbrains.kotlin.idea.fir.low.level.api.AbstractFirMultiModuleLazyResolveTest import org.jetbrains.kotlin.idea.fir.low.level.api.file.structure.AbstractFileStructureTest +import org.jetbrains.kotlin.idea.fir.low.level.api.file.structure.AbstractFileStructureAndOutOfBlockModificationTrackerConsistencyTest import org.jetbrains.kotlin.idea.folding.AbstractKotlinFoldingTest import org.jetbrains.kotlin.idea.frontend.api.fir.AbstractResolveCallTest import org.jetbrains.kotlin.idea.fir.low.level.api.trackers.AbstractProjectWideOutOfBlockKotlinModificationTrackerTest @@ -1041,6 +1042,9 @@ fun main(args: Array) { testClass { model("outOfBlockProjectWide") } + testClass { + model("outOfBlockProjectWide") + } testClass { model("fileStructure") } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/element/builder/FirElementBuilder.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/element/builder/FirElementBuilder.kt index 7821d2cbe36..9e0d633e5b7 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/element/builder/FirElementBuilder.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/element/builder/FirElementBuilder.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.element.builder import com.intellij.psi.PsiElement +import org.jetbrains.annotations.TestOnly import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.FirLazyDeclarationResolver @@ -13,9 +14,11 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.annotations.ThreadSafe import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.FirFileBuilder import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache import org.jetbrains.kotlin.idea.fir.low.level.api.file.structure.FileStructureCache +import org.jetbrains.kotlin.idea.fir.low.level.api.file.structure.FileStructureElement import org.jetbrains.kotlin.idea.util.getElementTextInContext import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject +import org.jetbrains.kotlin.psi.psiUtil.isAncestor import org.jetbrains.kotlin.psi2ir.deparenthesize /** @@ -53,6 +56,16 @@ internal class FirElementBuilder { return psi.getFirOfClosestParent(mappings)?.second ?: error("FirElement is not found for:\n${element.getElementTextInContext()}") } + + @TestOnly + fun getStructureElementFor( + element: KtElement, + moduleFileCache: ModuleFileCache, + fileStructureCache: FileStructureCache, + ): FileStructureElement { + val fileStructure = fileStructureCache.getFileStructure(element.containingKtFile, moduleFileCache) + return fileStructure.getStructureElementFor(element) + } } private fun KtElement.getFirOfClosestParent(cache: Map): Pair? { diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/AbstractReanalyzableFileStructureElementCreationTest.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/AbstractFileStructureAndOutOfBlockModificationTrackerConsistencyTest.kt similarity index 56% rename from idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/AbstractReanalyzableFileStructureElementCreationTest.kt rename to idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/AbstractFileStructureAndOutOfBlockModificationTrackerConsistencyTest.kt index 69d35919185..9e76b38dbc2 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/AbstractReanalyzableFileStructureElementCreationTest.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/AbstractFileStructureAndOutOfBlockModificationTrackerConsistencyTest.kt @@ -12,63 +12,49 @@ import junit.framework.Assert import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveStateImpl import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState import org.jetbrains.kotlin.idea.fir.low.level.api.api.LowLevelFirApiFacade -import org.jetbrains.kotlin.idea.search.getKotlinFqName +import org.jetbrains.kotlin.idea.fir.low.level.api.trackers.AbstractProjectWideOutOfBlockKotlinModificationTrackerTest import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase -import org.jetbrains.kotlin.idea.util.getElementTextInContext -import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.InTextDirectivesUtils import java.io.File -abstract class AbstractReanalyzableFileStructureElementCreationTest : KotlinLightCodeInsightFixtureTestCase() { +abstract class AbstractFileStructureAndOutOfBlockModificationTrackerConsistencyTest : KotlinLightCodeInsightFixtureTestCase() { override fun isFirPlugin(): Boolean = true fun doTest(path: String) { val testDataFile = File(path) - val initialFileText = FileUtil.loadFile(testDataFile) - val ktFile = myFixture.configureByText(testDataFile.name, initialFileText) as KtFile - val expectedFqName = - InTextDirectivesUtils.findStringWithPrefixes(initialFileText, STRUCTURE_ELEMENT_FQ_NAME_DIRECTIVE) - ?: error("Please specify // STRUCTURE_ELEMENT directive") - val shouldStructureElementBeRecreated = - InTextDirectivesUtils.getPrefixedBoolean(initialFileText, SHOULD_ELEMENT_BE_RECREATED) - ?: error("Please specify // SHOULD_ELEMENT_BE_RECREATED directive") + val fileText = FileUtil.loadFile(testDataFile) + val ktFile = myFixture.configureByText(testDataFile.name, fileText) as KtFile + val textToType = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// TYPE:") + ?: AbstractProjectWideOutOfBlockKotlinModificationTrackerTest.DEFAULT_TEXT_TO_TYPE + val outOfBlock = InTextDirectivesUtils.getPrefixedBoolean(fileText, "// OUT_OF_BLOCK:") + ?: error("Please, specify should out of block change happen or not by `// OUT_OF_BLOCK:` directive") val elementAtCaret = ktFile.findElementAtCaret() val (initialStructureElement, initialFileStructure, initialModuleResolveState) = getStructureElementForKtElement(elementAtCaret) - Assert.assertEquals(expectedFqName, initialStructureElement.psi.getKotlinFqName()?.asString()) - myFixture.type("hello") + myFixture.type(textToType) PsiDocumentManager.getInstance(project).commitAllDocuments() val newElementAtCaret = ktFile.findElementAtCaret() val (newStructureElement, newFileStructure, newModuleResolveState) = getStructureElementForKtElement(newElementAtCaret) - Assert.assertEquals( - "Structure elements should be build by the same KtDeclaration's", - expectedFqName, - newStructureElement.psi.getKotlinFqName()?.asString() - ) Assert.assertTrue("Structure elements should be different after typing", newStructureElement !== initialStructureElement) + Assert.assertEquals( - "FirModuleResolveState should change only of out of block modification", - shouldStructureElementBeRecreated, + "FirModuleResolveState should change only on out of block modification", + outOfBlock, newModuleResolveState !== initialModuleResolveState ) Assert.assertEquals( - "FileStructure state should change only of out of block modification", - shouldStructureElementBeRecreated, + "FileStructure state should change only on out of block modification", + outOfBlock, initialFileStructure !== newFileStructure ) } - private fun KtFile.findElementAtCaret(): KtElement { - val elementAtCaret = findElementAt(myFixture.caretOffset)!!.parentOfType()!! - if (elementAtCaret is KtDeclaration) { - error("Expected element inside declaration but was\n${elementAtCaret.getElementTextInContext()}") - } - return elementAtCaret - } + private fun KtFile.findElementAtCaret(): KtElement = + findElementAt(myFixture.caretOffset)!!.parentOfType()!! private fun getStructureElementForKtElement(element: KtElement): Triple { val moduleResolveState = LowLevelFirApiFacade.getResolveStateFor(element) as FirModuleResolveStateImpl @@ -77,9 +63,4 @@ abstract class AbstractReanalyzableFileStructureElementCreationTest : KotlinLigh val fileStructureElement = fileStructure.getStructureElementFor(element) return Triple(fileStructureElement, fileStructure, moduleResolveState) } - - companion object { - private const val STRUCTURE_ELEMENT_FQ_NAME_DIRECTIVE = "// STRUCTURE_ELEMENT:" - private const val SHOULD_ELEMENT_BE_RECREATED = "// SHOULD_ELEMENT_BE_RECREATED:" - } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructureAndOutOfBlockModificationTrackerConsistencyTestGenerated.java b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructureAndOutOfBlockModificationTrackerConsistencyTestGenerated.java new file mode 100644 index 00000000000..82efa737118 --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructureAndOutOfBlockModificationTrackerConsistencyTestGenerated.java @@ -0,0 +1,95 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.fir.low.level.api.file.structure; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/outOfBlockProjectWide") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class FileStructureAndOutOfBlockModificationTrackerConsistencyTestGenerated extends AbstractFileStructureAndOutOfBlockModificationTrackerConsistencyTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInOutOfBlockProjectWide() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/outOfBlockProjectWide"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("localFun.kt") + public void testLocalFun() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/outOfBlockProjectWide/localFun.kt"); + } + + @TestMetadata("topLevelExpressionBodyFunWithType.kt") + public void testTopLevelExpressionBodyFunWithType() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/outOfBlockProjectWide/topLevelExpressionBodyFunWithType.kt"); + } + + @TestMetadata("topLevelExpressionBodyFunWithoutType.kt") + public void testTopLevelExpressionBodyFunWithoutType() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/outOfBlockProjectWide/topLevelExpressionBodyFunWithoutType.kt"); + } + + @TestMetadata("topLevelFunWithType.kt") + public void testTopLevelFunWithType() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/outOfBlockProjectWide/topLevelFunWithType.kt"); + } + + @TestMetadata("topLevelUnitFun.kt") + public void testTopLevelUnitFun() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/outOfBlockProjectWide/topLevelUnitFun.kt"); + } + + @TestMetadata("typeInFunctionAnnotation.kt") + public void testTypeInFunctionAnnotation() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/outOfBlockProjectWide/typeInFunctionAnnotation.kt"); + } + + @TestMetadata("typeInFunctionAnnotationParameter.kt") + public void testTypeInFunctionAnnotationParameter() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/outOfBlockProjectWide/typeInFunctionAnnotationParameter.kt"); + } + + @TestMetadata("typeInFunctionModifiers.kt") + public void testTypeInFunctionModifiers() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/outOfBlockProjectWide/typeInFunctionModifiers.kt"); + } + + @TestMetadata("typeInFunctionName.kt") + public void testTypeInFunctionName() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/outOfBlockProjectWide/typeInFunctionName.kt"); + } + + @TestMetadata("typeInFunctionParams.kt") + public void testTypeInFunctionParams() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/outOfBlockProjectWide/typeInFunctionParams.kt"); + } + + @TestMetadata("typeInFunctionParamsType.kt") + public void testTypeInFunctionParamsType() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/outOfBlockProjectWide/typeInFunctionParamsType.kt"); + } + + @TestMetadata("typeInFunctionReturnType.kt") + public void testTypeInFunctionReturnType() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/outOfBlockProjectWide/typeInFunctionReturnType.kt"); + } + + @TestMetadata("typeInFunctionTypeParams.kt") + public void testTypeInFunctionTypeParams() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/outOfBlockProjectWide/typeInFunctionTypeParams.kt"); + } +} diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/ReanalyzableFileStructureElementCreationTestGenerated.java b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/ReanalyzableFileStructureElementCreationTestGenerated.java deleted file mode 100644 index 9c0d25e4ebe..00000000000 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/ReanalyzableFileStructureElementCreationTestGenerated.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. - * 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.fir.low.level.api.file.structure; - -import com.intellij.testFramework.TestDataPath; -import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; -import org.jetbrains.kotlin.test.KotlinTestUtils; -import org.jetbrains.kotlin.test.TestMetadata; -import org.junit.runner.RunWith; - -import java.io.File; -import java.util.regex.Pattern; - -/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ -@SuppressWarnings("all") -@TestMetadata("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/elementBuilder") -@TestDataPath("$PROJECT_ROOT") -@RunWith(JUnit3RunnerWithInners.class) -public class ReanalyzableFileStructureElementCreationTestGenerated extends AbstractReanalyzableFileStructureElementCreationTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); - } - - public void testAllFilesPresentInElementBuilder() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/elementBuilder"), Pattern.compile("^(.+)\\.kt$"), null, true); - } - - @TestMetadata("topLevelExpressionBodyFunWithType.kt") - public void testTopLevelExpressionBodyFunWithType() throws Exception { - runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/elementBuilder/topLevelExpressionBodyFunWithType.kt"); - } - - @TestMetadata("topLevelExpressionBodyFunWithoutType.kt") - public void testTopLevelExpressionBodyFunWithoutType() throws Exception { - runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/elementBuilder/topLevelExpressionBodyFunWithoutType.kt"); - } - - @TestMetadata("topLevelFunWithType.kt") - public void testTopLevelFunWithType() throws Exception { - runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/elementBuilder/topLevelFunWithType.kt"); - } - - @TestMetadata("topLevelUnitFun.kt") - public void testTopLevelUnitFun() throws Exception { - runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/elementBuilder/topLevelUnitFun.kt"); - } -} diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/trackers/AbstractProjectWideOutOfBlockKotlinModificationTrackerTest.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/trackers/AbstractProjectWideOutOfBlockKotlinModificationTrackerTest.kt index 8c35c487bdf..c1ec05132c6 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/trackers/AbstractProjectWideOutOfBlockKotlinModificationTrackerTest.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/trackers/AbstractProjectWideOutOfBlockKotlinModificationTrackerTest.kt @@ -32,6 +32,6 @@ abstract class AbstractProjectWideOutOfBlockKotlinModificationTrackerTest : Kotl } companion object { - private const val DEFAULT_TEXT_TO_TYPE = "hello" + const val DEFAULT_TEXT_TO_TYPE = "hello" } } \ No newline at end of file