From 82866176fb1cec5f54a767f3f85329fce2355108 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Thu, 25 Jun 2020 15:59:39 +0300 Subject: [PATCH] FIR IDE: introduce symbol API --- .../kotlin/idea/frontend/api/Invalidatable.kt | 18 ++++- .../frontend/api/symbols/KtClassLikeSymbol.kt | 25 +++++++ .../api/symbols/KtFunctionLikeSymbol.kt | 30 ++++++++ .../idea/frontend/api/symbols/KtSymbol.kt | 18 +++++ .../frontend/api/symbols/KtSymbolProvider.kt | 41 +++++++++++ .../api/symbols/KtTypeParameterSymbol.kt | 10 +++ .../api/symbols/KtVariableLikeSymbol.kt | 41 +++++++++++ .../idea/frontend/api/symbols/markers.kt | 34 +++++++++ .../idea/frontend/api/fir/ConeTypeInfo.kt | 5 +- .../frontend/api/fir/FirAnalysisSession.kt | 1 - .../frontend/api/fir/KtSymbolByFirBuilder.kt | 73 +++++++++++++++++++ .../symbols/KtFirAnonymousFunctionSymbol.kt | 39 ++++++++++ .../fir/symbols/KtFirClassOrObjectSymbol.kt | 59 +++++++++++++++ .../api/fir/symbols/KtFirConstructorSymbol.kt | 53 ++++++++++++++ .../KtFirConstructorValueParameterSymbol.kt | 45 ++++++++++++ .../api/fir/symbols/KtFirEnumEntrySymbol.kt | 32 ++++++++ .../api/fir/symbols/KtFirFieldSymbol.kt | 35 +++++++++ .../api/fir/symbols/KtFirFunctionSymbol.kt | 60 +++++++++++++++ .../KtFirFunctionValueParameterSymbol.kt | 34 +++++++++ .../fir/symbols/KtFirLocalVariableSymbol.kt | 37 ++++++++++ .../api/fir/symbols/KtFirPropertySymbol.kt | 46 ++++++++++++ .../frontend/api/fir/symbols/KtFirSymbol.kt | 32 ++++++++ .../api/fir/symbols/KtFirTypeAliasSymbol.kt | 27 +++++++ .../fir/symbols/KtFirTypeParameterSymbol.kt | 31 ++++++++ .../frontend/api/fir/utils/ReadOnlyWeakRef.kt | 25 +++++++ .../api/fir/utils/ValidityAwareCachedValue.kt | 34 +++++++++ .../frontend/api/fir/utils/typeBuilder.kt | 24 ++++++ .../kotlin/idea/references/FirKtReference.kt | 6 +- 28 files changed, 906 insertions(+), 9 deletions(-) create mode 100644 idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtClassLikeSymbol.kt create mode 100644 idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtFunctionLikeSymbol.kt create mode 100644 idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbol.kt create mode 100644 idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolProvider.kt create mode 100644 idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtTypeParameterSymbol.kt create mode 100644 idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtVariableLikeSymbol.kt create mode 100644 idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/markers.kt create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirAnonymousFunctionSymbol.kt create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirClassOrObjectSymbol.kt create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirConstructorSymbol.kt create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirConstructorValueParameterSymbol.kt create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirEnumEntrySymbol.kt create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFieldSymbol.kt create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionSymbol.kt create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionValueParameterSymbol.kt create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirLocalVariableSymbol.kt create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertySymbol.kt create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirSymbol.kt create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirTypeAliasSymbol.kt create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirTypeParameterSymbol.kt create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/ReadOnlyWeakRef.kt create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/ValidityAwareCachedValue.kt create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/typeBuilder.kt diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/Invalidatable.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/Invalidatable.kt index 9dbb157c1a2..97940191df5 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/Invalidatable.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/Invalidatable.kt @@ -13,10 +13,22 @@ interface Invalidatable { fun isValid(): Boolean fun invalidationReason(): String +} - fun assertIsValid() { - assert(isValid()) { "Access to invalid $this, invalidation reason is ${invalidationReason()}" } - } +@Suppress("NOTHING_TO_INLINE") +inline fun Invalidatable.assertIsValid() { + assert(isValid()) { "Access to invalid $this, invalidation reason is ${invalidationReason()}" } +} + +inline fun Invalidatable.withValidityAssertion(action: () -> R): R { + assertIsValid() + return action() +} + +interface InvalidatableByValidityToken : Invalidatable { + val token: Invalidatable + override fun isValid(): Boolean = token.isValid() + override fun invalidationReason(): String = token.invalidationReason() } class ReadActionConfinementValidityToken(project: Project) : Invalidatable { 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 new file mode 100644 index 00000000000..1100de8302c --- /dev/null +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtClassLikeSymbol.kt @@ -0,0 +1,25 @@ +/* + * 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.name.ClassId + + +abstract class KtClassLikeSymbol : KtSymbol, KtNamedSymbol, KtSymbolWithKind { + abstract val classId: ClassId +} + +abstract class KtTypeAliasSymbol : KtClassLikeSymbol() { + final override val symbolKind: KtSymbolKind get() = KtSymbolKind.TOP_LEVEL +} + +abstract class KtClassOrObjectSymbol : KtClassLikeSymbol(), KtSymbolWithTypeParameters { + abstract val classKind: KtClassKind +} + +enum class KtClassKind { + CLASS, ABSTRACT_CLASS, ENUM_CLASS, ENUM_ENTRY, ANNOTATION_CLASS, OBJECT, COMPANION_OBJECT, INTERFACE +} \ No newline at end of file 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 new file mode 100644 index 00000000000..566ab75d224 --- /dev/null +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtFunctionLikeSymbol.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 + +import org.jetbrains.kotlin.name.FqName + +sealed class KtFunctionLikeSymbol : KtTypedSymbol, KtSymbolWithKind { + abstract val valueParameters: List +} + +abstract class KtAnonymousFunctionSymbol : KtFunctionLikeSymbol() { + final override val symbolKind: KtSymbolKind get() = KtSymbolKind.LOCAL +} + +abstract class KtFunctionSymbol : KtFunctionLikeSymbol(), KtNamedSymbol, KtPossibleExtensionSymbol, KtSymbolWithTypeParameters { + abstract val isSuspend: Boolean + abstract val isOperator: Boolean + abstract val fqName: FqName? + + abstract override val valueParameters: List +} + +abstract class KtConstructorSymbol : KtFunctionLikeSymbol() { + abstract override val valueParameters: List + abstract val isPrimary: Boolean + abstract val owner: KtClassOrObjectSymbol +} \ No newline at end of file diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbol.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbol.kt new file mode 100644 index 00000000000..8fa205682f9 --- /dev/null +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbol.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.psi.PsiElement +import org.jetbrains.kotlin.idea.frontend.api.Invalidatable + +interface KtSymbol : Invalidatable { + val origin: KtSymbolOrigin + val psi: PsiElement? +} + +enum class KtSymbolOrigin { + SOURCE, LIBRARY, JAVA, SAM_CONSTRUCTOR +} \ No newline at end of file diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolProvider.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolProvider.kt new file mode 100644 index 00000000000..ada85d0646b --- /dev/null +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolProvider.kt @@ -0,0 +1,41 @@ +/* + * 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.Invalidatable +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.psi.* + +abstract class KtSymbolProvider : Invalidatable { + open fun getSymbol(psi: KtDeclaration): KtSymbol = when (psi) { + is KtParameter -> getParameterSymbol(psi) + is KtNamedFunction -> getFunctionSymbol(psi) + is KtConstructor<*> -> getConstructorSymbol(psi) + is KtTypeParameter -> getTypeParameterSymbol(psi) + is KtTypeAlias -> getTypeAliasSymbol(psi) + is KtEnumEntry -> getEnumEntrySymbol(psi) + is KtLambdaExpression -> getAnonymousFunctionSymbol(psi) + is KtProperty -> getVariableSymbol(psi) + is KtClassOrObject -> getClassOrObjectSymbol(psi) + else -> error("Cannot build symbol for ${psi::class}") + } + + abstract fun getParameterSymbol(psi: KtParameter): KtParameterSymbol + abstract fun getFunctionSymbol(psi: KtNamedFunction): KtFunctionSymbol + abstract fun getConstructorSymbol(psi: KtConstructor<*>): KtConstructorSymbol + abstract fun getTypeParameterSymbol(psi: KtTypeParameter): KtTypeParameterSymbol + abstract fun getTypeAliasSymbol(psi: KtTypeAlias): KtTypeAliasSymbol + abstract fun getEnumEntrySymbol(psi: KtEnumEntry): KtEnumEntrySymbol + abstract fun getAnonymousFunctionSymbol(psi: KtNamedFunction): KtAnonymousFunctionSymbol + abstract fun getAnonymousFunctionSymbol(psi: KtLambdaExpression): KtAnonymousFunctionSymbol + abstract fun getVariableSymbol(psi: KtProperty): KtVariableSymbol + abstract fun getClassOrObjectSymbol(psi: KtClassOrObject): KtClassOrObjectSymbol + + /** + * @return symbol with specified [classId] or `null` in case such symbol is not found + */ + abstract fun getClassOrObjectSymbolByClassId(classId: ClassId): KtClassOrObjectSymbol? +} \ No newline at end of file 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 new file mode 100644 index 00000000000..f39a2def411 --- /dev/null +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtTypeParameterSymbol.kt @@ -0,0 +1,10 @@ +/* + * 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 + +abstract class KtTypeParameterSymbol : KtSymbol, KtNamedSymbol + + 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 new file mode 100644 index 00000000000..7fe29a679b4 --- /dev/null +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtVariableLikeSymbol.kt @@ -0,0 +1,41 @@ +/* + * 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.name.FqName + +abstract class KtVariableLikeSymbol : KtTypedSymbol, KtNamedSymbol, KtSymbolWithKind + +abstract class KtEnumEntrySymbol : KtVariableLikeSymbol() { + final override val symbolKind: KtSymbolKind get() = KtSymbolKind.MEMBER +} + +abstract class KtParameterSymbol : KtVariableLikeSymbol() + +abstract class KtVariableSymbol : KtVariableLikeSymbol() { + abstract val isVal: Boolean +} + +abstract class KtFieldSymbol : KtVariableSymbol() { + final override val symbolKind: KtSymbolKind get() = KtSymbolKind.MEMBER +} + +// TODO getters & setters +abstract class KtPropertySymbol : KtVariableSymbol(), KtPossibleExtensionSymbol { + abstract val fqName: FqName +} + +abstract class KtLocalVariableSymbol : KtVariableSymbol() + +abstract class KtSimpleFunctionParameterSymbol : KtParameterSymbol() + +abstract class KtConstructorParameterSymbol : KtParameterSymbol(), KtNamedSymbol { + abstract val constructorParameterKind: KtConstructorParameterSymbolKind +} + +enum class KtConstructorParameterSymbolKind { + VAL_PROPERTY, VAR_PROPERTY, NON_PROPERTY +} \ No newline at end of file diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/markers.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/markers.kt new file mode 100644 index 00000000000..766a6a0bc8e --- /dev/null +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/markers.kt @@ -0,0 +1,34 @@ +/* + * 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.TypeInfo +import org.jetbrains.kotlin.name.Name + +interface KtNamedSymbol : KtSymbol { + val name: Name +} + +interface KtSymbolWithKind : KtSymbol { + val symbolKind: KtSymbolKind +} + +enum class KtSymbolKind { + TOP_LEVEL, MEMBER, LOCAL +} + +interface KtTypedSymbol : KtSymbol { + val type: TypeInfo +} + +interface KtPossibleExtensionSymbol { + val isExtension: Boolean + val receiverType: TypeInfo? +} + +interface KtSymbolWithTypeParameters { + val typeParameters: List +} diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/ConeTypeInfo.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/ConeTypeInfo.kt index b79ae9232d7..9cfbec2677d 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/ConeTypeInfo.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/ConeTypeInfo.kt @@ -7,10 +7,7 @@ package org.jetbrains.kotlin.idea.frontend.api.fir import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl -import org.jetbrains.kotlin.idea.frontend.api.ClassTypeExpectedException -import org.jetbrains.kotlin.idea.frontend.api.ErrorTypeClassIdAccessException -import org.jetbrains.kotlin.idea.frontend.api.Invalidatable -import org.jetbrains.kotlin.idea.frontend.api.TypeInfo +import org.jetbrains.kotlin.idea.frontend.api.* import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.AbstractTypeCheckerContext diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/FirAnalysisSession.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/FirAnalysisSession.kt index 7dd4a0458f1..da25929b60b 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/FirAnalysisSession.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/FirAnalysisSession.kt @@ -12,7 +12,6 @@ import com.intellij.psi.PsiField import com.intellij.psi.PsiMethod import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.diagnostics.Diagnostic -import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference 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 new file mode 100644 index 00000000000..2466867d645 --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt @@ -0,0 +1,73 @@ +/* + * 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 + +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl +import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider +import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag +import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag +import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol +import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl +import org.jetbrains.kotlin.idea.frontend.api.* +import org.jetbrains.kotlin.idea.frontend.api.Invalidatable +import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.* +import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirClassOrObjectSymbol +import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirLocalVariableSymbol +import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirPropertySymbol +import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirFunctionSymbol +import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirFunctionValueParameterSymbol +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtVariableSymbol + +internal class KtSymbolByFirBuilder(private val validityToken: Invalidatable) { + fun buildSymbol(fir: FirDeclaration): KtSymbol = when (fir) { + is FirRegularClass -> buildClassSymbol(fir) + is FirSimpleFunction -> buildFunctionSymbol(fir) + is FirProperty -> buildPropertySymbol(fir) + is FirValueParameterImpl -> buildParameterSymbol(fir) + is FirConstructor -> buildFirConstructorSymbol(fir) + is FirTypeParameter -> buildFirTypeParameterSymbol(fir) + is FirTypeAlias -> buildFirTypeAliasSymbol(fir) + is FirEnumEntry -> buildFirEnumEntrySymbol(fir) + is FirField -> buildFirFieldSymbol(fir) + is FirAnonymousFunction -> buildFirAnonymousFunction(fir) + else -> + TODO(fir::class.toString()) + } + + fun buildClassSymbol(fir: FirRegularClass) = KtFirClassOrObjectSymbol(fir, validityToken) + + // TODO it can be a constructor parameter, which may be split into parameter & property + // we should handle them both + fun buildParameterSymbol(fir: FirValueParameterImpl) = KtFirFunctionValueParameterSymbol(fir, validityToken) + fun buildFirConstructorParameter(fir: FirValueParameterImpl) = KtFirConstructorValueParameterSymbol(fir, validityToken) + + fun buildFunctionSymbol(fir: FirSimpleFunction) = KtFirFunctionSymbol(fir, validityToken, this) + fun buildFirConstructorSymbol(fir: FirConstructor) = KtFirConstructorSymbol(fir, validityToken, this) + fun buildFirTypeParameterSymbol(fir: FirTypeParameter) = KtFirTypeParameterSymbol(fir, validityToken) + fun buildFirTypeAliasSymbol(fir: FirTypeAlias) = KtFirTypeAliasSymbol(fir, validityToken) + fun buildFirEnumEntrySymbol(fir: FirEnumEntry) = KtFirEnumEntrySymbol(fir, validityToken) + fun buildFirFieldSymbol(fir: FirField) = KtFirFieldSymbol(fir, validityToken) + fun buildFirAnonymousFunction(fir: FirAnonymousFunction) = KtFirAnonymousFunctionSymbol(fir, validityToken, this) + + fun buildPropertySymbol(fir: FirProperty): KtVariableSymbol { + return when { + fir.isLocal -> KtFirLocalVariableSymbol(fir, validityToken) + else -> KtFirPropertySymbol(fir, validityToken) + } + } +} + +internal fun FirElement.buildSymbol(builder: KtSymbolByFirBuilder) = + (this as? FirDeclaration)?.let(builder::buildSymbol) + +internal fun FirDeclaration.buildSymbol(builder: KtSymbolByFirBuilder) = + builder.buildSymbol(this) \ No newline at end of file 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 new file mode 100644 index 00000000000..eb183bbcce6 --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirAnonymousFunctionSymbol.kt @@ -0,0 +1,39 @@ +/* + * 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 + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction +import org.jetbrains.kotlin.fir.declarations.FirEnumEntry +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl +import org.jetbrains.kotlin.idea.fir.findPsi +import org.jetbrains.kotlin.idea.frontend.api.Invalidatable +import org.jetbrains.kotlin.idea.frontend.api.TypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef +import org.jetbrains.kotlin.idea.frontend.api.symbols.* +import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.name.Name + +internal class KtFirAnonymousFunctionSymbol( + fir: FirAnonymousFunction, + override val token: Invalidatable, + private val builder: KtSymbolByFirBuilder +) : KtAnonymousFunctionSymbol(), KtFirSymbol { + override val fir: FirAnonymousFunction by weakRef(fir) + override val psi: PsiElement? by cached { fir.findPsi(fir.session) } + + override val type: TypeInfo by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) } + override val valueParameters: List by cached { + fir.valueParameters.map { valueParameter -> + check(valueParameter is FirValueParameterImpl) + builder.buildParameterSymbol(valueParameter) + } + } +} \ 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 new file mode 100644 index 00000000000..b9ce205197f --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirClassOrObjectSymbol.kt @@ -0,0 +1,59 @@ +/* + * 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 + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.idea.fir.findPsi +import org.jetbrains.kotlin.idea.frontend.api.Invalidatable +import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder +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.symbols.KtClassKind +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind +import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.Name + +internal class KtFirClassOrObjectSymbol( + fir: FirRegularClass, + override val token: Invalidatable, + private val builder: KtSymbolByFirBuilder +) : KtClassOrObjectSymbol(), KtFirSymbol { + override val fir: FirRegularClass by ReadOnlyWeakRef(fir, this) + override val psi: PsiElement? by cached { fir.findPsi(fir.session) } + override val name: Name get() = withValidityAssertion { fir.classId.shortClassName } + override val classId: ClassId get() = withValidityAssertion { fir.classId } + + override val typeParameters by cached { + fir.typeParameters.map { typeParameter -> + builder.buildTypeParameterSymbol(typeParameter.symbol.fir) + } + } + + override val classKind: KtClassKind + get() = withValidityAssertion { + when (fir.classKind) { + ClassKind.INTERFACE -> KtClassKind.INTERFACE + ClassKind.ENUM_CLASS -> KtClassKind.ENUM_CLASS + ClassKind.ENUM_ENTRY -> KtClassKind.ENUM_ENTRY + ClassKind.ANNOTATION_CLASS -> KtClassKind.ANNOTATION_CLASS + ClassKind.CLASS -> if (fir.modality == Modality.ABSTRACT) KtClassKind.ABSTRACT_CLASS else KtClassKind.CLASS + ClassKind.OBJECT -> if (fir.isCompanion) KtClassKind.COMPANION_OBJECT else KtClassKind.OBJECT + } + } + override val symbolKind: KtSymbolKind + get() = withValidityAssertion { + when { + fir.isLocal -> KtSymbolKind.LOCAL + fir.symbol.classId.isNestedClass -> KtSymbolKind.MEMBER + else -> KtSymbolKind.TOP_LEVEL + } + } +} \ 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 new file mode 100644 index 00000000000..f5d8c2bef1a --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirConstructorSymbol.kt @@ -0,0 +1,53 @@ +/* + * 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 + +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.impl.FirValueParameterImpl +import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.idea.fir.findPsi +import org.jetbrains.kotlin.idea.frontend.api.Invalidatable +import org.jetbrains.kotlin.idea.frontend.api.TypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorParameterSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind +import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion + +internal class KtFirConstructorSymbol( + fir: FirConstructor, + override val token: Invalidatable, + private val builder: KtSymbolByFirBuilder +) : KtConstructorSymbol(), KtFirSymbol { + override val fir: FirConstructor by weakRef(fir) + override val psi: PsiElement? by cached { fir.findPsi(fir.session) } + + override val type: TypeInfo by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) } + override val valueParameters: List by cached { + fir.valueParameters.map { valueParameter -> + check(valueParameter is FirValueParameterImpl) + builder.buildFirConstructorParameter(valueParameter) + } + } + + override val isPrimary: Boolean get() = withValidityAssertion { fir.isPrimary } + override val symbolKind: KtSymbolKind get() = KtSymbolKind.MEMBER + + override val owner: KtClassOrObjectSymbol by cached { + val session = fir.session + val classId = fir.symbol.callableId.classId ?: error("ClassID should present for constructor") + val firClass = session.firSymbolProvider.getClassLikeSymbolByFqName(classId)?.fir + ?: error("Class with id $classId id was not found") + check(firClass is FirRegularClass) { "Owner class for constructor should be FirRegularClass, but ${firClass::class} was met" } + builder.buildClassSymbol(firClass) + } +} \ 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 new file mode 100644 index 00000000000..8367b808acc --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirConstructorValueParameterSymbol.kt @@ -0,0 +1,45 @@ +/* + * 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 + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl +import org.jetbrains.kotlin.idea.fir.findPsi +import org.jetbrains.kotlin.idea.frontend.api.Invalidatable +import org.jetbrains.kotlin.idea.frontend.api.TypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef +import org.jetbrains.kotlin.idea.frontend.api.symbols.* +import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.name.Name + +internal class KtFirConstructorValueParameterSymbol( + fir: FirValueParameterImpl, + override val token: Invalidatable +) : KtConstructorParameterSymbol(), KtFirSymbol { + override val fir: FirValueParameterImpl by weakRef(fir) + override val psi: PsiElement? by cached { fir.findPsi(fir.session) } + + override val name: Name get() = withValidityAssertion { fir.name } + override val type: TypeInfo by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) } + override val symbolKind: KtSymbolKind + get() = withValidityAssertion { + when { + fir.isVal || fir.isVal -> KtSymbolKind.MEMBER + else -> KtSymbolKind.LOCAL + } + } + override val constructorParameterKind: KtConstructorParameterSymbolKind + get() = withValidityAssertion { + when { + fir.isVal -> KtConstructorParameterSymbolKind.VAL_PROPERTY + fir.isVar -> KtConstructorParameterSymbolKind.VAR_PROPERTY + else -> KtConstructorParameterSymbolKind.NON_PROPERTY + } + } +} \ 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 new file mode 100644 index 00000000000..158950238a9 --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirEnumEntrySymbol.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 + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.fir.declarations.FirEnumEntry +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.idea.fir.findPsi +import org.jetbrains.kotlin.idea.frontend.api.Invalidatable +import org.jetbrains.kotlin.idea.frontend.api.TypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtEnumEntrySymbol +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.name.Name + +internal class KtFirEnumEntrySymbol( + fir: FirEnumEntry, + override val token: Invalidatable +) : KtEnumEntrySymbol(), KtFirSymbol { + override val fir: FirEnumEntry by weakRef(fir) + override val psi: PsiElement? by cached { fir.findPsi(fir.session) } + + override val name: Name get() = withValidityAssertion { fir.name } + override val type: TypeInfo by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) } +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFieldSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFieldSymbol.kt new file mode 100644 index 00000000000..46445d21074 --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFieldSymbol.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.frontend.api.fir.symbols + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.fir.declarations.FirField +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.declarations.FirTypeParameter +import org.jetbrains.kotlin.idea.fir.findPsi +import org.jetbrains.kotlin.idea.frontend.api.Invalidatable +import org.jetbrains.kotlin.idea.frontend.api.TypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFieldSymbol +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.symbols.KtTypeParameterSymbol +import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.name.Name + +internal class KtFirFieldSymbol( + fir: FirField, + override val token: Invalidatable +) : KtFieldSymbol(), KtFirSymbol { + override val fir: FirField by weakRef(fir) + override val psi: PsiElement? by cached { fir.findPsi(fir.session) } + + override val type: TypeInfo by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) } + override val isVal: Boolean get() = withValidityAssertion { fir.isVal } + override val name: Name get() = withValidityAssertion { fir.name } +} \ 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 new file mode 100644 index 00000000000..31efd25f2ef --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionSymbol.kt @@ -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.fir.symbols + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl +import org.jetbrains.kotlin.fir.declarations.isLocal +import org.jetbrains.kotlin.fir.declarations.isOperator +import org.jetbrains.kotlin.fir.declarations.isSuspend +import org.jetbrains.kotlin.idea.fir.findPsi +import org.jetbrains.kotlin.idea.frontend.api.Invalidatable +import org.jetbrains.kotlin.idea.frontend.api.TypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind +import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name + +internal class KtFirFunctionSymbol( + fir: FirSimpleFunction, + override val token: Invalidatable, + private val builder: KtSymbolByFirBuilder, +) : KtFunctionSymbol(), KtFirSymbol { + override val fir: FirSimpleFunction by weakRef(fir) + override val psi: PsiElement? by cached { fir.findPsi(fir.session) } + override val name: Name get() = withValidityAssertion { fir.name } + override val type: TypeInfo by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) } + override val valueParameters: List by cached { + fir.valueParameters.map { valueParameter -> + check(valueParameter is FirValueParameterImpl) + builder.buildParameterSymbol(valueParameter) + } + } + override val typeParameters by cached { + fir.typeParameters.map { typeParameter -> + builder.buildTypeParameterSymbol(typeParameter.symbol.fir) + } + } + override val isSuspend: Boolean get() = withValidityAssertion { fir.isSuspend } + override val receiverType: TypeInfo? by cached { fir.receiverTypeRef?.asTypeInfo(fir.session, token) } + override val isOperator: Boolean get() = withValidityAssertion { fir.isOperator } + override val isExtension: Boolean get() = withValidityAssertion { fir.receiverTypeRef != null } + override val fqName: FqName? get() = withValidityAssertion { fir.symbol.callableId.asFqNameForDebugInfo() } + override val symbolKind: KtSymbolKind + get() = withValidityAssertion { + when { + fir.isLocal -> KtSymbolKind.LOCAL + fir.symbol.callableId.classId == null -> KtSymbolKind.TOP_LEVEL + else -> KtSymbolKind.MEMBER + } + } +} \ 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 new file mode 100644 index 00000000000..77f21b16b9a --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionValueParameterSymbol.kt @@ -0,0 +1,34 @@ +/* + * 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 + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl +import org.jetbrains.kotlin.idea.fir.findPsi +import org.jetbrains.kotlin.idea.frontend.api.Invalidatable +import org.jetbrains.kotlin.idea.frontend.api.TypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtLocalVariableSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSimpleFunctionParameterSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind +import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.name.Name + +internal class KtFirFunctionValueParameterSymbol( + fir: FirValueParameterImpl, + override val token: Invalidatable +) : KtSimpleFunctionParameterSymbol(), + KtFirSymbol { + override val fir: FirValueParameterImpl by weakRef(fir) + override val psi: PsiElement? by cached { fir.findPsi(fir.session) } + + override val name: Name get() = withValidityAssertion { fir.name } + override val type: TypeInfo by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) } + override val symbolKind: KtSymbolKind get() = KtSymbolKind.LOCAL +} \ 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 new file mode 100644 index 00000000000..25b087c412a --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirLocalVariableSymbol.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 + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.idea.fir.findPsi +import org.jetbrains.kotlin.idea.frontend.api.Invalidatable +import org.jetbrains.kotlin.idea.frontend.api.TypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtLocalVariableSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind +import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.name.Name + +internal class KtFirLocalVariableSymbol( + fir: FirProperty, + override val token: Invalidatable +) : KtLocalVariableSymbol(), + KtFirSymbol { + init { + assert(fir.isLocal) + } + + override val fir: FirProperty by weakRef(fir) + override val psi: PsiElement? by cached { fir.findPsi(fir.session) } + + override val isVal: Boolean get() = withValidityAssertion { fir.isVal } + override val name: Name get() = withValidityAssertion { fir.name } + override val type: TypeInfo by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) } + override val symbolKind: KtSymbolKind get() = KtSymbolKind.LOCAL +} \ No newline at end of file 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 new file mode 100644 index 00000000000..af31a14a5b9 --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertySymbol.kt @@ -0,0 +1,46 @@ +/* + * 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 + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.idea.fir.findPsi +import org.jetbrains.kotlin.idea.frontend.api.Invalidatable +import org.jetbrains.kotlin.idea.frontend.api.TypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind +import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name + +internal class KtFirPropertySymbol( + fir: FirProperty, + override val token: Invalidatable +) : KtPropertySymbol(), KtFirSymbol { + init { + assert(!fir.isLocal) + } + + override val fir: FirProperty by weakRef(fir) + override val psi: PsiElement? by cached { fir.findPsi(fir.session) } + + override val fqName: FqName get() = withValidityAssertion { fir.symbol.callableId.asFqNameForDebugInfo() } + override val isVal: Boolean get() = withValidityAssertion { fir.isVal } + override val name: Name get() = withValidityAssertion { fir.name } + override val type: TypeInfo by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) } + override val receiverType: TypeInfo? by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) } + override val isExtension: Boolean get() = withValidityAssertion { fir.receiverTypeRef != null } + override val symbolKind: KtSymbolKind + get() = withValidityAssertion { + when (fir.symbol.callableId.classId) { + null -> KtSymbolKind.TOP_LEVEL + else -> KtSymbolKind.MEMBER + } + } +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirSymbol.kt new file mode 100644 index 00000000000..29a6952415c --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirSymbol.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 + +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin +import org.jetbrains.kotlin.idea.frontend.api.InvalidatableByValidityToken +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin +import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion + +internal interface KtFirSymbol : KtSymbol, InvalidatableByValidityToken { + val fir: F + override val origin: KtSymbolOrigin get() = withValidityAssertion { fir.origin.asKtSymbolOrigin() } +} + +private fun FirDeclarationOrigin.asKtSymbolOrigin() = when (this) { + FirDeclarationOrigin.Source -> KtSymbolOrigin.SOURCE + FirDeclarationOrigin.Library -> KtSymbolOrigin.LIBRARY + FirDeclarationOrigin.Java -> KtSymbolOrigin.JAVA + FirDeclarationOrigin.SamConstructor -> KtSymbolOrigin.SAM_CONSTRUCTOR + FirDeclarationOrigin.Synthetic -> throw InvalidFirDeclarationOriginForSymbol(this) + FirDeclarationOrigin.FakeOverride -> throw InvalidFirDeclarationOriginForSymbol(this) + FirDeclarationOrigin.Enhancement -> throw InvalidFirDeclarationOriginForSymbol(this) + is FirDeclarationOrigin.Plugin -> throw InvalidFirDeclarationOriginForSymbol(this) +} + +class InvalidFirDeclarationOriginForSymbol(origin: FirDeclarationOrigin) : + IllegalStateException("Invalid FirDeclarationOrigin $origin") \ 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 new file mode 100644 index 00000000000..c66b6779fad --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirTypeAliasSymbol.kt @@ -0,0 +1,27 @@ +/* + * 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 + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.idea.fir.findPsi +import org.jetbrains.kotlin.idea.frontend.api.Invalidatable +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.symbols.KtTypeAliasSymbol +import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.Name + +internal class KtFirTypeAliasSymbol( + fir: FirTypeAlias, + override val token: Invalidatable +) : KtTypeAliasSymbol(), KtFirSymbol { + override val fir: FirTypeAlias by ReadOnlyWeakRef(fir, this) + override val psi: PsiElement? by cached { fir.findPsi(fir.session) } + override val name: Name get() = withValidityAssertion { fir.name } + override val classId: ClassId get() = withValidityAssertion { fir.symbol.classId } +} \ 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 new file mode 100644 index 00000000000..6589c88f442 --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirTypeParameterSymbol.kt @@ -0,0 +1,31 @@ +/* + * 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 + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.declarations.FirTypeParameter +import org.jetbrains.kotlin.idea.fir.findPsi +import org.jetbrains.kotlin.idea.frontend.api.Invalidatable +import org.jetbrains.kotlin.idea.frontend.api.TypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtLocalVariableSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol +import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.name.Name + +internal class KtFirTypeParameterSymbol( + fir: FirTypeParameter, + override val token: Invalidatable +) : KtTypeParameterSymbol(), KtFirSymbol { + override val fir: FirTypeParameter by weakRef(fir) + override val psi: PsiElement? by cached { fir.findPsi(fir.session) } + + override val name: Name get() = withValidityAssertion { fir.name } +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/ReadOnlyWeakRef.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/ReadOnlyWeakRef.kt new file mode 100644 index 00000000000..a0907ee13cc --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/ReadOnlyWeakRef.kt @@ -0,0 +1,25 @@ +/* + * 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.utils + +import org.jetbrains.kotlin.idea.frontend.api.Invalidatable +import java.lang.ref.WeakReference +import kotlin.reflect.KProperty + +class ReadOnlyWeakRef(value: V, val invalidatable: Invalidatable) { + val weakRef = WeakReference(value) + + @Suppress("NOTHING_TO_INLINE") + inline operator fun getValue(thisRef: Any, property: KProperty<*>): V = + weakRef.get() ?: if (invalidatable.isValid()) { + error("Cone type was garbage collected while analysis session is still valid") + } else { + error("Accessing the invalid coneType") + } +} + +@Suppress("NOTHING_TO_INLINE") +internal inline fun Invalidatable.weakRef(value: V) = ReadOnlyWeakRef(value, this) \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/ValidityAwareCachedValue.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/ValidityAwareCachedValue.kt new file mode 100644 index 00000000000..90cc8312573 --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/ValidityAwareCachedValue.kt @@ -0,0 +1,34 @@ +/* + * 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.utils + +import org.jetbrains.kotlin.idea.frontend.api.Invalidatable +import org.jetbrains.kotlin.idea.frontend.api.InvalidatableByValidityToken +import org.jetbrains.kotlin.idea.frontend.api.assertIsValid +import kotlin.properties.ReadOnlyProperty +import kotlin.reflect.KProperty + +// all access are considered to be from a single thread +// which should be checked in invalidatable.assertIsValid() +class ValidityAwareCachedValue( + private val invalidatable: Invalidatable, + private val init: () -> T +) : ReadOnlyProperty { + var value: Any? = UNITITIALIZED + + @Suppress("UNCHECKED_CAST") + override fun getValue(thisRef: Any, property: KProperty<*>): T { + invalidatable.assertIsValid() + if (value === UNITITIALIZED) { + value = init() + } + return value as T + } +} + +internal fun InvalidatableByValidityToken.cached(init: () -> T) = ValidityAwareCachedValue(token, init) + +internal object UNITITIALIZED \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/typeBuilder.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/typeBuilder.kt new file mode 100644 index 00000000000..090fe72f3ae --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/typeBuilder.kt @@ -0,0 +1,24 @@ +/* + * 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.utils + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.types.coneTypeUnsafe +import org.jetbrains.kotlin.idea.frontend.api.Invalidatable +import org.jetbrains.kotlin.idea.frontend.api.InvalidatableByValidityToken +import org.jetbrains.kotlin.idea.frontend.api.TypeInfo +import org.jetbrains.kotlin.idea.frontend.api.fir.ConeTypeInfo + +internal fun FirTypeRef.asTypeInfo(session: FirSession, invalidatable: Invalidatable): TypeInfo { + val context = ConeTypeCheckerContext( + isErrorTypeEqualsToAnything = true, + isStubTypeEqualsToAnything = true, + session = session + ) + return ConeTypeInfo(coneTypeUnsafe(), context, invalidatable) +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirKtReference.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirKtReference.kt index d0436615086..08815363797 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirKtReference.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirKtReference.kt @@ -7,9 +7,13 @@ package org.jetbrains.kotlin.idea.references import com.intellij.psi.PsiElement import org.jetbrains.kotlin.idea.frontend.api.fir.FirAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol interface FirKtReference : KtReference { - fun getResolvedToPsi(analysisSession: FirAnalysisSession): Collection + fun resolveToSymbols(analysisSession: FirAnalysisSession): Collection + + fun getResolvedToPsi(analysisSession: FirAnalysisSession): Collection = + resolveToSymbols(analysisSession).mapNotNull(KtSymbol::psi) override val resolver get() = KtFirReferenceResolver } \ No newline at end of file