Support platform/impl modifiers for classes
Do not report "unused parameter" for parameters of platform declarations. Do not allow platform class constructors to have val/var parameters or have an explicit delegation call to another constructor. Do not allow platform classes to have 'init' blocks. Also suppress the "supertype not initialized" error for platform classes: the supertype should be initialized in the impl class
This commit is contained in:
@@ -636,9 +636,8 @@ class ControlFlowInformationProvider private constructor(
|
||||
when (owner) {
|
||||
is KtPrimaryConstructor -> if (!element.hasValOrVar()) {
|
||||
val containingClass = owner.getContainingClassOrObject()
|
||||
val containingClassDescriptor = trace.get(
|
||||
DECLARATION_TO_DESCRIPTOR, containingClass)
|
||||
if (!DescriptorUtils.isAnnotationClass(containingClassDescriptor)) {
|
||||
val containingClassDescriptor = trace.get(DECLARATION_TO_DESCRIPTOR, containingClass) as? ClassDescriptor
|
||||
if (!DescriptorUtils.isAnnotationClass(containingClassDescriptor) && containingClassDescriptor?.isPlatform == false) {
|
||||
report(UNUSED_PARAMETER.on(element, variableDescriptor), ctxt)
|
||||
}
|
||||
}
|
||||
@@ -652,6 +651,7 @@ class ControlFlowInformationProvider private constructor(
|
||||
if (isMain
|
||||
|| functionDescriptor.isOverridableOrOverrides
|
||||
|| owner.hasModifier(KtTokens.OVERRIDE_KEYWORD)
|
||||
|| functionDescriptor.isPlatform || functionDescriptor.isImpl
|
||||
|| OperatorNameConventions.GET_VALUE == functionName
|
||||
|| OperatorNameConventions.SET_VALUE == functionName
|
||||
|| OperatorNameConventions.PROPERTY_DELEGATED == functionName) {
|
||||
|
||||
@@ -493,7 +493,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<KtConstructorDelegationCall> PLATFORM_CLASS_CONSTRUCTOR_DELEGATION_CALL = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtParameter> PLATFORM_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> PLATFORM_PROPERTY_INITIALIZER = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+2
-1
@@ -259,7 +259,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_CLASS_CONSTRUCTOR_DELEGATION_CALL, "Explicit delegation call for constructor of a platform class is not allowed");
|
||||
MAP.put(PLATFORM_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER, "Platform class constructor cannot have a property parameter");
|
||||
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");
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.lang.ASTNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.KtNodeTypes;
|
||||
import org.jetbrains.kotlin.parsing.KotlinParsing;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -65,6 +66,14 @@ public class KtConstructorDelegationCall extends KtElementImpl implements KtCall
|
||||
return findChildByClass(KtConstructorDelegationReferenceExpression.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this delegation call is not present in the source code. Note that we always parse delegation calls
|
||||
* for secondary constructors, even if there's no explicit call in the source (see {@link KotlinParsing#parseSecondaryConstructor}).
|
||||
*
|
||||
* class Foo {
|
||||
* constructor(name: String) // <--- implicit constructor delegation call (empty element after RPAR)
|
||||
* }
|
||||
*/
|
||||
public boolean isImplicit() {
|
||||
KtConstructorDelegationReferenceExpression callee = getCalleeExpression();
|
||||
return callee != null && callee.getFirstChild() == null;
|
||||
|
||||
@@ -169,6 +169,11 @@ public class BodyResolver {
|
||||
@NotNull KtSecondaryConstructor constructor,
|
||||
@NotNull ClassConstructorDescriptor descriptor
|
||||
) {
|
||||
if (descriptor.isPlatform()) {
|
||||
// For platform classes, we do not resolve constructor delegation calls because they are prohibited
|
||||
return DataFlowInfo.Companion.getEMPTY();
|
||||
}
|
||||
|
||||
OverloadResolutionResults<?> results = callResolver.resolveConstructorDelegationCall(
|
||||
trace, scope, outerDataFlowInfo,
|
||||
descriptor, constructor.getDelegationCall());
|
||||
@@ -362,6 +367,7 @@ public class BodyResolver {
|
||||
descriptor.getUnsubstitutedPrimaryConstructor() != null &&
|
||||
superClass.getKind() != ClassKind.INTERFACE &&
|
||||
!superClass.getConstructors().isEmpty() &&
|
||||
!descriptor.isPlatform() &&
|
||||
!ErrorUtils.isError(superClass)
|
||||
) {
|
||||
trace.report(SUPERTYPE_NOT_INITIALIZED.on(specifier));
|
||||
@@ -556,6 +562,9 @@ public class BodyResolver {
|
||||
if (classDescriptor.getConstructors().isEmpty()) {
|
||||
trace.report(ANONYMOUS_INITIALIZER_IN_INTERFACE.on(anonymousInitializer));
|
||||
}
|
||||
if (classDescriptor.isPlatform()) {
|
||||
trace.report(PLATFORM_DECLARATION_WITH_BODY.on(anonymousInitializer));
|
||||
}
|
||||
}
|
||||
|
||||
private void processModifiersOnInitializer(@NotNull KtModifierListOwner owner, @NotNull LexicalScope scope) {
|
||||
|
||||
@@ -228,12 +228,36 @@ class DeclarationsChecker(
|
||||
TypeAliasExpander(reportStrategy).expandWithoutAbbreviation(typeAliasExpansion, Annotations.EMPTY)
|
||||
}
|
||||
|
||||
private fun checkConstructorDeclaration(constructorDescriptor: ClassConstructorDescriptor, declaration: KtDeclaration) {
|
||||
private fun checkConstructorDeclaration(constructorDescriptor: ClassConstructorDescriptor, declaration: KtConstructor<*>) {
|
||||
declaration.checkTypeReferences()
|
||||
modifiersChecker.checkModifiersForDeclaration(declaration, constructorDescriptor)
|
||||
identifierChecker.checkDeclaration(declaration, trace)
|
||||
checkVarargParameters(trace, constructorDescriptor)
|
||||
checkConstructorVisibility(constructorDescriptor, declaration)
|
||||
checkPlatformClassConstructor(constructorDescriptor, declaration)
|
||||
}
|
||||
|
||||
private fun checkPlatformClassConstructor(constructorDescriptor: ClassConstructorDescriptor, declaration: KtConstructor<*>) {
|
||||
if (!constructorDescriptor.isPlatform) return
|
||||
|
||||
if (declaration.hasBody()) {
|
||||
trace.report(PLATFORM_DECLARATION_WITH_BODY.on(declaration))
|
||||
}
|
||||
|
||||
if (declaration is KtPrimaryConstructor && !DescriptorUtils.isAnnotationClass(constructorDescriptor.constructedClass)) {
|
||||
for (parameter in declaration.valueParameters) {
|
||||
if (parameter.hasValOrVar()) {
|
||||
trace.report(PLATFORM_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER.on(parameter))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (declaration is KtSecondaryConstructor) {
|
||||
val delegationCall = declaration.getDelegationCall()
|
||||
if (!delegationCall.isImplicit) {
|
||||
trace.report(PLATFORM_CLASS_CONSTRUCTOR_DELEGATION_CALL.on(delegationCall))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkConstructorVisibility(constructorDescriptor: ClassConstructorDescriptor, declaration: KtDeclaration) {
|
||||
@@ -711,6 +735,7 @@ class DeclarationsChecker(
|
||||
|
||||
if (containingDescriptor is ClassDescriptor) {
|
||||
val inInterface = containingDescriptor.kind == ClassKind.INTERFACE
|
||||
val isPlatformClass = containingDescriptor.isPlatform
|
||||
if (hasAbstractModifier && !classCanHaveAbstractMembers(containingDescriptor)) {
|
||||
trace.report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(function, functionDescriptor.name.asString(), containingDescriptor))
|
||||
}
|
||||
@@ -726,7 +751,7 @@ class DeclarationsChecker(
|
||||
trace.report(REDUNDANT_OPEN_IN_INTERFACE.on(function))
|
||||
}
|
||||
}
|
||||
if (!hasBody && !hasAbstractModifier && !hasExternalModifier && !inInterface) {
|
||||
if (!hasBody && !hasAbstractModifier && !hasExternalModifier && !inInterface && !isPlatformClass) {
|
||||
trace.report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user