From a7ce770cb40ceb82434b6a2226472fe09b5fbbe1 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Fri, 25 Nov 2016 12:59:29 +0300 Subject: [PATCH] Don't report error for properties and functions without body that either `external` by themselves or are members of `external` classes --- .../jetbrains/kotlin/resolve/DeclarationsChecker.kt | 6 ++++-- .../jetbrains/kotlin/resolve/DescriptorUtils.java | 12 ++++++++++++ .../kotlin/js/translate/utils/AnnotationsUtils.java | 5 +---- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt index dbd8089df55..3b87e824c1d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors.* import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject import org.jetbrains.kotlin.psi.psiUtil.visibilityModifier import org.jetbrains.kotlin.resolve.BindingContext.* import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractMembers @@ -724,7 +725,8 @@ class DeclarationsChecker( } else { val isUninitialized = trace.bindingContext.get(BindingContext.IS_UNINITIALIZED, propertyDescriptor) ?: false - if (backingFieldRequired && !inTrait && !propertyDescriptor.isLateInit && !isPlatform && isUninitialized) { + val isExternal = DescriptorUtils.isEffectivelyExternal(propertyDescriptor) + if (backingFieldRequired && !inTrait && !propertyDescriptor.isLateInit && !isPlatform && isUninitialized && !isExternal) { if (containingDeclaration !is ClassDescriptor || hasAccessorImplementation) { trace.report(MUST_BE_INITIALIZED.on(property)) } @@ -760,7 +762,7 @@ class DeclarationsChecker( val containingDescriptor = functionDescriptor.containingDeclaration val hasAbstractModifier = function.hasModifier(KtTokens.ABSTRACT_KEYWORD) - val hasExternalModifier = function.hasModifier(KtTokens.EXTERNAL_KEYWORD) + val hasExternalModifier = DescriptorUtils.isEffectivelyExternal(functionDescriptor) if (containingDescriptor is ClassDescriptor) { val inInterface = containingDescriptor.kind == ClassKind.INTERFACE diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java index 017a42fba5b..f1066e39366 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java @@ -575,4 +575,16 @@ public class DescriptorUtils { public static Collection getAllDescriptors(@NotNull MemberScope scope) { return scope.getContributedDescriptors(DescriptorKindFilter.ALL, MemberScope.Companion.getALL_NAME_FILTER()); } + + public static boolean isEffectivelyExternal(@NotNull MemberDescriptor descriptor) { + if (descriptor.isExternal()) return true; + + if (descriptor instanceof PropertyAccessorDescriptor) { + PropertyDescriptor variableDescriptor = ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty(); + if (isEffectivelyExternal(variableDescriptor)) return true; + } + + ClassDescriptor containingClass = getContainingClass(descriptor); + return containingClass != null && isEffectivelyExternal(containingClass); + } } diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/translate/utils/AnnotationsUtils.java b/js/js.frontend/src/org/jetbrains/kotlin/js/translate/utils/AnnotationsUtils.java index c03e7cedd27..0896f485e92 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/translate/utils/AnnotationsUtils.java +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/translate/utils/AnnotationsUtils.java @@ -133,10 +133,7 @@ public final class AnnotationsUtils { } private static boolean isEffectivelyExternal(@NotNull DeclarationDescriptor descriptor) { - if (descriptor instanceof MemberDescriptor && ((MemberDescriptor) descriptor).isExternal()) return true; - - ClassDescriptor containingClass = DescriptorUtils.getContainingClass(descriptor); - return containingClass != null && isEffectivelyExternal(containingClass); + return descriptor instanceof MemberDescriptor && DescriptorUtils.isEffectivelyExternal((MemberDescriptor) descriptor); } public static boolean isLibraryObject(@NotNull DeclarationDescriptor descriptor) {