[FIR] Report inherited java members referencing FunctionN
^KT-60000 Fixed
This commit is contained in:
committed by
Space Team
parent
0c35e97a8d
commit
70e98c9c2b
+7
@@ -657,6 +657,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION) { firDiagnostic ->
|
||||
UnsupportedInheritanceFromJavaMemberReferencingKotlinFunctionImpl(
|
||||
firSymbolBuilder.buildSymbol(firDiagnostic.a),
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.CYCLIC_INHERITANCE_HIERARCHY) { firDiagnostic ->
|
||||
CyclicInheritanceHierarchyImpl(
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
|
||||
+5
@@ -502,6 +502,11 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
val reason: String
|
||||
}
|
||||
|
||||
interface UnsupportedInheritanceFromJavaMemberReferencingKotlinFunction : KtFirDiagnostic<PsiElement> {
|
||||
override val diagnosticClass get() = UnsupportedInheritanceFromJavaMemberReferencingKotlinFunction::class
|
||||
val symbol: KtSymbol
|
||||
}
|
||||
|
||||
interface CyclicInheritanceHierarchy : KtFirDiagnostic<PsiElement> {
|
||||
override val diagnosticClass get() = CyclicInheritanceHierarchy::class
|
||||
}
|
||||
|
||||
+6
@@ -590,6 +590,12 @@ internal class SupertypeNotAClassOrInterfaceImpl(
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<KtElement>(firDiagnostic, token), KtFirDiagnostic.SupertypeNotAClassOrInterface
|
||||
|
||||
internal class UnsupportedInheritanceFromJavaMemberReferencingKotlinFunctionImpl(
|
||||
override val symbol: KtSymbol,
|
||||
firDiagnostic: KtPsiDiagnostic,
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.UnsupportedInheritanceFromJavaMemberReferencingKotlinFunction
|
||||
|
||||
internal class CyclicInheritanceHierarchyImpl(
|
||||
firDiagnostic: KtPsiDiagnostic,
|
||||
token: KtLifetimeToken,
|
||||
|
||||
+3
@@ -248,6 +248,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
val SUPERTYPE_NOT_A_CLASS_OR_INTERFACE by error<KtElement> {
|
||||
parameter<String>("reason")
|
||||
}
|
||||
val UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION by error<PsiElement>(PositioningStrategy.DECLARATION_NAME) {
|
||||
parameter<FirBasedSymbol<*>>("symbol")
|
||||
}
|
||||
val CYCLIC_INHERITANCE_HIERARCHY by error<PsiElement>()
|
||||
val EXPANDED_TYPE_CANNOT_BE_INHERITED by error<KtTypeReference> {
|
||||
parameter<ConeKotlinType>("type")
|
||||
|
||||
@@ -214,6 +214,7 @@ object FirErrors {
|
||||
val SEALED_INHERITOR_IN_DIFFERENT_MODULE by error0<KtTypeReference>()
|
||||
val CLASS_INHERITS_JAVA_SEALED_CLASS by error0<KtTypeReference>()
|
||||
val SUPERTYPE_NOT_A_CLASS_OR_INTERFACE by error1<KtElement, String>()
|
||||
val UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION by error1<PsiElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val CYCLIC_INHERITANCE_HIERARCHY by error0<PsiElement>()
|
||||
val EXPANDED_TYPE_CANNOT_BE_INHERITED by error1<KtTypeReference, ConeKotlinType>()
|
||||
val PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE by error0<KtModifierListOwner>(SourceElementPositioningStrategies.VARIANCE_MODIFIER)
|
||||
|
||||
+1
@@ -105,6 +105,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
FirPrimaryConstructorSuperTypeChecker,
|
||||
FirDynamicSupertypeChecker,
|
||||
FirEnumCompanionInEnumConstructorCallChecker,
|
||||
FirBadInheritedJavaSignaturesChecker,
|
||||
)
|
||||
|
||||
override val regularClassCheckers: Set<FirRegularClassChecker>
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.isJavaOrEnhancement
|
||||
import org.jetbrains.kotlin.fir.scopes.processAllCallables
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.classId
|
||||
import org.jetbrains.kotlin.fir.types.contains
|
||||
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.FunctionN
|
||||
|
||||
object FirBadInheritedJavaSignaturesChecker : FirClassChecker() {
|
||||
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
fun containsFunctionN(type: ConeKotlinType) = type.classId == FunctionN
|
||||
|
||||
declaration.unsubstitutedScope(context).processAllCallables { symbol ->
|
||||
if (!symbol.isJavaOrEnhancement) {
|
||||
return@processAllCallables
|
||||
}
|
||||
|
||||
val hasBadReturnType = symbol.resolvedReturnType.contains(::containsFunctionN)
|
||||
// NB: This case with receiver is not covered with tests
|
||||
// and was replicated, because it's present in the original
|
||||
// checker.
|
||||
val hasBadReceiverType = symbol.resolvedReceiverTypeRef?.type?.contains(::containsFunctionN) == true
|
||||
val hasBadValueParameter = symbol is FirFunctionSymbol<*> && symbol.valueParameterSymbols.any { valueParameter ->
|
||||
valueParameter.resolvedReturnType.contains(::containsFunctionN)
|
||||
}
|
||||
|
||||
if (hasBadReturnType || hasBadReceiverType || hasBadValueParameter) {
|
||||
reporter.reportOn(
|
||||
declaration.source,
|
||||
FirErrors.UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION,
|
||||
symbol, context,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -608,6 +608,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_FEATURE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_SUSPEND_TEST
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNUSED_VARIABLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_VIOLATED
|
||||
@@ -820,6 +821,11 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
map.put(CLASS_INHERITS_JAVA_SEALED_CLASS, "Inheritance of Java sealed classes is prohibited")
|
||||
|
||||
map.put(SUPERTYPE_NOT_A_CLASS_OR_INTERFACE, "Supertype is not a class or interface", TO_STRING)
|
||||
map.put(
|
||||
UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION,
|
||||
"Inheritance of a Java member referencing 'kotlin.jvm.functions.FunctionN': {0} is unsupported",
|
||||
TO_STRING,
|
||||
)
|
||||
map.put(CYCLIC_INHERITANCE_HIERARCHY, "There's a cycle in the inheritance hierarchy for this type")
|
||||
map.put(
|
||||
EXPANDED_TYPE_CANNOT_BE_INHERITED,
|
||||
|
||||
+8
-3
@@ -1,4 +1,3 @@
|
||||
|
||||
// FILE: A.java
|
||||
|
||||
import kotlin.jvm.functions.FunctionN;
|
||||
@@ -7,10 +6,16 @@ public class A {
|
||||
public void foo(FunctionN<?> w) { }
|
||||
}
|
||||
|
||||
public class A2 {
|
||||
public FunctionN<?> foo() { }
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
class B : A()
|
||||
<!UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION!>class B<!> : A()
|
||||
<!UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION!>class B2<!> : A2()
|
||||
|
||||
fun foo() {
|
||||
object : A() {}
|
||||
<!UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION!>object<!> : A() {}
|
||||
<!UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION!>object<!> : A2() {}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
// FILE: A.java
|
||||
|
||||
import kotlin.jvm.functions.FunctionN;
|
||||
@@ -7,10 +6,16 @@ public class A {
|
||||
public void foo(FunctionN<?> w) { }
|
||||
}
|
||||
|
||||
public class A2 {
|
||||
public FunctionN<?> foo() { }
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
class <!UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION!>B<!> : A()
|
||||
class <!UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION!>B2<!> : A2()
|
||||
|
||||
fun foo() {
|
||||
<!UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION!>object<!> : A() {}
|
||||
<!UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION!>object<!> : A2() {}
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
package
|
||||
|
||||
public fun foo(): kotlin.Unit
|
||||
|
||||
public open class A {
|
||||
public constructor A()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(/*0*/ w: kotlin.jvm.functions.FunctionN<*>!): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class B : A {
|
||||
public constructor B()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun foo(/*0*/ w: kotlin.jvm.functions.FunctionN<*>!): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -14,6 +14,7 @@ object StandardClassIds {
|
||||
val BASE_RANGES_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("ranges"))
|
||||
val BASE_JVM_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("jvm"))
|
||||
val BASE_JVM_INTERNAL_PACKAGE = BASE_JVM_PACKAGE.child(Name.identifier("internal"))
|
||||
val BASE_JVM_FUNCTIONS_PACKAGE = BASE_JVM_PACKAGE.child(Name.identifier("functions"))
|
||||
val BASE_ANNOTATION_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("annotation"))
|
||||
val BASE_INTERNAL_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("internal"))
|
||||
val BASE_INTERNAL_IR_PACKAGE = BASE_INTERNAL_PACKAGE.child(Name.identifier("ir"))
|
||||
@@ -183,6 +184,8 @@ object StandardClassIds {
|
||||
val FlexibleMutability = "FlexibleMutability".internalIrId()
|
||||
val EnhancedNullability = "EnhancedNullability".jvmInternalId()
|
||||
|
||||
val FunctionN = "FunctionN".jvmFunctionsId()
|
||||
|
||||
val InlineOnly = "InlineOnly".internalId()
|
||||
|
||||
val OnlyInputTypes = "OnlyInputTypes".internalId()
|
||||
@@ -265,6 +268,7 @@ private fun String.rangesId() = ClassId(StandardClassIds.BASE_RANGES_PACKAGE, Na
|
||||
private fun String.annotationId() = ClassId(StandardClassIds.BASE_ANNOTATION_PACKAGE, Name.identifier(this))
|
||||
private fun String.jvmId() = ClassId(StandardClassIds.BASE_JVM_PACKAGE, Name.identifier(this))
|
||||
private fun String.jvmInternalId() = ClassId(StandardClassIds.BASE_JVM_INTERNAL_PACKAGE, Name.identifier(this))
|
||||
private fun String.jvmFunctionsId() = ClassId(StandardClassIds.BASE_JVM_FUNCTIONS_PACKAGE, Name.identifier(this))
|
||||
private fun String.internalId() = ClassId(StandardClassIds.BASE_INTERNAL_PACKAGE, Name.identifier(this))
|
||||
private fun String.internalIrId() = ClassId(StandardClassIds.BASE_INTERNAL_IR_PACKAGE, Name.identifier(this))
|
||||
private fun String.coroutinesId() = ClassId(StandardClassIds.BASE_COROUTINES_PACKAGE, Name.identifier(this))
|
||||
|
||||
Reference in New Issue
Block a user