From 5cfac8fa3fc0f90ea16dea48afd24359faf292c7 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Mon, 29 Jun 2020 17:20:28 +0300 Subject: [PATCH] FIR IDE: introduce symbol pointers for restoring symbols in another read action fix pointer --- .../kotlin/generators/tests/GenerateTests.kt | 5 ++ .../frontend/api/ImplicitReceiverSmartCast.kt | 2 + .../idea/frontend/api/KtAnalysisSession.kt | 1 + .../idea/frontend/api/KtTypeArgument.kt | 2 + .../api/symbols/DebugSymbolRenderer.kt | 2 +- .../frontend/api/symbols/KtClassLikeSymbol.kt | 2 + .../api/symbols/KtFunctionLikeSymbol.kt | 2 + .../frontend/api/symbols/KtPackageSymbol.kt | 2 + .../idea/frontend/api/symbols/KtSymbol.kt | 2 + .../frontend/api/symbols/KtSymbolPointer.kt | 35 +++++++++++++ .../idea/frontend/api/symbols/markers.kt | 2 +- .../idea/frontend/api/{ => types}/KtType.kt | 4 +- .../symbols/KtFirAnonymousFunctionSymbol.kt | 2 + .../fir/symbols/KtFirClassOrObjectSymbol.kt | 6 +++ .../api/fir/symbols/KtFirConstructorSymbol.kt | 20 +++++-- .../api/fir/symbols/KtFirPackageSymbol.kt | 6 +-- .../testData/symbolPointer/class.kt | 2 + .../symbolPointer/classPrimaryConstructor.kt | 2 + .../api/symbols/AbstractSymbolPointerTest.kt | 52 +++++++++++++++++++ .../symbols/SymbolPointerTestGenerated.java | 40 ++++++++++++++ 20 files changed, 180 insertions(+), 11 deletions(-) create mode 100644 idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolPointer.kt rename idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/{ => types}/KtType.kt (88%) create mode 100644 idea/idea-frontend-fir/testData/symbolPointer/class.kt create mode 100644 idea/idea-frontend-fir/testData/symbolPointer/classPrimaryConstructor.kt create mode 100644 idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/AbstractSymbolPointerTest.kt create mode 100644 idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/SymbolPointerTestGenerated.java diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index a8ddffc4880..2abe8a9c2d1 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -89,6 +89,7 @@ import org.jetbrains.kotlin.idea.fir.AbstractKtDeclarationAndFirDeclarationEqual import org.jetbrains.kotlin.idea.folding.AbstractKotlinFoldingTest import org.jetbrains.kotlin.idea.frontend.api.fir.AbstractResolveCallTest import org.jetbrains.kotlin.idea.frontend.api.symbols.AbstractStdlibSymbolsBuildingTest +import org.jetbrains.kotlin.idea.frontend.api.symbols.AbstractSymbolPointerTest import org.jetbrains.kotlin.idea.frontend.api.symbols.AbstractSymbolsByPsiBuildingTest import org.jetbrains.kotlin.idea.hierarchy.AbstractHierarchyTest import org.jetbrains.kotlin.idea.hierarchy.AbstractHierarchyWithLibTest @@ -952,6 +953,10 @@ fun main(args: Array) { testClass { model("stdLibSymbols", extension = "txt") } + + testClass { + model("symbolPointer", extension = "kt") + } } testGroup("idea/idea-frontend-fir/idea-fir-low-level-api/tests", "idea/testData") { diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/ImplicitReceiverSmartCast.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/ImplicitReceiverSmartCast.kt index 9c6259356ec..5e63a8a034b 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/ImplicitReceiverSmartCast.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/ImplicitReceiverSmartCast.kt @@ -5,6 +5,8 @@ package org.jetbrains.kotlin.idea.frontend.api +import org.jetbrains.kotlin.idea.frontend.api.types.KtType + data class ImplicitReceiverSmartCast(val types: Collection, val kind: ImplicitReceiverSmartcastKind) enum class ImplicitReceiverSmartcastKind { diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt index 859f0378167..fc1f90e7595 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.frontend.api import com.intellij.openapi.project.Project import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.idea.frontend.api.symbols.* +import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.psi.* diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtTypeArgument.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtTypeArgument.kt index 2aa92b8dc24..bc00b24824f 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtTypeArgument.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtTypeArgument.kt @@ -5,6 +5,8 @@ package org.jetbrains.kotlin.idea.frontend.api +import org.jetbrains.kotlin.idea.frontend.api.types.KtType + sealed class KtTypeArgument object KtStarProjectionTypeArgument : KtTypeArgument() diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/DebugSymbolRenderer.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/DebugSymbolRenderer.kt index c3bf437511e..6fcdefd1c40 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/DebugSymbolRenderer.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/DebugSymbolRenderer.kt @@ -5,7 +5,7 @@ package org.jetbrains.kotlin.idea.frontend.api.symbols -import org.jetbrains.kotlin.idea.frontend.api.KtType +import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtClassLikeSymbol.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtClassLikeSymbol.kt index 19b21768ab3..177704b7c2b 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtClassLikeSymbol.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtClassLikeSymbol.kt @@ -18,6 +18,8 @@ abstract class KtTypeAliasSymbol : KtClassLikeSymbol() { abstract class KtClassOrObjectSymbol : KtClassLikeSymbol(), KtSymbolWithTypeParameters, KtSymbolWithModality { abstract val classKind: KtClassKind + + abstract override fun createPointer(): KtSymbolPointer } enum class KtClassKind { diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtFunctionLikeSymbol.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtFunctionLikeSymbol.kt index d2012a9dd34..fdcafadfeb2 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtFunctionLikeSymbol.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtFunctionLikeSymbol.kt @@ -32,4 +32,6 @@ abstract class KtConstructorSymbol : KtFunctionLikeSymbol() { abstract override val valueParameters: List abstract val isPrimary: Boolean abstract val owner: KtClassOrObjectSymbol + + abstract override fun createPointer(): KtSymbolPointer } \ No newline at end of file diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtPackageSymbol.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtPackageSymbol.kt index 53c89de7865..8ef9e19c571 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtPackageSymbol.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtPackageSymbol.kt @@ -9,4 +9,6 @@ import org.jetbrains.kotlin.name.FqName abstract class KtPackageSymbol : KtSymbol { abstract val fqName: FqName + + abstract override fun createPointer(): KtSymbolPointer } \ No newline at end of file diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbol.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbol.kt index 3226e468b34..e923ea4038c 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbol.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbol.kt @@ -11,6 +11,8 @@ import org.jetbrains.kotlin.idea.frontend.api.ValidityOwner interface KtSymbol : ValidityOwner { val origin: KtSymbolOrigin val psi: PsiElement? + + fun createPointer(): KtSymbolPointer = NonRestorableKtSymbolPointer } enum class KtSymbolOrigin { diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolPointer.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolPointer.kt new file mode 100644 index 00000000000..5bd7a5e4c1c --- /dev/null +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolPointer.kt @@ -0,0 +1,35 @@ +/* + * 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 + +/** + * `KtSymbol` is valid only during read action it was created in + * To pass the symbol from one read action to another the KtSymbolPointer should be used + * + * We can restore the symbol + * * for function & property symbol if its signature was not changed + * * for local variable symbol if code block it was declared in was not changed + * * for class & type alias symbols if its qualified name was not changed + * * for package symbol if the package is still exists + * + * @see org.jetbrains.kotlin.idea.frontend.api.ReadActionConfinementValidityToken + */ +interface KtSymbolPointer { + /** + * @return restored symbol (possibly the new symbol instance) if one is still valid, `null` otherwise + */ + fun restoreSymbol(analysisSession: KtAnalysisSession): S? +} + +object NonRestorableKtSymbolPointer : KtSymbolPointer { + override fun restoreSymbol(analysisSession: KtAnalysisSession): Nothing? = null +} + +inline fun symbolPointer(crossinline getSymbol: (KtAnalysisSession) -> S?) = object : KtSymbolPointer { + override fun restoreSymbol(analysisSession: KtAnalysisSession): S? = getSymbol(analysisSession) +} \ No newline at end of file diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/markers.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/markers.kt index 2c1fc16a833..3c0f23877b7 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/markers.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/markers.kt @@ -5,7 +5,7 @@ package org.jetbrains.kotlin.idea.frontend.api.symbols -import org.jetbrains.kotlin.idea.frontend.api.KtType +import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.name.Name interface KtNamedSymbol : KtSymbol { diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtType.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/types/KtType.kt similarity index 88% rename from idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtType.kt rename to idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/types/KtType.kt index ca33b85b4cc..dbc4ad51acb 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtType.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/types/KtType.kt @@ -3,8 +3,10 @@ * 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 +package org.jetbrains.kotlin.idea.frontend.api.types +import org.jetbrains.kotlin.idea.frontend.api.KtTypeArgument +import org.jetbrains.kotlin.idea.frontend.api.ValidityOwner import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol import org.jetbrains.kotlin.name.ClassId diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirAnonymousFunctionSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirAnonymousFunctionSymbol.kt index 55eb3c54ace..a10bd13df32 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirAnonymousFunctionSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirAnonymousFunctionSymbol.kt @@ -31,4 +31,6 @@ internal class KtFirAnonymousFunctionSymbol( builder.buildParameterSymbol(valueParameter) } } + + override fun createPointer(): KtSymbolPointer = NonRestorableKtSymbolPointer } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirClassOrObjectSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirClassOrObjectSymbol.kt index a3365bf44f6..1495ff68f02 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirClassOrObjectSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirClassOrObjectSymbol.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.idea.fir.findPsi +import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.ValidityOwner import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder import org.jetbrains.kotlin.idea.frontend.api.fir.utils.ReadOnlyWeakRef @@ -57,4 +58,9 @@ internal class KtFirClassOrObjectSymbol( else -> KtSymbolKind.TOP_LEVEL } } + + override fun createPointer(): KtSymbolPointer { + val classId = classId + return symbolPointer { session -> session.symbolProvider.getClassOrObjectSymbolByClassId(classId) } + } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirConstructorSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirConstructorSymbol.kt index 5b5cb6ae69d..1ca16030522 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirConstructorSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirConstructorSymbol.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols import com.intellij.psi.PsiElement import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirRegularClass +import org.jetbrains.kotlin.fir.declarations.getPrimaryConstructorIfAny import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.idea.fir.findPsi @@ -16,10 +17,7 @@ import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef -import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol -import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorParameterSymbol -import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorSymbol -import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind +import org.jetbrains.kotlin.idea.frontend.api.symbols.* import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion internal class KtFirConstructorSymbol( @@ -49,4 +47,18 @@ internal class KtFirConstructorSymbol( check(firClass is FirRegularClass) { "Owner class for constructor should be FirRegularClass, but ${firClass::class} was met" } builder.buildClassSymbol(firClass) } + + override fun createPointer(): KtSymbolPointer = withValidityAssertion { + if (!isPrimary) { + // TODO for now we can not find symbol for member function :( + return NonRestorableKtSymbolPointer + } + val ownerClassId = owner.classId + return symbolPointer { session -> + val ownerSymbol = session.symbolProvider.getClassOrObjectSymbolByClassId(ownerClassId) ?: return@symbolPointer null + check(ownerSymbol is KtFirSymbol<*>) + val classFir = (ownerSymbol.fir as? FirRegularClass) ?: error("FirRegularClass expected but ${ownerSymbol.fir::class} found") + classFir.getPrimaryConstructorIfAny()?.let(builder::buildConstructorSymbol) + } + } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPackageSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPackageSymbol.kt index c46afb6a61c..217da38a42c 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPackageSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPackageSymbol.kt @@ -13,12 +13,10 @@ import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.idea.frontend.api.ValidityOwner import org.jetbrains.kotlin.idea.frontend.api.ValidityOwnerByValidityToken import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached -import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPackageSymbol -import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin -import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolPointer -import org.jetbrains.kotlin.idea.frontend.api.symbols.symbolPointer import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil +import org.jetbrains.kotlin.idea.frontend.api.symbols.* import org.jetbrains.kotlin.name.FqName class KtFirPackageSymbol( diff --git a/idea/idea-frontend-fir/testData/symbolPointer/class.kt b/idea/idea-frontend-fir/testData/symbolPointer/class.kt new file mode 100644 index 00000000000..a7ca22abab4 --- /dev/null +++ b/idea/idea-frontend-fir/testData/symbolPointer/class.kt @@ -0,0 +1,2 @@ +class A { +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/testData/symbolPointer/classPrimaryConstructor.kt b/idea/idea-frontend-fir/testData/symbolPointer/classPrimaryConstructor.kt new file mode 100644 index 00000000000..161cb193d08 --- /dev/null +++ b/idea/idea-frontend-fir/testData/symbolPointer/classPrimaryConstructor.kt @@ -0,0 +1,2 @@ +class A() { +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/AbstractSymbolPointerTest.kt b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/AbstractSymbolPointerTest.kt new file mode 100644 index 00000000000..2645f0a9ab5 --- /dev/null +++ b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/AbstractSymbolPointerTest.kt @@ -0,0 +1,52 @@ +/* + * 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 com.intellij.openapi.util.io.FileUtil +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.idea.addExternalTestFiles +import org.jetbrains.kotlin.idea.executeOnPooledThreadInReadAction +import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession +import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase +import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor +import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType +import org.jetbrains.kotlin.test.KotlinTestUtils +import org.junit.Assert +import java.io.File + +abstract class AbstractSymbolPointerTest : KotlinLightCodeInsightFixtureTestCase() { + protected fun doTest(path: String) { + val file = File(path) + val ktFile = myFixture.configureByText(file.name, FileUtil.loadFile(file)) as KtFile + + val pointers = executeOnPooledThreadInReadAction { + val analysisSession = KtFirAnalysisSession(ktFile) + val declarationSymbols = ktFile.collectDescendantsOfType().map { declaration -> + analysisSession.symbolProvider.getSymbol(declaration) + } + declarationSymbols.map { PointerWithPsi(it.createPointer(), it.psi!!) } + } + + // another read action + executeOnPooledThreadInReadAction { + val analysisSession = KtFirAnalysisSession(ktFile) + pointers.forEach { (pointer, psi) -> + val restored = pointer.restoreSymbol(analysisSession) ?: error("Symbol $psi was not not restored correctly") + Assert.assertEquals(restored.psi!!, psi) + } + } + } +} + +private data class PointerWithPsi(val pointer: KtSymbolPointer<*>, val psi: PsiElement) \ No newline at end of file diff --git a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/SymbolPointerTestGenerated.java b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/SymbolPointerTestGenerated.java new file mode 100644 index 00000000000..1f4bca61363 --- /dev/null +++ b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/SymbolPointerTestGenerated.java @@ -0,0 +1,40 @@ +/* + * 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 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/testData/symbolPointer") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class SymbolPointerTestGenerated extends AbstractSymbolPointerTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInSymbolPointer() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/testData/symbolPointer"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("class.kt") + public void testClass() throws Exception { + runTest("idea/idea-frontend-fir/testData/symbolPointer/class.kt"); + } + + @TestMetadata("classPrimaryConstructor.kt") + public void testClassPrimaryConstructor() throws Exception { + runTest("idea/idea-frontend-fir/testData/symbolPointer/classPrimaryConstructor.kt"); + } +}