Support platform/impl modifiers for properties
Do not allow platform properties to have backing fields, initializers, be delegated, lateinit or const, or have accessors with bodies
This commit is contained in:
@@ -494,6 +494,8 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtDeclaration> PLATFORM_DECLARATION_WITH_BODY = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<KtParameter> PLATFORM_DECLARATION_WITH_DEFAULT_PARAMETER = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<KtExpression> PLATFORM_PROPERTY_INITIALIZER = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Errors/warnings inside code blocks
|
||||
|
||||
+2
@@ -260,6 +260,8 @@ public class DefaultErrorMessages {
|
||||
MAP.put(PLATFORM_DECLARATION_WITH_BODY, "Platform declaration must not have a body");
|
||||
MAP.put(PLATFORM_DECLARATION_WITH_DEFAULT_PARAMETER, "Platform declaration cannot have parameters with default values");
|
||||
|
||||
MAP.put(PLATFORM_PROPERTY_INITIALIZER, "Platform property cannot have an initializer");
|
||||
|
||||
MAP.put(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, "Projections are not allowed on type arguments of functions and properties");
|
||||
MAP.put(SUPERTYPE_NOT_INITIALIZED, "This type has a constructor, and thus must be initialized here");
|
||||
MAP.put(NOTHING_TO_OVERRIDE, "''{0}'' overrides nothing", NAME);
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import com.google.common.collect.ImmutableSet
|
||||
import com.google.common.collect.Sets
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
@@ -650,17 +649,19 @@ class DeclarationsChecker(
|
||||
|
||||
val initializer = property.initializer
|
||||
val delegate = property.delegate
|
||||
val isPlatform = propertyDescriptor.isPlatform
|
||||
if (initializer != null) {
|
||||
if (inTrait) {
|
||||
trace.report(PROPERTY_INITIALIZER_IN_INTERFACE.on(initializer))
|
||||
}
|
||||
else {
|
||||
if (!backingFieldRequired) {
|
||||
trace.report(PROPERTY_INITIALIZER_NO_BACKING_FIELD.on(initializer))
|
||||
}
|
||||
else if (property.receiverTypeReference != null) {
|
||||
trace.report(EXTENSION_PROPERTY_WITH_BACKING_FIELD.on(initializer))
|
||||
}
|
||||
else if (isPlatform) {
|
||||
trace.report(PLATFORM_PROPERTY_INITIALIZER.on(initializer))
|
||||
}
|
||||
else if (!backingFieldRequired) {
|
||||
trace.report(PROPERTY_INITIALIZER_NO_BACKING_FIELD.on(initializer))
|
||||
}
|
||||
else if (property.receiverTypeReference != null) {
|
||||
trace.report(EXTENSION_PROPERTY_WITH_BACKING_FIELD.on(initializer))
|
||||
}
|
||||
}
|
||||
else if (delegate != null) {
|
||||
@@ -670,7 +671,7 @@ class DeclarationsChecker(
|
||||
}
|
||||
else {
|
||||
val isUninitialized = trace.bindingContext.get(BindingContext.IS_UNINITIALIZED, propertyDescriptor) ?: false
|
||||
if (backingFieldRequired && !inTrait && !propertyDescriptor.isLateInit && isUninitialized) {
|
||||
if (backingFieldRequired && !inTrait && !propertyDescriptor.isLateInit && !isPlatform && isUninitialized) {
|
||||
if (containingDeclaration !is ClassDescriptor || hasAccessorImplementation) {
|
||||
trace.report(MUST_BE_INITIALIZED.on(property))
|
||||
}
|
||||
@@ -681,11 +682,9 @@ class DeclarationsChecker(
|
||||
else if (noExplicitTypeOrGetterType(property)) {
|
||||
trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property))
|
||||
}
|
||||
if (backingFieldRequired && !inTrait && propertyDescriptor.isLateInit && !isUninitialized) {
|
||||
if (trace[MUST_BE_LATEINIT, propertyDescriptor] ?: false) {}
|
||||
else {
|
||||
trace.report(UNNECESSARY_LATEINIT.on(property))
|
||||
}
|
||||
if (backingFieldRequired && !inTrait && propertyDescriptor.isLateInit && !isUninitialized &&
|
||||
trace[MUST_BE_LATEINIT, propertyDescriptor] != true) {
|
||||
trace.report(UNNECESSARY_LATEINIT.on(property))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -800,11 +799,18 @@ class DeclarationsChecker(
|
||||
private fun checkAccessor(
|
||||
propertyDescriptor: PropertyDescriptor,
|
||||
accessor: KtPropertyAccessor?,
|
||||
accessorDescriptor: PropertyAccessorDescriptor?) {
|
||||
accessorDescriptor: PropertyAccessorDescriptor?
|
||||
) {
|
||||
if (accessor == null || accessorDescriptor == null) return
|
||||
if (propertyDescriptor.isPlatform && accessor.hasBody()) {
|
||||
trace.report(PLATFORM_DECLARATION_WITH_BODY.on(accessor))
|
||||
}
|
||||
|
||||
val accessorModifierList = accessor.modifierList ?: return
|
||||
val tokens = modifiersChecker.getTokensCorrespondingToModifiers(accessorModifierList,
|
||||
Sets.newHashSet(KtTokens.PUBLIC_KEYWORD, KtTokens.PROTECTED_KEYWORD, KtTokens.PRIVATE_KEYWORD, KtTokens.INTERNAL_KEYWORD))
|
||||
val tokens = modifiersChecker.getTokensCorrespondingToModifiers(
|
||||
accessorModifierList,
|
||||
setOf(KtTokens.PUBLIC_KEYWORD, KtTokens.PROTECTED_KEYWORD, KtTokens.PRIVATE_KEYWORD, KtTokens.INTERNAL_KEYWORD)
|
||||
)
|
||||
if (accessor.isGetter) {
|
||||
if (accessorDescriptor.visibility != propertyDescriptor.visibility) {
|
||||
reportVisibilityModifierDiagnostics(tokens.values, Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY)
|
||||
|
||||
@@ -808,7 +808,10 @@ public class DescriptorResolver {
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
KotlinSourceElementKt.toSourceElement(property),
|
||||
modifierList != null && modifierList.hasModifier(KtTokens.LATEINIT_KEYWORD),
|
||||
modifierList != null && modifierList.hasModifier(KtTokens.CONST_KEYWORD)
|
||||
modifierList != null && modifierList.hasModifier(KtTokens.CONST_KEYWORD),
|
||||
modifierList != null && modifierList.hasModifier(KtTokens.PLATFORM_KEYWORD) ||
|
||||
containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).isPlatform(),
|
||||
modifierList != null && modifierList.hasModifier(KtTokens.IMPL_KEYWORD)
|
||||
);
|
||||
wrapper.setDescriptor(propertyDescriptor);
|
||||
|
||||
@@ -1123,7 +1126,9 @@ public class DescriptorResolver {
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
KotlinSourceElementKt.toSourceElement(parameter),
|
||||
/* lateInit = */ false,
|
||||
/* isConst = */ false
|
||||
/* isConst = */ false,
|
||||
/* isPlatform = */ false,
|
||||
/* isImpl = */ false
|
||||
);
|
||||
propertyWrapper.setDescriptor(propertyDescriptor);
|
||||
propertyDescriptor.setType(type, Collections.<TypeParameterDescriptor>emptyList(),
|
||||
|
||||
@@ -85,14 +85,14 @@ class LocalVariableResolver(
|
||||
propertyDescriptor,
|
||||
delegateExpression,
|
||||
typingContext.scope,
|
||||
typingContext.trace);
|
||||
typingContext.trace)
|
||||
}
|
||||
}
|
||||
|
||||
val initializer = property.initializer
|
||||
var typeInfo: KotlinTypeInfo
|
||||
if (initializer != null) {
|
||||
val outType = propertyDescriptor.getType()
|
||||
val outType = propertyDescriptor.type
|
||||
typeInfo = facade.getTypeInfo(initializer, context.replaceExpectedType(outType))
|
||||
val dataFlowInfo = typeInfo.dataFlowInfo
|
||||
val type = typeInfo.type
|
||||
@@ -146,7 +146,9 @@ class LocalVariableResolver(
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
variable.toSourceElement(),
|
||||
/* lateInit = */ false,
|
||||
/* isConst = */ false
|
||||
/* isConst = */ false,
|
||||
/* isPlatform = */ false,
|
||||
/* isImpl = */ false
|
||||
)
|
||||
// For a local variable the type must not be deferred
|
||||
type = variableTypeAndInitializerResolver.resolveType(propertyDescriptor, scope, variable, dataFlowInfo, trace, local = true)
|
||||
|
||||
@@ -90,8 +90,8 @@ object ModifierCheckerCore {
|
||||
CONST_KEYWORD to EnumSet.of(MEMBER_PROPERTY, TOP_LEVEL_PROPERTY),
|
||||
OPERATOR_KEYWORD to EnumSet.of(FUNCTION),
|
||||
INFIX_KEYWORD to EnumSet.of(FUNCTION),
|
||||
PLATFORM_KEYWORD to EnumSet.of(FUNCTION, CLASS_ONLY, OBJECT, INTERFACE, INNER_CLASS, ENUM_CLASS, ANNOTATION_CLASS), // TODO
|
||||
IMPL_KEYWORD to EnumSet.of(FUNCTION, CLASS_ONLY, OBJECT, INTERFACE, INNER_CLASS, ENUM_CLASS, ANNOTATION_CLASS) // TODO
|
||||
PLATFORM_KEYWORD to EnumSet.of(FUNCTION, TOP_LEVEL_PROPERTY_WITHOUT_FIELD_OR_DELEGATE, CLASS_ONLY, OBJECT, INTERFACE, INNER_CLASS, ENUM_CLASS, ANNOTATION_CLASS), // TODO
|
||||
IMPL_KEYWORD to EnumSet.of(FUNCTION, TOP_LEVEL_PROPERTY_WITHOUT_FIELD_OR_DELEGATE, CLASS_ONLY, OBJECT, INTERFACE, INNER_CLASS, ENUM_CLASS, ANNOTATION_CLASS) // TODO
|
||||
)
|
||||
|
||||
val featureDependencies = mapOf(
|
||||
|
||||
@@ -97,7 +97,9 @@ class DynamicCallableDescriptors(storageManager: StorageManager, builtIns: Kotli
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
SourceElement.NO_SOURCE,
|
||||
/* lateInit = */ false,
|
||||
/* isConst = */ false
|
||||
/* isConst = */ false,
|
||||
/* isPlatform = */ false,
|
||||
/* isImpl = */ false
|
||||
)
|
||||
propertyDescriptor.setType(
|
||||
dynamicType,
|
||||
|
||||
Reference in New Issue
Block a user