LL API: introduce helper function for throwing invalid FirElement exception
This commit is contained in:
committed by
teamcityserver
parent
c0eb669191
commit
4bca296dc6
+43
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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.fir.low.level.api.api
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
class InvalidFirElementTypeException(
|
||||||
|
actualFirClass: KClass<out FirElement>?,
|
||||||
|
ktElement: KtElement?,
|
||||||
|
expectedFirClasses: List<KClass<out FirElement>>,
|
||||||
|
) : IllegalStateException() {
|
||||||
|
override val message: String = buildString {
|
||||||
|
if (ktElement != null) {
|
||||||
|
append("For $ktElement with text `${ktElement.text}`, ")
|
||||||
|
}
|
||||||
|
val message = when (expectedFirClasses.size) {
|
||||||
|
0 -> "Unexpected FirElement of type:"
|
||||||
|
1 -> "The FirElement of type ${expectedFirClasses.single()} expected, but"
|
||||||
|
else -> "One of [${expectedFirClasses.joinToString()}] FirElement types expected, but"
|
||||||
|
}
|
||||||
|
append(if (ktElement == null) message else message.replaceFirstChar { it.lowercase(Locale.getDefault()) })
|
||||||
|
if (actualFirClass != null) {
|
||||||
|
append(" ${actualFirClass.simpleName} found")
|
||||||
|
} else {
|
||||||
|
append(" no FirElement found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun throwUnexpectedFirElementError(
|
||||||
|
firElement: FirElement?,
|
||||||
|
ktElement: KtElement? = null,
|
||||||
|
vararg expectedFirClasses: KClass<out FirElement>
|
||||||
|
): Nothing {
|
||||||
|
throw InvalidFirElementTypeException(firElement?.let { it::class }, ktElement, expectedFirClasses.toList())
|
||||||
|
}
|
||||||
+3
-9
@@ -93,7 +93,7 @@ inline fun <reified F : FirDeclaration, R> KtDeclaration.withFirDeclarationOfTyp
|
|||||||
phase: FirResolvePhase = FirResolvePhase.RAW_FIR,
|
phase: FirResolvePhase = FirResolvePhase.RAW_FIR,
|
||||||
action: (F) -> R
|
action: (F) -> R
|
||||||
): R = withFirDeclaration(resolveState, phase) { firDeclaration ->
|
): R = withFirDeclaration(resolveState, phase) { firDeclaration ->
|
||||||
if (firDeclaration !is F) throw InvalidFirElementTypeException(this, F::class, firDeclaration::class)
|
if (firDeclaration !is F) throwUnexpectedFirElementError(firDeclaration, this, F::class)
|
||||||
action(firDeclaration)
|
action(firDeclaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ inline fun <reified F : FirDeclaration, R> KtLambdaExpression.withFirDeclaration
|
|||||||
action: (F) -> R
|
action: (F) -> R
|
||||||
): R {
|
): R {
|
||||||
val firDeclaration = resolveState.findSourceFirDeclaration(this)
|
val firDeclaration = resolveState.findSourceFirDeclaration(this)
|
||||||
if (firDeclaration !is F) throw InvalidFirElementTypeException(this, F::class, firDeclaration::class)
|
if (firDeclaration !is F) throwUnexpectedFirElementError(firDeclaration, this, F::class)
|
||||||
return action(firDeclaration)
|
return action(firDeclaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +233,7 @@ inline fun <reified E : FirElement> KtElement.getOrBuildFirOfType(
|
|||||||
): E {
|
): E {
|
||||||
val fir = this.getOrBuildFir(resolveState)
|
val fir = this.getOrBuildFir(resolveState)
|
||||||
if (fir is E) return fir
|
if (fir is E) return fir
|
||||||
throw InvalidFirElementTypeException(this, E::class, fir::class)
|
throwUnexpectedFirElementError(fir, this, E::class)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -242,9 +242,3 @@ inline fun <reified E : FirElement> KtElement.getOrBuildFirOfType(
|
|||||||
*/
|
*/
|
||||||
fun KtFile.getOrBuildFirFile(resolveState: FirModuleResolveState): FirFile =
|
fun KtFile.getOrBuildFirFile(resolveState: FirModuleResolveState): FirFile =
|
||||||
resolveState.getOrBuildFirFile(this)
|
resolveState.getOrBuildFirFile(this)
|
||||||
|
|
||||||
class InvalidFirElementTypeException(
|
|
||||||
ktElement: KtElement,
|
|
||||||
expectedFirClass: KClass<out FirElement>,
|
|
||||||
actualFirClass: KClass<out FirElement>
|
|
||||||
) : IllegalStateException("For $ktElement with text `${ktElement.text}` the $expectedFirClass expected, but $actualFirClass found")
|
|
||||||
|
|||||||
+2
-1
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.psi
|
|||||||
import org.jetbrains.kotlin.fir.realPsi
|
import org.jetbrains.kotlin.fir.realPsi
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.InvalidFirElementTypeException
|
import org.jetbrains.kotlin.idea.fir.low.level.api.api.InvalidFirElementTypeException
|
||||||
|
import org.jetbrains.kotlin.idea.fir.low.level.api.api.throwUnexpectedFirElementError
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.getNonLocalContainingOrThisDeclaration
|
import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.getNonLocalContainingOrThisDeclaration
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.FirFileBuilder
|
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.FirFileBuilder
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache
|
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache
|
||||||
@@ -56,7 +57,7 @@ internal inline fun <reified F : FirDeclaration> KtDeclaration.findFirDeclaratio
|
|||||||
moduleFileCache: ModuleFileCache
|
moduleFileCache: ModuleFileCache
|
||||||
): FirDeclaration {
|
): FirDeclaration {
|
||||||
val fir = findFirDeclarationForAnyFirSourceDeclaration(firFileBuilder, firSymbolProvider, moduleFileCache)
|
val fir = findFirDeclarationForAnyFirSourceDeclaration(firFileBuilder, firSymbolProvider, moduleFileCache)
|
||||||
if (fir !is F) throw InvalidFirElementTypeException(this, F::class, fir::class)
|
if (fir !is F) throwUnexpectedFirElementError(fir, this, F::class)
|
||||||
return fir
|
return fir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.components
|
|||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.idea.fir.evaluate.FirCompileTimeConstantEvaluator
|
import org.jetbrains.kotlin.idea.fir.evaluate.FirCompileTimeConstantEvaluator
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFir
|
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFir
|
||||||
|
import org.jetbrains.kotlin.idea.fir.low.level.api.api.throwUnexpectedFirElementError
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.components.KtCompileTimeConstantProvider
|
import org.jetbrains.kotlin.idea.frontend.api.components.KtCompileTimeConstantProvider
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.convertConstantExpression
|
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.convertConstantExpression
|
||||||
@@ -24,7 +25,7 @@ internal class KtFirCompileTimeConstantProvider(
|
|||||||
override fun evaluate(expression: KtExpression): KtSimpleConstantValue<*>? = withValidityAssertion {
|
override fun evaluate(expression: KtExpression): KtSimpleConstantValue<*>? = withValidityAssertion {
|
||||||
when (val fir = expression.getOrBuildFir(firResolveState)) {
|
when (val fir = expression.getOrBuildFir(firResolveState)) {
|
||||||
is FirExpression -> FirCompileTimeConstantEvaluator().evaluate(fir)?.convertConstantExpression()
|
is FirExpression -> FirCompileTimeConstantEvaluator().evaluate(fir)?.convertConstantExpression()
|
||||||
else -> error("Unexpected ${fir::class}")
|
else -> throwUnexpectedFirElementError(fir, expression)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -39,7 +39,7 @@ internal class KtFirExpressionTypeProvider(
|
|||||||
is FirExpression -> fir.typeRef.coneType.asKtType()
|
is FirExpression -> fir.typeRef.coneType.asKtType()
|
||||||
is FirNamedReference -> fir.getReferencedElementType().asKtType()
|
is FirNamedReference -> fir.getReferencedElementType().asKtType()
|
||||||
is FirStatement -> with(analysisSession) { builtinTypes.UNIT }
|
is FirStatement -> with(analysisSession) { builtinTypes.UNIT }
|
||||||
else -> error("Unexpected ${fir::class}")
|
else -> error("Unexpected ${fir?.let { it::class }}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.expressions.FirStatement
|
|||||||
import org.jetbrains.kotlin.fir.references.FirNamedReference
|
import org.jetbrains.kotlin.fir.references.FirNamedReference
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFir
|
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFir
|
||||||
|
import org.jetbrains.kotlin.idea.fir.low.level.api.api.throwUnexpectedFirElementError
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.components.KtPsiTypeProvider
|
import org.jetbrains.kotlin.idea.frontend.api.components.KtPsiTypeProvider
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.getReferencedElementType
|
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.getReferencedElementType
|
||||||
@@ -36,7 +37,7 @@ internal class KtFirPsiTypeProvider(
|
|||||||
is FirExpression -> fir.typeRef.coneType.asPsiType(mode, expression)
|
is FirExpression -> fir.typeRef.coneType.asPsiType(mode, expression)
|
||||||
is FirNamedReference -> fir.getReferencedElementType().asPsiType(mode, expression)
|
is FirNamedReference -> fir.getReferencedElementType().asPsiType(mode, expression)
|
||||||
is FirStatement -> PsiType.VOID
|
is FirStatement -> PsiType.VOID
|
||||||
else -> error("Unexpected ${fir::class}")
|
else -> throwUnexpectedFirElementError(fir, expression)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@ internal class KtFirPsiTypeProvider(
|
|||||||
when (val fir = ktTypeReference.getOrBuildFir(firResolveState)) {
|
when (val fir = ktTypeReference.getOrBuildFir(firResolveState)) {
|
||||||
// NB: [FirErrorTypeRef] is a subtype of [FirResolvedTypeRef], and the error type in it will be properly handled by [asPsiType].
|
// NB: [FirErrorTypeRef] is a subtype of [FirResolvedTypeRef], and the error type in it will be properly handled by [asPsiType].
|
||||||
is FirResolvedTypeRef -> fir.coneType.asPsiType(mode, ktTypeReference)
|
is FirResolvedTypeRef -> fir.coneType.asPsiType(mode, ktTypeReference)
|
||||||
else -> error("Unexpected ${fir::class}")
|
else -> throwUnexpectedFirElementError(fir, ktTypeReference)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +62,7 @@ internal class KtFirPsiTypeProvider(
|
|||||||
fir.typeRef.coneType.getReceiverOfReflectionType()?.asPsiType(mode, receiver)
|
fir.typeRef.coneType.getReceiverOfReflectionType()?.asPsiType(mode, receiver)
|
||||||
is FirCallableReferenceAccess ->
|
is FirCallableReferenceAccess ->
|
||||||
fir.typeRef.coneType.getReceiverOfReflectionType()?.asPsiType(mode, receiver)
|
fir.typeRef.coneType.getReceiverOfReflectionType()?.asPsiType(mode, receiver)
|
||||||
else -> error("Unexpected ${fir::class}")
|
else -> throwUnexpectedFirElementError(fir, ktDoubleColonExpression)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user