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 fc1f90e7595..4ddfc28f29c 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 @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.idea.frontend.api import com.intellij.openapi.project.Project import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScopeProvider import org.jetbrains.kotlin.idea.frontend.api.symbols.* import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.name.ClassId @@ -18,6 +19,7 @@ abstract class KtAnalysisSession(project: Project) : ValidityOwner { override fun invalidationReason(): String = validityToken.invalidationReason() abstract val symbolProvider: KtSymbolProvider + abstract val scopeProvider: KtScopeProvider abstract fun getSmartCastedToTypes(expression: KtExpression): Collection? diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/scopes/KtScope.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/scopes/KtScope.kt new file mode 100644 index 00000000000..52332af04c3 --- /dev/null +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/scopes/KtScope.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.scopes + +import org.jetbrains.kotlin.idea.frontend.api.ValidityOwner +import org.jetbrains.kotlin.idea.frontend.api.symbols.* +import org.jetbrains.kotlin.name.Name + +interface KtScope : ValidityOwner { + fun getAllNames(): Set + fun getCallableNames(): Set + fun getClassLikeSymbolNames(): Set + + + fun getAllSymbols(): Sequence + fun getCallableSymbols(): Sequence + fun getClassClassLikeSymbols(): Sequence + + fun containsName(name: Name): Boolean +} + +interface KtMemberScope : KtScope { + val owner: KtClassOrObjectSymbol +} + +interface KtDeclaredMemberScope : KtScope { + val owner: KtClassOrObjectSymbol +} + +interface KtPackageScope : KtScope, KtSubstitutedScope { + val owner: KtPackageSymbol +} + +interface KtUnsubstitutedScope : KtScope { + fun substitute(/*substitution*/): KtSubstitutedScope = TODO() +} + +interface KtSubstitutedScope : KtScope \ No newline at end of file diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/scopes/KtScopeProvider.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/scopes/KtScopeProvider.kt new file mode 100644 index 00000000000..260ac49c07c --- /dev/null +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/scopes/KtScopeProvider.kt @@ -0,0 +1,16 @@ +/* + * 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.scopes + +import org.jetbrains.kotlin.idea.frontend.api.ValidityOwner +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPackageSymbol + +abstract class KtScopeProvider : ValidityOwner { + abstract fun getMemberScope(classSymbol: KtClassOrObjectSymbol): KtMemberScope + abstract fun getDeclaredMemberScope(classSymbol: KtClassOrObjectSymbol): KtDeclaredMemberScope + abstract fun getPackageScope(packageSymbol: KtPackageSymbol): KtPackageScope +} \ No newline at end of file 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 fcdbf4da73d..730ab705291 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 @@ -21,7 +21,9 @@ import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.idea.fir.* import org.jetbrains.kotlin.idea.fir.low.level.api.LowLevelFirApiFacade import org.jetbrains.kotlin.idea.frontend.api.* +import org.jetbrains.kotlin.idea.frontend.api.fir.scopes.KtFirScopeProvider import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbolProvider +import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScopeProvider import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolProvider @@ -59,6 +61,8 @@ constructor( firSymbolBuilder ) + override val scopeProvider: KtScopeProvider = KtFirScopeProvider(token, firSymbolBuilder, firSession) + init { assertIsValid() } 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 0f1d1b57019..eda11879e5b 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 @@ -39,7 +39,6 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtVariableSymbol import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil /** * Maps FirElement to KtSymbol & ConeType to KtType, thread safe diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirDeclaredMemberScope.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirDeclaredMemberScope.kt new file mode 100644 index 00000000000..df8164fbb27 --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirDeclaredMemberScope.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.scopes + +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope +import org.jetbrains.kotlin.idea.frontend.api.ValidityOwner +import org.jetbrains.kotlin.idea.frontend.api.ValidityOwnerByValidityToken +import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder +import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirClassOrObjectSymbol +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef +import org.jetbrains.kotlin.idea.frontend.api.scopes.KtDeclaredMemberScope +import org.jetbrains.kotlin.idea.frontend.api.scopes.KtUnsubstitutedScope + +internal class KtFirDeclaredMemberScope( + override val owner: KtFirClassOrObjectSymbol, + override val token: ValidityOwner, + builder: KtSymbolByFirBuilder +) : KtFirDelegatingScope(builder), + KtDeclaredMemberScope, + KtUnsubstitutedScope, + ValidityOwnerByValidityToken { + override val firScope: FirScope by weakRef(declaredMemberScope(owner.fir)) +} + diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirDelegatingScope.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirDelegatingScope.kt new file mode 100644 index 00000000000..d5ff6352535 --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirDelegatingScope.kt @@ -0,0 +1,82 @@ +/* + * 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.scopes + +import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.scopes.processClassifiersByName +import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef +import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScope +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.withValidityAssertion +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtClass + +internal abstract class KtFirDelegatingScope(private val builder: KtSymbolByFirBuilder) : KtScope { + abstract val firScope: FirScope + + private var allNamesCached: Set? = null + + override fun getAllNames(): Set = withValidityAssertion { + if (allNamesCached == null) { + allNamesCached = firScope.getCallableNames() + firScope.getClassifierNames() + } + allNamesCached!! + } + + override fun getCallableNames(): Set = withValidityAssertion { + firScope.getCallableNames() + } + + override fun getClassLikeSymbolNames(): Set = withValidityAssertion { + firScope.getClassifierNames() + } + + override fun getAllSymbols(): Sequence = withValidityAssertion { + sequence { + yieldAll(getCallableSymbols()) + yieldAll(getClassClassLikeSymbols()) + } + } + + override fun getCallableSymbols(): Sequence = withValidityAssertion { + sequence { + firScope.getCallableNames().forEach { name -> + val callables = mutableListOf() + firScope.processFunctionsByName(name) { firSymbol -> + (firSymbol.fir as? FirSimpleFunction)?.let { fir -> + callables.add(builder.buildFunctionSymbol(fir)) + } + } + firScope.processPropertiesByName(name) { firSymbol -> + callables.add(builder.buildSymbol(firSymbol.fir)) + } + yieldAll(callables) + } + } + } + + override fun getClassClassLikeSymbols(): Sequence = withValidityAssertion { + sequence { + firScope.getClassifierNames().forEach { name -> + val classLikeSymbols = mutableListOf() + firScope.processClassifiersByName(name) { firSymbol -> + (firSymbol.fir as? FirClassLikeDeclaration<*>)?.let { + classLikeSymbols.add(builder.buildClassLikeSymbol(it)) + } + } + yieldAll(classLikeSymbols) + } + } + } + + override fun containsName(name: Name): Boolean = withValidityAssertion { + name in getAllNames() + } +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirMemberScope.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirMemberScope.kt new file mode 100644 index 00000000000..56f7746b82f --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirMemberScope.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.scopes + +import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.buildUseSiteMemberScope +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.idea.frontend.api.ValidityOwner +import org.jetbrains.kotlin.idea.frontend.api.ValidityOwnerByValidityToken +import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder +import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirClassOrObjectSymbol +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef +import org.jetbrains.kotlin.idea.frontend.api.scopes.KtMemberScope +import org.jetbrains.kotlin.idea.frontend.api.scopes.KtUnsubstitutedScope + +internal class KtFirMemberScope( + override val owner: KtFirClassOrObjectSymbol, + override val token: ValidityOwner, + builder: KtSymbolByFirBuilder +) : KtFirDelegatingScope(builder), KtMemberScope, KtUnsubstitutedScope, ValidityOwnerByValidityToken { + override val firScope: FirScope by weakRef { + owner.fir.buildUseSiteMemberScope(owner.fir.session, ScopeSession()) + } +} + diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirPackageScope.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirPackageScope.kt new file mode 100644 index 00000000000..915e84afe41 --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirPackageScope.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.scopes + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope +import org.jetbrains.kotlin.idea.frontend.api.ValidityOwner +import org.jetbrains.kotlin.idea.frontend.api.ValidityOwnerByValidityToken +import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder +import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirPackageSymbol +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef +import org.jetbrains.kotlin.idea.frontend.api.scopes.KtPackageScope +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPackageSymbol + +internal class KtFirPackageScope( + override val owner: KtFirPackageSymbol, + override val token: ValidityOwner, + builder: KtSymbolByFirBuilder, + session: FirSession, +) : KtPackageScope, KtFirDelegatingScope(builder), ValidityOwnerByValidityToken { + override val firScope: FirScope by weakRef { + FirPackageMemberScope(owner.fqName, session) + } +} \ No newline at end of file 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 new file mode 100644 index 00000000000..e30cc03a0a1 --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirScopeProvider.kt @@ -0,0 +1,55 @@ +/* + * 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.scopes + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.idea.frontend.api.ValidityOwner +import org.jetbrains.kotlin.idea.frontend.api.ValidityOwnerByValidityToken +import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder +import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirClassOrObjectSymbol +import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirPackageSymbol +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef +import org.jetbrains.kotlin.idea.frontend.api.scopes.KtDeclaredMemberScope +import org.jetbrains.kotlin.idea.frontend.api.scopes.KtMemberScope +import org.jetbrains.kotlin.idea.frontend.api.scopes.KtPackageScope +import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScopeProvider +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPackageSymbol +import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import java.util.* + +internal class KtFirScopeProvider( + override val token: ValidityOwner, + private val builder: KtSymbolByFirBuilder, + session: FirSession +) : KtScopeProvider(), ValidityOwnerByValidityToken { + private val session by weakRef(session) + + private val memberScopeCache = IdentityHashMap() + private val declaredMemberScopeCache = IdentityHashMap() + private val packageMemberScopeCache = IdentityHashMap() + + override fun getMemberScope(classSymbol: KtClassOrObjectSymbol): KtMemberScope = withValidityAssertion { + memberScopeCache.getOrPut(classSymbol) { + check(classSymbol is KtFirClassOrObjectSymbol) + KtFirMemberScope(classSymbol, token, builder) + } + } + + override fun getDeclaredMemberScope(classSymbol: KtClassOrObjectSymbol): KtDeclaredMemberScope = withValidityAssertion { + declaredMemberScopeCache.getOrPut(classSymbol) { + check(classSymbol is KtFirClassOrObjectSymbol) + KtFirDeclaredMemberScope(classSymbol, token, builder) + } + } + + override fun getPackageScope(packageSymbol: KtPackageSymbol): KtPackageScope = withValidityAssertion { + packageMemberScopeCache.getOrPut(packageSymbol) { + check(packageSymbol is KtFirPackageSymbol) + KtFirPackageScope(packageSymbol, token, builder, session) + } + } +} \ 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 217da38a42c..b076582cfbf 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 @@ -24,8 +24,8 @@ class KtFirPackageSymbol( private val project: Project, override val token: ValidityOwner ) : KtPackageSymbol(), ValidityOwnerByValidityToken { - override val psi: PsiElement by cached { - KtPackage(PsiManager.getInstance(project), fqName, GlobalSearchScope.allScope(project)) + override val psi: PsiElement? by cached { + PsiPackageImpl(PsiManager.getInstance(project), fqName.asString().replace('/', '.')) } override val origin: KtSymbolOrigin @@ -35,14 +35,4 @@ class KtFirPackageSymbol( check(session is KtFirAnalysisSession) session.firSymbolBuilder.createPackageSymbolIfOneExists(fqName) } -} - -class KtPackage( - manager: PsiManager, - private val fqName: FqName, - private val scope: GlobalSearchScope -) : PsiPackageImpl(manager, fqName.asString()) { - override fun copy() = KtPackage(manager, fqName, scope) - - override fun isValid(): Boolean = PackageIndexUtil.packageExists(fqName, scope, project) -} +} \ 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 index 8e1aa177930..0abc403ea94 100644 --- 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 @@ -22,4 +22,6 @@ class ReadOnlyWeakRef(value: V, val validityOwner: ValidityOwner) { } @Suppress("NOTHING_TO_INLINE") -internal inline fun ValidityOwner.weakRef(value: V) = ReadOnlyWeakRef(value, this) \ No newline at end of file +internal inline fun ValidityOwner.weakRef(value: V) = ReadOnlyWeakRef(value, this) + +internal inline fun ValidityOwner.weakRef(value: () -> V) = ReadOnlyWeakRef(value(), this) \ No newline at end of file