[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 CYCLIC_GENERIC_UPPER_BOUND by error<FirSourceElement, PsiElement>()
|
||||||
|
|
||||||
val DEPRECATED_TYPE_PARAMETER_SYNTAX by error<FirSourceElement, KtTypeParameterList>()
|
val DEPRECATED_TYPE_PARAMETER_SYNTAX by error<FirSourceElement, KtTypeParameterList>()
|
||||||
|
|
||||||
|
val MISPLACED_TYPE_PARAMETER_CONSTRAINTS by warning<FirSourceElement, KtTypeParameter>()
|
||||||
}
|
}
|
||||||
|
|
||||||
val REFLECTION by object : DiagnosticGroup("Reflection") {
|
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 RETURN_TYPE_MISMATCH by error2<FirSourceElement, KtExpression, ConeKotlinType, ConeKotlinType>(SourceElementPositioningStrategies.WHOLE_ELEMENT)
|
||||||
val CYCLIC_GENERIC_UPPER_BOUND by error0<FirSourceElement, PsiElement>()
|
val CYCLIC_GENERIC_UPPER_BOUND by error0<FirSourceElement, PsiElement>()
|
||||||
val DEPRECATED_TYPE_PARAMETER_SYNTAX by error0<FirSourceElement, KtTypeParameterList>()
|
val DEPRECATED_TYPE_PARAMETER_SYNTAX by error0<FirSourceElement, KtTypeParameterList>()
|
||||||
|
val MISPLACED_TYPE_PARAMETER_CONSTRAINTS by warning0<FirSourceElement, KtTypeParameter>()
|
||||||
|
|
||||||
// Reflection
|
// Reflection
|
||||||
val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1<FirSourceElement, KtExpression, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
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)
|
checkBoundUniqueness(declaration, context, reporter)
|
||||||
checkConflictingBounds(declaration, context, reporter)
|
checkConflictingBounds(declaration, context, reporter)
|
||||||
checkTypeAliasBound(declaration, containingDeclaration, context, reporter)
|
checkTypeAliasBound(declaration, containingDeclaration, context, reporter)
|
||||||
|
checkBoundsPlacement(declaration, context, reporter)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkFinalUpperBounds(
|
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 =
|
private fun KotlinTypeMarker.isRelated(context: TypeCheckerProviderContext, type: KotlinTypeMarker?): Boolean =
|
||||||
isSubtypeOf(context, type) || isSupertypeOf(context, type)
|
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_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.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.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.MISSING_VAL_ON_ANNOTATION_PARAMETER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_VARARG_PARAMETERS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_VARARG_PARAMETERS
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED
|
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(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
|
// Reflection
|
||||||
map.put(
|
map.put(
|
||||||
EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED,
|
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
|
// See KT-9438: Enforce the Single Instantiation Inheritance Rule for type parameters
|
||||||
|
|
||||||
interface A
|
interface A
|
||||||
|
|||||||
+4
-4
@@ -1,19 +1,19 @@
|
|||||||
class A
|
class A
|
||||||
interface I0<T : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!>>
|
interface I0<T : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!>>
|
||||||
interface I1<T> where 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 : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!>> foo0() {}
|
||||||
fun <E> foo1() where E : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!> {}
|
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
|
val <E : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!>> E.p1: Int
|
||||||
get() = 1
|
get() = 1
|
||||||
val <E> E.p2: Int where E : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!>
|
val <E> E.p2: Int where E : <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>A<Int><!>
|
||||||
get() = 1
|
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
|
get() = 1
|
||||||
|
|
||||||
// See KT-8200
|
// See KT-8200
|
||||||
interface X
|
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 I0<T : <!UNRESOLVED_REFERENCE!>Unresolved0<String><!>>
|
||||||
interface I1<T> where T : <!UNRESOLVED_REFERENCE!>Unresolved1<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 : <!UNRESOLVED_REFERENCE!>Unresolved4<String><!>> foo0() {}
|
||||||
fun <E> foo1() where E : <!UNRESOLVED_REFERENCE!>Unresolved5<String><!> {}
|
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
|
val <E : <!UNRESOLVED_REFERENCE!>Unresolved7<!>> E.p1: Int
|
||||||
get() = 1
|
get() = 1
|
||||||
val <E> E.p2: Int where E : <!UNRESOLVED_REFERENCE!>Unresolved8<!>
|
val <E> E.p2: Int where E : <!UNRESOLVED_REFERENCE!>Unresolved8<!>
|
||||||
get() = 1
|
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
|
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> {
|
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 <<!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 {}
|
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,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.MISPLACED_TYPE_PARAMETER_CONSTRAINTS) { firDiagnostic ->
|
||||||
|
MisplacedTypeParameterConstraintsImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED) { firDiagnostic ->
|
add(FirErrors.EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED) { firDiagnostic ->
|
||||||
ExtensionInClassReferenceNotAllowedImpl(
|
ExtensionInClassReferenceNotAllowedImpl(
|
||||||
firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.a as FirCallableDeclaration),
|
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
|
override val diagnosticClass get() = DeprecatedTypeParameterSyntax::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class MisplacedTypeParameterConstraints : KtFirDiagnostic<KtTypeParameter>() {
|
||||||
|
override val diagnosticClass get() = MisplacedTypeParameterConstraints::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class ExtensionInClassReferenceNotAllowed : KtFirDiagnostic<KtExpression>() {
|
abstract class ExtensionInClassReferenceNotAllowed : KtFirDiagnostic<KtExpression>() {
|
||||||
override val diagnosticClass get() = ExtensionInClassReferenceNotAllowed::class
|
override val diagnosticClass get() = ExtensionInClassReferenceNotAllowed::class
|
||||||
abstract val referencedDeclaration: KtCallableSymbol
|
abstract val referencedDeclaration: KtCallableSymbol
|
||||||
|
|||||||
+7
@@ -1182,6 +1182,13 @@ internal class DeprecatedTypeParameterSyntaxImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
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(
|
internal class ExtensionInClassReferenceNotAllowedImpl(
|
||||||
override val referencedDeclaration: KtCallableSymbol,
|
override val referencedDeclaration: KtCallableSymbol,
|
||||||
firDiagnostic: FirPsiDiagnostic<*>,
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
|||||||
Reference in New Issue
Block a user