FIR: allow reporting multiple FirDiagnostics from a ConeDiagnostic
This commit is contained in:
committed by
Mikhail Glukhikh
parent
1f15ce2d26
commit
0d4e9ca0b9
+4
-3
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.toFirDiagnostic
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.toFirDiagnostics
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
|
||||
@@ -77,7 +77,8 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect
|
||||
if (source.kind == FirFakeSourceElementKind.ImplicitConstructor) {
|
||||
return
|
||||
}
|
||||
val coneDiagnostic = diagnostic.toFirDiagnostic(source)
|
||||
reporter.report(coneDiagnostic, context)
|
||||
for (coneDiagnostic in diagnostic.toFirDiagnostics(source)) {
|
||||
reporter.report(coneDiagnostic, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-11
@@ -21,13 +21,13 @@ import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.utils.ifEmpty
|
||||
|
||||
fun ConeDiagnostic.toFirDiagnostic(source: FirSourceElement): FirDiagnostic<FirSourceElement>? = when (this) {
|
||||
private fun ConeDiagnostic.toFirDiagnostic(source: FirSourceElement): FirDiagnostic<FirSourceElement>? = when (this) {
|
||||
is ConeUnresolvedReferenceError -> FirErrors.UNRESOLVED_REFERENCE.on(source, this.name?.asString() ?: "<No name>")
|
||||
is ConeUnresolvedSymbolError -> FirErrors.UNRESOLVED_REFERENCE.on(source, this.classId.asString())
|
||||
is ConeUnresolvedNameError -> FirErrors.UNRESOLVED_REFERENCE.on(source, this.name.asString())
|
||||
is ConeHiddenCandidateError -> FirErrors.HIDDEN.on(source, this.candidateSymbol)
|
||||
is ConeInapplicableCandidateError -> mapInapplicableCandidateError(this, source)
|
||||
is ConeAmbiguityError -> if (!this.applicability.isSuccess) {
|
||||
FirErrors.NONE_APPLICABLE.on(source, this.candidates)
|
||||
} else {
|
||||
@@ -53,6 +53,13 @@ fun ConeDiagnostic.toFirDiagnostic(source: FirSourceElement): FirDiagnostic<FirS
|
||||
else -> throw IllegalArgumentException("Unsupported diagnostic type: ${this.javaClass}")
|
||||
}
|
||||
|
||||
fun ConeDiagnostic.toFirDiagnostics(source: FirSourceElement): List<FirDiagnostic<FirSourceElement>> {
|
||||
if (this is ConeInapplicableCandidateError) {
|
||||
return mapInapplicableCandidateError(this, source)
|
||||
}
|
||||
return listOfNotNull(toFirDiagnostic(source))
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.isEffectivelyNotNull(): Boolean {
|
||||
return when (this) {
|
||||
is ConeClassLikeType -> !isMarkedNullable
|
||||
@@ -68,8 +75,7 @@ private fun mapUnsafeCallError(
|
||||
source: FirSourceElement,
|
||||
rootCause: ResolutionDiagnostic?,
|
||||
): FirDiagnostic<*>? {
|
||||
if (rootCause != null &&
|
||||
rootCause is InapplicableWrongReceiver &&
|
||||
if (rootCause is InapplicableWrongReceiver &&
|
||||
rootCause.actualType?.isNullable == true &&
|
||||
(rootCause.expectedType == null || rootCause.expectedType!!.isEffectivelyNotNull())
|
||||
) {
|
||||
@@ -102,15 +108,16 @@ private fun mapUnsafeCallError(
|
||||
private fun mapInapplicableCandidateError(
|
||||
diagnostic: ConeInapplicableCandidateError,
|
||||
source: FirSourceElement,
|
||||
): FirDiagnostic<*> {
|
||||
): List<FirDiagnostic<FirSourceElement>> {
|
||||
// TODO: Need to distinguish SMARTCAST_IMPOSSIBLE
|
||||
val rootCause = diagnostic.candidate.diagnostics.find { it.applicability == diagnostic.applicability }
|
||||
mapUnsafeCallError(diagnostic, source, rootCause)?.let { return it }
|
||||
return diagnostic.candidate.diagnostics.filter { it.applicability == diagnostic.applicability }.mapNotNull { rootCause ->
|
||||
mapUnsafeCallError(diagnostic, source, rootCause)?.let { return@mapNotNull it }
|
||||
|
||||
return when (rootCause) {
|
||||
is VarargArgumentOutsideParentheses -> FirErrors.VARARG_OUTSIDE_PARENTHESES.on(rootCause.argument.source ?: source)
|
||||
else -> FirErrors.INAPPLICABLE_CANDIDATE.on(source, diagnostic.candidate.symbol)
|
||||
}
|
||||
when (rootCause) {
|
||||
is VarargArgumentOutsideParentheses -> FirErrors.VARARG_OUTSIDE_PARENTHESES.on(rootCause.argument.source ?: source)
|
||||
else -> null
|
||||
}
|
||||
}.ifEmpty { listOf(FirErrors.INAPPLICABLE_CANDIDATE.on(source, diagnostic.candidate.symbol)) }
|
||||
}
|
||||
|
||||
private fun ConeSimpleDiagnostic.getFactory(): FirDiagnosticFactory0<FirSourceElement, *> {
|
||||
|
||||
+3
-6
@@ -9,14 +9,11 @@ import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.toFirDiagnostic
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.toFirDiagnostics
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext
|
||||
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
|
||||
import org.jetbrains.kotlin.idea.frontend.api.components.KtAnalysisSessionComponent
|
||||
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnostic
|
||||
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnosticWithPsi
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.diagnostics.KT_DIAGNOSTIC_CONVERTER
|
||||
@@ -34,7 +31,7 @@ internal interface KtFirAnalysisSessionComponent {
|
||||
KT_DIAGNOSTIC_CONVERTER.convert(analysisSession, this as FirDiagnostic<*>)
|
||||
|
||||
fun ConeDiagnostic.asKtDiagnostic(source: FirSourceElement): KtDiagnosticWithPsi<*>? {
|
||||
val firDiagnostic = toFirDiagnostic(source) ?: return null
|
||||
val firDiagnostic = toFirDiagnostics(source).firstOrNull() ?: return null
|
||||
check(firDiagnostic is FirPsiDiagnostic<*>)
|
||||
return firDiagnostic.asKtDiagnostic()
|
||||
}
|
||||
@@ -44,4 +41,4 @@ internal interface KtFirAnalysisSessionComponent {
|
||||
isStubTypeEqualsToAnything = true,
|
||||
analysisSession.firResolveState.rootModuleSession.typeContext //TODO use correct session here
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user