FIR IDE: rework high level API

Make analysis session to always be a receiver parameter
This commit is contained in:
Ilya Kirillov
2020-08-13 15:28:28 +03:00
parent cadf99ca1e
commit 37ac654444
43 changed files with 539 additions and 308 deletions
@@ -6,10 +6,17 @@
package org.jetbrains.kotlin.idea.frontend.api
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScopeProvider
import org.jetbrains.kotlin.idea.frontend.api.components.*
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.KtSymbolWithKind
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.*
/**
@@ -25,24 +32,86 @@ import org.jetbrains.kotlin.psi.*
* To create analysis session consider using [analyze]
*/
abstract class KtAnalysisSession(override val token: ValidityToken) : ValidityTokenOwner {
abstract val symbolProvider: KtSymbolProvider
abstract val scopeProvider: KtScopeProvider
abstract val containingDeclarationProvider: KtSymbolContainingDeclarationProvider
protected abstract val smartCastProvider: KtSmartCastProvider
protected abstract val typeProvider: KtTypeProvider
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
abstract fun getSmartCastedToTypes(expression: KtExpression): Collection<KtType>?
abstract fun getImplicitReceiverSmartCasts(expression: KtExpression): Collection<ImplicitReceiverSmartCast>
abstract fun getReturnTypeForKtDeclaration(declaration: KtDeclaration): KtType
abstract fun getKtExpressionType(expression: KtExpression): KtType
abstract fun isSubclassOf(klass: KtClassOrObject, superClassId: ClassId): Boolean
abstract fun getDiagnosticsForElement(element: KtElement): Collection<Diagnostic>
abstract fun resolveCall(call: KtCallExpression): CallInfo?
abstract fun resolveCall(call: KtBinaryExpression): CallInfo?
/// TODO: get rid of
@Deprecated("Used only in completion now, temporary")
abstract fun createContextDependentCopy(): KtAnalysisSession
fun KtExpression.getSmartCasts(): Collection<KtType> = smartCastProvider.getSmartCastedToTypes(this)
fun KtExpression.getImplicitReceiverSmartCasts(): Collection<ImplicitReceiverSmartCast> = smartCastProvider.getImplicitReceiverSmartCasts(this)
fun KtExpression.getKtType(): KtType = typeProvider.getKtExpressionType(this)
fun KtDeclaration.getReturnKtType(): KtType = typeProvider.getReturnTypeForKtDeclaration(this)
fun KtElement.getDiagnostics(): Collection<Diagnostic> = diagnosticProvider.getDiagnosticsForElement(this)
fun KtSymbolWithKind.getContainingSymbol(): KtSymbolWithKind? = containingDeclarationProvider.getContainingDeclaration(this)
fun KtClassOrObjectSymbol.getMemberScope(): KtMemberScope = scopeProvider.getMemberScope(this)
fun KtClassOrObjectSymbol.getDeclaredMemberScope(): KtDeclaredMemberScope = scopeProvider.getDeclaredMemberScope(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 KtClassOrObject.getClassOrObjectSymbol(): KtClassOrObjectSymbol = symbolProvider.getClassOrObjectSymbol(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(): CallInfo? = callResolver.resolveCall(this)
fun KtBinaryExpression.resolveCall(): CallInfo? = 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()
}
}
@@ -10,15 +10,5 @@ import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.references.KtSimpleReference
interface KtSymbolBasedReference : KtReference {
fun resolveToSymbols(analysisSession: KtAnalysisSession): Collection<KtSymbol>
}
fun KtReference.resolveToSymbols(analysisSession: KtAnalysisSession): Collection<KtSymbol> {
check(this is KtSymbolBasedReference) { "To get reference symbol the one should be KtSymbolBasedReference" }
return resolveToSymbols(analysisSession)
}
fun KtSimpleReference<*>.resolveToSymbol(analysisSession: KtAnalysisSession): KtSymbol? {
check(this is KtSymbolBasedReference) { "To get reference symbol the one should be KtSymbolBasedReference but was ${this::class}" }
return resolveToSymbols(analysisSession).singleOrNull()
fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol>
}
@@ -0,0 +1,15 @@
/*
* 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.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
final override val token: ValidityToken get() = analysisSession.token
}
@@ -0,0 +1,15 @@
/*
* 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.CallInfo
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtCallExpression
abstract class KtCallResolver : KtAnalysisSessionComponent() {
abstract fun resolveCall(call: KtCallExpression): CallInfo?
abstract fun resolveCall(call: KtBinaryExpression): CallInfo?
}
@@ -0,0 +1,13 @@
/*
* 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.diagnostics.Diagnostic
import org.jetbrains.kotlin.psi.KtElement
abstract class KtDiagnosticProvider : KtAnalysisSessionComponent() {
abstract fun getDiagnosticsForElement(element: KtElement): Collection<Diagnostic>
}
@@ -3,22 +3,22 @@
* 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
package org.jetbrains.kotlin.idea.frontend.api.components
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
import org.jetbrains.kotlin.idea.frontend.api.scopes.*
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.types.KtType
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
abstract class KtScopeProvider : ValidityTokenOwner {
abstract class KtScopeProvider : KtAnalysisSessionComponent() {
abstract fun getMemberScope(classSymbol: KtClassOrObjectSymbol): KtMemberScope
abstract fun getDeclaredMemberScope(classSymbol: KtClassOrObjectSymbol): KtDeclaredMemberScope
abstract fun getPackageScope(packageSymbol: KtPackageSymbol): KtPackageScope
abstract fun getCompositeScope(subScopes: List<KtScope>): KtCompositeScope
abstract fun getScopeForType(type: KtType): KtScope?
abstract fun getTypeScope(type: KtType): KtScope?
abstract fun getScopeContextForPosition(originalFile: KtFile, positionInFakeFile: KtElement): KtScopeContext
}
@@ -0,0 +1,15 @@
/*
* 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.ImplicitReceiverSmartCast
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.psi.KtExpression
abstract class KtSmartCastProvider : KtAnalysisSessionComponent() {
abstract fun getSmartCastedToTypes(expression: KtExpression): Collection<KtType>
abstract fun getImplicitReceiverSmartCasts(expression: KtExpression): Collection<ImplicitReceiverSmartCast>
}
@@ -3,11 +3,11 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.frontend.api.symbols
package org.jetbrains.kotlin.idea.frontend.api.components
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithKind
abstract class KtSymbolContainingDeclarationProvider {
abstract class KtSymbolContainingDeclarationProvider : KtAnalysisSessionComponent() {
/**
* Returns containing declaration for symbol:
* for top-level declarations returns null
@@ -0,0 +1,15 @@
/*
* 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.types.KtType
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtExpression
abstract class KtTypeProvider : KtAnalysisSessionComponent() {
abstract fun getReturnTypeForKtDeclaration(declaration: KtDeclaration): KtType
abstract fun getKtExpressionType(expression: KtExpression): KtType
}
@@ -17,7 +17,7 @@ class KtPsiBasedSymbolPointer<S : KtSymbol>(private val psiPointer: SmartPsiElem
val psi = psiPointer.element ?: return null
@Suppress("UNCHECKED_CAST")
return analysisSession.symbolProvider.getSymbol(psi) as S?
return with(analysisSession) { psi.getSymbol() } as S?
}
companion object {
@@ -26,7 +26,10 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
abstract class KtSymbolPointer<out S : KtSymbol> {
/**
* @return restored symbol (possibly the new symbol instance) if one is still valid, `null` otherwise
*
* Consider using [org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession.restoreSymbol]
*/
@Deprecated("Consider using org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession.restoreSymbol")
abstract fun restoreSymbol(analysisSession: KtAnalysisSession): S?
}
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.idea.frontend.api.types
import org.jetbrains.kotlin.idea.frontend.api.*
import org.jetbrains.kotlin.name.ClassId
object KtTypeRenderer {
private object KtTypeRenderer {
fun render(type: KtType, options: KtTypeRendererOptions = KtTypeRendererOptions.DEFAULT): String = type.withValidityAssertion {
buildString { render(type, options) }
}
@@ -108,4 +108,8 @@ data class KtTypeRendererOptions(
renderFqNames = true
)
}
}
}
fun KtType.render(options: KtTypeRendererOptions = KtTypeRendererOptions.DEFAULT): String =
KtTypeRenderer.render(this, options)