FIR IDE: introduce AbstractSymbolByReferencePointerRestoreTest

This commit is contained in:
Ilya Kirillov
2021-03-19 15:58:15 +01:00
parent 846dc1b9b9
commit 0bb37db4bf
46 changed files with 271 additions and 159 deletions
@@ -1040,7 +1040,11 @@ fun main(args: Array<String>) {
}
testClass<AbstractSymbolFromLibraryPointerRestoreTest> {
model("resoreSymbolFromLibrary", extension = "txt")
model("resoreSymbolFromLibrary")
}
testClass<AbstractSymbolByReferencePointerRestoreTest> {
model("symbolByReference")
}
testClass<AbstractMemoryLeakInSymbolsTest> {
@@ -2,8 +2,7 @@ fun test(s: String) {
var i: Int = 0
<expr>i</expr> = s.length
}
// RESULT
// RESULT
// expression: i
// type: kotlin.Int
@@ -1,6 +1,5 @@
val x = <expr>1 + 2</expr>
// RESULT
// RESULT
// expression: 1 + 2
// type: kotlin.Int
@@ -3,8 +3,7 @@ fun x(): Int {
<expr>break</expr>
}
}
// RESULT
// RESULT
// expression: break
// type: kotlin.Nothing
@@ -1,8 +1,7 @@
fun x(): Int {
<expr>for(i in 1..2) {}</expr>
}
// RESULT
// RESULT
// expression: for(i in 1..2) {}
// type: kotlin.Unit
@@ -1,7 +1,6 @@
val a = 12
val x = <expr>12.toByte()</expr>
// RESULT
// RESULT
// expression: 12.toByte()
// type: kotlin.Byte
@@ -1,6 +1,5 @@
val x = <expr>(1 + 2)</expr> + 3
// RESULT
// RESULT
// expression: (1 + 2)
// type: kotlin.Int
@@ -1,7 +1,6 @@
val a = 10
val x = "abc${<expr>a</expr>}defg"
// RESULT
// RESULT
// expression: a
// type: kotlin.Int
@@ -1,7 +1,6 @@
val a = 10
val x = "abc${<expr>a</expr> + 20}defg"
// RESULT
// RESULT
// expression: a
// type: kotlin.Int
@@ -1,6 +1,5 @@
val x = <expr>1</expr>
// RESULT
// RESULT
// expression: 1
// type: kotlin.Int
@@ -1,7 +1,6 @@
val a = 10
<expr>val x = 1</expr>
// RESULT
// RESULT
// expression: val x = 1
// type: kotlin.Unit
@@ -1,8 +1,7 @@
fun x(): Int {
<expr>return 1</expr>
}
// RESULT
// RESULT
// expression: return 1
// type: kotlin.Nothing
@@ -1,6 +1,5 @@
val x = <expr>"abc"</expr>
// RESULT
// RESULT
// expression: "abc"
// type: kotlin.String
@@ -1,8 +1,7 @@
fun x(): Int {
<expr>while(true) {}</expr>
}
// RESULT
// RESULT
// expression: while(true) {}
// type: kotlin.Unit
@@ -9,11 +9,10 @@ abstract class B {
abstract fun foo(x: String): Int
}
// RESULT
// RESULT
// ALL:
// B.foo(x: Int): Int
// DIRECT:
// B.foo(x: Int): Int
@@ -22,8 +22,8 @@ interface D {
fun foo(x: String)
}
// RESULT
// RESULT
// ALL:
// C.foo(x: String): Unit
// D.foo(x: String): Unit
@@ -31,4 +31,3 @@ interface D {
// DIRECT:
// C.foo(x: String): Unit
// D.foo(x: String): Unit
@@ -22,8 +22,8 @@ interface D {
fun foo(x: String)
}
// RESULT
// RESULT
// ALL:
// C.foo(x: String): Unit
// D.foo(x: String): Unit
@@ -31,4 +31,3 @@ interface D {
// DIRECT:
// C.foo(x: String): Unit
// D.foo(x: String): Unit
@@ -16,12 +16,11 @@ abstract class C {
abstract val x: Int
}
// RESULT
// RESULT
// ALL:
// B.x: Int
// C.x: Int
// DIRECT:
// B.x: Int
@@ -25,8 +25,8 @@ interface D {
fun foo(x: String)
}
// RESULT
// RESULT
// ALL:
// B.foo(x: String): Unit
// C.foo(x: String): Unit
@@ -36,4 +36,3 @@ interface D {
// B.foo(x: String): Unit
// C.foo(x: String): Unit
// D.foo(x: String): Unit
@@ -18,8 +18,8 @@ open class D {
open fun foo(x: Int) {}
}
// RESULT
// RESULT
// ALL:
// B.foo(x: Int): Unit
// C.foo(x: Int): Unit
@@ -27,4 +27,3 @@ open class D {
// DIRECT:
// B.foo(x: Int): Unit
@@ -1,8 +1,9 @@
// RUNTIME
class: kotlin/Lazy
// class: kotlin/Lazy
// SYMBOLS:
// RESULT
/*
KtFirNamedClassOrObjectSymbol:
annotationClassIds: []
annotations: []
@@ -21,3 +22,4 @@ KtFirNamedClassOrObjectSymbol:
symbolKind: TOP_LEVEL
typeParameters: [KtFirTypeParameterSymbol(T)]
visibility: PUBLIC
*/
@@ -1,8 +1,9 @@
// RUNTIME
class: java/lang/String
// class: java/lang/String
// SYMBOLS:
// RESULT
/*
KtFirNamedClassOrObjectSymbol:
annotationClassIds: []
annotations: []
@@ -21,3 +22,4 @@ KtFirNamedClassOrObjectSymbol:
symbolKind: TOP_LEVEL
typeParameters: []
visibility: PUBLIC
*/
@@ -1,11 +1,13 @@
// RUNTIME
callable: kotlin/LazyThreadSafetyMode.SYNCHRONIZED
// callable: kotlin/LazyThreadSafetyMode.SYNCHRONIZED
// SYMBOLS:
// RESULT
/*
KtFirEnumEntrySymbol:
annotatedType: [] kotlin/LazyThreadSafetyMode
containingEnumClassIdIfNonLocal: kotlin/LazyThreadSafetyMode
name: SYNCHRONIZED
origin: LIBRARY
symbolKind: MEMBER
*/
@@ -1,6 +1,7 @@
callable: kotlin/collections/List.get
// callable: kotlin/collections/List.get
// SYMBOLS:
// RESULT
/*
KtFirFunctionSymbol:
annotatedType: [] E
annotationClassIds: []
@@ -21,3 +22,4 @@ KtFirFunctionSymbol:
typeParameters: []
valueParameters: [KtFirFunctionValueParameterSymbol(index)]
visibility: PUBLIC
*/
@@ -1,6 +1,7 @@
callable: kotlin/collections/List.listIterator
// callable: kotlin/collections/List.listIterator
// SYMBOLS:
// RESULT
/*
KtFirFunctionSymbol:
annotatedType: [] kotlin/collections/ListIterator<E>
annotationClassIds: []
@@ -42,3 +43,4 @@ KtFirFunctionSymbol:
typeParameters: []
valueParameters: [KtFirFunctionValueParameterSymbol(index)]
visibility: PUBLIC
*/
@@ -1,6 +1,7 @@
class: kotlin/collections/MutableMap.MutableEntry
// class: kotlin/collections/MutableMap.MutableEntry
// SYMBOLS:
// RESULT
/*
KtFirNamedClassOrObjectSymbol:
annotationClassIds: []
annotations: []
@@ -19,3 +20,4 @@ KtFirNamedClassOrObjectSymbol:
symbolKind: MEMBER
typeParameters: [KtFirTypeParameterSymbol(K), KtFirTypeParameterSymbol(V)]
visibility: PUBLIC
*/
@@ -2,4 +2,14 @@ var x: Int = 0
get() = <caret>field
set(value) {
field = value
}
}
// RESULT
/*
KtFirBackingFieldSymbol:
annotatedType: [] kotlin/Int
name: field
origin: PROPERTY_BACKING_FIELD
owningProperty: KtFirKotlinPropertySymbol(x)
symbolKind: LOCAL
*/
@@ -3,8 +3,8 @@
fun x() {
val a = <caret>ArrayList(listOf(1))
}
// RESULT
// RESULT
/*
KtFirConstructorSymbol:
annotatedType: [] java/util/ArrayList<E>
@@ -19,4 +19,3 @@ KtFirConstructorSymbol:
valueParameters: [KtFirConstructorValueParameterSymbol(c)]
visibility: PUBLIC
*/
+3 -1
View File
@@ -1,7 +1,8 @@
class A {
}
// SYMBOLS:
// RESULT
/*
KtFirNamedClassOrObjectSymbol:
annotationClassIds: []
annotations: []
@@ -20,3 +21,4 @@ KtFirNamedClassOrObjectSymbol:
symbolKind: TOP_LEVEL
typeParameters: []
visibility: PUBLIC
*/
@@ -1,7 +1,8 @@
class A() {
}
// SYMBOLS:
// RESULT
/*
KtFirConstructorSymbol:
annotatedType: [] A
annotationClassIds: []
@@ -33,3 +34,4 @@ KtFirNamedClassOrObjectSymbol:
symbolKind: TOP_LEVEL
typeParameters: []
visibility: PUBLIC
*/
@@ -3,7 +3,8 @@ class A() {
constructor(y: Int, z: String) : this(y)
}
// SYMBOLS:
// RESULT
/*
KtFirConstructorSymbol:
annotatedType: [] A
annotationClassIds: []
@@ -91,3 +92,4 @@ KtFirNamedClassOrObjectSymbol:
symbolKind: TOP_LEVEL
typeParameters: []
visibility: PUBLIC
*/
+3 -1
View File
@@ -2,7 +2,8 @@ enum class X {
Y, Z;
}
// SYMBOLS:
// RESULT
/*
KtFirEnumEntrySymbol:
annotatedType: [] X
containingEnumClassIdIfNonLocal: X
@@ -35,3 +36,4 @@ KtFirNamedClassOrObjectSymbol:
symbolKind: TOP_LEVEL
typeParameters: []
visibility: PUBLIC
*/
@@ -3,7 +3,8 @@ class A {
fun y()
}
// SYMBOLS:
// RESULT
/*
KtFirFunctionSymbol:
annotatedType: [] kotlin/Int
annotationClassIds: []
@@ -64,3 +65,4 @@ KtFirNamedClassOrObjectSymbol:
symbolKind: TOP_LEVEL
typeParameters: []
visibility: PUBLIC
*/
@@ -3,7 +3,8 @@ class A {
val Int.y get() = this
}
// SYMBOLS:
// RESULT
/*
KtFirKotlinPropertySymbol:
annotatedType: [] kotlin/Int
annotationClassIds: []
@@ -84,3 +85,4 @@ KtFirNamedClassOrObjectSymbol:
symbolKind: TOP_LEVEL
typeParameters: []
visibility: PUBLIC
*/
@@ -1,7 +1,8 @@
fun x(): Int = 10
fun y() {}
// SYMBOLS:
// RESULT
/*
KtFirFunctionSymbol:
annotatedType: [] kotlin/Int
annotationClassIds: []
@@ -43,3 +44,4 @@ KtFirFunctionSymbol:
typeParameters: []
valueParameters: []
visibility: PUBLIC
*/
@@ -1,7 +1,8 @@
val x: Int = 10
val Int.y get() = this
// SYMBOLS:
// RESULT
/*
KtFirKotlinPropertySymbol:
annotatedType: [] kotlin/Int
annotationClassIds: []
@@ -63,3 +64,4 @@ KtFirKotlinPropertySymbol:
setter: null
symbolKind: TOP_LEVEL
visibility: PUBLIC
*/
@@ -14,12 +14,13 @@ import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescrip
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
import java.nio.file.Paths
abstract class AbstractSymbolByFqNameTest : KotlinLightCodeInsightFixtureTestCase() {
protected fun doTest(path: String) {
val fakeKtFile = myFixture.configureByText("file.kt", "fun a() {}") as KtFile
val symbolData = SymbolByFqName.getSymbolDataFromFile(path)
val symbolData = SymbolByFqName.getSymbolDataFromFile(Paths.get(path))
val renderedSymbols = executeOnPooledThreadInReadAction {
analyze(fakeKtFile) {
@@ -13,12 +13,17 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import java.io.File
import java.nio.file.Path
object SymbolByFqName {
fun getSymbolDataFromFile(filePath: String): SymbolData {
val testFileText = FileUtil.loadFile(File(filePath))
val identifier = testFileText.lineSequence().first { line -> SymbolData.identifiers.any { line.startsWith(it) } }
return SymbolData.create(identifier)
fun getSymbolDataFromFile(filePath: Path): SymbolData {
val testFileText = FileUtil.loadFile(filePath.toFile())
val identifier = testFileText.lineSequence().first { line ->
SymbolData.identifiers.any { identifier ->
line.startsWith(identifier) || line.startsWith("// $identifier")
}
}
return SymbolData.create(identifier.removePrefix("// "))
}
fun textWithRenderedSymbolData(filePath: String, rendered: String): String = buildString {
@@ -0,0 +1,18 @@
/*
* 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.frontend.api.symbols
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.test.framework.TestFileStructure
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
abstract class AbstractSymbolByReferencePointerRestoreTest : AbstractSymbolPointerRestoreTest() {
override fun KtAnalysisSession.collectSymbols(fileStructure: TestFileStructure): List<KtSymbol> {
val referenceExpression = getElementOfTypeAtCaret<KtNameReferenceExpression>()
return listOfNotNull(referenceExpression.mainReference.resolveToSymbol())
}
}
@@ -27,7 +27,8 @@ abstract class AbstractSymbolByReferenceTest : AbstractKtIdeaTest() {
val actual = TestStructureRenderer.render(
fileStructure,
TestStructureExpectedDataBlock(renderedSymbol)
TestStructureExpectedDataBlock(renderedSymbol),
renderingMode = TestStructureRenderer.RenderingMode.ALL_BLOCKS_IN_MULTI_LINE_COMMENT,
)
KotlinTestUtils.assertEqualsToFile(fileStructure.filePath.toFile(), actual)
}
@@ -7,11 +7,12 @@ package org.jetbrains.kotlin.idea.frontend.api.symbols
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.SymbolByFqName
import org.jetbrains.kotlin.idea.test.framework.TestFileStructure
import org.jetbrains.kotlin.psi.KtFile
abstract class AbstractSymbolFromLibraryPointerRestoreTest : AbstractSymbolPointerRestoreTest() {
override fun KtAnalysisSession.collectSymbols(filePath: String, ktFile: KtFile): List<KtSymbol> {
val symbolData = SymbolByFqName.getSymbolDataFromFile(filePath)
override fun KtAnalysisSession.collectSymbols(fileStructure: TestFileStructure): List<KtSymbol> {
val symbolData = SymbolByFqName.getSymbolDataFromFile(fileStructure.filePath)
return with(symbolData) { toSymbols() }
}
}
@@ -6,13 +6,14 @@
package org.jetbrains.kotlin.idea.frontend.api.symbols
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.test.framework.TestFileStructure
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
abstract class AbstractSymbolFromSourcePointerRestoreTest : AbstractSymbolPointerRestoreTest() {
override fun KtAnalysisSession.collectSymbols(filePath: String, ktFile: KtFile): List<KtSymbol> =
ktFile.collectDescendantsOfType<KtDeclaration>().map { declaration ->
override fun KtAnalysisSession.collectSymbols(fileStructure: TestFileStructure): List<KtSymbol> =
fileStructure.mainKtFile.collectDescendantsOfType<KtDeclaration>().map { declaration ->
declaration.getSymbol()
}
}
@@ -7,74 +7,81 @@ package org.jetbrains.kotlin.idea.frontend.api.symbols
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.editor.Document
import com.intellij.psi.PsiDocumentManager
import org.jetbrains.kotlin.idea.executeOnPooledThreadInReadAction
import org.jetbrains.kotlin.idea.analyseOnPooledThreadInReadAction
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.SymbolByFqName
import org.jetbrains.kotlin.idea.frontend.api.analyze
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.framework.AbstractKtIdeaTest
import org.jetbrains.kotlin.idea.test.framework.TestFileStructure
import org.jetbrains.kotlin.idea.test.framework.TestStructureExpectedDataBlock
import org.jetbrains.kotlin.idea.test.framework.TestStructureRenderer
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.util.suffixIfNot
import org.junit.Assert
import java.io.File
abstract class AbstractSymbolPointerRestoreTest : KotlinLightCodeInsightFixtureTestCase() {
abstract fun KtAnalysisSession.collectSymbols(filePath: String, ktFile: KtFile): List<KtSymbol>
abstract class AbstractSymbolPointerRestoreTest : AbstractKtIdeaTest() {
abstract fun KtAnalysisSession.collectSymbols(fileStructure: TestFileStructure): List<KtSymbol>
protected fun doTest(path: String) {
val file = File(path)
val ktFile = myFixture.configureByText(file.name.suffixIfNot(".kt"), FileUtil.loadFile(file)) as KtFile
val pointersWithRendered = executeOnPooledThreadInReadAction {
analyze(ktFile) {
collectSymbols(path, ktFile).map { symbol ->
PointerWithRenderedSymbol(
symbol.createPointer(),
DebugSymbolRenderer.render(symbol)
)
}
override fun doTestByFileStructure(fileStructure: TestFileStructure) {
val pointersWithRendered = analyseOnPooledThreadInReadAction(fileStructure.mainKtFile) {
collectSymbols(fileStructure).map { symbol ->
PointerWithRenderedSymbol(
symbol.createPointer(),
DebugSymbolRenderer.render(symbol)
)
}
}
val actual = SymbolByFqName.textWithRenderedSymbolData(
path,
pointersWithRendered.joinToString(separator = "\n") { it.rendered },
val actual = TestStructureRenderer.render(
fileStructure,
TestStructureExpectedDataBlock(values = pointersWithRendered.map { it.rendered }),
renderingMode = TestStructureRenderer.RenderingMode.ALL_BLOCKS_IN_MULTI_LINE_COMMENT,
)
KotlinTestUtils.assertEqualsToFile(File(path), actual)
KotlinTestUtils.assertEqualsToFile(fileStructure.filePath.toFile(), actual)
doOutOfBlockModification(fileStructure.mainKtFile)
restoreSymbolsInOtherReadActionAndCompareResults(fileStructure, pointersWithRendered)
}
private fun restoreSymbolsInOtherReadActionAndCompareResults(
fileStructure: TestFileStructure,
pointersWithRendered: List<PointerWithRenderedSymbol>
) {
val restored = analyseOnPooledThreadInReadAction(fileStructure.mainKtFile) {
pointersWithRendered.map { (pointer, expectedRender) ->
val restored = pointer.restoreSymbol() ?: error("Symbol $expectedRender was not not restored correctly")
DebugSymbolRenderer.render(restored)
}
}
val actualRestored = TestStructureRenderer.render(
fileStructure,
TestStructureExpectedDataBlock(values = restored),
renderingMode = TestStructureRenderer.RenderingMode.ALL_BLOCKS_IN_MULTI_LINE_COMMENT,
)
KotlinTestUtils.assertEqualsToFile(fileStructure.filePath.toFile(), actualRestored)
}
private fun doOutOfBlockModification(ktFile: KtFile) {
CommandProcessor.getInstance().runUndoTransparentAction {
runWriteAction {
KtPsiFactory(ktFile).apply {
ktFile.add(createNewLine(lineBreaks = 2))
ktFile.add(createProperty("val aaaaaa: Int = 10"))
}
PsiDocumentManager.getInstance(project).apply {
commitDocument(getDocument(ktFile) ?: error("Cannot find document for ktFile"))
}
val document = PsiDocumentManager.getInstance(project).getDocument(ktFile) ?: error("Cannot find document for ktFile")
val initialText = ktFile.text
val ktPsiFactory = KtPsiFactory(ktFile)
ktFile.add(ktPsiFactory.createNewLine(lineBreaks = 2))
ktFile.add(ktPsiFactory.createProperty("val aaaaaa: Int = 10"))
commitDocument(document)
document.setText(initialText)
commitDocument(document)
}
}
}
// another read action
executeOnPooledThreadInReadAction {
analyze(ktFile) {
val restored = pointersWithRendered.map { (pointer, expectedRender) ->
val restored = pointer.restoreSymbol() ?: error("Symbol $expectedRender was not not restored correctly")
DebugSymbolRenderer.render(restored)
}
val actualRestored = SymbolByFqName.textWithRenderedSymbolData(
path,
restored.joinToString(separator = "\n"),
)
KotlinTestUtils.assertEqualsToFile(File(path), actualRestored)
}
}
private fun commitDocument(document: Document) {
PsiDocumentManager.getInstance(project).commitDocument(document)
}
}
@@ -0,0 +1,41 @@
/*
* Copyright 2010-2021 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.frontend.api.symbols;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
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/testData/symbolByReference")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class SymbolByReferencePointerRestoreTestGenerated extends AbstractSymbolByReferencePointerRestoreTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
@TestMetadata("accessorField.kt")
public void testAccessorField() throws Exception {
runTest("idea/idea-frontend-fir/testData/symbolByReference/accessorField.kt");
}
public void testAllFilesPresentInSymbolByReference() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/testData/symbolByReference"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@TestMetadata("constructorViaTypeAlias.kt")
public void testConstructorViaTypeAlias() throws Exception {
runTest("idea/idea-frontend-fir/testData/symbolByReference/constructorViaTypeAlias.kt");
}
}
@@ -26,36 +26,36 @@ public class SymbolFromLibraryPointerRestoreTestGenerated extends AbstractSymbol
}
public void testAllFilesPresentInResoreSymbolFromLibrary() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary"), Pattern.compile("^(.+)\\.txt$"), null, true);
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@TestMetadata("class.txt")
@TestMetadata("class.kt")
public void testClass() throws Exception {
runTest("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/class.txt");
runTest("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/class.kt");
}
@TestMetadata("classFromJdk.txt")
@TestMetadata("classFromJdk.kt")
public void testClassFromJdk() throws Exception {
runTest("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/classFromJdk.txt");
runTest("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/classFromJdk.kt");
}
@TestMetadata("enumEntry.txt")
@TestMetadata("enumEntry.kt")
public void testEnumEntry() throws Exception {
runTest("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/enumEntry.txt");
runTest("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/enumEntry.kt");
}
@TestMetadata("memberFunction.txt")
@TestMetadata("memberFunction.kt")
public void testMemberFunction() throws Exception {
runTest("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/memberFunction.txt");
runTest("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/memberFunction.kt");
}
@TestMetadata("memberFunctionWithOverloads.txt")
@TestMetadata("memberFunctionWithOverloads.kt")
public void testMemberFunctionWithOverloads() throws Exception {
runTest("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/memberFunctionWithOverloads.txt");
runTest("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/memberFunctionWithOverloads.kt");
}
@TestMetadata("nestedClass.txt")
@TestMetadata("nestedClass.kt")
public void testNestedClass() throws Exception {
runTest("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/nestedClass.txt");
runTest("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/nestedClass.kt");
}
}
@@ -8,19 +8,25 @@ package org.jetbrains.kotlin.idea.test.framework
import org.jetbrains.kotlin.psi.psiUtil.getStartOffsetIn
object TestStructureRenderer {
fun render(testStructure: TestFileStructure, vararg expectedData: TestStructureExpectedDataBlock): String = buildString {
fun render(
testStructure: TestFileStructure,
vararg expectedData: TestStructureExpectedDataBlock,
renderingMode: RenderingMode = RenderingMode.EVERY_LINE_WITH_SINGLE_LINE_COMMENT,
): String =
render(testStructure, expectedData.toList(), renderingMode)
fun render(
testStructure: TestFileStructure,
expectedData: List<TestStructureExpectedDataBlock>,
renderingMode: RenderingMode = RenderingMode.EVERY_LINE_WITH_SINGLE_LINE_COMMENT
): String = buildString {
renderFiles(testStructure)
renderExpectedData(expectedData.toList())
appendLine()
renderExpectedData(expectedData, renderingMode)
renderCaretSymbol(testStructure)
renderExpressionTag(testStructure)
}
fun render(testStructure: TestFileStructure, expectedData: List<TestStructureExpectedDataBlock>): String = buildString {
renderFiles(testStructure)
renderExpectedData(expectedData)
renderCaretSymbol(testStructure)
}
private fun StringBuilder.renderCaretSymbol(testStructure: TestFileStructure) {
testStructure.caretPosition?.let { position ->
insert(position, KtTest.CARET_SYMBOL)
@@ -45,29 +51,33 @@ object TestStructureRenderer {
}
}
private fun StringBuilder.renderExpectedData(expectedData: List<TestStructureExpectedDataBlock>) {
if (expectedData.isNotEmpty()) {
appendLine(KtTest.RESULT_DIRECTIVE)
appendLine()
expectedData.forEach { block ->
renderExpectedDataBlock(block)
private fun StringBuilder.renderExpectedData(expectedData: List<TestStructureExpectedDataBlock>, renderingMode: RenderingMode) {
if (expectedData.isEmpty()) return
appendLine(KtTest.RESULT_DIRECTIVE)
if (renderingMode == RenderingMode.ALL_BLOCKS_IN_MULTI_LINE_COMMENT) {
appendLine("/*")
}
expectedData.forEachIndexed { index, block ->
renderExpectedDataBlock(
block,
asSingleLineComment = renderingMode == RenderingMode.EVERY_LINE_WITH_SINGLE_LINE_COMMENT
)
if (index != expectedData.lastIndex) {
appendLine()
}
}
if (renderingMode == RenderingMode.ALL_BLOCKS_IN_MULTI_LINE_COMMENT) {
appendLine("*/")
}
}
private fun StringBuilder.renderExpectedDataBlock(block: TestStructureExpectedDataBlock) {
block.name?.let { name -> appendLine("// $name") }
block.values.forEach { value ->
if (value.lines().size > 1) {
appendLine(
"""|/*
|${value.trim()}
|*/
""".trimMargin()
)
} else {
appendLine("// $value")
private fun StringBuilder.renderExpectedDataBlock(block: TestStructureExpectedDataBlock, asSingleLineComment: Boolean) {
val singleLineCommentPrefix = if (asSingleLineComment) "// " else ""
block.name?.let { name -> appendLine("$singleLineCommentPrefix$name") }
block.values.forEachIndexed { index, value ->
appendLine("$singleLineCommentPrefix${value.trim()}")
if (index != block.values.lastIndex && !asSingleLineComment) {
appendLine()
}
}
}
@@ -77,4 +87,9 @@ object TestStructureRenderer {
appendLine(file.psiFile.text)
appendLine()
}
enum class RenderingMode {
EVERY_LINE_WITH_SINGLE_LINE_COMMENT,
ALL_BLOCKS_IN_MULTI_LINE_COMMENT
}
}