JVM: produce a better error on @JvmStatic external in interface

Java does not permit `static native` methods in interfaces, so this
never worked on any existing JRE.

 #KT-43696 Fixed
This commit is contained in:
pyos
2021-07-14 12:07:36 +02:00
committed by Alexander Udalov
parent ad7ed483f3
commit f5dd5ead1f
12 changed files with 55 additions and 3 deletions
@@ -90,7 +90,7 @@ class JvmStaticChecker(jvmTarget: JvmTarget, languageVersionSettings: LanguageVe
supportJvmStaticInInterface &&
descriptor is DeclarationDescriptorWithVisibility
) {
checkVisibility(descriptor, diagnosticHolder, declaration)
checkForInterface(descriptor, diagnosticHolder, declaration)
if (isLessJVM18) {
diagnosticHolder.report(ErrorsJvm.JVM_STATIC_IN_INTERFACE_1_6.on(declaration))
}
@@ -116,15 +116,18 @@ class JvmStaticChecker(jvmTarget: JvmTarget, languageVersionSettings: LanguageVe
}
}
private fun checkVisibility(
private fun checkForInterface(
descriptor: DeclarationDescriptorWithVisibility,
diagnosticHolder: DiagnosticSink,
declaration: KtDeclaration
) {
if (descriptor.visibility != DescriptorVisibilities.PUBLIC) {
diagnosticHolder.report(ErrorsJvm.JVM_STATIC_ON_NON_PUBLIC_MEMBER.on(declaration))
} else if (descriptor is MemberDescriptor && descriptor.isExternal) {
diagnosticHolder.report(ErrorsJvm.JVM_STATIC_ON_EXTERNAL_IN_INTERFACE.on(declaration))
} else if (descriptor is PropertyDescriptor) {
descriptor.setter?.let { checkVisibility(it, diagnosticHolder, declaration) }
descriptor.getter?.let { checkForInterface(it, diagnosticHolder, declaration) }
descriptor.setter?.let { checkForInterface(it, diagnosticHolder, declaration) }
}
}
}
@@ -45,6 +45,7 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
MAP.put(JVM_STATIC_ON_NON_PUBLIC_MEMBER, "Only public members in interface companion objects can be annotated with '@JvmStatic'");
MAP.put(JVM_STATIC_IN_INTERFACE_1_6, "'@JvmStatic' annotation in interface supported only with JVM target 1.8 and above. Recompile with '-jvm-target 1.8'\"");
MAP.put(JVM_STATIC_ON_CONST_OR_JVM_FIELD, "'@JvmStatic' annotation is useless for const or '@JvmField' properties");
MAP.put(JVM_STATIC_ON_EXTERNAL_IN_INTERFACE, "'@JvmStatic' annotation cannot be used on 'external' members of interface companions");
MAP.put(OVERRIDE_CANNOT_BE_STATIC, "Override member cannot be '@JvmStatic' in object");
MAP.put(OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS, "'@JvmOverloads' annotation has no effect for methods without default arguments");
MAP.put(OVERLOADS_ABSTRACT, "'@JvmOverloads' annotation cannot be used on abstract methods");
@@ -34,6 +34,7 @@ public interface ErrorsJvm {
DiagnosticFactory0<KtDeclaration> JVM_STATIC_ON_NON_PUBLIC_MEMBER = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
DiagnosticFactory0<KtDeclaration> JVM_STATIC_IN_INTERFACE_1_6 = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
DiagnosticFactory0<KtDeclaration> JVM_STATIC_ON_CONST_OR_JVM_FIELD = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
DiagnosticFactory0<KtDeclaration> JVM_STATIC_ON_EXTERNAL_IN_INTERFACE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
DiagnosticFactory0<PsiElement> INAPPLICABLE_JVM_NAME = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtAnnotationEntry> ILLEGAL_JVM_NAME = DiagnosticFactory0.create(ERROR);