FIR IDE: introduce file structure tests
This commit is contained in:
@@ -83,6 +83,7 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.AbstractFirMultiModuleResolve
|
||||
import org.jetbrains.kotlin.idea.fir.AbstractKtDeclarationAndFirDeclarationEqualityChecker
|
||||
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.folding.AbstractKotlinFoldingTest
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.AbstractResolveCallTest
|
||||
import org.jetbrains.kotlin.idea.frontend.api.scopes.AbstractMemberScopeByFqNameTest
|
||||
@@ -1036,6 +1037,9 @@ fun main(args: Array<String>) {
|
||||
testClass<AbstractFirLazyDeclarationResolveTest> {
|
||||
model("lazyResolve")
|
||||
}
|
||||
testClass<AbstractFileStructureTest> {
|
||||
model("fileStructure")
|
||||
}
|
||||
}
|
||||
|
||||
testGroup("idea/idea-fir/tests", "idea") {
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
class A {/* NonLocalDeclarationFileStructureElement */
|
||||
fun x() {/* IncrementallyReanalyzableFunction */
|
||||
|
||||
}
|
||||
fun y(): Int = 10/* IncrementallyReanalyzableFunction */
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
fun a() {/* IncrementallyReanalyzableFunction */
|
||||
class X
|
||||
}
|
||||
|
||||
class Y {/* NonLocalDeclarationFileStructureElement */
|
||||
fun b() {/* IncrementallyReanalyzableFunction */
|
||||
class Z
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
fun x() {/* IncrementallyReanalyzableFunction */
|
||||
fun y() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class A {/* NonLocalDeclarationFileStructureElement */
|
||||
fun z() {/* IncrementallyReanalyzableFunction */
|
||||
fun q() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
class A {/* NonLocalDeclarationFileStructureElement */
|
||||
class B {/* NonLocalDeclarationFileStructureElement */
|
||||
fun x() {/* IncrementallyReanalyzableFunction */
|
||||
}
|
||||
|
||||
class C {/* NonLocalDeclarationFileStructureElement */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class E {/* NonLocalDeclarationFileStructureElement */
|
||||
|
||||
}
|
||||
|
||||
fun y(): Int = 10/* IncrementallyReanalyzableFunction */
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun foo(): Int = 42/* IncrementallyReanalyzableFunction */
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun foo() = 42/* NonLocalDeclarationFileStructureElement */
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
fun foo(): Int {/* IncrementallyReanalyzableFunction */
|
||||
println("")
|
||||
return 10
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
fun foo() {/* IncrementallyReanalyzableFunction */
|
||||
println("")
|
||||
}
|
||||
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.openapi.application.runUndoTransparentWriteAction
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.psi.PsiComment
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.util.collectDescendantsOfType
|
||||
import com.intellij.psi.util.forEachDescendantOfType
|
||||
import com.intellij.psi.util.parentOfType
|
||||
import junit.framework.Assert
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveStateImpl
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.LowLevelFirApiFacade
|
||||
import org.jetbrains.kotlin.idea.search.getKotlinFqName
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.idea.util.getElementTextInContext
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.isFakeElement
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractFileStructureTest : 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 fileStructure = ktFile.getFileStructure()
|
||||
val allStructureElements = fileStructure.getAllStructureElements(ktFile)
|
||||
val declarationToStructureElement = allStructureElements.associateBy { it.psi }
|
||||
runUndoTransparentWriteAction {
|
||||
ktFile.collectDescendantsOfType<PsiComment>().forEach { it.delete() }
|
||||
ktFile.forEachDescendantOfType<KtDeclaration> { ktDeclaration ->
|
||||
val structureElement = declarationToStructureElement[ktDeclaration] ?: return@forEachDescendantOfType
|
||||
val comment = structureElement.createComment()
|
||||
when (ktDeclaration) {
|
||||
is KtClassOrObject -> {
|
||||
val lBrace = ktDeclaration.body?.lBrace
|
||||
if (lBrace != null) {
|
||||
ktDeclaration.body!!.addAfter(comment, lBrace)
|
||||
} else {
|
||||
ktDeclaration.parent.addAfter(comment, ktDeclaration)
|
||||
}
|
||||
}
|
||||
is KtFunction -> {
|
||||
val lBrace = ktDeclaration.bodyBlockExpression?.lBrace
|
||||
if (lBrace != null) {
|
||||
ktDeclaration.bodyBlockExpression!!.addAfter(comment, lBrace)
|
||||
} else {
|
||||
ktDeclaration.parent.addAfter(comment, ktDeclaration)
|
||||
}
|
||||
}
|
||||
else -> error("Unsupported declaration $ktDeclaration")
|
||||
}
|
||||
}
|
||||
}
|
||||
KotlinTestUtils.assertEqualsToFile(testDataFile, ktFile.text)
|
||||
}
|
||||
|
||||
private fun FileStructureElement.createComment(): PsiComment {
|
||||
val text = """/* ${this::class.simpleName!!} */"""
|
||||
return KtPsiFactory(psi.project).createComment(text)
|
||||
}
|
||||
|
||||
private fun KtFile.getFileStructure(): FileStructure {
|
||||
val moduleResolveState = LowLevelFirApiFacade.getResolveStateFor(this) as FirModuleResolveStateImpl
|
||||
return moduleResolveState.fileStructureCache.getFileStructure(
|
||||
ktFile = this,
|
||||
moduleFileCache = moduleResolveState.rootModuleSession.cache
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private fun FileStructure.getAllStructureElements(ktFile: KtFile): Collection<FileStructureElement> = buildSet {
|
||||
ktFile.forEachDescendantOfType<KtElement> { ktElement ->
|
||||
add(getStructureElementFor(ktElement))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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/fileStructure")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class FileStructureTestGenerated extends AbstractFileStructureTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInFileStructure() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/fileStructure"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("class.kt")
|
||||
public void testClass() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/fileStructure/class.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localClass.kt")
|
||||
public void testLocalClass() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/fileStructure/localClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localFun.kt")
|
||||
public void testLocalFun() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/fileStructure/localFun.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nestedClasses.kt")
|
||||
public void testNestedClasses() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/fileStructure/nestedClasses.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelExpressionBodyFunWithType.kt")
|
||||
public void testTopLevelExpressionBodyFunWithType() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/fileStructure/topLevelExpressionBodyFunWithType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelExpressionBodyFunWithoutType.kt")
|
||||
public void testTopLevelExpressionBodyFunWithoutType() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/fileStructure/topLevelExpressionBodyFunWithoutType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelFunWithType.kt")
|
||||
public void testTopLevelFunWithType() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/fileStructure/topLevelFunWithType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelUnitFun.kt")
|
||||
public void testTopLevelUnitFun() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/fileStructure/topLevelUnitFun.kt");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user