diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmCheckerProvider.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmCheckerProvider.kt index 35b6fe8c2f4..a2088456c69 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmCheckerProvider.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmCheckerProvider.kt @@ -26,10 +26,8 @@ import org.jetbrains.kotlin.load.java.lazy.types.isMarkedNullable import org.jetbrains.kotlin.load.kotlin.nativeDeclarations.NativeFunChecker import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.AdditionalCheckerProvider -import org.jetbrains.kotlin.resolve.DeclarationChecker -import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils -import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.* +import org.jetbrains.kotlin.resolve.annotations.findPublicFieldAnnotation import org.jetbrains.kotlin.resolve.annotations.hasInlineAnnotation import org.jetbrains.kotlin.resolve.annotations.hasIntrinsicAnnotation import org.jetbrains.kotlin.resolve.annotations.hasPlatformStaticAnnotation @@ -57,7 +55,8 @@ public class KotlinJvmCheckerProvider(private val module: ModuleDescriptor) : Ad LocalFunInlineChecker(), ReifiedTypeParameterAnnotationChecker(), NativeFunChecker(), - OverloadsAnnotationChecker()), + OverloadsAnnotationChecker(), + PublicFieldAnnotationChecker()), additionalCallCheckers = listOf(NeedSyntheticChecker(), JavaAnnotationCallChecker(), JavaAnnotationMethodCallChecker(), TraitDefaultMethodCallChecker()), @@ -68,7 +67,11 @@ public class KotlinJvmCheckerProvider(private val module: ModuleDescriptor) : Ad public class LocalFunInlineChecker : DeclarationChecker { - override fun check(declaration: JetDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink) { + override fun check( + declaration: JetDeclaration, + descriptor: DeclarationDescriptor, + diagnosticHolder: DiagnosticSink, + bindingContext: BindingContext) { if (descriptor.hasInlineAnnotation() && declaration is JetNamedFunction && descriptor is FunctionDescriptor && @@ -80,7 +83,12 @@ public class LocalFunInlineChecker : DeclarationChecker { public class PlatformStaticAnnotationChecker : DeclarationChecker { - override fun check(declaration: JetDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink) { + override fun check( + declaration: JetDeclaration, + descriptor: DeclarationDescriptor, + diagnosticHolder: DiagnosticSink, + bindingContext: BindingContext + ) { if (descriptor.hasPlatformStaticAnnotation()) { if (declaration is JetNamedFunction || declaration is JetProperty || declaration is JetPropertyAccessor) { checkDeclaration(declaration, descriptor, diagnosticHolder) @@ -119,7 +127,12 @@ public class PlatformStaticAnnotationChecker : DeclarationChecker { } public class OverloadsAnnotationChecker: DeclarationChecker { - override fun check(declaration: JetDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink) { + override fun check( + declaration: JetDeclaration, + descriptor: DeclarationDescriptor, + diagnosticHolder: DiagnosticSink, + bindingContext: BindingContext + ) { if (descriptor.getAnnotations().findAnnotation(FqName("kotlin.jvm.jvmOverloads")) != null) { checkDeclaration(declaration, descriptor, diagnosticHolder) } @@ -142,9 +155,37 @@ public class OverloadsAnnotationChecker: DeclarationChecker { } } +public class PublicFieldAnnotationChecker: DeclarationChecker { + override fun check( + declaration: JetDeclaration, + descriptor: DeclarationDescriptor, + diagnosticHolder: DiagnosticSink, + bindingContext: BindingContext + ) { + val annotation = descriptor.findPublicFieldAnnotation() ?: return + + fun report() { + val annotationEntry = bindingContext.get(BindingContext.ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT, annotation) ?: return + diagnosticHolder.report(ErrorsJvm.INAPPLICABLE_PUBLIC_FIELD.on(annotationEntry)) + } + + if (descriptor !is PropertyDescriptor) { + report() + } + else if (!bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor)) { + report() + } + } +} + public class ReifiedTypeParameterAnnotationChecker : DeclarationChecker { - override fun check(declaration: JetDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink) { + override fun check( + declaration: JetDeclaration, + descriptor: DeclarationDescriptor, + diagnosticHolder: DiagnosticSink, + bindingContext: BindingContext + ) { if (descriptor.hasIntrinsicAnnotation()) return if (descriptor is CallableDescriptor && !descriptor.hasInlineAnnotation()) { diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/native.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/native.kt index 38b2d42bd8a..0a71b4aa01e 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/native.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/native.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm import org.jetbrains.kotlin.psi.JetDeclarationWithBody +import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.annotations.hasInlineAnnotation import org.jetbrains.kotlin.resolve.diagnostics.SuppressDiagnosticsByAnnotations import org.jetbrains.kotlin.resolve.diagnostics.FUNCTION_NO_BODY_ERRORS @@ -41,7 +42,12 @@ public fun DeclarationDescriptor.hasNativeAnnotation(): Boolean { public class SuppressNoBodyErrorsForNativeDeclarations : SuppressDiagnosticsByAnnotations(FUNCTION_NO_BODY_ERRORS, NATIVE_ANNOTATION_CLASS_NAME) public class NativeFunChecker : DeclarationChecker { - override fun check(declaration: JetDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink) { + override fun check( + declaration: JetDeclaration, + descriptor: DeclarationDescriptor, + diagnosticHolder: DiagnosticSink, + bindingContext: BindingContext + ) { if (!descriptor.hasNativeAnnotation()) return if (DescriptorUtils.isTrait(descriptor.getContainingDeclaration())) { diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java index 8a96d821c42..3f3c39dd126 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java @@ -68,6 +68,8 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension { MAP.put(ErrorsJvm.TRAIT_CANT_CALL_DEFAULT_METHOD_VIA_SUPER, "Interfaces can't call Java default methods via super"); MAP.put(ErrorsJvm.WHEN_ENUM_CAN_BE_NULL_IN_JAVA, "Enum argument can be null in Java, but exhaustive when contains no null branch"); + + MAP.put(ErrorsJvm.INAPPLICABLE_PUBLIC_FIELD, "publicField annotation is not applicable to this declaration"); } @NotNull diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java index 3e16df39687..9fddc2d9a71 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java @@ -56,6 +56,8 @@ public interface ErrorsJvm { DiagnosticFactory0 TRAIT_CANT_CALL_DEFAULT_METHOD_VIA_SUPER = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 INAPPLICABLE_PUBLIC_FIELD = DiagnosticFactory0.create(ERROR); + // TODO: make this a warning DiagnosticFactory1 NO_REFLECTION_IN_CLASS_PATH = DiagnosticFactory1.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 7a440bd1f1e..078556686d8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -114,7 +114,6 @@ public interface Errors { DiagnosticFactory2 REDUNDANT_MODIFIER = DiagnosticFactory2.create(WARNING); DiagnosticFactory0 INAPPLICABLE_ANNOTATION = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 INAPPLICABLE_PLATFORM_NAME = DiagnosticFactory0.create(ERROR); - DiagnosticFactory0 INAPPLICABLE_PUBLIC_FIELD = DiagnosticFactory0.create(ERROR); // Annotations diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 587e4c7f0ec..5eed0c12740 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -137,7 +137,6 @@ public class DefaultErrorMessages { MAP.put(REPEATED_MODIFIER, "Repeated ''{0}''", TO_STRING); MAP.put(INAPPLICABLE_ANNOTATION, "This annotation is only applicable to top level functions"); MAP.put(INAPPLICABLE_PLATFORM_NAME, "platformName annotation is not applicable to this declaration"); - MAP.put(INAPPLICABLE_PUBLIC_FIELD, "publicField annotation is not applicable to this declaration"); MAP.put(REDUNDANT_MODIFIER, "Modifier ''{0}'' is redundant because ''{1}'' is present", TO_STRING, TO_STRING); MAP.put(ABSTRACT_MODIFIER_IN_TRAIT, "Modifier ''abstract'' is redundant in interface"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DataClassAnnotationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DataClassAnnotationChecker.kt index 6815253427e..68e44ff29c3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DataClassAnnotationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DataClassAnnotationChecker.kt @@ -23,7 +23,12 @@ import org.jetbrains.kotlin.builtins.* public class DataClassAnnotationChecker : DeclarationChecker { - override fun check(declaration: JetDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink) { + override fun check( + declaration: JetDeclaration, + descriptor: DeclarationDescriptor, + diagnosticHolder: DiagnosticSink, + bindingContext: BindingContext + ) { if (descriptor !is ClassDescriptor) return if (declaration !is JetClassOrObject) return diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationChecker.kt index 47c9cb1e1f5..897ea5c6126 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationChecker.kt @@ -20,8 +20,12 @@ import org.jetbrains.kotlin.psi.JetDeclaration import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -public trait DeclarationChecker { +public interface DeclarationChecker { - public fun check(declaration: JetDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink); + public fun check( + declaration: JetDeclaration, + descriptor: DeclarationDescriptor, + diagnosticHolder: DiagnosticSink, + bindingContext: BindingContext); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java index dd667a41bbc..bea60497b7c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java @@ -32,7 +32,6 @@ import org.jetbrains.kotlin.lexer.JetTokens; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; -import org.jetbrains.kotlin.resolve.annotations.AnnotationsPackage; import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant; import org.jetbrains.kotlin.resolve.constants.StringValue; @@ -150,7 +149,6 @@ public class ModifiersChecker { checkVarargsModifiers(modifierListOwner, descriptor); } checkPlatformNameApplicability(descriptor); - checkPublicFieldApplicability(descriptor); runDeclarationCheckers(modifierListOwner, descriptor); } @@ -164,7 +162,6 @@ public class ModifiersChecker { reportIllegalModalityModifiers(modifierListOwner); reportIllegalVisibilityModifiers(modifierListOwner); checkPlatformNameApplicability(descriptor); - checkPublicFieldApplicability(descriptor); runDeclarationCheckers(modifierListOwner, descriptor); } @@ -323,24 +320,6 @@ public class ModifiersChecker { } - private void checkPublicFieldApplicability(@NotNull DeclarationDescriptor descriptor) { - AnnotationDescriptor annotation = AnnotationsPackage.findPublicFieldAnnotation(descriptor); - if (annotation == null) return; - - JetAnnotationEntry annotationEntry = trace.get(BindingContext.ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT, annotation); - if (annotationEntry == null) return; - - if (!(descriptor instanceof PropertyDescriptor)) { - trace.report(INAPPLICABLE_PUBLIC_FIELD.on(annotationEntry)); - return; - } - - PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; - if (Boolean.FALSE.equals(trace.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor))) { - trace.report(INAPPLICABLE_PUBLIC_FIELD.on(annotationEntry)); - } - } - private static boolean isRenamableDeclaration(@NotNull DeclarationDescriptor descriptor) { DeclarationDescriptor containingDescriptor = descriptor.getContainingDeclaration(); @@ -442,7 +421,7 @@ public class ModifiersChecker { private void runDeclarationCheckers(@NotNull JetDeclaration declaration, @NotNull DeclarationDescriptor descriptor) { for (DeclarationChecker checker : additionalCheckerProvider.getDeclarationCheckers()) { - checker.check(declaration, descriptor, trace); + checker.check(declaration, descriptor, trace, trace.getBindingContext()); } } diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/nativeAnnotationCheckers.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/nativeAnnotationCheckers.kt index fdebcbd3f77..dff2309a3a7 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/nativeAnnotationCheckers.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/nativeAnnotationCheckers.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.js.resolve.diagnostics.ErrorsJs import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils import org.jetbrains.kotlin.psi.JetDeclaration import org.jetbrains.kotlin.psi.JetNamedFunction +import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DeclarationChecker import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.types.TypeUtils @@ -35,9 +36,13 @@ private abstract class AbstractNativeAnnotationsChecker(private val requiredAnno open fun additionalCheck(declaration: JetNamedFunction, descriptor: FunctionDescriptor, diagnosticHolder: DiagnosticSink) {} - override fun check(declaration: JetDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink) { - val annotationDescriptor = descriptor.getAnnotations().findAnnotation(requiredAnnotation.fqName) - if (annotationDescriptor == null) return + override fun check( + declaration: JetDeclaration, + descriptor: DeclarationDescriptor, + diagnosticHolder: DiagnosticSink, + bindingContext: BindingContext + ) { + val annotationDescriptor = descriptor.getAnnotations().findAnnotation(requiredAnnotation.fqName) ?: return if (declaration !is JetNamedFunction || descriptor !is FunctionDescriptor) { diagnosticHolder.report(ErrorsJs.NATIVE_ANNOTATIONS_ALLOWED_ONLY_ON_MEMBER_OR_EXTENSION_FUN.on(declaration, annotationDescriptor.getType())) diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/unsupportedFeatureCheckers.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/unsupportedFeatureCheckers.kt index 8ac9a876d8a..dcefa7fd311 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/unsupportedFeatureCheckers.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/unsupportedFeatureCheckers.kt @@ -26,12 +26,17 @@ import org.jetbrains.kotlin.diagnostics.rendering.renderKindWithName import org.jetbrains.kotlin.js.resolve.diagnostics.ErrorsJs import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DeclarationChecker import org.jetbrains.kotlin.resolve.DescriptorUtils class ClassDeclarationChecker : DeclarationChecker { - override fun check(declaration: JetDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink) { - + override fun check( + declaration: JetDeclaration, + descriptor: DeclarationDescriptor, + diagnosticHolder: DiagnosticSink, + bindingContext: BindingContext + ) { if (declaration !is JetClassOrObject || declaration is JetObjectDeclaration || declaration is JetEnumEntry) return // hack to avoid to get diagnostics when compile kotlin builtins