[FIR] Implement TYPEALIAS_SHOULD_EXPAND_TO_CLASS

This commit is contained in:
Ivan Kochurkin
2021-06-16 17:21:32 +03:00
committed by teamcityserver
parent e8a790993b
commit 937846b62d
11 changed files with 74 additions and 18 deletions
@@ -921,6 +921,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val TYPE_ALIAS by object : DiagnosticGroup("Type alias") {
val TOPLEVEL_TYPEALIASES_ONLY by error<KtTypeAlias>()
val RECURSIVE_TYPEALIAS_EXPANSION by error<KtElement>()
val TYPEALIAS_SHOULD_EXPAND_TO_CLASS by error<KtElement> {
parameter<ConeKotlinType>("expandedType")
}
}
val EXTENDED_CHECKERS by object : DiagnosticGroup("Extended checkers") {
@@ -500,6 +500,7 @@ object FirErrors {
// Type alias
val TOPLEVEL_TYPEALIASES_ONLY by error0<KtTypeAlias>()
val RECURSIVE_TYPEALIAS_EXPANSION by error0<KtElement>()
val TYPEALIAS_SHOULD_EXPAND_TO_CLASS by error1<KtElement, ConeKotlinType>()
// Extended checkers
val REDUNDANT_VISIBILITY_MODIFIER by warning0<KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
@@ -12,12 +12,49 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnsupportedDynamicType
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
import org.jetbrains.kotlin.fir.types.*
object FirTypeAliasChecker : FirMemberDeclarationChecker() {
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration !is FirTypeAlias) return
if (context.containingDeclarations.lastOrNull() !is FirFile) {
reporter.reportOn(declaration.source, FirErrors.TOPLEVEL_TYPEALIASES_ONLY, context)
}
fun containsTypeParameter(type: ConeKotlinType): Boolean {
if (type is ConeTypeParameterType) {
return true
}
if (type is ConeClassLikeType && type.lookupTag.toSymbol(context.session) is FirTypeAliasSymbol) {
for (typeArgument in type.typeArguments) {
val typeArgumentType = (typeArgument as? ConeKotlinType) ?: (typeArgument as? ConeKotlinTypeProjection)?.type
if (typeArgumentType != null && containsTypeParameter(typeArgumentType)) {
return true
}
}
}
return false
}
val expandedTypeRef = declaration.expandedTypeRef
val fullyExpandedType = expandedTypeRef.coneType.fullyExpandedType(context.session)
if (containsTypeParameter(fullyExpandedType) ||
fullyExpandedType is ConeClassErrorType && fullyExpandedType.diagnostic is ConeUnsupportedDynamicType
) {
reporter.reportOn(
declaration.expandedTypeRef.source,
FirErrors.TYPEALIAS_SHOULD_EXPAND_TO_CLASS,
expandedTypeRef.coneType,
context
)
}
}
}
@@ -308,6 +308,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SYNTAX
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.THROWABLE_TYPE_MISMATCH
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TOO_MANY_ARGUMENTS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TOPLEVEL_TYPEALIASES_ONLY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPEALIAS_SHOULD_EXPAND_TO_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_CANT_BE_USED_FOR_CONST_VAL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_MISMATCH
@@ -1183,6 +1184,11 @@ class FirDefaultErrorMessages {
// Type alias
map.put(TOPLEVEL_TYPEALIASES_ONLY, "Nested and local type aliases are not supported")
map.put(RECURSIVE_TYPEALIAS_EXPANSION, "Recursive type alias in expansion")
map.put(
TYPEALIAS_SHOULD_EXPAND_TO_CLASS,
"Type alias expands to {0}, which is not a class, an interface, or an object",
RENDER_TYPE
)
// Returns
map.put(RETURN_NOT_ALLOWED, "'return' is not allowed here")
@@ -9,7 +9,7 @@ typealias TTNullableTString = TNullableTString
fun f3() = TTNullableTString::class
inline fun <reified T> f4(b: Boolean): Any {
<!TOPLEVEL_TYPEALIASES_ONLY!>typealias X = T<!>
<!TOPLEVEL_TYPEALIASES_ONLY!>typealias Y = T?<!>
<!TOPLEVEL_TYPEALIASES_ONLY!>typealias X = <!TYPEALIAS_SHOULD_EXPAND_TO_CLASS!>T<!><!>
<!TOPLEVEL_TYPEALIASES_ONLY!>typealias Y = <!TYPEALIAS_SHOULD_EXPAND_TO_CLASS!>T?<!><!>
return if (b) <!UNRESOLVED_REFERENCE!>X<!>::class else <!UNRESOLVED_REFERENCE!>Y<!>::class
}
@@ -1,16 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -TOPLEVEL_TYPEALIASES_ONLY
typealias ToTypeParam1<T> = T
typealias ToTypeParam2<T> = ToTypeParam1<T>
typealias ToTypeParam3<T1, T2> = ToTypeParam2<T1>
typealias ToTypeParam4 = ToTypeParam1<Any>
typealias ToFun1 = () -> Unit
typealias ToFun2<T> = (T) -> Unit
class Outer {
typealias ToTypeParam1<T> = T
typealias ToTypeParam2<T> = ToTypeParam1<T>
typealias ToTypeParam3<T1, T2> = ToTypeParam2<T1>
typealias ToTypeParam4 = ToTypeParam1<Any>
}
@@ -1,5 +1,8 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -TOPLEVEL_TYPEALIASES_ONLY
typealias Dyn = <!TYPEALIAS_SHOULD_EXPAND_TO_CLASS, UNSUPPORTED!>dynamic<!>
typealias ToTypeParam1<T> = <!TYPEALIAS_SHOULD_EXPAND_TO_CLASS!>T<!>
typealias ToTypeParam2<T> = <!TYPEALIAS_SHOULD_EXPAND_TO_CLASS!>ToTypeParam1<T><!>
typealias ToTypeParam3<T1, T2> = <!TYPEALIAS_SHOULD_EXPAND_TO_CLASS!>ToTypeParam2<T1><!>
@@ -10,9 +10,11 @@ public final class Outer {
public typealias ToTypeParam3</*0*/ T1, /*1*/ T2> = Outer.ToTypeParam2<T1>
public typealias ToTypeParam4 = Outer.ToTypeParam1<kotlin.Any>
}
public typealias Dyn = [ERROR : dynamic type in wrong context]
public typealias ToFun1 = () -> kotlin.Unit
public typealias ToFun2</*0*/ T> = (T) -> kotlin.Unit
public typealias ToTypeParam1</*0*/ T> = T
public typealias ToTypeParam2</*0*/ T> = ToTypeParam1<T>
public typealias ToTypeParam3</*0*/ T1, /*1*/ T2> = ToTypeParam2<T1>
public typealias ToTypeParam4 = ToTypeParam1<kotlin.Any>
@@ -2498,6 +2498,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.TYPEALIAS_SHOULD_EXPAND_TO_CLASS) { firDiagnostic ->
TypealiasShouldExpandToClassImpl(
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
firDiagnostic as FirPsiDiagnostic,
token,
)
}
add(FirErrors.REDUNDANT_VISIBILITY_MODIFIER) { firDiagnostic ->
RedundantVisibilityModifierImpl(
firDiagnostic as FirPsiDiagnostic,
@@ -1757,6 +1757,11 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = RecursiveTypealiasExpansion::class
}
abstract class TypealiasShouldExpandToClass : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = TypealiasShouldExpandToClass::class
abstract val expandedType: KtType
}
abstract class RedundantVisibilityModifier : KtFirDiagnostic<KtModifierListOwner>() {
override val diagnosticClass get() = RedundantVisibilityModifier::class
}
@@ -2841,6 +2841,14 @@ internal class RecursiveTypealiasExpansionImpl(
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
}
internal class TypealiasShouldExpandToClassImpl(
override val expandedType: KtType,
firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.TypealiasShouldExpandToClass(), KtAbstractFirDiagnostic<KtElement> {
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
}
internal class RedundantVisibilityModifierImpl(
firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,