diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index d5469712fb2..2f93f03855c 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -90,6 +90,7 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.AbstractSessionsInva import org.jetbrains.kotlin.idea.fir.low.level.api.trackers.AbstractProjectWideOutOfBlockKotlinModificationTrackerTest import org.jetbrains.kotlin.idea.folding.AbstractKotlinFoldingTest import org.jetbrains.kotlin.idea.frontend.api.components.AbstractExpectedExpressionTypeTest +import org.jetbrains.kotlin.idea.frontend.api.components.AbstractHLExpressionTypeTest import org.jetbrains.kotlin.idea.frontend.api.components.AbstractOverriddenDeclarationProviderTest import org.jetbrains.kotlin.idea.frontend.api.components.AbstractReturnExpressionTargetTest import org.jetbrains.kotlin.idea.frontend.api.fir.AbstractResolveCallTest @@ -1046,6 +1047,10 @@ fun main(args: Array) { testClass { model("components/overridenDeclarations") } + + testClass { + model("components/expressionType") + } } testGroup("idea/idea-frontend-fir/idea-fir-low-level-api/tests", "idea/testData") { diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FirElementsRecorder.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FirElementsRecorder.kt index dd9694b6a7d..aa054500947 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FirElementsRecorder.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FirElementsRecorder.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.file.structure import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.realPsi import org.jetbrains.kotlin.fir.references.* import org.jetbrains.kotlin.fir.types.FirErrorTypeRef @@ -54,12 +55,16 @@ internal open class FirElementsRecorder : FirVisitor) { - (element.realPsi as? KtElement)?.let { psi -> - cache(psi, element, data) - } + cacheElement(element, data) element.acceptChildren(this, data) } + override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: MutableMap) { + cacheElement(variableAssignment.lValue, data) // FirReference is not cached by default + visitElement(variableAssignment, data) + } + + //@formatter:off override fun visitReference(reference: FirReference, data: MutableMap) {} override fun visitControlFlowGraphReference(controlFlowGraphReference: FirControlFlowGraphReference, data: MutableMap) {} @@ -85,6 +90,12 @@ internal open class FirElementsRecorder : FirVisitor) { + (element.realPsi as? KtElement)?.let { psi -> + cache(psi, element, cache) + } + } + companion object { @OptIn(ExperimentalStdlibApi::class) fun recordElementsFrom(firDeclaration: FirDeclaration, recorder: FirElementsRecorder): Map = diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirExpressionTypeProvider.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirExpressionTypeProvider.kt index 19ab4a10e10..ca757bf3d16 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirExpressionTypeProvider.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirExpressionTypeProvider.kt @@ -11,7 +11,14 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.argumentMapping import org.jetbrains.kotlin.fir.psi +import org.jetbrains.kotlin.fir.references.FirErrorNamedReference +import org.jetbrains.kotlin.fir.references.FirNamedReference +import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference +import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError +import org.jetbrains.kotlin.fir.types.ConeClassErrorType +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.coneType +import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFir import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirOfType import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirSafe import org.jetbrains.kotlin.idea.frontend.api.ValidityToken @@ -20,6 +27,7 @@ import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtTypedSymbol import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.idea.references.FirReferenceResolveHelper import org.jetbrains.kotlin.psi.* internal class KtFirExpressionTypeProvider( @@ -32,7 +40,23 @@ internal class KtFirExpressionTypeProvider( } override fun getKtExpressionType(expression: KtExpression): KtType = withValidityAssertion { - expression.getOrBuildFirOfType(firResolveState).typeRef.coneType.asKtType() + val coneType = when (val fir = expression.getOrBuildFir(firResolveState)) { + is FirExpression -> fir.typeRef.coneType + is FirNamedReference -> fir.getReferencedElementType() + else -> error("Unexpected ${fir::class}") + } + coneType.asKtType() + } + + private fun FirNamedReference.getReferencedElementType(): ConeKotlinType { + val symbols = when (this) { + is FirResolvedNamedReference -> listOf(resolvedSymbol) + is FirErrorNamedReference -> FirReferenceResolveHelper.getFirSymbolsByErrorNamedReference(this) + else -> error("Unexpected ${this::class}") + } + val firCallableDeclaration = symbols.singleOrNull()?.fir as? FirCallableDeclaration<*> + return firCallableDeclaration?.returnTypeRef?.coneType + ?: ConeClassErrorType(ConeUnresolvedNameError(name)) } override fun getExpectedType(expression: PsiElement): KtType? = diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt index 4b1176dcb3c..850a7104819 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeWrongNumberOfTypeArgumen import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.idea.fir.getCandidateSymbols @@ -174,12 +175,19 @@ internal object FirReferenceResolveHelper { is FirReturnExpression -> getSymbolsByReturnExpression(expression, fir, symbolBuilder) is FirErrorNamedReference -> getSymbolsByErrorNamedReference(fir, symbolBuilder) is FirVariableAssignment -> getSymbolsByVariableAssignment(fir, session, symbolBuilder) + is FirResolvedNamedReference -> getSymbolByResolvedNameReference(fir, session, symbolBuilder) is FirResolvable -> getSymbolsByResolvable(fir, expression, session, symbolBuilder) is FirNamedArgumentExpression -> getSymbolsByNameArgumentExpression(expression, analysisSession, symbolBuilder) else -> handleUnknownFirElement(expression, analysisSession, session, symbolBuilder) } } + private fun getSymbolByResolvedNameReference( + fir: FirResolvedNamedReference, + session: FirSession, + symbolBuilder: KtSymbolByFirBuilder + ): Collection = fir.toTargetSymbol(session, symbolBuilder) + private fun KtSimpleNameExpression.isSyntheticOperatorReference() = when (this) { is KtOperationReferenceExpression -> operationSignTokenType in syntheticTokenTypes else -> false @@ -265,19 +273,24 @@ internal object FirReferenceResolveHelper { return calleeReference.toTargetSymbol(session, symbolBuilder) } + private fun getSymbolsByErrorNamedReference( fir: FirErrorNamedReference, symbolBuilder: KtSymbolByFirBuilder - ): List { - val candidates = when (val diagnostic = fir.diagnostic) { - is ConeAmbiguityError -> diagnostic.candidates - is ConeOperatorAmbiguityError -> diagnostic.candidates - is ConeInapplicableCandidateError -> listOf(diagnostic.candidate.symbol) - else -> emptyList() - } - return candidates.mapNotNull { it.fir.buildSymbol(symbolBuilder) } + ): List = + getFirSymbolsByErrorNamedReference(fir).mapNotNull { it.fir.buildSymbol(symbolBuilder) } + + + fun getFirSymbolsByErrorNamedReference( + errorNamedReference: FirErrorNamedReference, + ): Collection> = when (val diagnostic = errorNamedReference.diagnostic) { + is ConeAmbiguityError -> diagnostic.candidates + is ConeOperatorAmbiguityError -> diagnostic.candidates + is ConeInapplicableCandidateError -> listOf(diagnostic.candidate.symbol) + else -> emptyList() } + private fun getSymbolsByReturnExpression( expression: KtSimpleNameExpression, fir: FirReturnExpression, diff --git a/idea/idea-frontend-fir/testData/components/expressionType/assignmentExpressionTarget.kt b/idea/idea-frontend-fir/testData/components/expressionType/assignmentExpressionTarget.kt new file mode 100644 index 00000000000..5e9c2cbc3bd --- /dev/null +++ b/idea/idea-frontend-fir/testData/components/expressionType/assignmentExpressionTarget.kt @@ -0,0 +1,9 @@ +fun test(s: String) { + var i: Int = 0 + i = s.length +} +// RESULT + +// expression: i +// type: kotlin.Int + diff --git a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/components/AbstractHLExpressionTypeTest.kt b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/components/AbstractHLExpressionTypeTest.kt new file mode 100644 index 00000000000..8a5de39743a --- /dev/null +++ b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/components/AbstractHLExpressionTypeTest.kt @@ -0,0 +1,34 @@ +/* + * 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.components + +import org.jetbrains.kotlin.idea.executeOnPooledThreadInReadAction +import org.jetbrains.kotlin.idea.frontend.api.analyze +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.idea.util.application.executeOnPooledThread +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.test.KotlinTestUtils + +abstract class AbstractHLExpressionTypeTest : AbstractKtIdeaTest() { + override fun doTestByFileStructure(fileStructure: TestFileStructure) { + val expression = fileStructure.mainFile.selectedExpression as KtExpression? + ?: error("Selected expression was not provided") + val type = executeOnPooledThreadInReadAction { + analyze(expression) { expression.getKtType().render() } + } + val actual = TestStructureRenderer.render( + fileStructure, + TestStructureExpectedDataBlock( + "expression: ${expression.text}", + "type: $type" + ) + ) + KotlinTestUtils.assertEqualsToFile(fileStructure.filePath.toFile(), actual) + } +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/components/HLExpressionTypeTestGenerated.java b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/components/HLExpressionTypeTestGenerated.java new file mode 100644 index 00000000000..d9d06e6d401 --- /dev/null +++ b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/components/HLExpressionTypeTestGenerated.java @@ -0,0 +1,36 @@ +/* + * 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.components; + +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/components/expressionType") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class HLExpressionTypeTestGenerated extends AbstractHLExpressionTypeTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInExpressionType() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/testData/components/expressionType"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("assignmentExpressionTarget.kt") + public void testAssignmentExpressionTarget() throws Exception { + runTest("idea/idea-frontend-fir/testData/components/expressionType/assignmentExpressionTarget.kt"); + } +} diff --git a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/test/framework/AbstractKtIdeaTest.kt b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/test/framework/AbstractKtIdeaTest.kt index 6b2d0c2325e..5fc25d2cf79 100644 --- a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/test/framework/AbstractKtIdeaTest.kt +++ b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/test/framework/AbstractKtIdeaTest.kt @@ -6,7 +6,10 @@ package org.jetbrains.kotlin.idea.test.framework import com.intellij.openapi.util.io.FileUtil +import com.intellij.psi.PsiElement +import com.intellij.psi.util.parentOfType import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase +import org.jetbrains.kotlin.psi.KtFile import java.io.File abstract class AbstractKtIdeaTest : KotlinLightCodeInsightFixtureTestCase() { @@ -30,7 +33,7 @@ abstract class AbstractKtIdeaTest : KotlinLightCodeInsightFixtureTestCase() { filePath = testDataFile.toPath(), caretPosition = getCaretPosition(text), directives = directives, - mainFile = mainFile as TestFile.KtTestFile, + mainFile = mainFile as TestFile.KtTestRootFile, otherFiles = testFiles ) } @@ -51,12 +54,14 @@ abstract class AbstractKtIdeaTest : KotlinLightCodeInsightFixtureTestCase() { } private fun createTestFile(file: FileSplitter.FileNameWithText, isMainFile: Boolean): TestFile { - val psiFile = if (isMainFile) { - myFixture.configureByText(file.name, file.text) + return if (isMainFile) { + val (ktFile, expression) = SelectedExpressionProvider.getFileWithSelectedExpressions(file.text) { + myFixture.configureByText(file.name, it) as KtFile + } + TestFile.KtTestRootFile(ktFile, expression) } else { - myFixture.addFileToProject(file.name, file.text) + TestFile.createByPsiFile(myFixture.addFileToProject(file.name, file.text)) } - return TestFile.createByPsiFile(psiFile) } abstract fun doTestByFileStructure(fileStructure: TestFileStructure) @@ -68,7 +73,7 @@ private object FileSplitter { fun splitIntoFiles(text: String, defaultName: String): List { val result = mutableListOf() val stopAt = text.indexOfOrNull(KtTest.RESULT_DIRECTIVE) ?: text.length - var index = text.indexOfOrNull(KtTest.FILE_DIRECTIVE) ?: return listOf(FileNameWithText(defaultName, text)) + var index = text.indexOfOrNull(KtTest.FILE_DIRECTIVE) ?: return listOf(FileNameWithText(defaultName, text.substring(0, stopAt).trim())) while (index < stopAt) { val eolIndex = text.indexOfOrNull("\n", index) ?: text.length val fileName = text.substring(index + KtTest.FILE_DIRECTIVE.length, eolIndex).trim() diff --git a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/test/framework/SelectedExpressionProvider.kt b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/test/framework/SelectedExpressionProvider.kt new file mode 100644 index 00000000000..cfc4337f52a --- /dev/null +++ b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/test/framework/SelectedExpressionProvider.kt @@ -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.test.framework + +import com.intellij.openapi.util.TextRange +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.psiUtil.elementsInRange + +object SelectedExpressionProvider { + fun getFileWithSelectedExpressions(fileText: String, createKtFile: (text: String) -> KtFile): KtFileWithSelectedExpression { + val fileTextWithoutTags = fileText.replace(TAGS.OPENING_EXPRESSION_TAG, "").replace(TAGS.CLOSING_EXPRESSION_TAG, "") + val ktFile = createKtFile(fileTextWithoutTags) + val selectedExpression = run { + val startCaretPosition = fileText.indexOf(TAGS.OPENING_EXPRESSION_TAG) + if (startCaretPosition < 0) { + return KtFileWithSelectedExpression(ktFile, selectedExpression = null) + } + val endCaretPosition = fileText.indexOf(TAGS.CLOSING_EXPRESSION_TAG) + if (endCaretPosition < 0) { + error("${TAGS.CLOSING_EXPRESSION_TAG} was not found in the file") + } + val elements = ktFile.elementsInRange(TextRange(startCaretPosition, endCaretPosition - TAGS.OPENING_EXPRESSION_TAG.length)) + if (elements.size != 1) { + error("Expected one element at rage but found ${elements.size} [${elements.joinToString { it.text }}]") + } + elements.single() as KtElement + } + return KtFileWithSelectedExpression(ktFile, selectedExpression) + } + + data class KtFileWithSelectedExpression(val file: KtFile, val selectedExpression: KtElement?) + + object TAGS { + const val OPENING_EXPRESSION_TAG = "" + const val CLOSING_EXPRESSION_TAG = "" + } +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/test/framework/TestFileStructure.kt b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/test/framework/TestFileStructure.kt index 336f9cc5287..be8d2771f67 100644 --- a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/test/framework/TestFileStructure.kt +++ b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/test/framework/TestFileStructure.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.idea.test.framework import com.intellij.psi.PsiFile import com.intellij.psi.PsiJavaFile +import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile import java.nio.file.Path @@ -14,7 +15,7 @@ class TestFileStructure( val filePath: Path, val caretPosition: Int?, val directives: TestFileDirectives, - val mainFile: TestFile.KtTestFile, + val mainFile: TestFile.KtTestRootFile, val otherFiles: List, ) { val mainKtFile: KtFile @@ -23,7 +24,9 @@ class TestFileStructure( val allFiles: List = listOf(mainFile) + otherFiles } -data class TestStructureExpectedDataBlock(val name: String, val values: List) +data class TestStructureExpectedDataBlock(val name: String? = null, val values: List) { + constructor(vararg values: String) : this(name = null, values.toList()) +} class TestFileDirectives( private val directives: Map @@ -44,6 +47,7 @@ sealed class TestFile { abstract val psiFile: PsiFile data class KtTestFile(override val psiFile: KtFile) : TestFile() + data class KtTestRootFile(override val psiFile: KtFile, val selectedExpression: KtElement?) : TestFile() data class JavaTestFile(override val psiFile: PsiJavaFile) : TestFile() companion object { diff --git a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/test/framework/TestStructureRenderer.kt b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/test/framework/TestStructureRenderer.kt index 97b7f6680ec..49becf86c32 100644 --- a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/test/framework/TestStructureRenderer.kt +++ b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/test/framework/TestStructureRenderer.kt @@ -5,7 +5,16 @@ 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 { + renderFiles(testStructure) + renderExpectedData(expectedData.toList()) + renderCaretSymbol(testStructure) + renderExpressionTag(testStructure) + } + fun render(testStructure: TestFileStructure, expectedData: List): String = buildString { renderFiles(testStructure) renderExpectedData(expectedData) @@ -18,6 +27,14 @@ object TestStructureRenderer { } } + private fun StringBuilder.renderExpressionTag(testStructure: TestFileStructure) { + testStructure.mainFile.selectedExpression?.let { expression -> + val offset = expression.getStartOffsetIn(testStructure.mainKtFile) + insert(offset + expression.textLength, SelectedExpressionProvider.TAGS.CLOSING_EXPRESSION_TAG) + insert(offset, SelectedExpressionProvider.TAGS.OPENING_EXPRESSION_TAG) + } + } + private fun StringBuilder.renderFiles(testStructure: TestFileStructure) { if (testStructure.otherFiles.isEmpty()) { appendLine(testStructure.mainFile.psiFile.text) @@ -40,7 +57,7 @@ object TestStructureRenderer { } private fun StringBuilder.renderExpectedDataBlock(block: TestStructureExpectedDataBlock) { - appendLine("// ${block.name}") + block.name?.let { name -> appendLine("// $name") } block.values.forEach { value -> appendLine("// $value") } diff --git a/idea/testData/fir/lazyResolve/inInit/results.txt b/idea/testData/fir/lazyResolve/inInit/results.txt index 8c81a2ab205..00e3f438aee 100644 --- a/idea/testData/fir/lazyResolve/inInit/results.txt +++ b/idea/testData/fir/lazyResolve/inInit/results.txt @@ -1 +1 @@ -this@R|/Foo|.R|/Foo.x| = Int(42) \ No newline at end of file +R|/Foo.x| \ No newline at end of file diff --git a/idea/testData/fir/lazyResolve/inSecondary/results.txt b/idea/testData/fir/lazyResolve/inSecondary/results.txt index 8c81a2ab205..00e3f438aee 100644 --- a/idea/testData/fir/lazyResolve/inSecondary/results.txt +++ b/idea/testData/fir/lazyResolve/inSecondary/results.txt @@ -1 +1 @@ -this@R|/Foo|.R|/Foo.x| = Int(42) \ No newline at end of file +R|/Foo.x| \ No newline at end of file