[FIR] Add JVM diagnostics about external declaration
This commit is contained in:
committed by
TeamCityServer
parent
4907bc296f
commit
816e8f487c
+7
@@ -103,4 +103,11 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") {
|
|||||||
val USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL by error<PsiElement>()
|
val USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL by error<PsiElement>()
|
||||||
val NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT by warning<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
|
val NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT by warning<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val EXTERNAL_DECLARATION by object : DiagnosticGroup("External Declaration") {
|
||||||
|
val EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT by error<KtDeclaration>(PositioningStrategy.ABSTRACT_MODIFIER)
|
||||||
|
val EXTERNAL_DECLARATION_CANNOT_HAVE_BODY by error<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||||
|
val EXTERNAL_DECLARATION_IN_INTERFACE by error<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||||
|
val EXTERNAL_DECLARATION_CANNOT_BE_INLINED by error<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -83,4 +83,10 @@ object FirJvmErrors {
|
|||||||
val USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL by error0<PsiElement>()
|
val USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL by error0<PsiElement>()
|
||||||
val NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT by warning0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
val NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT by warning0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||||
|
|
||||||
|
// External Declaration
|
||||||
|
val EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT by error0<KtDeclaration>(SourceElementPositioningStrategies.ABSTRACT_MODIFIER)
|
||||||
|
val EXTERNAL_DECLARATION_CANNOT_HAVE_BODY by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||||
|
val EXTERNAL_DECLARATION_IN_INTERFACE by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||||
|
val EXTERNAL_DECLARATION_CANNOT_BE_INLINED by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+42
-5
@@ -5,20 +5,45 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.jvm.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.jvm.checkers.declaration
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||||
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.getModifier
|
import org.jetbrains.kotlin.fir.analysis.checkers.getModifier
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.containingClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isExternal
|
import org.jetbrains.kotlin.fir.declarations.utils.isExternal
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isInline
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
|
||||||
object FirJvmExternalDeclarationChecker : FirBasicDeclarationChecker() {
|
object FirJvmExternalDeclarationChecker : FirBasicDeclarationChecker() {
|
||||||
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
checkInternal(declaration, null, null, context, reporter)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkInternal(
|
||||||
|
declaration: FirDeclaration,
|
||||||
|
reportSource: FirSourceElement?,
|
||||||
|
modality: Modality?,
|
||||||
|
context: CheckerContext,
|
||||||
|
reporter: DiagnosticReporter
|
||||||
|
) {
|
||||||
if (declaration !is FirMemberDeclaration) return
|
if (declaration !is FirMemberDeclaration) return
|
||||||
|
|
||||||
|
if (declaration is FirProperty) {
|
||||||
|
declaration.getter?.let {
|
||||||
|
checkInternal(it, declaration.source, declaration.modality, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!declaration.isExternal) return
|
if (!declaration.isExternal) return
|
||||||
val source = declaration.source ?: return
|
val source = declaration.source ?: return
|
||||||
if (source.kind is FirFakeSourceElementKind) return
|
if (source.kind is FirFakeSourceElementKind) return
|
||||||
@@ -34,12 +59,24 @@ object FirJvmExternalDeclarationChecker : FirBasicDeclarationChecker() {
|
|||||||
externalModifier?.let {
|
externalModifier?.let {
|
||||||
reporter.reportOn(it.source, FirErrors.WRONG_MODIFIER_TARGET, it.token, target, context)
|
reporter.reportOn(it.source, FirErrors.WRONG_MODIFIER_TARGET, it.token, target, context)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement checkers for these JVM-specific errors (see ExternalFunChecker in FE1.0):
|
val containingClassSymbol = declaration.symbol.containingClass()?.toFirRegularClass(context.session)
|
||||||
// - EXTERNAL_DECLARATION_IN_INTERFACE
|
if (containingClassSymbol != null) {
|
||||||
// - EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT
|
if (containingClassSymbol.isInterface) {
|
||||||
// - EXTERNAL_DECLARATION_CANNOT_HAVE_BODY
|
reporter.reportOn(declaration.source, FirJvmErrors.EXTERNAL_DECLARATION_IN_INTERFACE, context)
|
||||||
// - EXTERNAL_DECLARATION_CANNOT_BE_INLINED
|
} else if ((modality ?: declaration.modality) == Modality.ABSTRACT) {
|
||||||
|
reporter.reportOn(reportSource ?: declaration.source, FirJvmErrors.EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (declaration !is FirConstructor && declaration.body != null) {
|
||||||
|
reporter.reportOn(declaration.source, FirJvmErrors.EXTERNAL_DECLARATION_CANNOT_HAVE_BODY, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (declaration.isInline) {
|
||||||
|
reporter.reportOn(declaration.source, FirJvmErrors.EXTERNAL_DECLARATION_CANNOT_BE_INLINED, context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
@@ -13,6 +13,10 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.CONFLICTIN
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.DELEGATION_BY_IN_JVM_RECORD
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.DELEGATION_BY_IN_JVM_RECORD
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.DEPRECATED_JAVA_ANNOTATION
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.DEPRECATED_JAVA_ANNOTATION
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.ENUM_JVM_RECORD
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.ENUM_JVM_RECORD
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.EXTERNAL_DECLARATION_CANNOT_BE_INLINED
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.EXTERNAL_DECLARATION_CANNOT_HAVE_BODY
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.EXTERNAL_DECLARATION_IN_INTERFACE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.FIELD_IN_JVM_RECORD
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.FIELD_IN_JVM_RECORD
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.ILLEGAL_JAVA_LANG_RECORD_SUPERTYPE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.ILLEGAL_JAVA_LANG_RECORD_SUPERTYPE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.ILLEGAL_JVM_NAME
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.ILLEGAL_JVM_NAME
|
||||||
@@ -155,6 +159,11 @@ object FirJvmDefaultErrorMessages {
|
|||||||
NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT,
|
NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT,
|
||||||
"Non-@JvmDefault interface method cannot override default Java method. Please annotate this method with @JvmDefault or enable `-Xjvm-default=all|all-compatibility`"
|
"Non-@JvmDefault interface method cannot override default Java method. Please annotate this method with @JvmDefault or enable `-Xjvm-default=all|all-compatibility`"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
map.put(EXTERNAL_DECLARATION_IN_INTERFACE, "Members of interfaces can not be external")
|
||||||
|
map.put(EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT, "External declaration can not be abstract")
|
||||||
|
map.put(EXTERNAL_DECLARATION_CANNOT_HAVE_BODY, "External declaration can not have a body")
|
||||||
|
map.put(EXTERNAL_DECLARATION_CANNOT_BE_INLINED, "Inline functions can not be external")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
abstract class A {
|
|
||||||
abstract val x : Int
|
|
||||||
external get
|
|
||||||
}
|
|
||||||
|
|
||||||
interface B {
|
|
||||||
val x: Int
|
|
||||||
external get
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
abstract class A {
|
abstract class A {
|
||||||
<!EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT!>abstract<!> val x : Int
|
<!EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT!>abstract<!> val x : Int
|
||||||
external get
|
external get
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
import kotlin.jvm.*
|
|
||||||
|
|
||||||
abstract class C {
|
|
||||||
abstract external fun foo()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun test() {
|
|
||||||
abstract class Local {
|
|
||||||
abstract external fun foo()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
import kotlin.jvm.*
|
import kotlin.jvm.*
|
||||||
|
|
||||||
abstract class C {
|
abstract class C {
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
import kotlin.jvm.*
|
|
||||||
|
|
||||||
external fun foo() {}
|
|
||||||
|
|
||||||
class C {
|
|
||||||
external fun foo() {}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
external fun foo() {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object O {
|
|
||||||
external fun foo() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun test() {
|
|
||||||
class Local {
|
|
||||||
external fun foo() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
object {
|
|
||||||
external fun foo() {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
import kotlin.jvm.*
|
import kotlin.jvm.*
|
||||||
|
|
||||||
<!EXTERNAL_DECLARATION_CANNOT_HAVE_BODY!>external fun foo()<!> {}
|
<!EXTERNAL_DECLARATION_CANNOT_HAVE_BODY!>external fun foo()<!> {}
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
import kotlin.jvm.*
|
|
||||||
|
|
||||||
abstract class C {
|
|
||||||
<!NOTHING_TO_INLINE!>inline<!> external fun foo()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun test() {
|
|
||||||
abstract class Local {
|
|
||||||
<!NOTHING_TO_INLINE!>inline<!> external fun foo()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
import kotlin.jvm.*
|
import kotlin.jvm.*
|
||||||
|
|
||||||
abstract class C {
|
abstract class C {
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
import kotlin.jvm.*
|
|
||||||
|
|
||||||
external fun <<!REIFIED_TYPE_PARAMETER_NO_INLINE!>reified<!> T> foo()
|
|
||||||
inline external fun <reified T> bar()
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
import kotlin.jvm.*
|
import kotlin.jvm.*
|
||||||
|
|
||||||
external fun <<!REIFIED_TYPE_PARAMETER_NO_INLINE!>reified<!> T> foo()
|
external fun <<!REIFIED_TYPE_PARAMETER_NO_INLINE!>reified<!> T> foo()
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
import kotlin.jvm.*
|
|
||||||
|
|
||||||
interface Tr {
|
|
||||||
external fun foo()
|
|
||||||
external fun bar() {}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
external fun foo()
|
|
||||||
external fun bar() {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
import kotlin.jvm.*
|
import kotlin.jvm.*
|
||||||
|
|
||||||
interface Tr {
|
interface Tr {
|
||||||
|
|||||||
+24
@@ -3756,4 +3756,28 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirJvmErrors.EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT) { firDiagnostic ->
|
||||||
|
ExternalDeclarationCannotBeAbstractImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirJvmErrors.EXTERNAL_DECLARATION_CANNOT_HAVE_BODY) { firDiagnostic ->
|
||||||
|
ExternalDeclarationCannotHaveBodyImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirJvmErrors.EXTERNAL_DECLARATION_IN_INTERFACE) { firDiagnostic ->
|
||||||
|
ExternalDeclarationInInterfaceImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirJvmErrors.EXTERNAL_DECLARATION_CANNOT_BE_INLINED) { firDiagnostic ->
|
||||||
|
ExternalDeclarationCannotBeInlinedImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
@@ -2612,4 +2612,20 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = NonJvmDefaultOverridesJavaDefault::class
|
override val diagnosticClass get() = NonJvmDefaultOverridesJavaDefault::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class ExternalDeclarationCannotBeAbstract : KtFirDiagnostic<KtDeclaration>() {
|
||||||
|
override val diagnosticClass get() = ExternalDeclarationCannotBeAbstract::class
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ExternalDeclarationCannotHaveBody : KtFirDiagnostic<KtDeclaration>() {
|
||||||
|
override val diagnosticClass get() = ExternalDeclarationCannotHaveBody::class
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ExternalDeclarationInInterface : KtFirDiagnostic<KtDeclaration>() {
|
||||||
|
override val diagnosticClass get() = ExternalDeclarationInInterface::class
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ExternalDeclarationCannotBeInlined : KtFirDiagnostic<KtDeclaration>() {
|
||||||
|
override val diagnosticClass get() = ExternalDeclarationCannotBeInlined::class
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+28
@@ -4245,3 +4245,31 @@ internal class NonJvmDefaultOverridesJavaDefaultImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class ExternalDeclarationCannotBeAbstractImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.ExternalDeclarationCannotBeAbstract(), KtAbstractFirDiagnostic<KtDeclaration> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ExternalDeclarationCannotHaveBodyImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.ExternalDeclarationCannotHaveBody(), KtAbstractFirDiagnostic<KtDeclaration> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ExternalDeclarationInInterfaceImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.ExternalDeclarationInInterface(), KtAbstractFirDiagnostic<KtDeclaration> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ExternalDeclarationCannotBeInlinedImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.ExternalDeclarationCannotBeInlined(), KtAbstractFirDiagnostic<KtDeclaration> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user