[FIR] Add utility for checking if FirReference is one of error reference

Also simplify relevant code in checkers
This commit is contained in:
Dmitriy Novozhilov
2022-12-14 18:40:28 +02:00
committed by Space Team
parent 7334694fd9
commit 34be0f05b2
11 changed files with 55 additions and 57 deletions
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
import org.jetbrains.kotlin.fir.references.isError
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions
@@ -142,10 +143,8 @@ object FirNativeThrowsChecker : FirBasicDeclarationChecker() {
return expression.hasUnresolvedArgument()
}
if (this is FirResolvable) {
when (this.calleeReference) {
is FirErrorNamedReference, is FirResolvedErrorReference -> return true
}
if (this is FirResolvable && calleeReference.isError()) {
return true
}
if (this is FirVarargArgumentsExpression) {
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
@@ -30,11 +31,8 @@ internal fun checkConstantArguments(
expression: FirExpression,
session: FirSession,
): ConstantArgumentKind? {
val expressionSymbol = expression.toResolvedCallableReference()
?.takeUnless { it is FirResolvedErrorReference }
?.resolvedSymbol as? FirCallableSymbol<*>
val classKindOfParent = (expressionSymbol?.getReferencedClassSymbol(session) as? FirRegularClassSymbol)
?.classKind
val expressionSymbol = expression.toReference()?.toResolvedCallableSymbol(discardErrorReference = true)
val classKindOfParent = (expressionSymbol?.getReferencedClassSymbol(session) as? FirRegularClassSymbol)?.classKind
when {
expression is FirNamedArgumentExpression -> {
@@ -13,9 +13,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.*
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
@@ -94,12 +92,9 @@ object FirCommonConstructorDelegationIssuesChecker : FirRegularClassChecker() {
return null
}
@OptIn(SymbolInternals::class)
private fun FirConstructor.getDelegated(): FirConstructor? {
this.symbol.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
val delegatedConstructorSymbol = (delegatedConstructor?.calleeReference as? FirResolvedNamedReference)
.takeUnless { it is FirResolvedErrorReference }
?.resolvedSymbol
@OptIn(SymbolInternals::class)
return delegatedConstructorSymbol?.fir as? FirConstructor
return delegatedConstructor?.calleeReference?.toResolvedConstructorSymbol(discardErrorReference = true)?.fir
}
}
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.expressions.FirImplicitInvokeCall
import org.jetbrains.kotlin.fir.expressions.arguments
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
import org.jetbrains.kotlin.fir.references.isError
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.types.*
@@ -65,11 +66,7 @@ object FirDelegatedPropertyChecker : FirPropertyChecker() {
*/
private fun checkFunctionReferenceErrors(functionCall: FirFunctionCall): Boolean {
val reference = functionCall.calleeReference
val diagnostic = when (reference) {
is FirErrorNamedReference -> reference.diagnostic
is FirResolvedErrorReference -> reference.diagnostic
else -> return false
}
val diagnostic = if (reference.isError()) reference.diagnostic else return false
if (reference.source?.kind != KtFakeSourceElementKind.DelegatedPropertyAccessor) return false
val expectedFunctionSignature =
(if (isGet) "getValue" else "setValue") + "(${functionCall.arguments.joinToString(", ") { it.typeRef.coneType.renderReadable() }})"
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
import org.jetbrains.kotlin.fir.references.isError
import org.jetbrains.kotlin.fir.references.toResolvedVariableSymbol
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
@@ -71,11 +72,8 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
else -> null
} ?: return
val diagnostic = when (val reference = componentCall.calleeReference) {
is FirErrorNamedReference -> reference.diagnostic
is FirResolvedErrorReference -> reference.diagnostic
else -> null
}
val reference = componentCall.calleeReference
val diagnostic = if (reference.isError()) reference.diagnostic else null
if (diagnostic != null) {
checkComponentCall(
originalDestructuringDeclarationOrInitializerSource,
@@ -88,7 +86,6 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
context
)
}
}
private fun checkInitializer(
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.fir.expressions.FirWhileLoop
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.isError
import org.jetbrains.kotlin.fir.resolve.calls.UnsafeCall
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError
@@ -105,9 +106,10 @@ object FirForLoopChecker : FirBlockChecker() {
noneApplicableFactory: KtDiagnosticFactory1<Collection<FirBasedSymbol<*>>>? = null,
unsafeCallFactory: KtDiagnosticFactory0? = null,
): Boolean {
when (val calleeReference = call.calleeReference) {
is FirErrorNamedReference, is FirResolvedErrorReference -> {
when (val diagnostic = (calleeReference as FirDiagnosticHolder).diagnostic) {
val calleeReference = call.calleeReference
when {
calleeReference.isError() -> {
when (val diagnostic = calleeReference.diagnostic) {
is ConeAmbiguityError -> if (diagnostic.applicability.isSuccess) {
reporter.reportOn(reportSource, ambiguityFactory, diagnostic.candidates.map { it.symbol }, context)
} else if (noneApplicableFactory != null) {
@@ -140,7 +142,7 @@ object FirForLoopChecker : FirBlockChecker() {
}
return true
}
is FirResolvedNamedReference -> {
calleeReference is FirResolvedNamedReference -> {
val symbol = calleeReference.resolvedSymbol
if (symbol is FirNamedFunctionSymbol) {
if (!symbol.isOperator) {
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.toResolvedConstructorSymbol
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
@@ -23,10 +24,7 @@ import org.jetbrains.kotlin.fir.types.coneType
object FirSealedClassConstructorCallChecker : FirQualifiedAccessExpressionChecker() {
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
val constructorSymbol = (expression.calleeReference as? FirResolvedNamedReference)
?.takeUnless { it is FirResolvedErrorReference }
?.resolvedSymbol as? FirConstructorSymbol
?: return
val constructorSymbol = expression.calleeReference.toResolvedConstructorSymbol(discardErrorReference = true) ?: return
val typeSymbol = (constructorSymbol.resolvedReturnTypeRef.coneType.fullyExpandedType(context.session) as? ConeClassLikeType)
?.lookupTag?.toSymbol(context.session) as? FirRegularClassSymbol
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.isCatchParameter
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
import org.jetbrains.kotlin.fir.references.isError
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.renderer.FirRenderer
import org.jetbrains.kotlin.fir.visitors.FirVisitor
@@ -84,14 +85,12 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() {
}
override fun visitQualifiedAccess(qualifiedAccess: FirQualifiedAccess, data: FirElement) {
when (val calleeReference = qualifiedAccess.calleeReference) {
is FirErrorNamedReference, is FirResolvedErrorReference -> {
errorReferences++
println((calleeReference as FirDiagnosticHolder).diagnostic.reason)
}
else -> {
normalReferences++
}
val calleeReference = qualifiedAccess.calleeReference
if (calleeReference.isError()) {
errorReferences++
println((calleeReference as FirDiagnosticHolder).diagnostic.reason)
} else {
normalReferences++
}
visitStatement(qualifiedAccess, data)
}
@@ -5,8 +5,11 @@
package org.jetbrains.kotlin.fir.references
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
val FirReference.resolved: FirResolvedNamedReference? get() = this as? FirResolvedNamedReference
@@ -52,3 +55,14 @@ fun FirReference.toResolvedFunctionSymbol(discardErrorReference: Boolean = false
fun FirReference.toResolvedConstructorSymbol(discardErrorReference: Boolean = false): FirConstructorSymbol? {
return this.toResolvedSymbol<FirConstructorSymbol>(discardErrorReference)
}
@OptIn(ExperimentalContracts::class)
fun FirReference.isError(): Boolean {
contract {
returns(true) implies (this@isError is FirDiagnosticHolder)
}
return when (this) {
is FirResolvedErrorReference, is FirErrorNamedReference -> true
else -> false
}
}
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
import org.jetbrains.kotlin.fir.references.isError
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirGlobalResolveProcessor
@@ -283,8 +284,8 @@ class FirResolveBench(val withProgress: Boolean, val listener: BenchListener? =
if (type is ConeErrorType) {
errorFunctionCallTypes++
val psi = callee.psi
if ((callee is FirErrorNamedReference || callee is FirResolvedErrorReference) && psi != null) {
reportProblem((callee as FirDiagnosticHolder).diagnostic.reason, psi)
if (callee.isError() && psi != null) {
reportProblem(callee.diagnostic.reason, psi)
}
}
}
@@ -300,8 +301,8 @@ class FirResolveBench(val withProgress: Boolean, val listener: BenchListener? =
if (type is ConeErrorType) {
errorQualifiedAccessTypes++
val psi = callee.psi
if ((callee is FirErrorNamedReference || callee is FirResolvedErrorReference) && psi != null) {
reportProblem((callee as FirDiagnosticHolder).diagnostic.reason, psi)
if (callee.isError() && psi != null) {
reportProblem(callee.diagnostic.reason, psi)
}
}
}
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirFunctionCallChecker
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.arguments
@@ -23,6 +24,7 @@ import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
import org.jetbrains.kotlin.fir.references.isError
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDiagnosticWithSingleCandidate
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
@@ -33,8 +35,9 @@ object FirAssignmentPluginFunctionCallChecker : FirFunctionCallChecker() {
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
if (!expression.isOverloadAssignCallCandidate()) return
if (expression.isFunctionResolveError()) {
if (expression.isOverloadedAssignCallError(context.session)) {
val calleeReference = expression.calleeReference
if (calleeReference.isError()) {
if (expression.isOverloadedAssignCallError(context.session, calleeReference.diagnostic)) {
reporter.reportOn(expression.source, NO_APPLICABLE_ASSIGN_METHOD, context)
}
} else if (expression.isOverloadedAssignCall(context.session) && !expression.isReturnTypeUnit()) {
@@ -45,13 +48,8 @@ object FirAssignmentPluginFunctionCallChecker : FirFunctionCallChecker() {
private fun FirFunctionCall.isOverloadAssignCallCandidate() =
arguments.size == 1 && source?.kind == KtFakeSourceElementKind.DesugaredCompoundAssignment
private fun FirFunctionCall.isFunctionResolveError() = when(calleeReference){
is FirErrorNamedReference, is FirResolvedErrorReference -> true
else -> false
}
private fun FirFunctionCall.isOverloadedAssignCallError(session: FirSession): Boolean {
val functionName = when (val diagnostic = (calleeReference as? FirDiagnosticHolder)?.diagnostic) {
private fun FirFunctionCall.isOverloadedAssignCallError(session: FirSession, diagnostic: ConeDiagnostic): Boolean {
val functionName = when (diagnostic) {
is ConeAmbiguityError -> diagnostic.name
is ConeDiagnosticWithSingleCandidate -> diagnostic.candidate.callInfo.name
is ConeUnresolvedNameError -> diagnostic.name