[FIR] Add MISPLACED_TYPE_PARAMETER_CONSTRAINTS check
This commit is contained in:
committed by
TeamCityServer
parent
412b941486
commit
0d525bbe85
+2
@@ -334,6 +334,8 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
||||
val CYCLIC_GENERIC_UPPER_BOUND by error<FirSourceElement, PsiElement>()
|
||||
|
||||
val DEPRECATED_TYPE_PARAMETER_SYNTAX by error<FirSourceElement, KtTypeParameterList>()
|
||||
|
||||
val MISPLACED_TYPE_PARAMETER_CONSTRAINTS by warning<FirSourceElement, KtTypeParameter>()
|
||||
}
|
||||
|
||||
val REFLECTION by object : DiagnosticGroup("Reflection") {
|
||||
|
||||
@@ -242,6 +242,7 @@ object FirErrors {
|
||||
val RETURN_TYPE_MISMATCH by error2<FirSourceElement, KtExpression, ConeKotlinType, ConeKotlinType>(SourceElementPositioningStrategies.WHOLE_ELEMENT)
|
||||
val CYCLIC_GENERIC_UPPER_BOUND by error0<FirSourceElement, PsiElement>()
|
||||
val DEPRECATED_TYPE_PARAMETER_SYNTAX by error0<FirSourceElement, KtTypeParameterList>()
|
||||
val MISPLACED_TYPE_PARAMETER_CONSTRAINTS by warning0<FirSourceElement, KtTypeParameter>()
|
||||
|
||||
// Reflection
|
||||
val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1<FirSourceElement, KtExpression, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
|
||||
+10
@@ -42,6 +42,7 @@ object FirTypeParameterBoundsChecker : FirTypeParameterChecker() {
|
||||
checkBoundUniqueness(declaration, context, reporter)
|
||||
checkConflictingBounds(declaration, context, reporter)
|
||||
checkTypeAliasBound(declaration, containingDeclaration, context, reporter)
|
||||
checkBoundsPlacement(declaration, context, reporter)
|
||||
}
|
||||
|
||||
private fun checkFinalUpperBounds(
|
||||
@@ -147,6 +148,15 @@ object FirTypeParameterBoundsChecker : FirTypeParameterChecker() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkBoundsPlacement(declaration: FirTypeParameter, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (declaration.bounds.size < 2) return
|
||||
|
||||
val (constraint, params) = declaration.bounds.partition { it.isInTypeConstraint() }
|
||||
if (params.isNotEmpty() && constraint.isNotEmpty()) {
|
||||
reporter.reportOn(declaration.source, FirErrors.MISPLACED_TYPE_PARAMETER_CONSTRAINTS, context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun KotlinTypeMarker.isRelated(context: TypeCheckerProviderContext, type: KotlinTypeMarker?): Boolean =
|
||||
isSubtypeOf(context, type) || isSupertypeOf(context, type)
|
||||
|
||||
|
||||
+6
@@ -140,6 +140,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_COMPANION_OB
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.METHOD_OF_ANY_IMPLEMENTED_IN_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISPLACED_TYPE_PARAMETER_CONSTRAINTS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_VARARG_PARAMETERS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED
|
||||
@@ -515,6 +516,11 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
||||
|
||||
map.put(DEPRECATED_TYPE_PARAMETER_SYNTAX, "Type parameters must be placed before the name of the function")
|
||||
|
||||
map.put(
|
||||
MISPLACED_TYPE_PARAMETER_CONSTRAINTS,
|
||||
"If a type parameter has multiple constraints, they all need to be placed in the 'where' clause"
|
||||
)
|
||||
|
||||
// Reflection
|
||||
map.put(
|
||||
EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED,
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
// See KT-9438: Enforce the Single Instantiation Inheritance Rule for type parameters
|
||||
|
||||
interface A
|
||||
|
||||
interface B
|
||||
|
||||
interface D<T>
|
||||
|
||||
interface IncorrectF<T : D<A>> where T : <!REPEATED_BOUND!>D<B><!>
|
||||
|
||||
interface CorrectF<T> where T : D<A>, T : <!REPEATED_BOUND!>D<B><!>
|
||||
|
||||
interface G<T>
|
||||
|
||||
interface IncorrectH<T : G<D<A>>> where T : <!REPEATED_BOUND!>G<D<T>><!>
|
||||
|
||||
interface CorrectH<T> where T : G<D<A>>, T : <!REPEATED_BOUND!>G<D<B>><!>
|
||||
|
||||
interface incorrectJ<T: G<D<T>>> where T : <!REPEATED_BOUND!>G<D<T?>><!>
|
||||
|
||||
interface correctJ<T> where T : G<D<T>>, T : <!REPEATED_BOUND!>G<D<T?>><!>
|
||||
|
||||
fun <T> bar() where T : D<A>, T : <!REPEATED_BOUND!>D<B><!> {}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// See KT-9438: Enforce the Single Instantiation Inheritance Rule for type parameters
|
||||
|
||||
interface A
|
||||
|
||||
+4
-4
@@ -1,19 +1,19 @@
|
||||
class A
|
||||
interface I0<T : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!>>
|
||||
interface I1<T> where T : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!>
|
||||
interface I2<T : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!>> where T : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!>
|
||||
interface I2<<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>T : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!><!>> where T : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!>
|
||||
|
||||
fun <E : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!>> foo0() {}
|
||||
fun <E> foo1() where E : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!> {}
|
||||
fun <E : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!>> foo2() where E : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!> {}
|
||||
fun <<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>E : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!><!>> foo2() where E : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!> {}
|
||||
|
||||
val <E : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!>> E.p1: Int
|
||||
get() = 1
|
||||
val <E> E.p2: Int where E : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!>
|
||||
get() = 1
|
||||
val <E : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!>> E.p3: Int where E : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!>
|
||||
val <<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>E : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!><!>> E.p3: Int where E : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!>
|
||||
get() = 1
|
||||
|
||||
// See KT-8200
|
||||
interface X
|
||||
public class EnumAttribute<T : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>X<T><!>>(val klass: Class<T>) where T : Enum<T>
|
||||
public class EnumAttribute<<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>T : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>X<T><!><!>>(val klass: Class<T>) where T : Enum<T>
|
||||
|
||||
+3
-3
@@ -1,14 +1,14 @@
|
||||
interface I0<T : <!UNRESOLVED_REFERENCE!>Unresolved0<String><!>>
|
||||
interface I1<T> where T : <!UNRESOLVED_REFERENCE!>Unresolved1<String><!>
|
||||
interface I2<T : <!UNRESOLVED_REFERENCE!>Unresolved2<String><!>> where T : <!UNRESOLVED_REFERENCE!>Unresolved3<String><!>
|
||||
interface I2<<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>T : <!UNRESOLVED_REFERENCE!>Unresolved2<String><!><!>> where T : <!UNRESOLVED_REFERENCE!>Unresolved3<String><!>
|
||||
|
||||
fun <E : <!UNRESOLVED_REFERENCE!>Unresolved4<String><!>> foo0() {}
|
||||
fun <E> foo1() where E : <!UNRESOLVED_REFERENCE!>Unresolved5<String><!> {}
|
||||
fun <E : <!UNRESOLVED_REFERENCE!>Unresolved6<String><!>> foo2() where E : <!UNRESOLVED_REFERENCE!>Unresolved7<String><!> {}
|
||||
fun <<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>E : <!UNRESOLVED_REFERENCE!>Unresolved6<String><!><!>> foo2() where E : <!UNRESOLVED_REFERENCE!>Unresolved7<String><!> {}
|
||||
|
||||
val <E : <!UNRESOLVED_REFERENCE!>Unresolved7<!>> E.p1: Int
|
||||
get() = 1
|
||||
val <E> E.p2: Int where E : <!UNRESOLVED_REFERENCE!>Unresolved8<!>
|
||||
get() = 1
|
||||
val <E : <!UNRESOLVED_REFERENCE!>Unresolved9<!>> E.p3: Int where E : <!UNRESOLVED_REFERENCE!>Unresolved10<!>
|
||||
val <<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>E : <!UNRESOLVED_REFERENCE!>Unresolved9<!><!>> E.p3: Int where E : <!UNRESOLVED_REFERENCE!>Unresolved10<!>
|
||||
get() = 1
|
||||
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
class Foo<T : Cloneable> where T : Comparable<T> {
|
||||
fun <U : Cloneable> foo(u: U): U where U: Comparable<U> {
|
||||
fun <<!BOUNDS_NOT_ALLOWED_IF_BOUNDED_BY_TYPE_PARAMETER!>T: Any<!>> bar() where T: U {}
|
||||
return u
|
||||
}
|
||||
|
||||
val <U : Cloneable> U.foo: U? where U: Comparable<U>
|
||||
get() { return null }
|
||||
}
|
||||
|
||||
class Bar<T : Cloneable, U> where U: Comparable<T> {
|
||||
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
class Foo<<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>T : Cloneable<!>> where T : Comparable<T> {
|
||||
fun <<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>U : Cloneable<!>> foo(u: U): U where U: Comparable<U> {
|
||||
fun <<!BOUNDS_NOT_ALLOWED_IF_BOUNDED_BY_TYPE_PARAMETER, MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>T: Any<!>> bar() where T: U {}
|
||||
|
||||
+6
@@ -1030,6 +1030,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.MISPLACED_TYPE_PARAMETER_CONSTRAINTS) { firDiagnostic ->
|
||||
MisplacedTypeParameterConstraintsImpl(
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED) { firDiagnostic ->
|
||||
ExtensionInClassReferenceNotAllowedImpl(
|
||||
firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.a as FirCallableDeclaration),
|
||||
|
||||
+4
@@ -731,6 +731,10 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = DeprecatedTypeParameterSyntax::class
|
||||
}
|
||||
|
||||
abstract class MisplacedTypeParameterConstraints : KtFirDiagnostic<KtTypeParameter>() {
|
||||
override val diagnosticClass get() = MisplacedTypeParameterConstraints::class
|
||||
}
|
||||
|
||||
abstract class ExtensionInClassReferenceNotAllowed : KtFirDiagnostic<KtExpression>() {
|
||||
override val diagnosticClass get() = ExtensionInClassReferenceNotAllowed::class
|
||||
abstract val referencedDeclaration: KtCallableSymbol
|
||||
|
||||
+7
@@ -1182,6 +1182,13 @@ internal class DeprecatedTypeParameterSyntaxImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class MisplacedTypeParameterConstraintsImpl(
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.MisplacedTypeParameterConstraints(), KtAbstractFirDiagnostic<KtTypeParameter> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ExtensionInClassReferenceNotAllowedImpl(
|
||||
override val referencedDeclaration: KtCallableSymbol,
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
|
||||
Reference in New Issue
Block a user