FIR IDE: pass candidate super types for AMBIGUOUS_SUPER
This way the IDE quickfix do not need to do resolution again to figure out what super type to offer in the quickfix.
This commit is contained in:
committed by
Ilya Kirillov
parent
7c3706dd3f
commit
bdc71a3281
+3
@@ -569,6 +569,9 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
}
|
}
|
||||||
add(FirErrors.AMBIGUOUS_SUPER) { firDiagnostic ->
|
add(FirErrors.AMBIGUOUS_SUPER) { firDiagnostic ->
|
||||||
AmbiguousSuperImpl(
|
AmbiguousSuperImpl(
|
||||||
|
firDiagnostic.a.map { coneKotlinType ->
|
||||||
|
firSymbolBuilder.typeBuilder.buildKtType(coneKotlinType)
|
||||||
|
},
|
||||||
firDiagnostic as FirPsiDiagnostic,
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
|
|||||||
+1
@@ -425,6 +425,7 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
|
|
||||||
abstract class AmbiguousSuper : KtFirDiagnostic<KtSuperExpression>() {
|
abstract class AmbiguousSuper : KtFirDiagnostic<KtSuperExpression>() {
|
||||||
override val diagnosticClass get() = AmbiguousSuper::class
|
override val diagnosticClass get() = AmbiguousSuper::class
|
||||||
|
abstract val candidates: List<KtType>
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class ConstructorInObject : KtFirDiagnostic<KtDeclaration>() {
|
abstract class ConstructorInObject : KtFirDiagnostic<KtDeclaration>() {
|
||||||
|
|||||||
+1
@@ -500,6 +500,7 @@ internal class InconsistentTypeParameterBoundsImpl(
|
|||||||
) : KtFirDiagnostic.InconsistentTypeParameterBounds(), KtAbstractFirDiagnostic<PsiElement>
|
) : KtFirDiagnostic.InconsistentTypeParameterBounds(), KtAbstractFirDiagnostic<PsiElement>
|
||||||
|
|
||||||
internal class AmbiguousSuperImpl(
|
internal class AmbiguousSuperImpl(
|
||||||
|
override val candidates: List<KtType>,
|
||||||
override val firDiagnostic: FirPsiDiagnostic,
|
override val firDiagnostic: FirPsiDiagnostic,
|
||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
) : KtFirDiagnostic.AmbiguousSuper(), KtAbstractFirDiagnostic<KtSuperExpression>
|
) : KtFirDiagnostic.AmbiguousSuper(), KtAbstractFirDiagnostic<KtSuperExpression>
|
||||||
|
|||||||
+3
-1
@@ -192,7 +192,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
parameter<FirRegularClassSymbol>("type")
|
parameter<FirRegularClassSymbol>("type")
|
||||||
parameter<Collection<ConeKotlinType>>("bounds")
|
parameter<Collection<ConeKotlinType>>("bounds")
|
||||||
}
|
}
|
||||||
val AMBIGUOUS_SUPER by error<KtSuperExpression>()
|
val AMBIGUOUS_SUPER by error<KtSuperExpression> {
|
||||||
|
parameter<List<ConeKotlinType>>("candidates")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val CONSTRUCTOR_PROBLEMS by object : DiagnosticGroup("Constructor problems") {
|
val CONSTRUCTOR_PROBLEMS by object : DiagnosticGroup("Constructor problems") {
|
||||||
|
|||||||
+1
-1
@@ -183,7 +183,7 @@ object FirErrors {
|
|||||||
val PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE by error0<KtModifierListOwner>(SourceElementPositioningStrategies.VARIANCE_MODIFIER)
|
val PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE by error0<KtModifierListOwner>(SourceElementPositioningStrategies.VARIANCE_MODIFIER)
|
||||||
val INCONSISTENT_TYPE_PARAMETER_VALUES by error3<KtClass, FirTypeParameterSymbol, FirRegularClassSymbol, Collection<ConeKotlinType>>(SourceElementPositioningStrategies.SUPERTYPES_LIST)
|
val INCONSISTENT_TYPE_PARAMETER_VALUES by error3<KtClass, FirTypeParameterSymbol, FirRegularClassSymbol, Collection<ConeKotlinType>>(SourceElementPositioningStrategies.SUPERTYPES_LIST)
|
||||||
val INCONSISTENT_TYPE_PARAMETER_BOUNDS by error3<PsiElement, FirTypeParameterSymbol, FirRegularClassSymbol, Collection<ConeKotlinType>>()
|
val INCONSISTENT_TYPE_PARAMETER_BOUNDS by error3<PsiElement, FirTypeParameterSymbol, FirRegularClassSymbol, Collection<ConeKotlinType>>()
|
||||||
val AMBIGUOUS_SUPER by error0<KtSuperExpression>()
|
val AMBIGUOUS_SUPER by error1<KtSuperExpression, List<ConeKotlinType>>()
|
||||||
|
|
||||||
// Constructor problems
|
// Constructor problems
|
||||||
val CONSTRUCTOR_IN_OBJECT by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
val CONSTRUCTOR_IN_OBJECT by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||||
|
|||||||
+3
-3
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.toFirDiagnostics
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.toFirDiagnostics
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
|
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirErrorImport
|
import org.jetbrains.kotlin.fir.declarations.FirErrorImport
|
||||||
|
import org.jetbrains.kotlin.fir.diagnostics.ConeAmbiguousSuper
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||||
@@ -75,11 +76,10 @@ class ErrorNodeDiagnosticCollectorComponent(
|
|||||||
|
|
||||||
private fun FirExpression?.cannotBeResolved(): Boolean {
|
private fun FirExpression?.cannotBeResolved(): Boolean {
|
||||||
return when (val diagnostic = (this?.typeRef as? FirErrorTypeRef)?.diagnostic) {
|
return when (val diagnostic = (this?.typeRef as? FirErrorTypeRef)?.diagnostic) {
|
||||||
is ConeUnresolvedNameError, is ConeInstanceAccessBeforeSuperCall -> true
|
is ConeUnresolvedNameError, is ConeInstanceAccessBeforeSuperCall, is ConeAmbiguousSuper -> true
|
||||||
is ConeSimpleDiagnostic -> diagnostic.kind == DiagnosticKind.NotASupertype ||
|
is ConeSimpleDiagnostic -> diagnostic.kind == DiagnosticKind.NotASupertype ||
|
||||||
diagnostic.kind == DiagnosticKind.SuperNotAvailable ||
|
diagnostic.kind == DiagnosticKind.SuperNotAvailable ||
|
||||||
diagnostic.kind == DiagnosticKind.UnresolvedLabel ||
|
diagnostic.kind == DiagnosticKind.UnresolvedLabel
|
||||||
diagnostic.kind == DiagnosticKind.AmbiguousSuper
|
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -636,7 +636,7 @@ class FirDefaultErrorMessages {
|
|||||||
SYMBOL,
|
SYMBOL,
|
||||||
RENDER_COLLECTION_OF_TYPES
|
RENDER_COLLECTION_OF_TYPES
|
||||||
)
|
)
|
||||||
map.put(AMBIGUOUS_SUPER, "Many supertypes available, please specify the one you mean in angle brackets, e.g. 'super<Foo>'")
|
map.put(AMBIGUOUS_SUPER, "Many supertypes available, please specify the one you mean in angle brackets, e.g. 'super<Foo>'", NOT_RENDERED)
|
||||||
|
|
||||||
// Constructor problems
|
// Constructor problems
|
||||||
map.put(CONSTRUCTOR_IN_OBJECT, "Constructors are not allowed for objects")
|
map.put(CONSTRUCTOR_IN_OBJECT, "Constructors are not allowed for objects")
|
||||||
|
|||||||
+1
-1
@@ -111,6 +111,7 @@ private fun ConeDiagnostic.toFirDiagnostic(
|
|||||||
runIf(variable.isLocalMember) { FirErrors.VARIABLE_WITH_NO_TYPE_NO_INITIALIZER.createOn(source) }
|
runIf(variable.isLocalMember) { FirErrors.VARIABLE_WITH_NO_TYPE_NO_INITIALIZER.createOn(source) }
|
||||||
is ConeUnderscoreIsReserved -> FirErrors.UNDERSCORE_IS_RESERVED.createOn(this.source)
|
is ConeUnderscoreIsReserved -> FirErrors.UNDERSCORE_IS_RESERVED.createOn(this.source)
|
||||||
is ConeUnderscoreUsageWithoutBackticks -> FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS.createOn(this.source)
|
is ConeUnderscoreUsageWithoutBackticks -> FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS.createOn(this.source)
|
||||||
|
is ConeAmbiguousSuper -> FirErrors.AMBIGUOUS_SUPER.createOn(source, this.candidateTypes)
|
||||||
else -> throw IllegalArgumentException("Unsupported diagnostic type: ${this.javaClass}")
|
else -> throw IllegalArgumentException("Unsupported diagnostic type: ${this.javaClass}")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,7 +408,6 @@ private fun ConeSimpleDiagnostic.getFactory(source: FirSourceElement): FirDiagno
|
|||||||
DiagnosticKind.EnumEntryAsType -> FirErrors.ENUM_ENTRY_AS_TYPE
|
DiagnosticKind.EnumEntryAsType -> FirErrors.ENUM_ENTRY_AS_TYPE
|
||||||
DiagnosticKind.NotASupertype -> FirErrors.NOT_A_SUPERTYPE
|
DiagnosticKind.NotASupertype -> FirErrors.NOT_A_SUPERTYPE
|
||||||
DiagnosticKind.SuperNotAvailable -> FirErrors.SUPER_NOT_AVAILABLE
|
DiagnosticKind.SuperNotAvailable -> FirErrors.SUPER_NOT_AVAILABLE
|
||||||
DiagnosticKind.AmbiguousSuper -> FirErrors.AMBIGUOUS_SUPER
|
|
||||||
DiagnosticKind.UnresolvedSupertype,
|
DiagnosticKind.UnresolvedSupertype,
|
||||||
DiagnosticKind.UnresolvedExpandedType,
|
DiagnosticKind.UnresolvedExpandedType,
|
||||||
DiagnosticKind.Other -> FirErrors.OTHER_ERROR
|
DiagnosticKind.Other -> FirErrors.OTHER_ERROR
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.utils.addIfNotNull
|
|||||||
fun BodyResolveComponents.findTypesForSuperCandidates(
|
fun BodyResolveComponents.findTypesForSuperCandidates(
|
||||||
superTypeRefs: List<FirTypeRef>,
|
superTypeRefs: List<FirTypeRef>,
|
||||||
containingCall: FirQualifiedAccess,
|
containingCall: FirQualifiedAccess,
|
||||||
): Collection<ConeKotlinType> {
|
): List<ConeKotlinType> {
|
||||||
val supertypes = superTypeRefs.map { (it as FirResolvedTypeRef).type }
|
val supertypes = superTypeRefs.map { (it as FirResolvedTypeRef).type }
|
||||||
val isMethodOfAny = containingCall is FirFunctionCall && isCallingMethodOfAny(containingCall)
|
val isMethodOfAny = containingCall is FirFunctionCall && isCallingMethodOfAny(containingCall)
|
||||||
if (supertypes.size <= 1 && !isMethodOfAny) return supertypes
|
if (supertypes.size <= 1 && !isMethodOfAny) return supertypes
|
||||||
@@ -61,7 +61,7 @@ private fun isCallingMethodOfAny(callExpression: FirFunctionCall): Boolean =
|
|||||||
private fun BodyResolveComponents.resolveSupertypesForMethodOfAny(
|
private fun BodyResolveComponents.resolveSupertypesForMethodOfAny(
|
||||||
supertypes: Collection<ConeKotlinType>,
|
supertypes: Collection<ConeKotlinType>,
|
||||||
calleeName: Name
|
calleeName: Name
|
||||||
): Collection<ConeKotlinType> {
|
): List<ConeKotlinType> {
|
||||||
val typesWithConcreteOverride = resolveSupertypesByMembers(supertypes, false) {
|
val typesWithConcreteOverride = resolveSupertypesByMembers(supertypes, false) {
|
||||||
getFunctionMembers(it, calleeName)
|
getFunctionMembers(it, calleeName)
|
||||||
}
|
}
|
||||||
@@ -71,13 +71,19 @@ private fun BodyResolveComponents.resolveSupertypesForMethodOfAny(
|
|||||||
listOf(session.builtinTypes.anyType.type)
|
listOf(session.builtinTypes.anyType.type)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun BodyResolveComponents.resolveSupertypesByCalleeName(supertypes: Collection<ConeKotlinType>, calleeName: Name): Collection<ConeKotlinType> =
|
private fun BodyResolveComponents.resolveSupertypesByCalleeName(
|
||||||
|
supertypes: Collection<ConeKotlinType>,
|
||||||
|
calleeName: Name
|
||||||
|
): List<ConeKotlinType> =
|
||||||
resolveSupertypesByMembers(supertypes, true) {
|
resolveSupertypesByMembers(supertypes, true) {
|
||||||
getFunctionMembers(it, calleeName) +
|
getFunctionMembers(it, calleeName) +
|
||||||
getPropertyMembers(it, calleeName)
|
getPropertyMembers(it, calleeName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun BodyResolveComponents.resolveSupertypesByPropertyName(supertypes: Collection<ConeKotlinType>, propertyName: Name): Collection<ConeKotlinType> =
|
private fun BodyResolveComponents.resolveSupertypesByPropertyName(
|
||||||
|
supertypes: Collection<ConeKotlinType>,
|
||||||
|
propertyName: Name
|
||||||
|
): List<ConeKotlinType> =
|
||||||
resolveSupertypesByMembers(supertypes, true) {
|
resolveSupertypesByMembers(supertypes, true) {
|
||||||
getPropertyMembers(it, propertyName)
|
getPropertyMembers(it, propertyName)
|
||||||
}
|
}
|
||||||
@@ -86,7 +92,7 @@ private inline fun BodyResolveComponents.resolveSupertypesByMembers(
|
|||||||
supertypes: Collection<ConeKotlinType>,
|
supertypes: Collection<ConeKotlinType>,
|
||||||
allowNonConcreteMembers: Boolean,
|
allowNonConcreteMembers: Boolean,
|
||||||
getMembers: (ConeKotlinType) -> Collection<FirCallableDeclaration>
|
getMembers: (ConeKotlinType) -> Collection<FirCallableDeclaration>
|
||||||
): Collection<ConeKotlinType> {
|
): List<ConeKotlinType> {
|
||||||
val typesWithConcreteMembers = SmartList<ConeKotlinType>()
|
val typesWithConcreteMembers = SmartList<ConeKotlinType>()
|
||||||
val typesWithNonConcreteMembers = SmartList<ConeKotlinType>()
|
val typesWithNonConcreteMembers = SmartList<ConeKotlinType>()
|
||||||
|
|
||||||
|
|||||||
+2
-5
@@ -8,10 +8,7 @@ package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
import org.jetbrains.kotlin.fir.diagnostics.*
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic
|
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.builder.buildErrorExpression
|
import org.jetbrains.kotlin.fir.expressions.builder.buildErrorExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall
|
import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall
|
||||||
@@ -266,7 +263,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
|||||||
}
|
}
|
||||||
else -> buildErrorTypeRef {
|
else -> buildErrorTypeRef {
|
||||||
source = superReferenceContainer.source
|
source = superReferenceContainer.source
|
||||||
diagnostic = ConeSimpleDiagnostic("Ambiguous supertype", DiagnosticKind.AmbiguousSuper)
|
diagnostic = ConeAmbiguousSuper(types)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
superReferenceContainer.resultType =
|
superReferenceContainer.resultType =
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.fir.diagnostics
|
package org.jetbrains.kotlin.fir.diagnostics
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
|
|
||||||
class ConeSimpleDiagnostic(override val reason: String, val kind: DiagnosticKind = DiagnosticKind.Other) : ConeDiagnostic
|
class ConeSimpleDiagnostic(override val reason: String, val kind: DiagnosticKind = DiagnosticKind.Other) : ConeDiagnostic
|
||||||
|
|
||||||
@@ -23,6 +24,11 @@ class ConeUnderscoreUsageWithoutBackticks(source: FirSourceElement) : ConeDiagno
|
|||||||
override val reason: String get() = "Names _, __, ___, ... can be used only in back-ticks (`_`, `__`, `___`, ...)"
|
override val reason: String get() = "Names _, __, ___, ... can be used only in back-ticks (`_`, `__`, `___`, ...)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ConeAmbiguousSuper(val candidateTypes: List<ConeKotlinType>) : ConeDiagnostic {
|
||||||
|
override val reason: String
|
||||||
|
get() = "Ambiguous supertype"
|
||||||
|
}
|
||||||
|
|
||||||
enum class DiagnosticKind {
|
enum class DiagnosticKind {
|
||||||
Syntax,
|
Syntax,
|
||||||
ExpressionExpected,
|
ExpressionExpected,
|
||||||
@@ -49,7 +55,6 @@ enum class DiagnosticKind {
|
|||||||
MissingStdlibClass,
|
MissingStdlibClass,
|
||||||
NotASupertype,
|
NotASupertype,
|
||||||
SuperNotAvailable,
|
SuperNotAvailable,
|
||||||
AmbiguousSuper,
|
|
||||||
|
|
||||||
LoopInSupertype,
|
LoopInSupertype,
|
||||||
RecursiveTypealiasExpansion,
|
RecursiveTypealiasExpansion,
|
||||||
|
|||||||
Reference in New Issue
Block a user