FIR IDE: split KtAnalysisSession into mixins

This commit is contained in:
Ilya Kirillov
2021-02-19 16:40:54 +01:00
parent 141b6b0e55
commit ca4ec997ee
26 changed files with 364 additions and 254 deletions
@@ -5,24 +5,9 @@
package org.jetbrains.kotlin.idea.frontend.api
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.frontend.api.calls.KtCall
import org.jetbrains.kotlin.idea.frontend.api.components.*
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnosticWithPsi
import org.jetbrains.kotlin.idea.frontend.api.scopes.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithDeclarations
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithKind
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithMembers
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.references.KtSimpleReference
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
/**
@@ -37,175 +22,69 @@ import org.jetbrains.kotlin.psi.*
*
* To create analysis session consider using [analyze]
*/
abstract class KtAnalysisSession(final override val token: ValidityToken) : ValidityTokenOwner {
protected abstract val smartCastProvider: KtSmartCastProvider
protected abstract val diagnosticProvider: KtDiagnosticProvider
protected abstract val scopeProvider: KtScopeProvider
protected abstract val containingDeclarationProvider: KtSymbolContainingDeclarationProvider
protected abstract val symbolProvider: KtSymbolProvider
protected abstract val callResolver: KtCallResolver
protected abstract val completionCandidateChecker: KtCompletionCandidateChecker
protected abstract val symbolDeclarationOverridesProvider: KtSymbolDeclarationOverridesProvider
protected abstract val referenceShortener: KtReferenceShortener
abstract class KtAnalysisSession(final override val token: ValidityToken) : ValidityTokenOwner,
KtSmartCastProviderMixIn,
KtCallResolverMixIn,
KtDiagnosticProviderMixIn,
KtScopeProviderMixIn,
KtCompletionCandidateCheckerMixIn,
KtTypeRendererMixIn,
KtSymbolDeclarationOverridesProviderMixIn,
KtExpressionTypeProviderMixIn,
KtTypeProviderMixIn,
KtSymbolProviderMixIn,
KtSymbolContainingDeclarationProviderMixIn,
KtSubtypingComponentMixIn,
KtExpressionInfoProviderMixIn,
KtSymbolsMixIn,
KtReferenceResolveMixIn,
KtReferenceShortenerMixIn {
@Suppress("LeakingThis")
protected open val typeRenderer: KtTypeRenderer = KtDefaultTypeRenderer(this, token)
protected abstract val expressionTypeProvider: KtExpressionTypeProvider
protected abstract val typeProvider: KtTypeProvider
protected abstract val subtypingComponent: KtSubtypingComponent
protected abstract val expressionHandlingComponent: KtExpressionHandlingComponent
override val analysisSession: KtAnalysisSession get() = this
abstract fun createContextDependentCopy(originalKtFile: KtFile, fakeKtElement: KtElement): KtAnalysisSession
internal val smartCastProvider: KtSmartCastProvider get() = smartCastProviderImpl
protected abstract val smartCastProviderImpl: KtSmartCastProvider
/**
* Return a list of **all** symbols which are overridden by symbol
*
* E.g, if we have `A.foo` overrides `B.foo` overrides `C.foo`, all two super declarations `B.foo`, `C.foo` will be returned
*
* Unwraps substituted overridden symbols (see [org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin.INTERSECTION_OVERRIDE])
*
* @see getDirectlyOverriddenSymbols
*/
fun KtCallableSymbol.getAllOverriddenSymbols(): List<KtCallableSymbol> =
symbolDeclarationOverridesProvider.getAllOverriddenSymbols(this)
internal val diagnosticProvider: KtDiagnosticProvider get() = diagnosticProviderImpl
protected abstract val diagnosticProviderImpl: KtDiagnosticProvider
/**
* Return a list of symbols which are **directly** overridden by symbol
**
* E.g, if we have `A.foo` overrides `B.foo` overrides `C.foo`, only declarations directly overriden `B.foo` will be returned
*
* Unwraps substituted overridden symbols (see [org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin.INTERSECTION_OVERRIDE])
*
* @see getAllOverriddenSymbols
*/
fun KtCallableSymbol.getDirectlyOverriddenSymbols(): List<KtCallableSymbol> =
symbolDeclarationOverridesProvider.getDirectlyOverriddenSymbols(this)
internal val scopeProvider: KtScopeProvider get() = scopeProviderImpl
protected abstract val scopeProviderImpl: KtScopeProvider
fun KtCallableSymbol.getIntersectionOverriddenSymbols(): Collection<KtCallableSymbol> =
symbolDeclarationOverridesProvider.getIntersectionOverriddenSymbols(this)
internal val containingDeclarationProvider: KtSymbolContainingDeclarationProvider get() = containingDeclarationProviderImpl
protected abstract val containingDeclarationProviderImpl: KtSymbolContainingDeclarationProvider
fun KtExpression.getSmartCast(): KtType? = smartCastProvider.getSmartCastedToType(this)
internal val symbolProvider: KtSymbolProvider get() = symbolProviderImpl
protected abstract val symbolProviderImpl: KtSymbolProvider
fun KtExpression.getImplicitReceiverSmartCast(): Collection<ImplicitReceiverSmartCast> =
smartCastProvider.getImplicitReceiverSmartCast(this)
internal val callResolver: KtCallResolver get() = callResolverImpl
protected abstract val callResolverImpl: KtCallResolver
fun KtExpression.getKtType(): KtType = expressionTypeProvider.getKtExpressionType(this)
internal val completionCandidateChecker: KtCompletionCandidateChecker get() = completionCandidateCheckerImpl
protected abstract val completionCandidateCheckerImpl: KtCompletionCandidateChecker
fun KtDeclaration.getReturnKtType(): KtType = expressionTypeProvider.getReturnTypeForKtDeclaration(this)
internal val symbolDeclarationOverridesProvider: KtSymbolDeclarationOverridesProvider get() = symbolDeclarationOverridesProviderImpl
protected abstract val symbolDeclarationOverridesProviderImpl: KtSymbolDeclarationOverridesProvider
infix fun KtType.isEqualTo(other: KtType): Boolean = subtypingComponent.isEqualTo(this, other)
internal val referenceShortener: KtReferenceShortener get() = referenceShortenerImpl
protected abstract val referenceShortenerImpl: KtReferenceShortener
infix fun KtType.isSubTypeOf(superType: KtType): Boolean = subtypingComponent.isSubTypeOf(this, superType)
infix fun KtType.isNotSubTypeOf(superType: KtType): Boolean = !subtypingComponent.isSubTypeOf(this, superType)
@Suppress("LeakingThis")
protected open val typeRendererImpl: KtTypeRenderer = KtDefaultTypeRenderer(this, token)
internal val typeRenderer: KtTypeRenderer get() = typeRendererImpl
fun PsiElement.getExpectedType(): KtType? = expressionTypeProvider.getExpectedType(this)
internal val expressionTypeProvider: KtExpressionTypeProvider get() = expressionTypeProviderImpl
protected abstract val expressionTypeProviderImpl: KtExpressionTypeProvider
val builtinTypes: KtBuiltinTypes get() = typeProvider.builtinTypes
internal val typeProvider: KtTypeProvider get() = typeProviderImpl
protected abstract val typeProviderImpl: KtTypeProvider
/**
* Approximates [KtType] with the a supertype which can be rendered in a source code
*
* Return `null` if the type do not need approximation and can be rendered as is
* Otherwise, for type `T` return type `S` such `T <: S` and `T` and every it type argument is [org.jetbrains.kotlin.idea.frontend.api.types.KtDenotableType]`
*/
fun KtType.approximateToSuperPublicDenotable(): KtType? = typeProvider.approximateToSuperPublicDenotableType(this)
internal val subtypingComponent: KtSubtypingComponent get() = subtypingComponentImpl
protected abstract val subtypingComponentImpl: KtSubtypingComponent
fun KtClassOrObjectSymbol.buildSelfClassType(): KtType = typeProvider.buildSelfClassType(this)
fun KtElement.getDiagnostics(filter: KtDiagnosticCheckerFilter): Collection<KtDiagnostic> =
diagnosticProvider.getDiagnosticsForElement(this, filter)
fun KtFile.collectDiagnosticsForFile(filter: KtDiagnosticCheckerFilter): Collection<KtDiagnosticWithPsi<*>> =
diagnosticProvider.collectDiagnosticsForFile(this, filter)
fun KtSymbolWithKind.getContainingSymbol(): KtSymbolWithKind? = containingDeclarationProvider.getContainingDeclaration(this)
fun KtSymbolWithMembers.getMemberScope(): KtMemberScope = scopeProvider.getMemberScope(this)
fun KtSymbolWithMembers.getDeclaredMemberScope(): KtDeclaredMemberScope = scopeProvider.getDeclaredMemberScope(this)
fun KtFileSymbol.getFileScope(): KtDeclarationScope<KtSymbolWithDeclarations> = scopeProvider.getFileScope(this)
fun KtPackageSymbol.getPackageScope(): KtPackageScope = scopeProvider.getPackageScope(this)
fun List<KtScope>.asCompositeScope(): KtCompositeScope = scopeProvider.getCompositeScope(this)
fun KtType.getTypeScope(): KtScope? = scopeProvider.getTypeScope(this)
fun KtFile.getScopeContextForPosition(positionInFakeFile: KtElement): KtScopeContext =
scopeProvider.getScopeContextForPosition(this, positionInFakeFile)
fun KtDeclaration.getSymbol(): KtSymbol = symbolProvider.getSymbol(this)
fun KtParameter.getParameterSymbol(): KtParameterSymbol = symbolProvider.getParameterSymbol(this)
fun KtNamedFunction.getFunctionSymbol(): KtFunctionSymbol = symbolProvider.getFunctionSymbol(this)
fun KtConstructor<*>.getConstructorSymbol(): KtConstructorSymbol = symbolProvider.getConstructorSymbol(this)
fun KtTypeParameter.getTypeParameterSymbol(): KtTypeParameterSymbol = symbolProvider.getTypeParameterSymbol(this)
fun KtTypeAlias.getTypeAliasSymbol(): KtTypeAliasSymbol = symbolProvider.getTypeAliasSymbol(this)
fun KtEnumEntry.getEnumEntrySymbol(): KtEnumEntrySymbol = symbolProvider.getEnumEntrySymbol(this)
fun KtNamedFunction.getAnonymousFunctionSymbol(): KtAnonymousFunctionSymbol = symbolProvider.getAnonymousFunctionSymbol(this)
fun KtLambdaExpression.getAnonymousFunctionSymbol(): KtAnonymousFunctionSymbol = symbolProvider.getAnonymousFunctionSymbol(this)
fun KtProperty.getVariableSymbol(): KtVariableSymbol = symbolProvider.getVariableSymbol(this)
fun KtObjectLiteralExpression.getAnonymousObjectSymbol(): KtAnonymousObjectSymbol = symbolProvider.getAnonymousObjectSymbol(this)
fun KtClassOrObject.getClassOrObjectSymbol(): KtClassOrObjectSymbol = symbolProvider.getClassOrObjectSymbol(this)
fun KtPropertyAccessor.getPropertyAccessorSymbol(): KtPropertyAccessorSymbol = symbolProvider.getPropertyAccessorSymbol(this)
fun KtFile.getFileSymbol(): KtFileSymbol = symbolProvider.getFileSymbol(this)
/**
* @return symbol with specified [this@getClassOrObjectSymbolByClassId] or `null` in case such symbol is not found
*/
fun ClassId.getCorrespondingToplevelClassOrObjectSymbol(): KtClassOrObjectSymbol? = symbolProvider.getClassOrObjectSymbolByClassId(this)
fun FqName.getContainingCallableSymbolsWithName(name: Name): Sequence<KtSymbol> = symbolProvider.getTopLevelCallableSymbols(this, name)
fun <S : KtSymbol> KtSymbolPointer<S>.restoreSymbol(): S? = restoreSymbol(this@KtAnalysisSession)
fun KtCallExpression.resolveCall(): KtCall? = callResolver.resolveCall(this)
fun KtBinaryExpression.resolveCall(): KtCall? = callResolver.resolveCall(this)
fun KtReference.resolveToSymbols(): Collection<KtSymbol> {
check(this is KtSymbolBasedReference) { "To get reference symbol the one should be KtSymbolBasedReference" }
return this@KtAnalysisSession.resolveToSymbols()
}
fun KtSimpleReference<*>.resolveToSymbol(): KtSymbol? {
check(this is KtSymbolBasedReference) { "To get reference symbol the one should be KtSymbolBasedReference but was ${this::class}" }
return resolveToSymbols().singleOrNull()
}
fun KtCallableSymbol.checkExtensionIsSuitable(
originalPsiFile: KtFile,
psiFakeCompletionExpression: KtSimpleNameExpression,
psiReceiverExpression: KtExpression?,
): Boolean = completionCandidateChecker.checkExtensionFitsCandidate(
this,
originalPsiFile,
psiFakeCompletionExpression,
psiReceiverExpression
)
fun KtType.render(options: KtTypeRendererOptions = KtTypeRendererOptions.DEFAULT): String =
typeRenderer.render(this, options)
fun KtReturnExpression.getReturnTargetSymbol(): KtCallableSymbol? =
expressionHandlingComponent.getReturnExpressionTargetSymbol(this)
fun collectPossibleReferenceShortenings(file: KtFile, selection: TextRange): ShortenCommand =
referenceShortener.collectShortenings(file, selection)
}
internal val expressionInfoProvider: KtExpressionInfoProvider get() = expressionInfoProviderImpl
protected abstract val expressionInfoProviderImpl: KtExpressionInfoProvider
}
@@ -6,9 +6,9 @@
package org.jetbrains.kotlin.idea.frontend.api.components
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
abstract class KtAnalysisSessionComponent : ValidityTokenOwner {
protected abstract val analysisSession: KtAnalysisSession
}
}
@@ -0,0 +1,12 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.frontend.api.components
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
interface KtAnalysisSessionMixIn {
val analysisSession: KtAnalysisSession
}
@@ -12,4 +12,13 @@ import org.jetbrains.kotlin.psi.KtCallExpression
abstract class KtCallResolver : KtAnalysisSessionComponent() {
abstract fun resolveCall(call: KtCallExpression): KtCall?
abstract fun resolveCall(call: KtBinaryExpression): KtCall?
}
interface KtCallResolverMixIn : KtAnalysisSessionMixIn {
fun KtCallExpression.resolveCall(): KtCall? =
analysisSession.callResolver.resolveCall(this)
fun KtBinaryExpression.resolveCall(): KtCall? =
analysisSession.callResolver.resolveCall(this)
}
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.idea.frontend.api.components
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtFile
@@ -18,4 +17,18 @@ abstract class KtCompletionCandidateChecker : KtAnalysisSessionComponent() {
nameExpression: KtSimpleNameExpression,
possibleExplicitReceiver: KtExpression?,
): Boolean
}
interface KtCompletionCandidateCheckerMixIn : KtAnalysisSessionMixIn {
fun KtCallableSymbol.checkExtensionIsSuitable(
originalPsiFile: KtFile,
psiFakeCompletionExpression: KtSimpleNameExpression,
psiReceiverExpression: KtExpression?,
): Boolean =
analysisSession.completionCandidateChecker.checkExtensionFitsCandidate(
this,
originalPsiFile,
psiFakeCompletionExpression,
psiReceiverExpression
)
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.idea.frontend.api.components
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnosticWithPsi
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
@@ -14,6 +15,14 @@ abstract class KtDiagnosticProvider : KtAnalysisSessionComponent() {
abstract fun collectDiagnosticsForFile(ktFile: KtFile, filter: KtDiagnosticCheckerFilter): Collection<KtDiagnosticWithPsi<*>>
}
interface KtDiagnosticProviderMixIn : KtAnalysisSessionMixIn {
fun KtElement.getDiagnostics(filter: KtDiagnosticCheckerFilter): Collection<KtDiagnostic> =
analysisSession.diagnosticProvider.getDiagnosticsForElement(this, filter)
fun KtFile.collectDiagnosticsForFile(filter: KtDiagnosticCheckerFilter): Collection<KtDiagnosticWithPsi<*>> =
analysisSession.diagnosticProvider.collectDiagnosticsForFile(this, filter)
}
enum class KtDiagnosticCheckerFilter {
ONLY_COMMON_CHECKERS,
ONLY_EXTENDED_CHECKERS,
@@ -1,14 +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.components
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionLikeSymbol
import org.jetbrains.kotlin.psi.KtReturnExpression
abstract class KtExpressionHandlingComponent : KtAnalysisSessionComponent() {
abstract fun getReturnExpressionTargetSymbol(returnExpression: KtReturnExpression): KtCallableSymbol?
}
@@ -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.components
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.psi.KtReturnExpression
abstract class KtExpressionInfoProvider : KtAnalysisSessionComponent() {
abstract fun getReturnExpressionTargetSymbol(returnExpression: KtReturnExpression): KtCallableSymbol?
}
interface KtExpressionInfoProviderMixIn : KtAnalysisSessionMixIn {
fun KtReturnExpression.getReturnTargetSymbol(): KtCallableSymbol? =
analysisSession.expressionInfoProvider.getReturnExpressionTargetSymbol(this)
}
@@ -17,3 +17,14 @@ abstract class KtExpressionTypeProvider : KtAnalysisSessionComponent() {
abstract fun getExpectedType(expression: PsiElement): KtType?
}
interface KtExpressionTypeProviderMixIn : KtAnalysisSessionMixIn {
fun KtExpression.getKtType(): KtType =
analysisSession.expressionTypeProvider.getKtExpressionType(this)
fun KtDeclaration.getReturnKtType(): KtType =
analysisSession.expressionTypeProvider.getReturnTypeForKtDeclaration(this)
fun PsiElement.getExpectedType(): KtType? =
analysisSession.expressionTypeProvider.getExpectedType(this)
}
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.frontend.api.components
import org.jetbrains.kotlin.idea.frontend.api.KtSymbolBasedReference
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.references.KtSimpleReference
interface KtReferenceResolveMixIn : KtAnalysisSessionMixIn {
fun KtReference.resolveToSymbols(): Collection<KtSymbol> {
check(this is KtSymbolBasedReference) { "To get reference symbol the one should be KtSymbolBasedReference" }
return analysisSession.resolveToSymbols()
}
fun KtSimpleReference<*>.resolveToSymbol(): KtSymbol? {
check(this is KtSymbolBasedReference) { "To get reference symbol the one should be KtSymbolBasedReference but was ${this::class}" }
return resolveToSymbols().singleOrNull()
}
}
@@ -12,6 +12,11 @@ abstract class KtReferenceShortener : KtAnalysisSessionComponent() {
abstract fun collectShortenings(file: KtFile, selection: TextRange): ShortenCommand
}
interface KtReferenceShortenerMixIn : KtAnalysisSessionMixIn {
fun collectPossibleReferenceShortenings(file: KtFile, selection: TextRange): ShortenCommand =
analysisSession.referenceShortener.collectShortenings(file, selection)
}
interface ShortenCommand {
fun invokeShortening()
}
@@ -29,4 +29,27 @@ abstract class KtScopeProvider : KtAnalysisSessionComponent() {
): KtScopeContext
}
interface KtScopeProviderMixIn : KtAnalysisSessionMixIn {
fun KtSymbolWithMembers.getMemberScope(): KtMemberScope =
analysisSession.scopeProvider.getMemberScope(this)
fun KtSymbolWithMembers.getDeclaredMemberScope(): KtDeclaredMemberScope =
analysisSession.scopeProvider.getDeclaredMemberScope(this)
fun KtFileSymbol.getFileScope(): KtDeclarationScope<KtSymbolWithDeclarations> =
analysisSession.scopeProvider.getFileScope(this)
fun KtPackageSymbol.getPackageScope(): KtPackageScope =
analysisSession.scopeProvider.getPackageScope(this)
fun List<KtScope>.asCompositeScope(): KtCompositeScope =
analysisSession.scopeProvider.getCompositeScope(this)
fun KtType.getTypeScope(): KtScope? =
analysisSession.scopeProvider.getTypeScope(this)
fun KtFile.getScopeContextForPosition(positionInFakeFile: KtElement): KtScopeContext =
analysisSession.scopeProvider.getScopeContextForPosition(this, positionInFakeFile)
}
data class KtScopeContext(val scopes: KtCompositeScope, val implicitReceiversTypes: List<KtType>)
@@ -12,4 +12,12 @@ import org.jetbrains.kotlin.psi.KtExpression
abstract class KtSmartCastProvider : KtAnalysisSessionComponent() {
abstract fun getSmartCastedToType(expression: KtExpression): KtType?
abstract fun getImplicitReceiverSmartCast(expression: KtExpression): Collection<ImplicitReceiverSmartCast>
}
interface KtSmartCastProviderMixIn : KtAnalysisSessionMixIn {
fun KtExpression.getSmartCast(): KtType? =
analysisSession.smartCastProvider.getSmartCastedToType(this)
fun KtExpression.getImplicitReceiverSmartCast(): Collection<ImplicitReceiverSmartCast> =
analysisSession.smartCastProvider.getImplicitReceiverSmartCast(this)
}
@@ -10,4 +10,15 @@ import org.jetbrains.kotlin.idea.frontend.api.types.KtType
abstract class KtSubtypingComponent : KtAnalysisSessionComponent() {
abstract fun isEqualTo(first: KtType, second: KtType): Boolean
abstract fun isSubTypeOf(subType: KtType, superType: KtType): Boolean
}
interface KtSubtypingComponentMixIn : KtAnalysisSessionMixIn {
infix fun KtType.isEqualTo(other: KtType): Boolean =
analysisSession.subtypingComponent.isEqualTo(this, other)
infix fun KtType.isSubTypeOf(superType: KtType): Boolean =
analysisSession.subtypingComponent.isSubTypeOf(this, superType)
infix fun KtType.isNotSubTypeOf(superType: KtType): Boolean =
!analysisSession.subtypingComponent.isSubTypeOf(this, superType)
}
@@ -8,11 +8,16 @@ package org.jetbrains.kotlin.idea.frontend.api.components
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithKind
abstract class KtSymbolContainingDeclarationProvider : KtAnalysisSessionComponent() {
abstract fun getContainingDeclaration(symbol: KtSymbolWithKind): KtSymbolWithKind?
}
interface KtSymbolContainingDeclarationProviderMixIn : KtAnalysisSessionMixIn {
/**
* Returns containing declaration for symbol:
* for top-level declarations returns null
* for class members returns containing class
* for local declaration returns declaration it was declared it
*/
abstract fun getContainingDeclaration(symbol: KtSymbolWithKind): KtSymbolWithKind?
fun KtSymbolWithKind.getContainingSymbol(): KtSymbolWithKind? =
analysisSession.containingDeclarationProvider.getContainingDeclaration(this)
}
@@ -10,24 +10,37 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
abstract class KtSymbolDeclarationOverridesProvider : KtAnalysisSessionComponent() {
/**
* Returns symbols that are overridden by requested
*/
abstract fun <T : KtSymbol> getAllOverriddenSymbols(
callableSymbol: T,
): List<KtCallableSymbol>
abstract fun <T : KtSymbol> getAllOverriddenSymbols(callableSymbol: T): List<KtCallableSymbol>
abstract fun <T : KtSymbol> getDirectlyOverriddenSymbols(callableSymbol: T): List<KtCallableSymbol>
/**
* Returns symbols that are overridden by requested
*/
abstract fun <T : KtSymbol> getDirectlyOverriddenSymbols(
callableSymbol: T,
): List<KtCallableSymbol>
/**
* If [symbol] origin is [org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin.INTERSECTION_OVERRIDE]
* Then returns the symbols which [symbol] overrides, otherwise empty collection
*/
abstract fun getIntersectionOverriddenSymbols(symbol: KtCallableSymbol): Collection<KtCallableSymbol>
}
interface KtSymbolDeclarationOverridesProviderMixIn : KtAnalysisSessionMixIn {
/**
* Return a list of **all** symbols which are overridden by symbol
*
* E.g, if we have `A.foo` overrides `B.foo` overrides `C.foo`, all two super declarations `B.foo`, `C.foo` will be returned
*
* Unwraps substituted overridden symbols (see [org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin.INTERSECTION_OVERRIDE])
*
* @see getDirectlyOverriddenSymbols
*/
fun KtCallableSymbol.getAllOverriddenSymbols(): List<KtCallableSymbol> =
analysisSession.symbolDeclarationOverridesProvider.getAllOverriddenSymbols(this)
/**
* Return a list of symbols which are **directly** overridden by symbol
**
* E.g, if we have `A.foo` overrides `B.foo` overrides `C.foo`, only declarations directly overriden `B.foo` will be returned
*
* Unwraps substituted overridden symbols (see [org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin.INTERSECTION_OVERRIDE])
*
* @see getAllOverriddenSymbols
*/
fun KtCallableSymbol.getDirectlyOverriddenSymbols(): List<KtCallableSymbol> =
analysisSession.symbolDeclarationOverridesProvider.getDirectlyOverriddenSymbols(this)
fun KtCallableSymbol.getIntersectionOverriddenSymbols(): Collection<KtCallableSymbol> =
analysisSession.symbolDeclarationOverridesProvider.getIntersectionOverriddenSymbols(this)
}
@@ -0,0 +1,14 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.frontend.api.components
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer
interface KtSymbolsMixIn : KtAnalysisSessionMixIn {
@Suppress("DEPRECATION")
fun <S : KtSymbol> KtSymbolPointer<S>.restoreSymbol(): S? = restoreSymbol(analysisSession)
}
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.idea.frontend.api.components
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
@@ -18,6 +17,23 @@ abstract class KtTypeProvider : KtAnalysisSessionComponent() {
abstract fun buildSelfClassType(symbol: KtClassOrObjectSymbol): KtType
}
interface KtTypeProviderMixIn : KtAnalysisSessionMixIn {
val builtinTypes: KtBuiltinTypes
get() = analysisSession.typeProvider.builtinTypes
/**
* Approximates [KtType] with the a supertype which can be rendered in a source code
*
* Return `null` if the type do not need approximation and can be rendered as is
* Otherwise, for type `T` return type `S` such `T <: S` and `T` and every it type argument is [org.jetbrains.kotlin.idea.frontend.api.types.KtDenotableType]`
*/
fun KtType.approximateToSuperPublicDenotable(): KtType? =
analysisSession.typeProvider.approximateToSuperPublicDenotableType(this)
fun KtClassOrObjectSymbol.buildSelfClassType(): KtType =
analysisSession.typeProvider.buildSelfClassType(this)
}
@Suppress("PropertyName")
abstract class KtBuiltinTypes : ValidityTokenOwner {
@@ -14,6 +14,11 @@ abstract class KtTypeRenderer : KtAnalysisSessionComponent() {
abstract fun render(type: KtType, options: KtTypeRendererOptions): String
}
interface KtTypeRendererMixIn : KtAnalysisSessionMixIn {
fun KtType.render(options: KtTypeRendererOptions = KtTypeRendererOptions.DEFAULT): String =
analysisSession.typeRenderer.render(this, options)
}
data class KtTypeRendererOptions(
val renderFqNames: Boolean,
val renderFunctionTypes: Boolean
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.idea.frontend.api.symbols
import org.jetbrains.kotlin.idea.frontend.api.components.KtAnalysisSessionComponent
import org.jetbrains.kotlin.idea.frontend.api.components.KtAnalysisSessionMixIn
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -43,10 +44,61 @@ abstract class KtSymbolProvider : KtAnalysisSessionComponent() {
abstract fun getClassOrObjectSymbol(psi: KtClassOrObject): KtClassOrObjectSymbol
abstract fun getPropertyAccessorSymbol(psi: KtPropertyAccessor): KtPropertyAccessorSymbol
/**
* @return symbol with specified [classId] or `null` in case such symbol is not found
*/
abstract fun getClassOrObjectSymbolByClassId(classId: ClassId): KtClassOrObjectSymbol?
abstract fun getTopLevelCallableSymbols(packageFqName: FqName, name: Name): Sequence<KtSymbol>
}
interface KtSymbolProviderMixIn : KtAnalysisSessionMixIn {
fun KtDeclaration.getSymbol(): KtSymbol =
analysisSession.symbolProvider.getSymbol(this)
fun KtParameter.getParameterSymbol(): KtParameterSymbol =
analysisSession.symbolProvider.getParameterSymbol(this)
fun KtNamedFunction.getFunctionSymbol(): KtFunctionSymbol =
analysisSession.symbolProvider.getFunctionSymbol(this)
fun KtConstructor<*>.getConstructorSymbol(): KtConstructorSymbol =
analysisSession.symbolProvider.getConstructorSymbol(this)
fun KtTypeParameter.getTypeParameterSymbol(): KtTypeParameterSymbol =
analysisSession.symbolProvider.getTypeParameterSymbol(this)
fun KtTypeAlias.getTypeAliasSymbol(): KtTypeAliasSymbol =
analysisSession.symbolProvider.getTypeAliasSymbol(this)
fun KtEnumEntry.getEnumEntrySymbol(): KtEnumEntrySymbol =
analysisSession.symbolProvider.getEnumEntrySymbol(this)
fun KtNamedFunction.getAnonymousFunctionSymbol(): KtAnonymousFunctionSymbol =
analysisSession.symbolProvider.getAnonymousFunctionSymbol(this)
fun KtLambdaExpression.getAnonymousFunctionSymbol(): KtAnonymousFunctionSymbol =
analysisSession.symbolProvider.getAnonymousFunctionSymbol(this)
fun KtProperty.getVariableSymbol(): KtVariableSymbol =
analysisSession.symbolProvider.getVariableSymbol(this)
fun KtObjectLiteralExpression.getAnonymousObjectSymbol(): KtAnonymousObjectSymbol =
analysisSession.symbolProvider.getAnonymousObjectSymbol(this)
fun KtClassOrObject.getClassOrObjectSymbol(): KtClassOrObjectSymbol =
analysisSession.symbolProvider.getClassOrObjectSymbol(this)
fun KtPropertyAccessor.getPropertyAccessorSymbol(): KtPropertyAccessorSymbol =
analysisSession.symbolProvider.getPropertyAccessorSymbol(this)
fun KtFile.getFileSymbol(): KtFileSymbol =
analysisSession.symbolProvider.getFileSymbol(this)
/**
* @return symbol with specified [this@getClassOrObjectSymbolByClassId] or `null` in case such symbol is not found
*/
fun ClassId.getCorrespondingToplevelClassOrObjectSymbol(): KtClassOrObjectSymbol? =
analysisSession.symbolProvider.getClassOrObjectSymbolByClassId(this)
fun FqName.getContainingCallableSymbolsWithName(name: Name): Sequence<KtSymbol> =
analysisSession.symbolProvider.getTopLevelCallableSymbols(this, name)
}
@@ -16,13 +16,11 @@ import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.ReadActionConfinementValidityToken
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.assertIsValidAndAccessible
import org.jetbrains.kotlin.idea.frontend.api.components.*
import org.jetbrains.kotlin.idea.frontend.api.fir.components.*
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbolProvider
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.EnclosingDeclarationContext
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.recordCompletionContext
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.threadLocal
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolProvider
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
@@ -38,22 +36,33 @@ private constructor(
assertIsValidAndAccessible()
}
override val smartCastProvider: KtSmartCastProvider = KtFirSmartcastProvider(this, token)
override val expressionTypeProvider: KtExpressionTypeProvider = KtFirExpressionTypeProvider(this, token)
public override val diagnosticProvider: KtDiagnosticProvider = KtFirDiagnosticProvider(this, token)
override val containingDeclarationProvider = KtFirSymbolContainingDeclarationProvider(this, token)
override val callResolver: KtCallResolver = KtFirCallResolver(this, token)
override val scopeProvider by threadLocal { KtFirScopeProvider(this, firSymbolBuilder, project, firResolveState, token) }
override val symbolProvider: KtSymbolProvider =
KtFirSymbolProvider(this, firResolveState.rootModuleSession.symbolProvider, firResolveState, firSymbolBuilder, token)
override val completionCandidateChecker: KtCompletionCandidateChecker = KtFirCompletionCandidateChecker(this, token)
override val symbolDeclarationOverridesProvider: KtSymbolDeclarationOverridesProvider =
KtFirSymbolDeclarationOverridesProvider(this, token)
override val referenceShortener: KtReferenceShortener = KtFirReferenceShortener(this, token, firResolveState)
override val smartCastProviderImpl = KtFirSmartcastProvider(this, token)
override val expressionHandlingComponent: KtExpressionHandlingComponent = KtFirExpressionHandlingComponent(this, token)
override val typeProvider: KtTypeProvider = KtFirTypeProvider(this, token)
override val subtypingComponent: KtSubtypingComponent = KtFirSubtypingComponent(this, token)
override val expressionTypeProviderImpl = KtFirExpressionTypeProvider(this, token)
override val diagnosticProviderImpl = KtFirDiagnosticProvider(this, token)
override val containingDeclarationProviderImpl = KtFirSymbolContainingDeclarationProvider(this, token)
override val callResolverImpl = KtFirCallResolver(this, token)
override val scopeProviderImpl by threadLocal { KtFirScopeProvider(this, firSymbolBuilder, project, firResolveState, token) }
override val symbolProviderImpl =
KtFirSymbolProvider(this, firResolveState.rootModuleSession.symbolProvider, firResolveState, firSymbolBuilder, token)
override val completionCandidateCheckerImpl = KtFirCompletionCandidateChecker(this, token)
override val symbolDeclarationOverridesProviderImpl =
KtFirSymbolDeclarationOverridesProvider(this, token)
override val referenceShortenerImpl = KtFirReferenceShortener(this, token, firResolveState)
override val expressionInfoProviderImpl = KtFirExpressionInfoProvider(this, token)
override val typeProviderImpl = KtFirTypeProvider(this, token)
override val subtypingComponentImpl = KtFirSubtypingComponent(this, token)
override fun createContextDependentCopy(originalKtFile: KtFile, fakeKtElement: KtElement): KtAnalysisSession {
check(context == KtFirAnalysisSessionContext.DefaultContext) {
@@ -7,29 +7,37 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.components
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.toFirDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
import org.jetbrains.kotlin.idea.frontend.api.components.KtAnalysisSessionComponent
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnosticWithPsi
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.diagnostics.KT_DIAGNOSTIC_CONVERTER
internal interface KtFirAnalysisSessionComponent {
val analysisSession: KtFirAnalysisSession
val rootModuleSession: FirSession get() = analysisSession.firResolveState.rootModuleSession
val firSymbolBuilder get() = analysisSession.firSymbolBuilder
val firResolveState get() = analysisSession.firResolveState
fun ConeKotlinType.asKtType() = analysisSession.firSymbolBuilder.buildKtType(this)
fun FirPsiDiagnostic<*>.asKtDiagnostic(): KtDiagnosticWithPsi<*> =
(analysisSession.diagnosticProvider as KtFirDiagnosticProvider).firDiagnosticAsKtDiagnostic(this)
KT_DIAGNOSTIC_CONVERTER.convert(analysisSession, this as FirDiagnostic<*>)
fun ConeDiagnostic.asKtDiagnostic(source: FirSourceElement): KtDiagnostic? =
(analysisSession.diagnosticProvider as KtFirDiagnosticProvider).coneDiagnosticAsKtDiagnostic(this, source)
fun ConeDiagnostic.asKtDiagnostic(source: FirSourceElement): KtDiagnosticWithPsi<*>? {
val firDiagnostic = toFirDiagnostic(source) ?: return null
check(firDiagnostic is FirPsiDiagnostic<*>)
return firDiagnostic.asKtDiagnostic()
}
fun createTypeCheckerContext() = ConeTypeCheckerContext(
isErrorTypeEqualsToAnything = true,
@@ -5,12 +5,6 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.components
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.toFirDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.idea.fir.low.level.api.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.idea.fir.low.level.api.api.collectDiagnosticsForFile
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getDiagnostics
@@ -19,7 +13,6 @@ import org.jetbrains.kotlin.idea.frontend.api.components.KtDiagnosticCheckerFilt
import org.jetbrains.kotlin.idea.frontend.api.components.KtDiagnosticProvider
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnosticWithPsi
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.diagnostics.KT_DIAGNOSTIC_CONVERTER
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
@@ -38,19 +31,10 @@ internal class KtFirDiagnosticProvider(
override fun collectDiagnosticsForFile(ktFile: KtFile, filter: KtDiagnosticCheckerFilter): Collection<KtDiagnosticWithPsi<*>> =
ktFile.collectDiagnosticsForFile(firResolveState, filter.asLLFilter()).map { it.asKtDiagnostic() }
fun firDiagnosticAsKtDiagnostic(diagnostic: FirPsiDiagnostic<*>): KtDiagnosticWithPsi<*> {
return KT_DIAGNOSTIC_CONVERTER.convert(analysisSession, diagnostic as FirDiagnostic<*>)
}
private fun KtDiagnosticCheckerFilter.asLLFilter() = when (this) {
KtDiagnosticCheckerFilter.ONLY_COMMON_CHECKERS -> DiagnosticCheckerFilter.ONLY_COMMON_CHECKERS
KtDiagnosticCheckerFilter.ONLY_EXTENDED_CHECKERS -> DiagnosticCheckerFilter.ONLY_EXTENDED_CHECKERS
KtDiagnosticCheckerFilter.EXTENDED_AND_COMMON_CHECKERS -> DiagnosticCheckerFilter.EXTENDED_AND_COMMON_CHECKERS
}
fun coneDiagnosticAsKtDiagnostic(coneDiagnostic: ConeDiagnostic, source: FirSourceElement): KtDiagnosticWithPsi<*>? {
val firDiagnostic = coneDiagnostic.toFirDiagnostic(source) ?: return null
check(firDiagnostic is FirPsiDiagnostic<*>)
return firDiagnosticAsKtDiagnostic(firDiagnostic)
}
}
@@ -8,16 +8,15 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.components
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirSafe
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.components.KtExpressionHandlingComponent
import org.jetbrains.kotlin.idea.frontend.api.components.KtExpressionInfoProvider
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionLikeSymbol
import org.jetbrains.kotlin.psi.KtReturnExpression
internal class KtFirExpressionHandlingComponent(
internal class KtFirExpressionInfoProvider(
override val analysisSession: KtFirAnalysisSession,
override val token: ValidityToken,
) : KtExpressionHandlingComponent(), KtFirAnalysisSessionComponent {
) : KtExpressionInfoProvider(), KtFirAnalysisSessionComponent {
override fun getReturnExpressionTargetSymbol(returnExpression: KtReturnExpression): KtCallableSymbol? {
val fir = returnExpression.getOrBuildFirSafe<FirReturnExpression>(firResolveState) ?: return null
val firTargetSymbol = fir.target.labeledElement
@@ -10,13 +10,10 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirSafe
import org.jetbrains.kotlin.idea.frontend.api.ImplicitReceiverSmartCast
import org.jetbrains.kotlin.idea.frontend.api.ImplicitReceiverSmartcastKind
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.*
import org.jetbrains.kotlin.idea.frontend.api.components.KtSmartCastProvider
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
import org.jetbrains.kotlin.psi.KtExpression
internal class KtFirSmartcastProvider(