diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 007946df000..133dee60fc4 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -45,7 +45,6 @@ import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractCodeInsightActionT import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractGenerateHashCodeAndEqualsActionTest import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractGenerateTestSupportMethodActionTest import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractGenerateToStringActionTest -import org.jetbrains.kotlin.idea.codeInsight.hints.AbstractKotlinLambdasHintsProvider import org.jetbrains.kotlin.idea.codeInsight.hints.AbstractKotlinReferenceTypeHintsProviderTest import org.jetbrains.kotlin.idea.codeInsight.moveUpDown.AbstractMoveLeftRightTest import org.jetbrains.kotlin.idea.codeInsight.moveUpDown.AbstractMoveStatementTest @@ -91,8 +90,9 @@ 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.scopes.AbstractMemberScopeByFqNameTest +import org.jetbrains.kotlin.idea.frontend.api.symbols.AbstractSymbolFromLibraryPointerRestoreTest import org.jetbrains.kotlin.idea.frontend.api.symbols.AbstractSymbolsByFqNameBuildingTest -import org.jetbrains.kotlin.idea.frontend.api.symbols.AbstractSymbolPointerTest +import org.jetbrains.kotlin.idea.frontend.api.symbols.AbstractSymbolFromSourcePointerRestoreTest import org.jetbrains.kotlin.idea.frontend.api.symbols.AbstractSymbolsByPsiBuildingTest import org.jetbrains.kotlin.idea.hierarchy.AbstractHierarchyTest import org.jetbrains.kotlin.idea.hierarchy.AbstractHierarchyWithLibTest @@ -970,9 +970,13 @@ fun main(args: Array) { model("memberScopeByFqName", extension = "txt") } - testClass { + testClass { model("symbolPointer", extension = "kt") } + + testClass { + model("resoreSymbolFromLibrary", extension = "txt") + } } 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/KtAnalysisSession.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt index f20b3c08006..b1a65b7baac 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 @@ -9,7 +9,6 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScopeProvider import org.jetbrains.kotlin.idea.frontend.api.symbols.* import org.jetbrains.kotlin.idea.frontend.api.types.KtType -import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeRenderer 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/symbols/DebugSymbolRenderer.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/DebugSymbolRenderer.kt index 7f9e10d900e..9e5c9a5beaa 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 @@ -9,6 +9,7 @@ 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 +import java.lang.reflect.InvocationTargetException import kotlin.reflect.KProperty import kotlin.reflect.jvm.javaGetter @@ -18,7 +19,12 @@ object DebugSymbolRenderer { appendLine("${klass.simpleName}:") klass.members.filterIsInstance>().sortedBy { it.name }.forEach { property -> if (property.name in ignoredPropertyNames) return@forEach - val value = property.javaGetter?.invoke(symbol) ?: return@forEach + val getter = property.javaGetter ?: return@forEach + val value = try { + getter.invoke(symbol) + } catch (e: InvocationTargetException) { + "Could not render due to ${e.cause}" + } val stringValue = renderValue(value) appendLine(" ${property.name}: $stringValue") } @@ -26,6 +32,7 @@ object DebugSymbolRenderer { private fun renderValue(value: Any?): String = when (value) { null -> "null" + is String -> value is Boolean -> value.toString() is Name -> value.asString() is FqName -> value.asString() diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtCallableSymbol.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtCallableSymbol.kt index 19288e840b3..2448ecd81ee 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtCallableSymbol.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtCallableSymbol.kt @@ -5,4 +5,8 @@ package org.jetbrains.kotlin.idea.frontend.api.symbols -abstract class KtCallableSymbol : KtSymbol \ No newline at end of file +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer + +abstract class KtCallableSymbol : KtSymbol { + 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/KtClassLikeSymbol.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtClassLikeSymbol.kt index 177704b7c2b..29caa164cc1 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 @@ -5,15 +5,18 @@ package org.jetbrains.kotlin.idea.frontend.api.symbols +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.name.ClassId abstract class KtClassLikeSymbol : KtSymbol, KtNamedSymbol, KtSymbolWithKind { abstract val classId: ClassId + abstract override fun createPointer(): KtSymbolPointer } abstract class KtTypeAliasSymbol : KtClassLikeSymbol() { final override val symbolKind: KtSymbolKind get() = KtSymbolKind.TOP_LEVEL + abstract override fun createPointer(): KtSymbolPointer } abstract class KtClassOrObjectSymbol : KtClassLikeSymbol(), KtSymbolWithTypeParameters, KtSymbolWithModality { 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 a5b23fbdcb4..4b813591ef4 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 @@ -5,15 +5,20 @@ package org.jetbrains.kotlin.idea.frontend.api.symbols +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName sealed class KtFunctionLikeSymbol : KtCallableSymbol(), KtTypedSymbol, KtSymbolWithKind { abstract val valueParameters: List + + abstract override fun createPointer(): KtSymbolPointer } abstract class KtAnonymousFunctionSymbol : KtFunctionLikeSymbol() { final override val symbolKind: KtSymbolKind get() = KtSymbolKind.LOCAL + + abstract override fun createPointer(): KtSymbolPointer } abstract class KtFunctionSymbol : KtFunctionLikeSymbol(), @@ -27,6 +32,8 @@ abstract class KtFunctionSymbol : KtFunctionLikeSymbol(), abstract val fqName: FqName? abstract override val valueParameters: List + + abstract override fun createPointer(): KtSymbolPointer } abstract class KtConstructorSymbol : KtFunctionLikeSymbol() { 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 8ef9e19c571..eb65ae2de76 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 @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.idea.frontend.api.symbols +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.name.FqName abstract class KtPackageSymbol : KtSymbol { 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 b9b85e01bd5..469c83002ae 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 @@ -7,12 +7,13 @@ package org.jetbrains.kotlin.idea.frontend.api.symbols import com.intellij.psi.PsiElement import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer interface KtSymbol : ValidityTokenOwner { val origin: KtSymbolOrigin val psi: PsiElement? - fun createPointer(): KtSymbolPointer = NonRestorableKtSymbolPointer + fun createPointer(): KtSymbolPointer } enum class KtSymbolOrigin { diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtTypeParameterSymbol.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtTypeParameterSymbol.kt index f39a2def411..6db6d110e89 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtTypeParameterSymbol.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtTypeParameterSymbol.kt @@ -5,6 +5,10 @@ package org.jetbrains.kotlin.idea.frontend.api.symbols -abstract class KtTypeParameterSymbol : KtSymbol, KtNamedSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer + +abstract class KtTypeParameterSymbol : KtSymbol, KtNamedSymbol { + abstract override fun createPointer(): KtSymbolPointer +} diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtVariableLikeSymbol.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtVariableLikeSymbol.kt index f4e2c1a5230..b377c97dbcd 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtVariableLikeSymbol.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtVariableLikeSymbol.kt @@ -5,39 +5,54 @@ package org.jetbrains.kotlin.idea.frontend.api.symbols +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName -abstract class KtVariableLikeSymbol : KtCallableSymbol(), KtTypedSymbol, KtNamedSymbol, KtSymbolWithKind +abstract class KtVariableLikeSymbol : KtCallableSymbol(), KtTypedSymbol, KtNamedSymbol, KtSymbolWithKind { + abstract override fun createPointer(): KtSymbolPointer +} abstract class KtEnumEntrySymbol : KtVariableLikeSymbol() { final override val symbolKind: KtSymbolKind get() = KtSymbolKind.MEMBER + abstract val enumClassId: ClassId + abstract override fun createPointer(): KtSymbolPointer } abstract class KtParameterSymbol : KtVariableLikeSymbol() { abstract val hasDefaultValue: Boolean + + abstract override fun createPointer(): KtSymbolPointer } abstract class KtVariableSymbol : KtVariableLikeSymbol() { abstract val isVal: Boolean + abstract override fun createPointer(): KtSymbolPointer } abstract class KtJavaFieldSymbol : KtVariableSymbol(), KtSymbolWithModality { final override val symbolKind: KtSymbolKind get() = KtSymbolKind.MEMBER + abstract override fun createPointer(): KtSymbolPointer } // TODO getters & setters abstract class KtPropertySymbol : KtVariableSymbol(), KtPossibleExtensionSymbol, KtSymbolWithModality { abstract val fqName: FqName + abstract override fun createPointer(): KtSymbolPointer } -abstract class KtLocalVariableSymbol : KtVariableSymbol() +abstract class KtLocalVariableSymbol : KtVariableSymbol() { + abstract override fun createPointer(): KtSymbolPointer +} abstract class KtFunctionParameterSymbol : KtParameterSymbol() { abstract val isVararg: Boolean + abstract override fun createPointer(): KtSymbolPointer } abstract class KtConstructorParameterSymbol : KtParameterSymbol(), KtNamedSymbol { abstract val constructorParameterKind: KtConstructorParameterSymbolKind + abstract override fun createPointer(): KtSymbolPointer } enum class KtConstructorParameterSymbolKind { diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/pointers/CouldNotCreateSymbolPointerException.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/pointers/CouldNotCreateSymbolPointerException.kt new file mode 100644 index 00000000000..d9d4e504e0b --- /dev/null +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/pointers/CouldNotCreateSymbolPointerException.kt @@ -0,0 +1,9 @@ +/* + * 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.pointers + +class CanNotCreateSymbolPointerForLocalLibraryDeclarationException(description: String) : + IllegalStateException("Could not create a symbol pointer for local symbol $description") \ No newline at end of file diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/pointers/KtPsiBasedSymbolPointer.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/pointers/KtPsiBasedSymbolPointer.kt new file mode 100644 index 00000000000..b218c704610 --- /dev/null +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/pointers/KtPsiBasedSymbolPointer.kt @@ -0,0 +1,30 @@ +/* + * 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.pointers + +import com.intellij.psi.SmartPsiElementPointer +import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer + +class KtPsiBasedSymbolPointer(private val psiPointer: SmartPsiElementPointer) : KtSymbolPointer() { + override fun restoreSymbol(analysisSession: KtAnalysisSession): S? { + val psi = psiPointer.element ?: return null + + @Suppress("UNCHECKED_CAST") + return analysisSession.symbolProvider.getSymbol(psi) as S? + } + + companion object { + fun createForSymbolFromSource(symbol: S): KtPsiBasedSymbolPointer? { + if (symbol.origin == KtSymbolOrigin.LIBRARY) return null + val psi = symbol.psi as? KtDeclaration ?: return null + return KtPsiBasedSymbolPointer(psi.createSmartPointer()) + } + } +} \ No newline at end of file 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/pointers/KtSymbolPointer.kt similarity index 50% rename from idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolPointer.kt rename to idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/pointers/KtSymbolPointer.kt index 5bd7a5e4c1c..33f4e3e472c 100644 --- 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/pointers/KtSymbolPointer.kt @@ -3,33 +3,33 @@ * 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 +package org.jetbrains.kotlin.idea.frontend.api.symbols.pointers import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol /** * `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 + * * for symbol which came from Kotlin source it will be restored based on [com.intellij.psi.SmartPsiElementPointer] + * * restoring symbols which came from Java source is not supported yet + * * for library symbols: + * * 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 { +abstract class KtSymbolPointer { /** * @return restored symbol (possibly the new symbol instance) if one is still valid, `null` otherwise */ - fun restoreSymbol(analysisSession: KtAnalysisSession): S? + abstract fun restoreSymbol(analysisSession: KtAnalysisSession): S? } -object NonRestorableKtSymbolPointer : KtSymbolPointer { - override fun restoreSymbol(analysisSession: KtAnalysisSession): Nothing? = null -} - -inline fun symbolPointer(crossinline getSymbol: (KtAnalysisSession) -> S?) = object : KtSymbolPointer { +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-fir/build.gradle.kts b/idea/idea-frontend-fir/build.gradle.kts index 13289ca5f94..dfe17dd1773 100644 --- a/idea/idea-frontend-fir/build.gradle.kts +++ b/idea/idea-frontend-fir/build.gradle.kts @@ -9,6 +9,7 @@ dependencies { compile(project(":idea:idea-frontend-api")) compile(project(":idea:idea-core")) compile(project(":compiler:fir:fir2ir")) + compile(project(":compiler:ir.tree")) compile(project(":compiler:fir:resolve")) compile(project(":compiler:fir:checkers")) compile(project(":compiler:fir:java")) diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeJavaModuleBasedSession.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeJavaModuleBasedSession.kt index 955584e7694..7404c775f73 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeJavaModuleBasedSession.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeJavaModuleBasedSession.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.idea.fir.low.level.api import com.intellij.openapi.module.impl.scopes.ModuleWithDependentsScope import com.intellij.openapi.project.Project -import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.analysis.registerCheckersComponent @@ -16,6 +15,7 @@ import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.extensions.registerExtensions import org.jetbrains.kotlin.fir.java.JavaSymbolProvider import org.jetbrains.kotlin.fir.resolve.calls.jvm.registerJvmCallConflictResolverFactory +import org.jetbrains.kotlin.fir.resolve.firProvider import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider @@ -48,6 +48,7 @@ internal class FirIdeJavaModuleBasedSession private constructor( moduleInfo: ModuleSourceInfo, firPhaseRunner: FirPhaseRunner, sessionProvider: FirSessionProvider, + librariesSession: FirIdeModuleLibraryDependenciesSession, ): FirIdeJavaModuleBasedSession { val scopeProvider = KotlinScopeProvider(::wrapScopeWithJvmMapped) val firBuilder = FirFileBuilder(sessionProvider as FirIdeSessionProvider, scopeProvider, firPhaseRunner) @@ -83,7 +84,7 @@ internal class FirIdeJavaModuleBasedSession private constructor( buildList { add(provider) add(JavaSymbolProvider(this@apply, sessionProvider.project, searchScope)) - add(FirIdeModuleLibraryDependenciesSession.create(moduleInfo, sessionProvider, project).firSymbolProvider) + add(librariesSession.firSymbolProvider) } ) as FirSymbolProvider ) diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeResolveStateService.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeResolveStateService.kt index 5432e936dbb..d4c0ca1a289 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeResolveStateService.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeResolveStateService.kt @@ -10,6 +10,7 @@ import com.intellij.openapi.project.Project import org.jetbrains.kotlin.idea.util.psiModificationTrackerBasedCachedValue import java.util.concurrent.ConcurrentHashMap import org.jetbrains.kotlin.idea.caches.project.* +import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeModuleLibraryDependenciesSession internal class FirIdeResolveStateService(private val project: Project) { private val stateCache by psiModificationTrackerBasedCachedValue(project) { @@ -19,14 +20,26 @@ internal class FirIdeResolveStateService(private val project: Project) { private fun createResolveStateFor(moduleInfo: IdeaModuleInfo): FirModuleResolveStateImpl { val sessionProvider = FirIdeSessionProvider(project) val firPhaseRunner = FirPhaseRunner() - val session = FirIdeJavaModuleBasedSession.create( + + val librariesSession = FirIdeModuleLibraryDependenciesSession.create(moduleInfo as ModuleSourceInfo, sessionProvider, project) + + val sourcesSession = FirIdeJavaModuleBasedSession.create( project, - moduleInfo as ModuleSourceInfo, + moduleInfo, firPhaseRunner, sessionProvider, + librariesSession, ).apply { sessionProvider.registerSession(moduleInfo, this) } - return FirModuleResolveStateImpl(moduleInfo, session, sessionProvider, session.firFileBuilder, session.cache) + + return FirModuleResolveStateImpl( + moduleInfo, + sourcesSession, + librariesSession, + sessionProvider, + sourcesSession.firFileBuilder, + sourcesSession.cache + ) } fun getResolveState(moduleInfo: IdeaModuleInfo): FirModuleResolveStateImpl = diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveState.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveState.kt index 04fb1a0b53a..f68bfd19191 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveState.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveState.kt @@ -27,7 +27,8 @@ import org.jetbrains.kotlin.psi.KtFile abstract class FirModuleResolveState { abstract val moduleInfo: IdeaModuleInfo - abstract val firSession: FirSession + abstract val firIdeSourcesSession: FirSession + abstract val firIdeLibrariesSession: FirSession abstract fun getSessionFor(moduleInfo: IdeaModuleInfo): FirSession @@ -57,7 +58,8 @@ abstract class FirModuleResolveState { internal open class FirModuleResolveStateImpl( override val moduleInfo: IdeaModuleInfo, - override val firSession: FirSession, + override val firIdeSourcesSession: FirSession, + override val firIdeLibrariesSession: FirSession, private val sessionProvider: FirIdeSessionProvider, val firFileBuilder: FirFileBuilder, val fileCache: ModuleFileCache, diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveStateForCompletion.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveStateForCompletion.kt index c3e1c143419..f98db435234 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveStateForCompletion.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveStateForCompletion.kt @@ -24,7 +24,8 @@ internal class FirModuleResolveStateForCompletion( private val originalState: FirModuleResolveStateImpl ) : FirModuleResolveState() { override val moduleInfo: IdeaModuleInfo get() = originalState.moduleInfo - override val firSession: FirSession get() = originalState.firSession + override val firIdeSourcesSession: FirSession get() = originalState.firIdeSourcesSession + override val firIdeLibrariesSession: FirSession get() = originalState.firIdeSourcesSession private val psiToFirCache = PsiToFirCache(originalState.fileCache) diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeLibrarySession.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeLibrarySession.kt index 26a790d21ff..8414de96efc 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeLibrarySession.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeLibrarySession.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo import org.jetbrains.kotlin.idea.caches.resolve.IDEPackagePartProvider +import org.jetbrains.kotlin.idea.fir.low.level.api.IdeSessionComponents import org.jetbrains.kotlin.idea.search.minus import org.jetbrains.kotlin.load.java.JavaClassFinderImpl import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory @@ -47,7 +48,7 @@ class FirIdeModuleLibraryDependenciesSession private constructor( val javaSymbolProvider = JavaSymbolProvider(this, sessionProvider.project, searchScope) val kotlinScopeProvider = KotlinScopeProvider(::wrapScopeWithJvmMapped) - + register(IdeSessionComponents::class, IdeSessionComponents.create(this)) register( FirSymbolProvider::class, FirCompositeSymbolProvider( diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/FirUtils.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/FirUtils.kt index 9844f1e554a..66560280d00 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/FirUtils.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/FirUtils.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.fir import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSymbolOwner import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression @@ -69,13 +70,19 @@ internal fun FirReference.getResolvedKtSymbolOfNameReference(builder: KtSymbolBy builder.buildSymbol(firDeclaration) } -inline fun D.unrollFakeOverrides(): D where D : FirDeclaration, D : FirSymbolOwner<*> { +internal inline fun D.unrollFakeOverrides(): D where D : FirDeclaration, D : FirSymbolOwner<*> { val symbol = symbol if (symbol !is PossiblyFirFakeOverrideSymbol<*, *>) return this - if (!symbol.isFakeOverride) return this + if (!symbol.isFakeOrIntersectionOverride) return this var current: FirBasedSymbol<*>? = symbol.overriddenSymbol - while (current is PossiblyFirFakeOverrideSymbol<*, *> && current.isFakeOverride) { + while (current is PossiblyFirFakeOverrideSymbol<*, *> && current.isFakeOrIntersectionOverride) { current = current.overriddenSymbol } return current?.fir as D } + +private inline val FirBasedSymbol<*>.isFakeOrIntersectionOverride: Boolean + get() { + val origin = (fir as? FirDeclaration)?.origin ?: return false + return origin == FirDeclarationOrigin.FakeOverride || origin == FirDeclarationOrigin.IntersectionOverride + } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt index e6f7cdf7482..49d511bd08c 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt @@ -42,10 +42,8 @@ import org.jetbrains.kotlin.psi.* internal class KtFirAnalysisSession private constructor( private val element: KtElement, - val firSession: FirSession, val firResolveState: FirModuleResolveState, internal val firSymbolBuilder: KtSymbolByFirBuilder, - private val typeContext: ConeTypeCheckerContext, token: ValidityToken, val isContextSession: Boolean, ) : KtAnalysisSession(token) { @@ -54,7 +52,7 @@ private constructor( override val symbolProvider: KtSymbolProvider = KtFirSymbolProvider( token, - firSession.firSymbolProvider, + firResolveState.firIdeLibrariesSession.firSymbolProvider, firResolveState, firSymbolBuilder ) @@ -62,7 +60,7 @@ private constructor( private val firScopeStorage = FirScopeRegistry() override val scopeProvider: KtScopeProvider by threadLocal { - KtFirScopeProvider(token, firSymbolBuilder, project, firSession, firResolveState, firScopeStorage) + KtFirScopeProvider(token, firSymbolBuilder, project, firResolveState, firScopeStorage) } init { @@ -111,7 +109,7 @@ private constructor( assertIsValid() var result = false forEachSuperClass(klass.getOrBuildFirSafe(firResolveState) ?: return false) { type -> - result = result || type.firClassLike(firSession)?.symbol?.classId == superClassId + result = result || type.firClassLike(firResolveState.firIdeSourcesSession)?.symbol?.classId == superClassId } return result } @@ -130,10 +128,8 @@ private constructor( val contextResolveState = LowLevelFirApiFacade.getResolveStateForCompletion(element, firResolveState) return KtFirAnalysisSession( element, - firSession, contextResolveState, firSymbolBuilder.createReadOnlyCopy(contextResolveState), - typeContext, token, isContextSession = true ) @@ -149,7 +145,7 @@ private constructor( } private fun resolveCall(firCall: FirFunctionCall, callExpression: KtExpression): CallInfo? { - val session = firResolveState.firSession + val session = firResolveState.firIdeSourcesSession val resolvedFunctionSymbol = firCall.calleeReference.toTargetSymbol(session, firSymbolBuilder) val resolvedCalleeSymbol = (firCall.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol return when { @@ -204,23 +200,17 @@ private constructor( @Deprecated("Please use org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSessionProviderKt.analyze") internal fun createForElement(element: KtElement): KtFirAnalysisSession { val firResolveState = LowLevelFirApiFacade.getResolveStateFor(element) - val firSession = firResolveState.firSession val project = element.project - val typeContext = ConeTypeCheckerContext(isErrorTypeEqualsToAnything = true, isStubTypeEqualsToAnything = true, firSession) val token = ReadActionConfinementValidityToken(project) val firSymbolBuilder = KtSymbolByFirBuilder( - firSession.firSymbolProvider, - typeContext, firResolveState, project, token ) return KtFirAnalysisSession( element, - firSession, firResolveState, firSymbolBuilder, - typeContext, token, isContextSession = false ) diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt index eb38cd25ae1..11fa52c83f4 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt @@ -9,10 +9,8 @@ import com.google.common.collect.MapMaker import com.intellij.openapi.project.Project import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.fir.FirElement -import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl -import org.jetbrains.kotlin.fir.resolve.firProvider import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag @@ -157,8 +155,8 @@ internal class KtSymbolByFirBuilder private constructor( (firProvider.getSymbolByLookupTag(lookupTag) as? FirTypeParameterSymbol)?.fir?.let(::buildTypeParameterSymbol) } - fun buildClassLikeSymbolByClassId(classId: ClassId, firSession: FirSession): FirRegularClass? = withValidityAssertion { - firSession.firProvider.getClassLikeSymbolByFqName(classId)?.fir as? FirRegularClass + fun buildClassLikeSymbolByClassId(classId: ClassId): FirRegularClass? = withValidityAssertion { + firProvider.getClassLikeSymbolByFqName(classId)?.fir as? FirRegularClass } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirScopeProvider.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirScopeProvider.kt index ebb6d4d63ff..713b0b530be 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirScopeProvider.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirScopeProvider.kt @@ -44,11 +44,9 @@ internal class KtFirScopeProvider( override val token: ValidityToken, private val builder: KtSymbolByFirBuilder, private val project: Project, - session: FirSession, firResolveState: FirModuleResolveState, firScopeRegistry: FirScopeRegistry, ) : KtScopeProvider(), ValidityTokenOwner { - private val session by weakRef(session) private val firResolveState by weakRef(firResolveState) private val firScopeStorage by weakRef(firScopeRegistry) @@ -78,8 +76,11 @@ internal class KtFirScopeProvider( override fun getPackageScope(packageSymbol: KtPackageSymbol): KtPackageScope = withValidityAssertion { packageMemberScopeCache.getOrPut(packageSymbol) { - val firPackageScope = FirPackageMemberScope(packageSymbol.fqName, session/*TODO use correct session here*/) - .also(firScopeStorage::register) + val firPackageScope = + FirPackageMemberScope( + packageSymbol.fqName, + firResolveState.firIdeSourcesSession/*TODO use correct session here*/ + ).also(firScopeStorage::register) KtFirPackageScope(firPackageScope, builder, token) } } @@ -89,9 +90,9 @@ internal class KtFirScopeProvider( } override fun getScopeForType(type: KtType): KtScope? { - check(type is KtFirType) { "KtFirScopePriovider can only work with KtFirType, but ${type::class} was provided" } + check(type is KtFirType) { "KtFirScopeProvider can only work with KtFirType, but ${type::class} was provided" } - val firTypeScope = type.coneType.scope(session, ScopeSession()) ?: return null + val firTypeScope = type.coneType.scope(firResolveState.firIdeSourcesSession, ScopeSession()) ?: return null return convertToKtScope(firTypeScope) } 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 5d481fa6f53..baf21fd3a19 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 @@ -7,19 +7,17 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols import com.intellij.psi.PsiElement import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction -import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState import org.jetbrains.kotlin.idea.frontend.api.ValidityToken -import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner 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.firRef -import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.symbols.* +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer internal class KtFirAnonymousFunctionSymbol( fir: FirAnonymousFunction, @@ -38,5 +36,8 @@ internal class KtFirAnonymousFunctionSymbol( } } - override fun createPointer(): KtSymbolPointer = NonRestorableKtSymbolPointer + override fun createPointer(): KtSymbolPointer { + KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } + error("Could not create a pointer for anonymous function from library") + } } \ 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 2b5d8023be3..2b69dc3f6cd 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 @@ -12,9 +12,12 @@ import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState import org.jetbrains.kotlin.idea.frontend.api.ValidityToken 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.symbols.pointers.KtFirClassOrObjectInLibrarySymbol import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef import org.jetbrains.kotlin.idea.frontend.api.symbols.* +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.CanNotCreateSymbolPointerForLocalLibraryDeclarationException +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name @@ -59,7 +62,10 @@ internal class KtFirClassOrObjectSymbol( } override fun createPointer(): KtSymbolPointer { - val classId = classId - return symbolPointer { session -> session.symbolProvider.getClassOrObjectSymbolByClassId(classId) } + KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } + if (symbolKind == KtSymbolKind.LOCAL) { + throw CanNotCreateSymbolPointerForLocalLibraryDeclarationException(classId.asString()) + } + return KtFirClassOrObjectInLibrarySymbol(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 e297cf179cf..2928198e2ab 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 @@ -9,19 +9,20 @@ 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.FirResolvePhase -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 import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState import org.jetbrains.kotlin.idea.frontend.api.ValidityToken -import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner 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.symbols.pointers.KtFirConstructorSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.createSignature import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef -import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.symbols.* +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.CanNotCreateSymbolPointerForLocalLibraryDeclarationException +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion import org.jetbrains.kotlin.name.ClassId @@ -60,17 +61,10 @@ internal class KtFirConstructorSymbol( } 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.firRef.withFir { (it as? FirRegularClass) } - ?: error("FirRegularClass expected") - classFir.getPrimaryConstructorIfAny()?.let(builder::buildConstructorSymbol) + KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } + if (symbolKind == KtSymbolKind.LOCAL) { + throw CanNotCreateSymbolPointerForLocalLibraryDeclarationException("${ownerClassId.asString()}.constructor") } + return KtFirConstructorSymbolPointer(ownerClassId, isPrimary, firRef.withFir { it.createSignature() }) } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirConstructorValueParameterSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirConstructorValueParameterSymbol.kt index c21e58a79e7..f099276d8b1 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirConstructorValueParameterSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirConstructorValueParameterSymbol.kt @@ -10,15 +10,12 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState import org.jetbrains.kotlin.idea.frontend.api.ValidityToken -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.firRef -import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef -import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorParameterSymbol -import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorParameterSymbolKind -import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind import org.jetbrains.kotlin.idea.frontend.api.types.KtType -import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef +import org.jetbrains.kotlin.idea.frontend.api.symbols.* +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.name.Name internal class KtFirConstructorValueParameterSymbol( @@ -48,5 +45,10 @@ internal class KtFirConstructorValueParameterSymbol( } } - override val hasDefaultValue: Boolean get() = withValidityAssertion { fir.defaultValue != null } + override val hasDefaultValue: Boolean get() = firRef.withFir { it.defaultValue != null } + + override fun createPointer(): KtSymbolPointer { + KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } + TODO("Creating symbols for library constructor parameters is not supported yet") + } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirEnumEntrySymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirEnumEntrySymbol.kt index ec5eebca482..40048d92891 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirEnumEntrySymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirEnumEntrySymbol.kt @@ -11,14 +11,15 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState import org.jetbrains.kotlin.idea.frontend.api.ValidityToken -import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner 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.symbols.pointers.KtFirEnumEntrySymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.createSignature import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef -import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.symbols.KtEnumEntrySymbol -import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name internal class KtFirEnumEntrySymbol( @@ -32,4 +33,10 @@ internal class KtFirEnumEntrySymbol( override val name: Name get() = firRef.withFir { it.name } override val type: KtType by firRef.withFirAndCache(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) { fir -> builder.buildKtType(fir.returnTypeRef) } + override val enumClassId: ClassId = firRef.withFir { it.symbol.callableId.classId ?: error("ClassId should present for enum") } + + override fun createPointer(): KtSymbolPointer { + KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } + return KtFirEnumEntrySymbolPointer(enumClassId, firRef.withFir { it.createSignature() }) + } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionSymbol.kt index 2cedcc15152..cd7cdbbcc11 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionSymbol.kt @@ -11,17 +11,15 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState import org.jetbrains.kotlin.idea.frontend.api.ValidityToken -import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner 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.symbols.pointers.KtFirMemberFunctionSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.createSignature import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef -import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef -import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCommonSymbolModality -import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol -import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind -import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin -import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.idea.frontend.api.symbols.* +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.CanNotCreateSymbolPointerForLocalLibraryDeclarationException +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -29,8 +27,7 @@ internal class KtFirFunctionSymbol( fir: FirSimpleFunction, resolveState: FirModuleResolveState, override val token: ValidityToken, - private val builder: KtSymbolByFirBuilder, - private val forcedOrigin: FirDeclarationOrigin? = null + private val builder: KtSymbolByFirBuilder ) : KtFunctionSymbol(), KtFirSymbol { override val firRef = firRef(fir, resolveState) override val psi: PsiElement? by firRef.withFirAndCache { it.findPsi(fir.session) } @@ -48,7 +45,6 @@ internal class KtFirFunctionSymbol( } } - override val origin: KtSymbolOrigin get() = withValidityAssertion { forcedOrigin?.asKtSymbolOrigin() ?: super.origin } override val isSuspend: Boolean get() = firRef.withFir { it.isSuspend } override val receiverType: KtType? by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir -> fir.receiverTypeRef?.let(builder::buildKtType) } override val isOperator: Boolean get() = firRef.withFir { it.isOperator } @@ -63,4 +59,16 @@ internal class KtFirFunctionSymbol( } } override val modality: KtCommonSymbolModality get() = firRef.withFir { it.modality.getSymbolModality() } + + override fun createPointer(): KtSymbolPointer { + KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } + return when (symbolKind) { + KtSymbolKind.TOP_LEVEL -> TODO("Creating symbol for top level fun is not supported yet") + KtSymbolKind.MEMBER -> KtFirMemberFunctionSymbolPointer( + firRef.withFir { it.symbol.callableId.classId ?: error("ClassId should not be null for member function") }, + firRef.withFir { it.createSignature() } + ) + KtSymbolKind.LOCAL -> throw CanNotCreateSymbolPointerForLocalLibraryDeclarationException(fqName?.asString() ?: name.asString()) + } + } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionValueParameterSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionValueParameterSymbol.kt index 7162e8a2c03..30fcf62a4a5 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionValueParameterSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionValueParameterSymbol.kt @@ -11,14 +11,13 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState import org.jetbrains.kotlin.idea.frontend.api.ValidityToken +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.firRef -import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionParameterSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind -import org.jetbrains.kotlin.idea.frontend.api.types.KtType -import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.name.Name internal class KtFirFunctionValueParameterSymbol( @@ -34,5 +33,11 @@ internal class KtFirFunctionValueParameterSymbol( override val isVararg: Boolean get() = firRef.withFir { it.isVararg } override val type: KtType by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir -> builder.buildKtType(fir.returnTypeRef) } override val symbolKind: KtSymbolKind get() = KtSymbolKind.LOCAL - override val hasDefaultValue: Boolean get() = withValidityAssertion { fir.defaultValue != null } + + override val hasDefaultValue: Boolean get() = firRef.withFir { it.defaultValue != null } + + override fun createPointer(): KtSymbolPointer { + KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } + TODO("Creating pointers for functions parameters from library is not supported yet") + } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirJavaFieldSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirJavaFieldSymbol.kt index 825103ba8a2..490b1663259 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirJavaFieldSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirJavaFieldSymbol.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCommonSymbolModality import org.jetbrains.kotlin.idea.frontend.api.symbols.KtJavaFieldSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion import org.jetbrains.kotlin.name.Name @@ -37,4 +38,8 @@ internal class KtFirJavaFieldSymbol( override val name: Name get() = firRef.withFir { it.name } override val modality: KtCommonSymbolModality get() = firRef.withFir { it.modality.getSymbolModality() } + + override fun createPointer(): KtSymbolPointer { + TODO("Creating pointers for java fields is not supported yet") + } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirLocalVariableSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirLocalVariableSymbol.kt index cfeb4180cb0..8631956077a 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirLocalVariableSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirLocalVariableSymbol.kt @@ -11,15 +11,15 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState import org.jetbrains.kotlin.idea.frontend.api.ValidityToken -import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner 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.firRef -import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.symbols.KtLocalVariableSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind -import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.CanNotCreateSymbolPointerForLocalLibraryDeclarationException +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.name.Name internal class KtFirLocalVariableSymbol( @@ -40,4 +40,9 @@ internal class KtFirLocalVariableSymbol( override val name: Name get() = firRef.withFir { it.name } override val type: KtType by firRef.withFirAndCache(FirResolvePhase.BODY_RESOLVE) { fir -> builder.buildKtType(fir.returnTypeRef) } override val symbolKind: KtSymbolKind get() = KtSymbolKind.LOCAL + + override fun createPointer(): KtSymbolPointer { + KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } + throw CanNotCreateSymbolPointerForLocalLibraryDeclarationException(name.asString()) + } } \ 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 c660e62aebc..bccfd874f70 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 @@ -15,6 +15,8 @@ import org.jetbrains.kotlin.idea.frontend.api.ValidityToken import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached import org.jetbrains.kotlin.idea.frontend.api.symbols.* +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.symbolPointer import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil import org.jetbrains.kotlin.name.FqName diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertySymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertySymbol.kt index 992fd40a030..5788e50b698 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertySymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertySymbol.kt @@ -6,24 +6,23 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.modality import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState import org.jetbrains.kotlin.idea.frontend.api.ValidityToken -import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner 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.symbols.pointers.KtFirMemberPropertySymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.createSignature import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef -import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCommonSymbolModality import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind -import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin -import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.CanNotCreateSymbolPointerForLocalLibraryDeclarationException +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -31,8 +30,7 @@ internal class KtFirPropertySymbol( fir: FirProperty, resolveState: FirModuleResolveState, override val token: ValidityToken, - private val builder: KtSymbolByFirBuilder, - private val forcedOrigin: FirDeclarationOrigin? + private val builder: KtSymbolByFirBuilder ) : KtPropertySymbol(), KtFirSymbol { init { assert(!fir.isLocal) @@ -41,7 +39,6 @@ internal class KtFirPropertySymbol( override val firRef = firRef(fir, resolveState) override val psi: PsiElement? by firRef.withFirAndCache { it.findPsi(fir.session) } - override val origin: KtSymbolOrigin get() = withValidityAssertion { forcedOrigin?.asKtSymbolOrigin() ?: super.origin } override val fqName: FqName get() = firRef.withFir { it.symbol.callableId.asFqNameForDebugInfo() } override val isVal: Boolean get() = firRef.withFir { it.isVal } @@ -57,4 +54,16 @@ internal class KtFirPropertySymbol( } } override val modality: KtCommonSymbolModality get() = firRef.withFir { it.modality.getSymbolModality() } + + override fun createPointer(): KtSymbolPointer { + KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } + return when (symbolKind) { + KtSymbolKind.TOP_LEVEL -> TODO("Creating symbol for top level fun is not supported yet") + KtSymbolKind.MEMBER -> KtFirMemberPropertySymbolPointer( + firRef.withFir { it.symbol.callableId.classId ?: error("ClassId should not be null for member property") }, + firRef.withFir { it.createSignature() } + ) + KtSymbolKind.LOCAL -> throw CanNotCreateSymbolPointerForLocalLibraryDeclarationException(fqName.asString()) + } + } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirTypeAliasSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirTypeAliasSymbol.kt index 4dc8d7600eb..dbbdb24bc58 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirTypeAliasSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirTypeAliasSymbol.kt @@ -10,13 +10,10 @@ import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState import org.jetbrains.kotlin.idea.frontend.api.ValidityToken -import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner -import org.jetbrains.kotlin.idea.frontend.api.fir.utils.ReadOnlyWeakRef -import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef -import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeAliasSymbol -import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name @@ -29,4 +26,9 @@ internal class KtFirTypeAliasSymbol( override val psi: PsiElement? by firRef.withFirAndCache { it.findPsi(fir.session) } override val name: Name get() = firRef.withFir { it.name } override val classId: ClassId get() = firRef.withFir { it.symbol.classId } + + override fun createPointer(): KtSymbolPointer { + KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } + TODO("Creating symbols for library typealiases is not supported yet") + } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirTypeParameterSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirTypeParameterSymbol.kt index 94cce0f357e..27ad1f861bc 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirTypeParameterSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirTypeParameterSymbol.kt @@ -10,12 +10,10 @@ import org.jetbrains.kotlin.fir.declarations.FirTypeParameter import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState import org.jetbrains.kotlin.idea.frontend.api.ValidityToken -import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner -import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef -import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol -import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.name.Name internal class KtFirTypeParameterSymbol( @@ -27,4 +25,9 @@ internal class KtFirTypeParameterSymbol( override val psi: PsiElement? by firRef.withFirAndCache { it.findPsi(fir.session) } override val name: Name get() = firRef.withFir { it.name } + + override fun createPointer(): KtSymbolPointer { + KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } + TODO("Creating symbols for library type parameters is not supported yet") + } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/firSymbolUtils.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/firSymbolUtils.kt index e9d799f3e93..5a6295ae275 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/firSymbolUtils.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/firSymbolUtils.kt @@ -6,8 +6,8 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCommonSymbolModality -import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolModality +import org.jetbrains.kotlin.idea.frontend.api.symbols.* +import org.jetbrains.kotlin.psi.KtDeclaration internal inline fun Modality?.getSymbolModality(): M = when (this) { Modality.FINAL -> KtCommonSymbolModality.FINAL diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirClassOrObjectInLibrarySymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirClassOrObjectInLibrarySymbol.kt new file mode 100644 index 00000000000..e76698ee997 --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirClassOrObjectInLibrarySymbol.kt @@ -0,0 +1,22 @@ +/* + * 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.fir.symbols.pointers + +import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer +import org.jetbrains.kotlin.name.ClassId + +class KtFirClassOrObjectInLibrarySymbol(private val classId: ClassId) : KtSymbolPointer() { + override fun restoreSymbol(analysisSession: KtAnalysisSession): KtClassOrObjectSymbol? { + require(analysisSession is KtFirAnalysisSession) + val firClass = analysisSession.firSymbolBuilder.buildClassLikeSymbolByClassId( + classId + ) ?: return null + return analysisSession.firSymbolBuilder.buildClassSymbol(firClass) + } +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirConstructorSymbolPointer.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirConstructorSymbolPointer.kt new file mode 100644 index 00000000000..2d3a26a91be --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirConstructorSymbolPointer.kt @@ -0,0 +1,30 @@ +/* + * 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.fir.symbols.pointers + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirConstructor +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorSymbol +import org.jetbrains.kotlin.ir.util.IdSignature +import org.jetbrains.kotlin.name.ClassId + +internal class KtFirConstructorSymbolPointer( + ownerClassId: ClassId, + private val isPrimary: Boolean, + private val signature: IdSignature +) : KtFirMemberSymbolPointer(ownerClassId) { + override fun KtFirAnalysisSession.chooseCandidateAndCreateSymbol( + candidates: Collection, + firSession: FirSession + ): KtConstructorSymbol? { + val firConstructor = candidates.findDeclarationWithSignature(signature, firSession) ?: return null + if (firConstructor.isPrimary != isPrimary) return null + return firSymbolBuilder.buildConstructorSymbol(firConstructor) + } +} + diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirEnumEntrySymbolPointer.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirEnumEntrySymbolPointer.kt new file mode 100644 index 00000000000..d99c3d3e052 --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirEnumEntrySymbolPointer.kt @@ -0,0 +1,28 @@ +/* + * 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.fir.symbols.pointers + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirEnumEntry +import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtEnumEntrySymbol +import org.jetbrains.kotlin.ir.util.IdSignature +import org.jetbrains.kotlin.name.ClassId + +internal class KtFirEnumEntrySymbolPointer( + ownerClassId: ClassId, + private val signature: IdSignature +) : KtFirMemberSymbolPointer(ownerClassId) { + override fun KtFirAnalysisSession.chooseCandidateAndCreateSymbol( + candidates: Collection, + firSession: FirSession + ): KtEnumEntrySymbol? { + val firProperty = candidates.findDeclarationWithSignature(signature, firSession) ?: return null + return firSymbolBuilder.buildEnumEntrySymbol(firProperty) + } +} + diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberFunctionSymbolPointer.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberFunctionSymbolPointer.kt new file mode 100644 index 00000000000..105c64babef --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberFunctionSymbolPointer.kt @@ -0,0 +1,28 @@ +/* + * 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.fir.symbols.pointers + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol +import org.jetbrains.kotlin.ir.util.IdSignature +import org.jetbrains.kotlin.name.ClassId + +internal class KtFirMemberFunctionSymbolPointer( + ownerClassId: ClassId, + private val signature: IdSignature +) : KtFirMemberSymbolPointer(ownerClassId) { + override fun KtFirAnalysisSession.chooseCandidateAndCreateSymbol( + candidates: Collection, + firSession: FirSession + ): KtFunctionSymbol? { + val firFunction = candidates.findDeclarationWithSignature(signature, firSession) ?: return null + return firSymbolBuilder.buildFunctionSymbol(firFunction) + } +} + diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberPropertySymbolPointer.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberPropertySymbolPointer.kt new file mode 100644 index 00000000000..a2b7f08c563 --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberPropertySymbolPointer.kt @@ -0,0 +1,28 @@ +/* + * 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.fir.symbols.pointers + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol +import org.jetbrains.kotlin.ir.util.IdSignature +import org.jetbrains.kotlin.name.ClassId + +internal class KtFirMemberPropertySymbolPointer( + ownerClassId: ClassId, + private val signature: IdSignature +) : KtFirMemberSymbolPointer(ownerClassId) { + override fun KtFirAnalysisSession.chooseCandidateAndCreateSymbol( + candidates: Collection, + firSession: FirSession + ): KtPropertySymbol? { + val firProperty = candidates.findDeclarationWithSignature(signature, firSession) ?: return null + return firSymbolBuilder.buildVariableSymbol(firProperty) as? KtPropertySymbol + } +} + diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberSymbolPointer.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberSymbolPointer.kt new file mode 100644 index 00000000000..8a810b12653 --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberSymbolPointer.kt @@ -0,0 +1,32 @@ +/* + * 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.fir.symbols.pointers + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer +import org.jetbrains.kotlin.name.ClassId + +internal abstract class KtFirMemberSymbolPointer( + private val ownerClassId: ClassId, +) : KtSymbolPointer() { + final override fun restoreSymbol(analysisSession: KtAnalysisSession): S? { + require(analysisSession is KtFirAnalysisSession) + val owner = analysisSession.firSymbolBuilder.buildClassLikeSymbolByClassId( + ownerClassId + ) ?: return null + return analysisSession.chooseCandidateAndCreateSymbol(owner.declarations, owner.session) + } + + protected abstract fun KtFirAnalysisSession.chooseCandidateAndCreateSymbol( + candidates: Collection, + firSession: FirSession + ): S? +} + diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/pointerUtils.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/pointerUtils.kt new file mode 100644 index 00000000000..9c16cdcd49e --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/pointerUtils.kt @@ -0,0 +1,37 @@ +/* + * 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.fir.symbols.pointers + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.backend.Fir2IrSignatureComposer +import org.jetbrains.kotlin.fir.backend.jvm.FirJvmKotlinMangler +import org.jetbrains.kotlin.fir.backend.jvm.FirJvmMangleComputer +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirFunction +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.signaturer.FirBasedSignatureComposer +import org.jetbrains.kotlin.fir.signaturer.FirMangler +import org.jetbrains.kotlin.idea.fir.low.level.api.ideSessionComponents +import org.jetbrains.kotlin.ir.util.IdSignature + +internal inline fun Collection.findDeclarationWithSignature( + signature: IdSignature, + firSession: FirSession +): D? { + val signatureComposer = firSession.ideSessionComponents.signatureComposer + for (declaration in this) { + if (declaration is D && signatureComposer.composeSignature(declaration) == signature) { + return declaration + } + } + return null +} + +internal fun FirDeclaration.createSignature(): IdSignature { + val signatureComposer = session.ideSessionComponents.signatureComposer + return signatureComposer.composeSignature(this) + ?: error("Could not compose signature for declaration, looks like it is private or local") +} 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 b6cba3b3fa9..7c2217d7be8 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 @@ -133,7 +133,7 @@ internal object FirReferenceResolveHelper { val expression = ref.expression val symbolBuilder = analysisSession.firSymbolBuilder val fir = expression.getOrBuildFir(analysisSession.firResolveState) - val session = analysisSession.firSession + val session = analysisSession.firResolveState.firIdeSourcesSession when (fir) { is FirResolvable -> { val calleeReference = diff --git a/idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/class.txt b/idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/class.txt new file mode 100644 index 00000000000..7e969f38444 --- /dev/null +++ b/idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/class.txt @@ -0,0 +1,13 @@ +// RUNTIME + +class: kotlin/Lazy + +// SYMBOLS: +KtFirClassOrObjectSymbol: + classId: kotlin/Lazy + classKind: INTERFACE + modality: ABSTRACT + name: Lazy + origin: LIBRARY + symbolKind: TOP_LEVEL + typeParameters: [KtFirTypeParameterSymbol(T)] diff --git a/idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/classFromJdk.txt b/idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/classFromJdk.txt new file mode 100644 index 00000000000..555523a00c1 --- /dev/null +++ b/idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/classFromJdk.txt @@ -0,0 +1,13 @@ +// RUNTIME + +class: java.lang.String + +// SYMBOLS: +KtFirClassOrObjectSymbol: + classId: java.lang.String + classKind: CLASS + modality: FINAL + name: String + origin: JAVA + symbolKind: MEMBER + typeParameters: [] diff --git a/idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/enumEntry.txt b/idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/enumEntry.txt new file mode 100644 index 00000000000..40024bd379d --- /dev/null +++ b/idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/enumEntry.txt @@ -0,0 +1,11 @@ +// RUNTIME + +callable: kotlin/LazyThreadSafetyMode.SYNCHRONIZED + +// SYMBOLS: +KtFirEnumEntrySymbol: + enumClassId: kotlin/LazyThreadSafetyMode + name: SYNCHRONIZED + origin: LIBRARY + symbolKind: MEMBER + type: kotlin/LazyThreadSafetyMode diff --git a/idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/memberFunction.txt b/idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/memberFunction.txt new file mode 100644 index 00000000000..9d5c643283a --- /dev/null +++ b/idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/memberFunction.txt @@ -0,0 +1,16 @@ +callable: kotlin/collections/List.get + +// SYMBOLS: +KtFirFunctionSymbol: + fqName: kotlin.collections.List.get + isExtension: false + isOperator: true + isSuspend: false + modality: ABSTRACT + name: get + origin: LIBRARY + receiverType: null + symbolKind: MEMBER + type: E + typeParameters: [] + valueParameters: [KtFirFunctionValueParameterSymbol(index)] diff --git a/idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/memberFunctionWithOverloads.txt b/idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/memberFunctionWithOverloads.txt new file mode 100644 index 00000000000..562ef82db4b --- /dev/null +++ b/idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/memberFunctionWithOverloads.txt @@ -0,0 +1,30 @@ +callable: kotlin/collections/List.listIterator + +// SYMBOLS: +KtFirFunctionSymbol: + fqName: kotlin.collections.List.listIterator + isExtension: false + isOperator: false + isSuspend: false + modality: ABSTRACT + name: listIterator + origin: LIBRARY + receiverType: null + symbolKind: MEMBER + type: kotlin/collections/ListIterator + typeParameters: [] + valueParameters: [] + +KtFirFunctionSymbol: + fqName: kotlin.collections.List.listIterator + isExtension: false + isOperator: false + isSuspend: false + modality: ABSTRACT + name: listIterator + origin: LIBRARY + receiverType: null + symbolKind: MEMBER + type: kotlin/collections/ListIterator + typeParameters: [] + valueParameters: [KtFirFunctionValueParameterSymbol(index)] diff --git a/idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/nestedClass.txt b/idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/nestedClass.txt new file mode 100644 index 00000000000..88d4d748abf --- /dev/null +++ b/idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/nestedClass.txt @@ -0,0 +1,11 @@ +class: kotlin/collections/MutableMap.MutableEntry + +// SYMBOLS: +KtFirClassOrObjectSymbol: + classId: kotlin/collections/MutableMap.MutableEntry + classKind: INTERFACE + modality: ABSTRACT + name: MutableEntry + origin: LIBRARY + symbolKind: MEMBER + typeParameters: [KtFirTypeParameterSymbol(K), KtFirTypeParameterSymbol(V)] diff --git a/idea/idea-frontend-fir/testData/symbolPointer/class.kt b/idea/idea-frontend-fir/testData/symbolPointer/class.kt index a7ca22abab4..88991ff0c0d 100644 --- a/idea/idea-frontend-fir/testData/symbolPointer/class.kt +++ b/idea/idea-frontend-fir/testData/symbolPointer/class.kt @@ -1,2 +1,12 @@ class A { -} \ No newline at end of file +} + +// SYMBOLS: +KtFirClassOrObjectSymbol: + classId: A + classKind: CLASS + modality: FINAL + name: A + origin: SOURCE + symbolKind: TOP_LEVEL + typeParameters: [] diff --git a/idea/idea-frontend-fir/testData/symbolPointer/classPrimaryConstructor.kt b/idea/idea-frontend-fir/testData/symbolPointer/classPrimaryConstructor.kt index 161cb193d08..09c2f9709a4 100644 --- a/idea/idea-frontend-fir/testData/symbolPointer/classPrimaryConstructor.kt +++ b/idea/idea-frontend-fir/testData/symbolPointer/classPrimaryConstructor.kt @@ -1,2 +1,21 @@ class A() { -} \ No newline at end of file +} + +// SYMBOLS: +KtFirConstructorSymbol: + isPrimary: true + origin: SOURCE + owner: KtFirClassOrObjectSymbol(A) + ownerClassId: A + symbolKind: MEMBER + type: A + valueParameters: [] + +KtFirClassOrObjectSymbol: + classId: A + classKind: CLASS + modality: FINAL + name: A + origin: SOURCE + symbolKind: TOP_LEVEL + typeParameters: [] diff --git a/idea/idea-frontend-fir/testData/symbolPointer/classSecondaryConstructors.kt b/idea/idea-frontend-fir/testData/symbolPointer/classSecondaryConstructors.kt new file mode 100644 index 00000000000..0fbcc5de104 --- /dev/null +++ b/idea/idea-frontend-fir/testData/symbolPointer/classSecondaryConstructors.kt @@ -0,0 +1,62 @@ +class A() { + constructor(x: Int): this() + constructor(y: Int, z: String) : this(y) +} + +// SYMBOLS: +KtFirConstructorSymbol: + isPrimary: true + origin: SOURCE + owner: KtFirClassOrObjectSymbol(A) + ownerClassId: A + symbolKind: MEMBER + type: A + valueParameters: [] + +KtFirFunctionValueParameterSymbol: + isVararg: false + name: x + origin: SOURCE + symbolKind: LOCAL + type: kotlin/Int + +KtFirConstructorSymbol: + isPrimary: false + origin: SOURCE + owner: KtFirClassOrObjectSymbol(A) + ownerClassId: A + symbolKind: MEMBER + type: A + valueParameters: Could not render due to java.lang.ClassCastException: org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirFunctionValueParameterSymbol cannot be cast to org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirConstructorValueParameterSymbol + +KtFirFunctionValueParameterSymbol: + isVararg: false + name: y + origin: SOURCE + symbolKind: LOCAL + type: kotlin/Int + +KtFirFunctionValueParameterSymbol: + isVararg: false + name: z + origin: SOURCE + symbolKind: LOCAL + type: kotlin/String + +KtFirConstructorSymbol: + isPrimary: false + origin: SOURCE + owner: KtFirClassOrObjectSymbol(A) + ownerClassId: A + symbolKind: MEMBER + type: A + valueParameters: Could not render due to java.lang.ClassCastException: org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirFunctionValueParameterSymbol cannot be cast to org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirConstructorValueParameterSymbol + +KtFirClassOrObjectSymbol: + classId: A + classKind: CLASS + modality: FINAL + name: A + origin: SOURCE + symbolKind: TOP_LEVEL + typeParameters: [] diff --git a/idea/idea-frontend-fir/testData/symbolPointer/enum.kt b/idea/idea-frontend-fir/testData/symbolPointer/enum.kt new file mode 100644 index 00000000000..15f08a2b861 --- /dev/null +++ b/idea/idea-frontend-fir/testData/symbolPointer/enum.kt @@ -0,0 +1,27 @@ +enum class X { + Y, Z; +} + +// SYMBOLS: +KtFirEnumEntrySymbol: + enumClassId: X + name: Y + origin: SOURCE + symbolKind: MEMBER + type: X + +KtFirEnumEntrySymbol: + enumClassId: X + name: Z + origin: SOURCE + symbolKind: MEMBER + type: X + +KtFirClassOrObjectSymbol: + classId: X + classKind: ENUM_CLASS + modality: FINAL + name: X + origin: SOURCE + symbolKind: TOP_LEVEL + typeParameters: [] diff --git a/idea/idea-frontend-fir/testData/symbolPointer/memberFunctions.kt b/idea/idea-frontend-fir/testData/symbolPointer/memberFunctions.kt new file mode 100644 index 00000000000..2707808e770 --- /dev/null +++ b/idea/idea-frontend-fir/testData/symbolPointer/memberFunctions.kt @@ -0,0 +1,42 @@ +class A { + fun x(): Int + fun y() +} + +// SYMBOLS: +KtFirFunctionSymbol: + fqName: A.x + isExtension: false + isOperator: false + isSuspend: false + modality: FINAL + name: x + origin: SOURCE + receiverType: null + symbolKind: MEMBER + type: kotlin/Int + typeParameters: [] + valueParameters: [] + +KtFirFunctionSymbol: + fqName: A.y + isExtension: false + isOperator: false + isSuspend: false + modality: FINAL + name: y + origin: SOURCE + receiverType: null + symbolKind: MEMBER + type: kotlin/Unit + typeParameters: [] + valueParameters: [] + +KtFirClassOrObjectSymbol: + classId: A + classKind: CLASS + modality: FINAL + name: A + origin: SOURCE + symbolKind: TOP_LEVEL + typeParameters: [] diff --git a/idea/idea-frontend-fir/testData/symbolPointer/memberProperties.kt b/idea/idea-frontend-fir/testData/symbolPointer/memberProperties.kt new file mode 100644 index 00000000000..6b65343436e --- /dev/null +++ b/idea/idea-frontend-fir/testData/symbolPointer/memberProperties.kt @@ -0,0 +1,36 @@ +class A { + val x: Int = 10 + val Int.y = this +} + +// SYMBOLS: +KtFirPropertySymbol: + fqName: A.x + isExtension: false + isVal: true + modality: FINAL + name: x + origin: SOURCE + receiverType: kotlin/Int + symbolKind: MEMBER + type: kotlin/Int + +KtFirPropertySymbol: + fqName: A.y + isExtension: true + isVal: true + modality: FINAL + name: y + origin: SOURCE + receiverType: A + symbolKind: MEMBER + type: A + +KtFirClassOrObjectSymbol: + classId: A + classKind: CLASS + modality: FINAL + name: A + origin: SOURCE + symbolKind: TOP_LEVEL + typeParameters: [] diff --git a/idea/idea-frontend-fir/testData/symbolPointer/topLevelFunctions.kt b/idea/idea-frontend-fir/testData/symbolPointer/topLevelFunctions.kt new file mode 100644 index 00000000000..78dbfa5d1d7 --- /dev/null +++ b/idea/idea-frontend-fir/testData/symbolPointer/topLevelFunctions.kt @@ -0,0 +1,31 @@ +fun x(): Int = 10 +fun y() {} + +// SYMBOLS: +KtFirFunctionSymbol: + fqName: x + isExtension: false + isOperator: false + isSuspend: false + modality: FINAL + name: x + origin: SOURCE + receiverType: null + symbolKind: TOP_LEVEL + type: kotlin/Int + typeParameters: [] + valueParameters: [] + +KtFirFunctionSymbol: + fqName: y + isExtension: false + isOperator: false + isSuspend: false + modality: FINAL + name: y + origin: SOURCE + receiverType: null + symbolKind: TOP_LEVEL + type: kotlin/Unit + typeParameters: [] + valueParameters: [] diff --git a/idea/idea-frontend-fir/testData/symbolPointer/topLevelProperties.kt b/idea/idea-frontend-fir/testData/symbolPointer/topLevelProperties.kt new file mode 100644 index 00000000000..f9170da498d --- /dev/null +++ b/idea/idea-frontend-fir/testData/symbolPointer/topLevelProperties.kt @@ -0,0 +1,25 @@ +val x: Int = 10 +val Int.y = this + +// SYMBOLS: +KtFirPropertySymbol: + fqName: x + isExtension: false + isVal: true + modality: FINAL + name: x + origin: SOURCE + receiverType: kotlin/Int + symbolKind: TOP_LEVEL + type: kotlin/Int + +KtFirPropertySymbol: + fqName: y + isExtension: true + isVal: true + modality: FINAL + name: y + origin: SOURCE + receiverType: ERROR CLASS: Unresolved this@null + symbolKind: TOP_LEVEL + type: ERROR CLASS: Unresolved this@null diff --git a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/AbstractSymbolByFqNameTest.kt b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/AbstractSymbolByFqNameTest.kt index b3faab9af90..9a761b80fa8 100644 --- a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/AbstractSymbolByFqNameTest.kt +++ b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/AbstractSymbolByFqNameTest.kt @@ -5,18 +5,12 @@ package org.jetbrains.kotlin.idea.frontend.api -import com.intellij.openapi.util.io.FileUtil import org.jetbrains.kotlin.idea.executeOnPooledThreadInReadAction -import org.jetbrains.kotlin.idea.fir.low.level.api.LowLevelFirApiFacade -import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.symbols.DebugSymbolRenderer import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol 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.KtFile import org.jetbrains.kotlin.test.KotlinTestUtils import java.io.File @@ -25,12 +19,7 @@ abstract class AbstractSymbolByFqNameTest : KotlinLightCodeInsightFixtureTestCas protected fun doTest(path: String) { val fakeKtFile = myFixture.configureByText("file.kt", "fun a() {}") as KtFile - val testDataFile = File(path) - val testFileText = FileUtil.loadFile(testDataFile) - - val identifier = testFileText.substringBeforeLast(SYMBOLS_TAG).trim() - - val symbolData = SymbolData.create(identifier) + val symbolData = SymbolByFqName.getSymbolDataFromFile(path) val renderedSymbols = executeOnPooledThreadInReadAction { analyze(fakeKtFile) { @@ -39,59 +28,13 @@ abstract class AbstractSymbolByFqNameTest : KotlinLightCodeInsightFixtureTestCas } } - val actual = buildString { - val actualSymbolsData = renderedSymbols.joinToString(separator = "\n") - val fileTextWithoutSymbolsData = testFileText.substringBeforeLast(SYMBOLS_TAG).trimEnd() - appendLine(fileTextWithoutSymbolsData) - appendLine() - appendLine(SYMBOLS_TAG) - append(actualSymbolsData) - } - KotlinTestUtils.assertEqualsToFile(testDataFile, actual) + val actual = SymbolByFqName.textWithRenderedSymbolData(path, renderedSymbols.joinToString(separator = "\n")) + KotlinTestUtils.assertEqualsToFile(File(path), actual) } protected abstract fun createSymbols(symbolData: SymbolData, analysisSession: KtAnalysisSession): List - override fun getDefaultProjectDescriptor(): KotlinLightProjectDescriptor = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE - - companion object { - private const val SYMBOLS_TAG = "// SYMBOLS:" - } -} - -sealed class SymbolData { - abstract fun toSymbols(analysisSession: KtAnalysisSession): List - - data class ClassData(val classId: ClassId) : SymbolData() { - override fun toSymbols(analysisSession: KtAnalysisSession): List { - val symbol = analysisSession.symbolProvider.getClassOrObjectSymbolByClassId(classId) ?: error("Class $classId is not found") - return listOf(symbol) - } - } - - data class CallableData(val packageName: FqName, val name: Name) : SymbolData() { - override fun toSymbols(analysisSession: KtAnalysisSession): List { - val symbols = analysisSession.symbolProvider.getTopLevelCallableSymbols(packageName, name).toList() - if (symbols.isEmpty()) { - error("No callable with fqName ${packageName}/${name} found") - } - return symbols - } - } - - companion object { - fun create(data: String): SymbolData = when { - data.startsWith("class:") -> ClassData(ClassId.fromString(data.removePrefix("class:").trim())) - data.startsWith("callable:") -> { - val fullName = data.removePrefix("callable:").trim() - val name = Name.identifier(fullName.substringAfterLast("/")) - val fqName = FqName(fullName.substringBeforeLast("/").replace('/', '.')) - CallableData(fqName, name) - } - else -> error("Invalid symbol") - } - } } diff --git a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/SymbolByFqName.kt b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/SymbolByFqName.kt new file mode 100644 index 00000000000..95fbf3e52e2 --- /dev/null +++ b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/SymbolByFqName.kt @@ -0,0 +1,90 @@ +/* + * 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 + +import com.intellij.openapi.util.io.FileUtil +import org.jetbrains.kotlin.fir.symbols.CallableId +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.test.InTextDirectivesUtils +import java.io.File + +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 textWithRenderedSymbolData(filePath: String, rendered: String): String = buildString { + val testFileText = FileUtil.loadFile(File(filePath)) + val fileTextWithoutSymbolsData = testFileText.substringBeforeLast(SYMBOLS_TAG).trimEnd() + appendLine(fileTextWithoutSymbolsData) + appendLine() + appendLine(SYMBOLS_TAG) + append(rendered) + } + + + private const val SYMBOLS_TAG = "// SYMBOLS:" +} + +sealed class SymbolData { + abstract fun toSymbols(analysisSession: KtAnalysisSession): List + + data class ClassData(val classId: ClassId) : SymbolData() { + override fun toSymbols(analysisSession: KtAnalysisSession): List { + val symbol = analysisSession.symbolProvider.getClassOrObjectSymbolByClassId(classId) ?: error("Class $classId is not found") + return listOf(symbol) + } + } + + data class CallableData(val callableId: CallableId) : SymbolData() { + override fun toSymbols(analysisSession: KtAnalysisSession): List { + val classId = callableId.classId + val symbols = if (classId == null) { + analysisSession.symbolProvider.getTopLevelCallableSymbols(callableId.packageName, callableId.callableName).toList() + } else { + val classSymbol = + analysisSession.symbolProvider.getClassOrObjectSymbolByClassId(classId) + ?: error("Class $classId is not found") + analysisSession.scopeProvider.getDeclaredMemberScope(classSymbol).getCallableSymbols() + .filter { (it as? KtNamedSymbol)?.name == callableId.callableName } + .toList() + } + if (symbols.isEmpty()) { + error("No callable with fqName $callableId found") + } + return symbols + } + } + + companion object { + val identifiers = arrayOf("callable:", "class:") + + fun create(data: String): SymbolData = when { + data.startsWith("class:") -> ClassData(ClassId.fromString(data.removePrefix("class:").trim())) + data.startsWith("callable:") -> { + val fullName = data.removePrefix("callable:").trim() + val name = if ('.' in fullName) fullName.substringAfterLast(".") else fullName.substringAfterLast('/') + val (packageName, className) = run { + val packageNameWithClassName = fullName.dropLast(name.length + 1) + when { + '.' in fullName -> + packageNameWithClassName.substringBeforeLast('/') to packageNameWithClassName.substringAfterLast('/') + else -> packageNameWithClassName to null + } + } + CallableData(CallableId(FqName(packageName.replace('/', '.')), className?.let { FqName(it) }, Name.identifier(name))) + } + else -> error("Invalid symbol") + } + } +} + diff --git a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/AbstractSymbolFromLibraryPointerRestoreTest.kt b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/AbstractSymbolFromLibraryPointerRestoreTest.kt new file mode 100644 index 00000000000..b51161ec0e7 --- /dev/null +++ b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/AbstractSymbolFromLibraryPointerRestoreTest.kt @@ -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 com.intellij.testFramework.LightProjectDescriptor +import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.SymbolByFqName +import org.jetbrains.kotlin.psi.KtFile + +abstract class AbstractSymbolFromLibraryPointerRestoreTest : AbstractSymbolPointerRestoreTest() { + override fun KtAnalysisSession.collectSymbols(filePath: String, ktFile: KtFile): List { + val symbolData = SymbolByFqName.getSymbolDataFromFile(filePath) + return symbolData.toSymbols(this) + } +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/AbstractSymbolFromSourcePointerRestoreTest.kt b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/AbstractSymbolFromSourcePointerRestoreTest.kt new file mode 100644 index 00000000000..ec94ab6d1a6 --- /dev/null +++ b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/AbstractSymbolFromSourcePointerRestoreTest.kt @@ -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.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 = + ktFile.collectDescendantsOfType().map { declaration -> + symbolProvider.getSymbol(declaration) + } +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/AbstractSymbolPointerRestoreTest.kt b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/AbstractSymbolPointerRestoreTest.kt new file mode 100644 index 00000000000..49828e487ef --- /dev/null +++ b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/AbstractSymbolPointerRestoreTest.kt @@ -0,0 +1,81 @@ +/* + * 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.application.runWriteAction +import com.intellij.openapi.command.CommandProcessor +import com.intellij.openapi.util.io.FileUtil +import com.intellij.psi.PsiDocumentManager +import org.jetbrains.kotlin.idea.executeOnPooledThreadInReadAction +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.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 + + 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) + ) + } + } + } + + val actual = SymbolByFqName.textWithRenderedSymbolData( + path, + pointersWithRendered.joinToString(separator = "\n") { it.rendered }, + ) + + KotlinTestUtils.assertEqualsToFile(File(path), actual) + + + 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")) + } + } + } + + // another read action + executeOnPooledThreadInReadAction { + analyze(ktFile) { + val restored = pointersWithRendered.map { (pointer, expectedRender) -> + val restored = pointer.restoreSymbol(this) ?: 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 data class PointerWithRenderedSymbol(val pointer: KtSymbolPointer<*>, val rendered: String) \ 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 deleted file mode 100644 index d4db2c6af0c..00000000000 --- a/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/AbstractSymbolPointerTest.kt +++ /dev/null @@ -1,56 +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.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.analyze -import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession -import org.jetbrains.kotlin.idea.frontend.api.getAnalysisSessionFor -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 { - analyze(ktFile) { - val declarationSymbols = ktFile.collectDescendantsOfType().map { declaration -> - symbolProvider.getSymbol(declaration) - } - declarationSymbols.map { PointerWithPsi(it.createPointer(), it.psi!!) } - } - } - - // another read action - executeOnPooledThreadInReadAction { - analyze(ktFile) { - pointers.forEach { (pointer, psi) -> - val restored = pointer.restoreSymbol(this) ?: 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/SymbolFromLibraryPointerRestoreTestGenerated.java b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/SymbolFromLibraryPointerRestoreTestGenerated.java new file mode 100644 index 00000000000..c04ce715f1f --- /dev/null +++ b/idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/SymbolFromLibraryPointerRestoreTestGenerated.java @@ -0,0 +1,60 @@ +/* + * 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/resoreSymbolFromLibrary") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class SymbolFromLibraryPointerRestoreTestGenerated extends AbstractSymbolFromLibraryPointerRestoreTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInResoreSymbolFromLibrary() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary"), Pattern.compile("^(.+)\\.txt$"), null, true); + } + + @TestMetadata("class.txt") + public void testClass() throws Exception { + runTest("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/class.txt"); + } + + @TestMetadata("classFromJdk.txt") + public void testClassFromJdk() throws Exception { + runTest("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/classFromJdk.txt"); + } + + @TestMetadata("enumEntry.txt") + public void testEnumEntry() throws Exception { + runTest("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/enumEntry.txt"); + } + + @TestMetadata("memberFunction.txt") + public void testMemberFunction() throws Exception { + runTest("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/memberFunction.txt"); + } + + @TestMetadata("memberFunctionWithOverloads.txt") + public void testMemberFunctionWithOverloads() throws Exception { + runTest("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/memberFunctionWithOverloads.txt"); + } + + @TestMetadata("nestedClass.txt") + public void testNestedClass() throws Exception { + runTest("idea/idea-frontend-fir/testData/resoreSymbolFromLibrary/nestedClass.txt"); + } +} 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/SymbolFromSourcePointerRestoreTestGenerated.java similarity index 56% rename from idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/SymbolPointerTestGenerated.java rename to idea/idea-frontend-fir/tests/org/jetbrains/kotlin/idea/frontend/api/symbols/SymbolFromSourcePointerRestoreTestGenerated.java index 1f4bca61363..7cb3d981295 100644 --- 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/SymbolFromSourcePointerRestoreTestGenerated.java @@ -19,7 +19,7 @@ import java.util.regex.Pattern; @TestMetadata("idea/idea-frontend-fir/testData/symbolPointer") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) -public class SymbolPointerTestGenerated extends AbstractSymbolPointerTest { +public class SymbolFromSourcePointerRestoreTestGenerated extends AbstractSymbolFromSourcePointerRestoreTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } @@ -37,4 +37,34 @@ public class SymbolPointerTestGenerated extends AbstractSymbolPointerTest { public void testClassPrimaryConstructor() throws Exception { runTest("idea/idea-frontend-fir/testData/symbolPointer/classPrimaryConstructor.kt"); } + + @TestMetadata("classSecondaryConstructors.kt") + public void testClassSecondaryConstructors() throws Exception { + runTest("idea/idea-frontend-fir/testData/symbolPointer/classSecondaryConstructors.kt"); + } + + @TestMetadata("enum.kt") + public void testEnum() throws Exception { + runTest("idea/idea-frontend-fir/testData/symbolPointer/enum.kt"); + } + + @TestMetadata("memberFunctions.kt") + public void testMemberFunctions() throws Exception { + runTest("idea/idea-frontend-fir/testData/symbolPointer/memberFunctions.kt"); + } + + @TestMetadata("memberProperties.kt") + public void testMemberProperties() throws Exception { + runTest("idea/idea-frontend-fir/testData/symbolPointer/memberProperties.kt"); + } + + @TestMetadata("topLevelFunctions.kt") + public void testTopLevelFunctions() throws Exception { + runTest("idea/idea-frontend-fir/testData/symbolPointer/topLevelFunctions.kt"); + } + + @TestMetadata("topLevelProperties.kt") + public void testTopLevelProperties() throws Exception { + runTest("idea/idea-frontend-fir/testData/symbolPointer/topLevelProperties.kt"); + } }