[FIR] Create FirResolvedErrorReference for error reference with single candidate
Note that this reference won't be created for hidden candidates, because they are designed to be truly invisible from the user side
This commit is contained in:
committed by
Space Team
parent
9e4e5eed68
commit
dde64c10ea
+22
-21
@@ -44,10 +44,7 @@ import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.realPsi
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.references.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.AbstractCandidate
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
||||
import org.jetbrains.kotlin.fir.resolve.createConeDiagnosticForCandidateWithError
|
||||
@@ -176,9 +173,29 @@ internal class KtFirCallResolver(
|
||||
resolveFragmentOfCall = resolveFragmentOfCall
|
||||
)
|
||||
}
|
||||
|
||||
fun <T> transformErrorReference(call: FirResolvable, calleeReference: T): KtCallInfo where T : FirNamedReference, T : FirDiagnosticHolder {
|
||||
val diagnostic = calleeReference.diagnostic
|
||||
val ktDiagnostic = calleeReference.createKtDiagnostic(psi)
|
||||
|
||||
if (diagnostic is ConeHiddenCandidateError)
|
||||
return KtErrorCallInfo(emptyList(), ktDiagnostic, token)
|
||||
|
||||
val candidateCalls = mutableListOf<KtCall>()
|
||||
if (diagnostic is ConeDiagnosticWithCandidates) {
|
||||
diagnostic.candidates.mapNotNullTo(candidateCalls) {
|
||||
createKtCall(psi, call, it, resolveFragmentOfCall)
|
||||
}
|
||||
} else {
|
||||
candidateCalls.addIfNotNull(createKtCall(psi, call, null, resolveFragmentOfCall))
|
||||
}
|
||||
return KtErrorCallInfo(candidateCalls, ktDiagnostic, token)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is FirResolvable -> {
|
||||
when (val calleeReference = calleeReference) {
|
||||
is FirResolvedErrorReference -> transformErrorReference(this, calleeReference)
|
||||
is FirResolvedNamedReference -> when (calleeReference.resolvedSymbol) {
|
||||
// `calleeReference.resolvedSymbol` isn't guaranteed to be callable. For example, function type parameters used in
|
||||
// expression positions (e.g. `T` in `println(T)`) are parsed as `KtSimpleNameExpression` and built into
|
||||
@@ -194,23 +211,7 @@ internal class KtFirCallResolver(
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
is FirErrorNamedReference -> {
|
||||
val diagnostic = calleeReference.diagnostic
|
||||
val ktDiagnostic = calleeReference.createKtDiagnostic(psi)
|
||||
|
||||
if (diagnostic is ConeHiddenCandidateError)
|
||||
return KtErrorCallInfo(emptyList(), ktDiagnostic, token)
|
||||
|
||||
val candidateCalls = mutableListOf<KtCall>()
|
||||
if (diagnostic is ConeDiagnosticWithCandidates) {
|
||||
diagnostic.candidates.mapNotNullTo(candidateCalls) {
|
||||
createKtCall(psi, this@toKtCallInfo, it, resolveFragmentOfCall)
|
||||
}
|
||||
} else {
|
||||
candidateCalls.addIfNotNull(createKtCall(psi, this, null, resolveFragmentOfCall))
|
||||
}
|
||||
KtErrorCallInfo(candidateCalls, ktDiagnostic, token)
|
||||
}
|
||||
is FirErrorNamedReference -> transformErrorReference(this, calleeReference)
|
||||
// Unresolved delegated constructor call is untransformed and end up as an `FirSuperReference`
|
||||
is FirSuperReference -> {
|
||||
val delegatedConstructorCall = this as? FirDelegatedConstructorCall ?: return null
|
||||
|
||||
+3
-2
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors
|
||||
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.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions
|
||||
@@ -142,8 +143,8 @@ object FirNativeThrowsChecker : FirBasicDeclarationChecker() {
|
||||
}
|
||||
|
||||
if (this is FirResolvable) {
|
||||
if (this.calleeReference is FirErrorNamedReference) {
|
||||
return true
|
||||
when (this.calleeReference) {
|
||||
is FirErrorNamedReference, is FirResolvedErrorReference -> return true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.modality
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
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.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
@@ -29,7 +30,9 @@ internal fun checkConstantArguments(
|
||||
expression: FirExpression,
|
||||
session: FirSession,
|
||||
): ConstantArgumentKind? {
|
||||
val expressionSymbol = expression.toResolvedCallableSymbol()
|
||||
val expressionSymbol = expression.toResolvedCallableReference()
|
||||
?.takeUnless { it is FirResolvedErrorReference }
|
||||
?.resolvedSymbol as? FirCallableSymbol<*>
|
||||
val classKindOfParent = (expressionSymbol?.getReferencedClassSymbol(session) as? FirRegularClassSymbol)
|
||||
?.classKind
|
||||
|
||||
|
||||
+4
-1
@@ -14,6 +14,7 @@ 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.resolve.diagnostics.ConeAmbiguityError
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
@@ -95,7 +96,9 @@ object FirCommonConstructorDelegationIssuesChecker : FirRegularClassChecker() {
|
||||
|
||||
private fun FirConstructor.getDelegated(): FirConstructor? {
|
||||
this.symbol.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
|
||||
val delegatedConstructorSymbol = (delegatedConstructor?.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol
|
||||
val delegatedConstructorSymbol = (delegatedConstructor?.calleeReference as? FirResolvedNamedReference)
|
||||
.takeUnless { it is FirResolvedErrorReference }
|
||||
?.resolvedSymbol
|
||||
@OptIn(SymbolInternals::class)
|
||||
return delegatedConstructorSymbol?.fir as? FirConstructor
|
||||
}
|
||||
|
||||
+13
-7
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
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.resolve.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
@@ -63,15 +64,20 @@ object FirDelegatedPropertyChecker : FirPropertyChecker() {
|
||||
* @return true if any error was reported; false otherwise.
|
||||
*/
|
||||
private fun checkFunctionReferenceErrors(functionCall: FirFunctionCall): Boolean {
|
||||
val errorNamedReference = functionCall.calleeReference as? FirErrorNamedReference ?: return false
|
||||
if (errorNamedReference.source?.kind != KtFakeSourceElementKind.DelegatedPropertyAccessor) return false
|
||||
val reference = functionCall.calleeReference
|
||||
val diagnostic = when (reference) {
|
||||
is FirErrorNamedReference -> reference.diagnostic
|
||||
is FirResolvedErrorReference -> 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() }})"
|
||||
val delegateDescription = if (isGet) "delegate" else "delegate for var (read-write property)"
|
||||
|
||||
fun reportInapplicableDiagnostics(candidates: Collection<FirBasedSymbol<*>>) {
|
||||
reporter.reportOn(
|
||||
errorNamedReference.source,
|
||||
reference.source,
|
||||
FirErrors.DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE,
|
||||
expectedFunctionSignature,
|
||||
candidates,
|
||||
@@ -80,9 +86,9 @@ object FirDelegatedPropertyChecker : FirPropertyChecker() {
|
||||
}
|
||||
|
||||
var errorReported = true
|
||||
when (val diagnostic = errorNamedReference.diagnostic) {
|
||||
when (diagnostic) {
|
||||
is ConeUnresolvedNameError -> reporter.reportOn(
|
||||
errorNamedReference.source,
|
||||
reference.source,
|
||||
FirErrors.DELEGATE_SPECIAL_FUNCTION_MISSING,
|
||||
expectedFunctionSignature,
|
||||
delegateType,
|
||||
@@ -94,7 +100,7 @@ object FirDelegatedPropertyChecker : FirPropertyChecker() {
|
||||
if (diagnostic.applicability.isSuccess) {
|
||||
// Match is successful but there are too many matches! So we report DELEGATE_SPECIAL_FUNCTION_AMBIGUITY.
|
||||
reporter.reportOn(
|
||||
errorNamedReference.source,
|
||||
reference.source,
|
||||
FirErrors.DELEGATE_SPECIAL_FUNCTION_AMBIGUITY,
|
||||
expectedFunctionSignature,
|
||||
diagnostic.candidates.map { it.symbol },
|
||||
@@ -106,7 +112,7 @@ object FirDelegatedPropertyChecker : FirPropertyChecker() {
|
||||
}
|
||||
|
||||
is ConeInapplicableWrongReceiver -> reporter.reportOn(
|
||||
errorNamedReference.source,
|
||||
reference.source,
|
||||
FirErrors.DELEGATE_SPECIAL_FUNCTION_MISSING,
|
||||
expectedFunctionSignature,
|
||||
delegateType,
|
||||
|
||||
+21
-14
@@ -15,10 +15,12 @@ import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.FirVariable
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
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.resolve.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.resolvedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
@@ -70,19 +72,24 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
|
||||
else -> null
|
||||
} ?: return
|
||||
|
||||
when (val reference = componentCall.calleeReference) {
|
||||
is FirErrorNamedReference ->
|
||||
checkComponentCall(
|
||||
originalDestructuringDeclarationOrInitializerSource,
|
||||
originalDestructuringDeclarationType,
|
||||
reference,
|
||||
declaration,
|
||||
componentCall,
|
||||
originalDestructuringDeclaration,
|
||||
reporter,
|
||||
context
|
||||
)
|
||||
val diagnostic = when (val reference = componentCall.calleeReference) {
|
||||
is FirErrorNamedReference -> reference.diagnostic
|
||||
is FirResolvedErrorReference -> reference.diagnostic
|
||||
else -> null
|
||||
}
|
||||
if (diagnostic != null) {
|
||||
checkComponentCall(
|
||||
originalDestructuringDeclarationOrInitializerSource,
|
||||
originalDestructuringDeclarationType,
|
||||
diagnostic,
|
||||
declaration,
|
||||
componentCall,
|
||||
originalDestructuringDeclaration,
|
||||
reporter,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun checkInitializer(
|
||||
@@ -105,14 +112,14 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
|
||||
private fun checkComponentCall(
|
||||
source: KtSourceElement,
|
||||
destructuringDeclarationType: ConeKotlinType,
|
||||
reference: FirErrorNamedReference,
|
||||
diagnostic: ConeDiagnostic,
|
||||
property: FirProperty,
|
||||
componentCall: FirComponentCall,
|
||||
destructuringDeclaration: FirVariable,
|
||||
reporter: DiagnosticReporter,
|
||||
context: CheckerContext
|
||||
) {
|
||||
when (val diagnostic = reference.diagnostic) {
|
||||
when (diagnostic) {
|
||||
is ConeUnresolvedNameError -> {
|
||||
reporter.reportOn(
|
||||
source,
|
||||
|
||||
+4
-2
@@ -26,10 +26,12 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NEXT_NONE_APPLICA
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPERATOR_MODIFIER_REQUIRED
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isOperator
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder
|
||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
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.resolve.calls.UnsafeCall
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
|
||||
@@ -104,8 +106,8 @@ object FirForLoopChecker : FirBlockChecker() {
|
||||
unsafeCallFactory: KtDiagnosticFactory0? = null,
|
||||
): Boolean {
|
||||
when (val calleeReference = call.calleeReference) {
|
||||
is FirErrorNamedReference -> {
|
||||
when (val diagnostic = calleeReference.diagnostic) {
|
||||
is FirErrorNamedReference, is FirResolvedErrorReference -> {
|
||||
when (val diagnostic = (calleeReference as FirDiagnosticHolder).diagnostic) {
|
||||
is ConeAmbiguityError -> if (diagnostic.applicability.isSuccess) {
|
||||
reporter.reportOn(reportSource, ambiguityFactory, diagnostic.candidates.map { it.symbol }, context)
|
||||
} else if (noneApplicableFactory != null) {
|
||||
|
||||
+2
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
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.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
@@ -23,6 +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
|
||||
|
||||
|
||||
+9
-10
@@ -11,13 +11,12 @@ import org.jetbrains.kotlin.fir.analysis.checkers.checkUpperBoundViolated
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
|
||||
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.resolve.diagnostics.ConeInapplicableWrongReceiver
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.isTypeAliasedConstructor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
@@ -29,15 +28,15 @@ object FirUpperBoundViolatedExpressionChecker : FirQualifiedAccessExpressionChec
|
||||
// declarations with their declared bounds.
|
||||
// it may be the called function declaration
|
||||
// or the class declaration
|
||||
val calleeReference = expression.calleeReference
|
||||
var calleeSymbol: FirCallableSymbol<*>? = null
|
||||
if (calleeReference is FirResolvedNamedReference) {
|
||||
calleeSymbol = calleeReference.toResolvedCallableSymbol()
|
||||
} else if (calleeReference is FirErrorNamedReference) {
|
||||
if (calleeReference.diagnostic is ConeInapplicableWrongReceiver) {
|
||||
return
|
||||
val calleeSymbol = when (val calleeReference = expression.calleeReference) {
|
||||
is FirResolvedErrorReference -> {
|
||||
if (calleeReference.diagnostic is ConeInapplicableWrongReceiver) {
|
||||
return
|
||||
}
|
||||
calleeReference.toResolvedCallableSymbol()
|
||||
}
|
||||
calleeSymbol = calleeReference.candidateSymbol as? FirCallableSymbol<*>
|
||||
is FirResolvedNamedReference -> calleeReference.toResolvedCallableSymbol()
|
||||
else -> null
|
||||
}
|
||||
|
||||
val typeArguments: List<TypeArgumentWithSourceInfo>
|
||||
|
||||
+2
-2
@@ -26,11 +26,11 @@ object RedundantExplicitTypeChecker : FirPropertyChecker() {
|
||||
if (!declaration.isLocal) return
|
||||
|
||||
val initializer = declaration.initializer ?: return
|
||||
val typeReference = declaration.returnTypeRef
|
||||
val typeReference = declaration.returnTypeRef.takeUnless { it is FirErrorTypeRef } ?: return
|
||||
|
||||
if (typeReference.source?.kind is KtFakeSourceElementKind) return
|
||||
|
||||
val type = declaration.returnTypeRef.coneType
|
||||
val type = typeReference.coneType
|
||||
|
||||
if (type.toSymbol(context.session) is FirTypeAliasSymbol) return
|
||||
if (typeReference.annotations.isNotEmpty()) return
|
||||
|
||||
+17
-7
@@ -20,6 +20,8 @@ import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
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.FirNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.types.ConeErrorType
|
||||
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
|
||||
@@ -52,20 +54,28 @@ class ErrorNodeDiagnosticCollectorComponent(
|
||||
}
|
||||
|
||||
override fun visitErrorNamedReference(errorNamedReference: FirErrorNamedReference, data: CheckerContext) {
|
||||
val source = errorNamedReference.source ?: return
|
||||
val qualifiedAccessOrAnnotationCall = data.qualifiedAccessOrAnnotationCalls.lastOrNull()?.takeIf {
|
||||
processErrorReference(errorNamedReference, errorNamedReference.diagnostic, data)
|
||||
}
|
||||
|
||||
override fun visitResolvedErrorReference(resolvedErrorReference: FirResolvedErrorReference, data: CheckerContext) {
|
||||
processErrorReference(resolvedErrorReference, resolvedErrorReference.diagnostic, data)
|
||||
}
|
||||
|
||||
private fun processErrorReference(reference: FirNamedReference, diagnostic: ConeDiagnostic, context: CheckerContext) {
|
||||
val source = reference.source ?: return
|
||||
val qualifiedAccessOrAnnotationCall = context.qualifiedAccessOrAnnotationCalls.lastOrNull()?.takeIf {
|
||||
// Use the source of the enclosing FirQualifiedAccess if it is exactly the call to the erroneous callee.
|
||||
when (it) {
|
||||
is FirQualifiedAccess -> it.calleeReference == errorNamedReference
|
||||
is FirAnnotationCall -> it.calleeReference == errorNamedReference
|
||||
is FirQualifiedAccess -> it.calleeReference == reference
|
||||
is FirAnnotationCall -> it.calleeReference == reference
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
// Don't report duplicated unresolved reference on annotation entry (already reported on its type)
|
||||
if (source.elementType == KtNodeTypes.ANNOTATION_ENTRY && errorNamedReference.diagnostic is ConeUnresolvedNameError) return
|
||||
if (source.elementType == KtNodeTypes.ANNOTATION_ENTRY && diagnostic is ConeUnresolvedNameError) return
|
||||
// Already reported in FirConventionFunctionCallChecker
|
||||
if (source.kind == KtFakeSourceElementKind.ArrayAccessNameReference &&
|
||||
errorNamedReference.diagnostic is ConeUnresolvedNameError
|
||||
diagnostic is ConeUnresolvedNameError
|
||||
) return
|
||||
|
||||
// If the receiver cannot be resolved, we skip reporting any further problems for this call.
|
||||
@@ -76,7 +86,7 @@ class ErrorNodeDiagnosticCollectorComponent(
|
||||
) return
|
||||
}
|
||||
|
||||
reportFirDiagnostic(errorNamedReference.diagnostic, source, data, qualifiedAccessOrAnnotationCall?.source)
|
||||
reportFirDiagnostic(diagnostic, source, context, qualifiedAccessOrAnnotationCall?.source)
|
||||
}
|
||||
|
||||
private fun FirExpression?.cannotBeResolved(): Boolean {
|
||||
|
||||
@@ -1302,6 +1302,18 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver
|
||||
simpleName(reference.name)
|
||||
}
|
||||
}
|
||||
is FirResolvedErrorReference -> {
|
||||
errorWithDiagnostic {
|
||||
resolved {
|
||||
symbolRef(reference.resolvedSymbol) {
|
||||
simpleName(reference.name)
|
||||
}
|
||||
}
|
||||
diagnosticHover {
|
||||
generate(reference.diagnostic)
|
||||
}
|
||||
}
|
||||
}
|
||||
is FirResolvedNamedReference -> {
|
||||
resolved {
|
||||
symbolRef(reference.resolvedSymbol) {
|
||||
|
||||
@@ -197,15 +197,6 @@ fun FirReference.toSymbolForCall(
|
||||
isReference
|
||||
)
|
||||
|
||||
is FirErrorNamedReference ->
|
||||
candidateSymbol?.toSymbolForCall(
|
||||
dispatchReceiver,
|
||||
preferGetter,
|
||||
explicitReceiver,
|
||||
isDelegate,
|
||||
isReference
|
||||
)
|
||||
|
||||
is FirThisReference -> {
|
||||
when (val boundSymbol = boundSymbol) {
|
||||
is FirClassSymbol<*> -> classifierStorage.getIrClassSymbol(boundSymbol).owner.thisReceiver?.symbol
|
||||
|
||||
+3
-6
@@ -1066,12 +1066,9 @@ class CallAndReferenceGenerator(
|
||||
}
|
||||
if (ownerFunction?.extensionReceiverParameter != null) {
|
||||
extensionReceiver = qualifiedAccess.findIrExtensionReceiver(explicitReceiverExpression)?.let {
|
||||
val symbol = when (val reference = qualifiedAccess.calleeReference) {
|
||||
is FirResolvedNamedReference -> reference.resolvedSymbol
|
||||
is FirErrorNamedReference -> reference.candidateSymbol
|
||||
else -> null
|
||||
} ?: error("Symbol for call ${qualifiedAccess.render()} not found")
|
||||
(symbol.fir as? FirCallableDeclaration)?.receiverParameter?.typeRef?.let { receiverType ->
|
||||
val symbol = qualifiedAccess.calleeReference.toResolvedCallableSymbol()
|
||||
?: error("Symbol for call ${qualifiedAccess.render()} not found")
|
||||
symbol.fir.receiverParameter?.typeRef?.let { receiverType ->
|
||||
with(visitor.implicitCastInserter) {
|
||||
it.cast(
|
||||
qualifiedAccess.extensionReceiver,
|
||||
|
||||
+10
-6
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder
|
||||
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
|
||||
@@ -18,6 +19,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub
|
||||
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.render
|
||||
import org.jetbrains.kotlin.fir.renderer.FirRenderer
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
@@ -82,12 +84,14 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() {
|
||||
}
|
||||
|
||||
override fun visitQualifiedAccess(qualifiedAccess: FirQualifiedAccess, data: FirElement) {
|
||||
val calleeReference = qualifiedAccess.calleeReference
|
||||
if (calleeReference is FirErrorNamedReference) {
|
||||
errorReferences++
|
||||
println(calleeReference.diagnostic.reason)
|
||||
} else {
|
||||
normalReferences++
|
||||
when (val calleeReference = qualifiedAccess.calleeReference) {
|
||||
is FirErrorNamedReference, is FirResolvedErrorReference -> {
|
||||
errorReferences++
|
||||
println((calleeReference as FirDiagnosticHolder).diagnostic.reason)
|
||||
}
|
||||
else -> {
|
||||
normalReferences++
|
||||
}
|
||||
}
|
||||
visitStatement(qualifiedAccess, data)
|
||||
}
|
||||
|
||||
@@ -285,6 +285,7 @@ class FirCallResolver(
|
||||
|
||||
val diagnostic = when (nameReference) {
|
||||
is FirErrorReferenceWithCandidate -> nameReference.diagnostic
|
||||
is FirResolvedErrorReference -> nameReference.diagnostic
|
||||
is FirErrorNamedReference -> nameReference.diagnostic
|
||||
else -> null
|
||||
}
|
||||
@@ -371,7 +372,7 @@ class FirCallResolver(
|
||||
|
||||
when {
|
||||
noSuccessfulCandidates -> {
|
||||
val errorReference = buildErrorReference(
|
||||
val errorReference = buildReferenceWithErrorCandidate(
|
||||
info,
|
||||
if (applicability == CandidateApplicability.K2_UNSUPPORTED) {
|
||||
val unsupportedResolutionDiagnostic = reducedCandidates.firstOrNull()?.diagnostics?.firstOrNull() as? Unsupported
|
||||
@@ -386,7 +387,7 @@ class FirCallResolver(
|
||||
}
|
||||
reducedCandidates.size > 1 -> {
|
||||
if (resolvedCallableReferenceAtom.hasBeenPostponed) {
|
||||
val errorReference = buildErrorReference(
|
||||
val errorReference = buildReferenceWithErrorCandidate(
|
||||
info,
|
||||
ConeAmbiguityError(info.name, applicability, reducedCandidates),
|
||||
callableReferenceAccess.source
|
||||
@@ -530,7 +531,7 @@ class FirCallResolver(
|
||||
explicitReceiver = null
|
||||
)
|
||||
} else {
|
||||
buildErrorReference(
|
||||
buildReferenceWithErrorCandidate(
|
||||
callInfo,
|
||||
if (annotationClassSymbol != null) ConeIllegalAnnotationError(reference.name)
|
||||
//calleeReference and annotationTypeRef are both error nodes so we need to avoid doubling of the diagnostic report
|
||||
@@ -635,133 +636,132 @@ class FirCallResolver(
|
||||
expectedCandidates: Collection<Candidate>? = null
|
||||
): FirNamedReference {
|
||||
val source = reference.source
|
||||
return when {
|
||||
|
||||
val diagnostic = when {
|
||||
expectedCallKind != null -> {
|
||||
fun isValueParametersNotEmpty(candidate: Candidate): Boolean {
|
||||
return (candidate.symbol.fir as? FirFunction)?.valueParameters?.size?.let { it > 0 } ?: false
|
||||
}
|
||||
|
||||
val candidate = candidates.singleOrNull()
|
||||
when (expectedCallKind) {
|
||||
CallKind.Function -> ConeFunctionCallExpectedError(name, candidates.any { isValueParametersNotEmpty(it) }, candidates)
|
||||
else -> {
|
||||
val singleExpectedCandidate = expectedCandidates?.singleOrNull()
|
||||
|
||||
val diagnostic = if (expectedCallKind == CallKind.Function) {
|
||||
ConeFunctionCallExpectedError(name, candidates.any { isValueParametersNotEmpty(it) }, candidates)
|
||||
} else {
|
||||
val singleExpectedCandidate = expectedCandidates?.singleOrNull()
|
||||
var fir = singleExpectedCandidate?.symbol?.fir
|
||||
if (fir is FirTypeAlias) {
|
||||
fir = (fir.expandedTypeRef.coneType.fullyExpandedType(session).toSymbol(session) as? FirRegularClassSymbol)?.fir
|
||||
}
|
||||
|
||||
var fir = singleExpectedCandidate?.symbol?.fir
|
||||
if (fir is FirTypeAlias) {
|
||||
fir = (fir.expandedTypeRef.coneType.fullyExpandedType(session).toSymbol(session) as? FirRegularClassSymbol)?.fir
|
||||
}
|
||||
|
||||
if (fir is FirRegularClass) {
|
||||
ConeResolutionToClassifierError(singleExpectedCandidate!!, fir.symbol)
|
||||
} else {
|
||||
val coneType = explicitReceiver?.typeRef?.coneType
|
||||
when {
|
||||
coneType != null && !coneType.isUnit -> {
|
||||
ConeFunctionExpectedError(
|
||||
name.asString(),
|
||||
(fir as? FirCallableDeclaration)?.returnTypeRef?.coneType ?: coneType
|
||||
)
|
||||
when (fir) {
|
||||
is FirRegularClass -> {
|
||||
ConeResolutionToClassifierError(singleExpectedCandidate!!, fir.symbol)
|
||||
}
|
||||
singleExpectedCandidate != null && !singleExpectedCandidate.currentApplicability.isSuccess -> {
|
||||
createConeDiagnosticForCandidateWithError(
|
||||
singleExpectedCandidate.currentApplicability,
|
||||
singleExpectedCandidate
|
||||
)
|
||||
else -> {
|
||||
val coneType = explicitReceiver?.typeRef?.coneType
|
||||
when {
|
||||
coneType != null && !coneType.isUnit -> {
|
||||
ConeFunctionExpectedError(
|
||||
name.asString(),
|
||||
(fir as? FirCallableDeclaration)?.returnTypeRef?.coneType ?: coneType
|
||||
)
|
||||
}
|
||||
singleExpectedCandidate != null && !singleExpectedCandidate.currentApplicability.isSuccess -> {
|
||||
createConeDiagnosticForCandidateWithError(
|
||||
singleExpectedCandidate.currentApplicability,
|
||||
singleExpectedCandidate
|
||||
)
|
||||
}
|
||||
else -> ConeUnresolvedNameError(name)
|
||||
}
|
||||
}
|
||||
else -> ConeUnresolvedNameError(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (candidate != null) {
|
||||
createErrorReferenceWithExistingCandidate(
|
||||
candidate,
|
||||
diagnostic,
|
||||
source,
|
||||
transformer.resolutionContext,
|
||||
components.resolutionStageRunner
|
||||
)
|
||||
} else {
|
||||
buildErrorReference(callInfo, diagnostic, source)
|
||||
}
|
||||
}
|
||||
|
||||
candidates.isEmpty() -> {
|
||||
val diagnostic = if (name.asString() == "invoke" && explicitReceiver is FirConstExpression<*>) {
|
||||
if (name.asString() == "invoke" && explicitReceiver is FirConstExpression<*>) {
|
||||
ConeFunctionExpectedError(explicitReceiver.value?.toString() ?: "", explicitReceiver.typeRef.coneType)
|
||||
} else {
|
||||
ConeUnresolvedNameError(name)
|
||||
}
|
||||
|
||||
buildErrorReference(
|
||||
callInfo,
|
||||
diagnostic,
|
||||
source
|
||||
)
|
||||
}
|
||||
|
||||
candidates.size > 1 -> buildErrorReference(
|
||||
callInfo,
|
||||
ConeAmbiguityError(name, applicability, candidates),
|
||||
source
|
||||
)
|
||||
candidates.size > 1 -> ConeAmbiguityError(name, applicability, candidates)
|
||||
|
||||
!applicability.isSuccess -> {
|
||||
val candidate = candidates.single()
|
||||
val diagnostic = createConeDiagnosticForCandidateWithError(applicability, candidate)
|
||||
createErrorReferenceWithExistingCandidate(
|
||||
candidate,
|
||||
diagnostic,
|
||||
source,
|
||||
transformer.resolutionContext,
|
||||
components.resolutionStageRunner
|
||||
)
|
||||
createConeDiagnosticForCandidateWithError(applicability, candidate)
|
||||
}
|
||||
|
||||
else -> {
|
||||
val candidate = candidates.single()
|
||||
val coneSymbol = candidate.symbol
|
||||
if (coneSymbol is FirBackingFieldSymbol) {
|
||||
coneSymbol.fir.propertySymbol.fir.isReferredViaField = true
|
||||
return buildBackingFieldReference {
|
||||
this.source = source
|
||||
resolvedSymbol = coneSymbol
|
||||
}
|
||||
}
|
||||
if ((coneSymbol as? FirPropertySymbol)?.hasExplicitBackingField == true) {
|
||||
return FirPropertyWithExplicitBackingFieldResolvedNamedReference(
|
||||
source, name, candidate.symbol, candidate.hasVisibleBackingField
|
||||
)
|
||||
}
|
||||
/*
|
||||
* This `if` is an optimization for local variables and properties without type parameters
|
||||
* Since they have no type variables, so we can don't run completion on them at all and create
|
||||
* resolved reference immediately
|
||||
*
|
||||
* But for callable reference resolution we should keep candidate, because it was resolved
|
||||
* with special resolution stages, which saved in candidate additional reference info,
|
||||
* like `resultingTypeForCallableReference`
|
||||
*/
|
||||
if (
|
||||
createResolvedReferenceWithoutCandidateForLocalVariables &&
|
||||
explicitReceiver?.typeRef?.coneTypeSafe<ConeIntegerLiteralType>() == null &&
|
||||
coneSymbol is FirVariableSymbol &&
|
||||
(coneSymbol !is FirPropertySymbol || (coneSymbol.fir as FirMemberDeclaration).typeParameters.isEmpty())
|
||||
) {
|
||||
return buildResolvedNamedReference {
|
||||
this.source = source
|
||||
this.name = name
|
||||
resolvedSymbol = coneSymbol
|
||||
}
|
||||
}
|
||||
FirNamedReferenceWithCandidate(source, name, candidate)
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (diagnostic != null) {
|
||||
return createErrorReferenceForSingleCandidate(candidates.singleOrNull(), diagnostic, callInfo, source)
|
||||
}
|
||||
|
||||
// successful candidate
|
||||
|
||||
val candidate = candidates.single()
|
||||
val coneSymbol = candidate.symbol
|
||||
if (coneSymbol is FirBackingFieldSymbol) {
|
||||
coneSymbol.fir.propertySymbol.fir.isReferredViaField = true
|
||||
return buildBackingFieldReference {
|
||||
this.source = source
|
||||
resolvedSymbol = coneSymbol
|
||||
}
|
||||
}
|
||||
if ((coneSymbol as? FirPropertySymbol)?.hasExplicitBackingField == true) {
|
||||
return FirPropertyWithExplicitBackingFieldResolvedNamedReference(
|
||||
source, name, candidate.symbol, candidate.hasVisibleBackingField
|
||||
)
|
||||
}
|
||||
/*
|
||||
* This `if` is an optimization for local variables and properties without type parameters
|
||||
* Since they have no type variables, so we can don't run completion on them at all and create
|
||||
* resolved reference immediately
|
||||
*
|
||||
* But for callable reference resolution we should keep candidate, because it was resolved
|
||||
* with special resolution stages, which saved in candidate additional reference info,
|
||||
* like `resultingTypeForCallableReference`
|
||||
*/
|
||||
if (
|
||||
createResolvedReferenceWithoutCandidateForLocalVariables &&
|
||||
explicitReceiver?.typeRef?.coneTypeSafe<ConeIntegerLiteralType>() == null &&
|
||||
coneSymbol is FirVariableSymbol &&
|
||||
(coneSymbol !is FirPropertySymbol || (coneSymbol.fir as FirMemberDeclaration).typeParameters.isEmpty())
|
||||
) {
|
||||
return buildResolvedNamedReference {
|
||||
this.source = source
|
||||
this.name = name
|
||||
resolvedSymbol = coneSymbol
|
||||
}
|
||||
}
|
||||
return FirNamedReferenceWithCandidate(source, name, candidate)
|
||||
}
|
||||
|
||||
private fun createErrorReferenceForSingleCandidate(
|
||||
candidate: Candidate?,
|
||||
diagnostic: ConeDiagnostic,
|
||||
callInfo: CallInfo,
|
||||
source: KtSourceElement?
|
||||
): FirNamedReference {
|
||||
if (candidate == null) return buildReferenceWithErrorCandidate(callInfo, diagnostic, source)
|
||||
return when (diagnostic) {
|
||||
is ConeUnresolvedError, is ConeHiddenCandidateError -> buildReferenceWithErrorCandidate(callInfo, diagnostic, source)
|
||||
else -> createErrorReferenceWithExistingCandidate(
|
||||
candidate,
|
||||
diagnostic,
|
||||
source,
|
||||
transformer.resolutionContext,
|
||||
components.resolutionStageRunner
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildErrorReference(
|
||||
private fun buildReferenceWithErrorCandidate(
|
||||
callInfo: CallInfo,
|
||||
diagnostic: ConeDiagnostic,
|
||||
source: KtSourceElement?
|
||||
|
||||
+25
-16
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.declarations.builder.buildReceiverParameterCopy
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInline
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
@@ -22,6 +23,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirPropertyAccessExpressionImpl
|
||||
import org.jetbrains.kotlin.fir.references.FirNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildResolvedCallableReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildResolvedErrorReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
||||
@@ -37,9 +39,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.ConvertibleIntegerOperators.binaryOp
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.isWrappedIntegerOperator
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.isWrappedIntegerOperatorForUnsignedType
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
@@ -379,11 +379,7 @@ class FirCallCompletionResultsWriterTransformer(
|
||||
session.lookupTracker?.recordTypeResolveAsLookup(resultType, typeRef.source ?: callableReferenceAccess.source, context.file.source)
|
||||
|
||||
val resolvedReference = when (calleeReference) {
|
||||
is FirErrorReferenceWithCandidate -> buildErrorNamedReference {
|
||||
source = calleeReference.source
|
||||
diagnostic = calleeReference.diagnostic
|
||||
candidateSymbol = calleeReference.candidateSymbol
|
||||
}
|
||||
is FirErrorReferenceWithCandidate -> calleeReference.toErrorReference(calleeReference.diagnostic)
|
||||
else -> buildResolvedCallableReference {
|
||||
source = calleeReference.source
|
||||
name = calleeReference.name
|
||||
@@ -400,6 +396,23 @@ class FirCallCompletionResultsWriterTransformer(
|
||||
.transformExtensionReceiver(StoreReceiver, subCandidate.chosenExtensionReceiverExpression())
|
||||
}
|
||||
|
||||
private fun FirNamedReferenceWithCandidate.toErrorReference(diagnostic: ConeDiagnostic): FirNamedReference {
|
||||
val calleeReference = this
|
||||
return when (calleeReference.candidateSymbol) {
|
||||
is FirErrorPropertySymbol, is FirErrorFunctionSymbol -> buildErrorNamedReference {
|
||||
source = calleeReference.source
|
||||
candidateSymbol = calleeReference.candidateSymbol
|
||||
this.diagnostic = diagnostic
|
||||
}
|
||||
else -> buildResolvedErrorReference {
|
||||
source = calleeReference.source
|
||||
name = calleeReference.name
|
||||
resolvedSymbol = calleeReference.candidateSymbol
|
||||
this.diagnostic = diagnostic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun transformVariableAssignment(
|
||||
variableAssignment: FirVariableAssignment,
|
||||
data: ExpectedArgumentType?,
|
||||
@@ -866,18 +879,14 @@ class FirCallCompletionResultsWriterTransformer(
|
||||
else -> null
|
||||
}
|
||||
|
||||
return if (errorDiagnostic != null) {
|
||||
buildErrorNamedReference {
|
||||
source = this@toResolvedReference.source
|
||||
diagnostic = errorDiagnostic
|
||||
candidateSymbol = this@toResolvedReference.candidateSymbol
|
||||
}
|
||||
} else {
|
||||
buildResolvedNamedReference {
|
||||
return when (errorDiagnostic) {
|
||||
null -> buildResolvedNamedReference {
|
||||
source = this@toResolvedReference.source
|
||||
name = this@toResolvedReference.name
|
||||
resolvedSymbol = this@toResolvedReference.candidateSymbol
|
||||
}
|
||||
|
||||
else -> toErrorReference(errorDiagnostic)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-5
@@ -14,13 +14,13 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirIntegerLiteralOperatorCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildResolvedErrorReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.scope
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
|
||||
import org.jetbrains.kotlin.fir.resolvedSymbol
|
||||
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
|
||||
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.scopes.getFunctions
|
||||
@@ -90,13 +90,21 @@ class IntegerLiteralAndOperatorApproximationTransformer(
|
||||
val wrappedFunctionSymbol = calleeReference.resolvedSymbol as FirNamedFunctionSymbol
|
||||
val originalFunctionSymbol = wrappedFunctionSymbol.fir.originalForWrappedIntegerOperator!!
|
||||
|
||||
call.replaceCalleeReference(
|
||||
buildResolvedNamedReference {
|
||||
val newCalleeReference = when (calleeReference) {
|
||||
is FirResolvedErrorReference -> buildResolvedErrorReference {
|
||||
name = calleeReference.name
|
||||
source = calleeReference.source
|
||||
resolvedSymbol = originalFunctionSymbol
|
||||
diagnostic = calleeReference.diagnostic
|
||||
}
|
||||
else -> buildResolvedNamedReference {
|
||||
name = calleeReference.name
|
||||
source = calleeReference.source
|
||||
resolvedSymbol = originalFunctionSymbol
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
call.replaceCalleeReference(newCalleeReference)
|
||||
}
|
||||
|
||||
if (approximatedType.isInt || approximatedType.isUInt) return call
|
||||
|
||||
+2
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildArgumentList
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildArrayOfCall
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
@@ -79,6 +80,7 @@ internal class FirArrayOfCallTransformer : FirDefaultTransformer<Nothing?>() {
|
||||
|
||||
private fun FirFunctionCall.getOriginalFunction(): FirCallableDeclaration? {
|
||||
val symbol: FirBasedSymbol<*>? = when (val reference = calleeReference) {
|
||||
is FirResolvedErrorReference -> null
|
||||
is FirResolvedNamedReference -> reference.resolvedSymbol
|
||||
is FirNamedReferenceWithCandidate -> reference.candidateSymbol
|
||||
else -> null
|
||||
|
||||
+3
-1
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildReturnExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildUnitExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirLazyBlock
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
||||
@@ -362,7 +363,8 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve
|
||||
return provideDelegateCall
|
||||
}
|
||||
|
||||
if (provideDelegateCall.calleeReference is FirResolvedNamedReference) {
|
||||
val provideDelegateReference = provideDelegateCall.calleeReference
|
||||
if (provideDelegateReference is FirResolvedNamedReference && provideDelegateReference !is FirResolvedErrorReference) {
|
||||
return provideDelegateCall
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.extensions.extensionService
|
||||
import org.jetbrains.kotlin.fir.references.*
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildExplicitSuperReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildResolvedErrorReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
@@ -891,9 +892,10 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
|
||||
|
||||
else -> {
|
||||
val altererNames = alteredAssignments.map { it.second::class.qualifiedName }
|
||||
val errorReference = buildErrorNamedReference {
|
||||
val errorReference = buildResolvedErrorReference {
|
||||
source = resolvedReference.source
|
||||
candidateSymbol = resolvedReference.resolvedSymbol
|
||||
name = resolvedReference.name
|
||||
resolvedSymbol = resolvedReference.resolvedSymbol
|
||||
diagnostic = ConeAmbiguousAlteredAssign(altererNames)
|
||||
}
|
||||
completeAssignment.replaceCalleeReference(errorReference)
|
||||
|
||||
@@ -839,9 +839,16 @@ class FirRenderer(
|
||||
}
|
||||
print(">")
|
||||
}
|
||||
if (resolvedNamedReference is FirResolvedErrorReference) {
|
||||
print("<${resolvedNamedReference.diagnostic.reason}>#")
|
||||
}
|
||||
print("|")
|
||||
}
|
||||
|
||||
override fun visitResolvedErrorReference(resolvedErrorReference: FirResolvedErrorReference) {
|
||||
visitResolvedNamedReference(resolvedErrorReference)
|
||||
}
|
||||
|
||||
private fun FirBasedSymbol<*>.unwrapIntersectionOverrides(): FirBasedSymbol<*> {
|
||||
(this as? FirCallableSymbol<*>)?.baseForIntersectionOverride?.let { return it.unwrapIntersectionOverrides() }
|
||||
return this
|
||||
|
||||
@@ -11,11 +11,13 @@ import org.jetbrains.kotlin.KtIoFileSourceFile
|
||||
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
|
||||
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.resolve.providers.firProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirProviderImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirGlobalResolveProcessor
|
||||
@@ -281,8 +283,8 @@ class FirResolveBench(val withProgress: Boolean, val listener: BenchListener? =
|
||||
if (type is ConeErrorType) {
|
||||
errorFunctionCallTypes++
|
||||
val psi = callee.psi
|
||||
if (callee is FirErrorNamedReference && psi != null) {
|
||||
reportProblem(callee.diagnostic.reason, psi)
|
||||
if ((callee is FirErrorNamedReference || callee is FirResolvedErrorReference) && psi != null) {
|
||||
reportProblem((callee as FirDiagnosticHolder).diagnostic.reason, psi)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -298,8 +300,8 @@ class FirResolveBench(val withProgress: Boolean, val listener: BenchListener? =
|
||||
if (type is ConeErrorType) {
|
||||
errorQualifiedAccessTypes++
|
||||
val psi = callee.psi
|
||||
if (callee is FirErrorNamedReference && psi != null) {
|
||||
reportProblem(callee.diagnostic.reason, psi)
|
||||
if ((callee is FirErrorNamedReference || callee is FirResolvedErrorReference) && psi != null) {
|
||||
reportProblem((callee as FirDiagnosticHolder).diagnostic.reason, psi)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-2
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.references.*
|
||||
@@ -675,12 +676,16 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
|
||||
|
||||
override fun visitNamedReference(namedReference: FirNamedReference, data: StringBuilder) {
|
||||
if (namedReference is FirErrorNamedReference) {
|
||||
data.append("[ERROR : ${namedReference.diagnostic.reason}]")
|
||||
data.append(namedReference.diagnostic.dump())
|
||||
return
|
||||
}
|
||||
visitElement(namedReference, data)
|
||||
}
|
||||
|
||||
private fun ConeDiagnostic.dump(): String {
|
||||
return "[ERROR : ${reason}]"
|
||||
}
|
||||
|
||||
override fun visitResolvedNamedReference(resolvedNamedReference: FirResolvedNamedReference, data: StringBuilder) {
|
||||
val symbol = resolvedNamedReference.resolvedSymbol
|
||||
renderImplicitReceiver(symbol, resolvedNamedReference.source.psi)
|
||||
@@ -698,6 +703,11 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitResolvedErrorReference(resolvedErrorReference: FirResolvedErrorReference, data: StringBuilder) {
|
||||
visitResolvedNamedReference(resolvedErrorReference, data)
|
||||
data.append(resolvedErrorReference.diagnostic.dump())
|
||||
}
|
||||
|
||||
override fun visitResolvedCallableReference(resolvedCallableReference: FirResolvedCallableReference, data: StringBuilder) {
|
||||
when (val symbol = resolvedCallableReference.resolvedSymbol) {
|
||||
is FirPropertySymbol -> renderPropertySymbol(symbol, data)
|
||||
@@ -772,8 +782,11 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
|
||||
is FirConstructorSymbol -> visitConstructor(callee.resolvedSymbol.fir as FirConstructor, data)
|
||||
else -> renderFunctionSymbol(callee.resolvedSymbol as FirNamedFunctionSymbol, data, functionCall)
|
||||
}
|
||||
if (callee is FirResolvedErrorReference) {
|
||||
data.append(callee.diagnostic.dump())
|
||||
}
|
||||
}
|
||||
is FirErrorNamedReference -> data.append("[ERROR : ${callee.diagnostic.reason}]")
|
||||
is FirErrorNamedReference -> data.append(callee.diagnostic.dump())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-2
@@ -16,10 +16,12 @@ 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.FirDiagnosticHolder
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.arguments
|
||||
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDiagnosticWithSingleCandidate
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
|
||||
@@ -42,10 +44,13 @@ object FirAssignmentPluginFunctionCallChecker : FirFunctionCallChecker() {
|
||||
private fun FirFunctionCall.isOverloadAssignCallCandidate() =
|
||||
arguments.size == 1 && source?.kind == KtFakeSourceElementKind.DesugaredCompoundAssignment
|
||||
|
||||
private fun FirFunctionCall.isFunctionResolveError() = calleeReference is FirErrorNamedReference
|
||||
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? FirErrorNamedReference)?.diagnostic) {
|
||||
val functionName = when (val diagnostic = (calleeReference as? FirDiagnosticHolder)?.diagnostic) {
|
||||
is ConeAmbiguityError -> diagnostic.name
|
||||
is ConeDiagnosticWithSingleCandidate -> diagnostic.candidate.callInfo.name
|
||||
is ConeUnresolvedNameError -> diagnostic.name
|
||||
|
||||
Reference in New Issue
Block a user