From 751949db691c14771f04c33f8e7242959688f26a Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 28 Oct 2016 11:22:35 +0300 Subject: [PATCH] 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 --- .../cfg/ControlFlowInformationProvider.kt | 6 +- .../jetbrains/kotlin/diagnostics/Errors.java | 3 +- .../rendering/DefaultErrorMessages.java | 3 +- .../psi/KtConstructorDelegationCall.java | 9 ++ .../kotlin/resolve/BodyResolver.java | 9 ++ .../kotlin/resolve/DeclarationsChecker.kt | 29 +++++- .../multiplatform/platformClass/classKinds.kt | 26 +++++ .../platformClass/classKinds.txt | 98 +++++++++++++++++++ .../explicitConstructorDelegation.kt | 14 +++ .../explicitConstructorDelegation.txt | 17 ++++ .../platformClass/platformClassMember.kt | 24 +++++ .../platformClass/platformClassMember.txt | 37 +++++++ .../platformClassWithFunctionBody.kt | 29 ++++++ .../platformClassWithFunctionBody.txt | 15 +++ .../platformClass/simplePlatformClass.kt | 12 +++ .../platformClass/simplePlatformClass.txt | 31 ++++++ .../multiplatform/platformClass/superClass.kt | 17 ++++ .../platformClass/superClass.txt | 88 +++++++++++++++++ .../noMultiplatformProjects.kt | 7 ++ .../noMultiplatformProjects.txt | 10 ++ .../checkers/DiagnosticsTestGenerated.java | 51 ++++++++++ 21 files changed, 528 insertions(+), 7 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/multiplatform/platformClass/classKinds.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/platformClass/classKinds.txt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/platformClass/explicitConstructorDelegation.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/platformClass/explicitConstructorDelegation.txt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassMember.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassMember.txt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassWithFunctionBody.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassWithFunctionBody.txt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/platformClass/simplePlatformClass.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/platformClass/simplePlatformClass.txt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/platformClass/superClass.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/platformClass/superClass.txt create mode 100644 compiler/testData/diagnostics/tests/sourceCompatibility/noMultiplatformProjects.kt create mode 100644 compiler/testData/diagnostics/tests/sourceCompatibility/noMultiplatformProjects.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt index d56e34db891..58cc897b080 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt @@ -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) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index bf107b0f57c..41abfdef487 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -493,7 +493,8 @@ public interface Errors { DiagnosticFactory0 PLATFORM_DECLARATION_WITH_BODY = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); DiagnosticFactory0 PLATFORM_DECLARATION_WITH_DEFAULT_PARAMETER = DiagnosticFactory0.create(ERROR); - + DiagnosticFactory0 PLATFORM_CLASS_CONSTRUCTOR_DELEGATION_CALL = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 PLATFORM_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 PLATFORM_PROPERTY_INITIALIZER = DiagnosticFactory0.create(ERROR); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 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 c73adb0e99f..33919798b4c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -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"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtConstructorDelegationCall.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtConstructorDelegationCall.java index 02b54c7fce9..75b5789c436 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtConstructorDelegationCall.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtConstructorDelegationCall.java @@ -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; diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java index 93e54e49c86..ca1db1fa675 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java @@ -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) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt index 29e21234da7..689a0702eb2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt @@ -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)) } } diff --git a/compiler/testData/diagnostics/tests/multiplatform/platformClass/classKinds.kt b/compiler/testData/diagnostics/tests/multiplatform/platformClass/classKinds.kt new file mode 100644 index 00000000000..d4b37788ab4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/platformClass/classKinds.kt @@ -0,0 +1,26 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +platform interface Interface + +platform annotation class Anno(val prop: String) + +platform object Object + +platform class Class + +platform enum class En { ENTRY } + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt + +impl interface Interface + +impl annotation class Anno(val prop: String) + +impl object Object + +impl class Class + +impl enum class En { ENTRY } diff --git a/compiler/testData/diagnostics/tests/multiplatform/platformClass/classKinds.txt b/compiler/testData/diagnostics/tests/multiplatform/platformClass/classKinds.txt new file mode 100644 index 00000000000..062a34a3f19 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/platformClass/classKinds.txt @@ -0,0 +1,98 @@ +// -- Module: -- +package + +public final platform annotation class Anno : kotlin.Annotation { + public constructor Anno(/*0*/ prop: kotlin.String) + public final val prop: kotlin.String + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final platform class Class { + public constructor Class() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final platform enum class En : kotlin.Enum { + enum entry ENTRY + + private constructor En() + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: En): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): En + public final /*synthesized*/ fun values(): kotlin.Array +} + +public platform interface Interface { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public platform object Object { + private constructor Object() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + + +// -- Module: -- +package + +public final impl annotation class Anno : kotlin.Annotation { + public constructor Anno(/*0*/ prop: kotlin.String) + public final val prop: kotlin.String + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final impl class Class { + public constructor Class() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final impl enum class En : kotlin.Enum { + enum entry ENTRY + + private constructor En() + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: En): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit + public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class! + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): En + public final /*synthesized*/ fun values(): kotlin.Array +} + +public impl interface Interface { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public impl object Object { + private constructor Object() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/platformClass/explicitConstructorDelegation.kt b/compiler/testData/diagnostics/tests/multiplatform/platformClass/explicitConstructorDelegation.kt new file mode 100644 index 00000000000..83028766590 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/platformClass/explicitConstructorDelegation.kt @@ -0,0 +1,14 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt +platform open class A { + constructor(s: String) + + constructor(n: Number) : this("A") +} + +platform class B : A { + constructor(i: Int) + + constructor() : super("B") +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/platformClass/explicitConstructorDelegation.txt b/compiler/testData/diagnostics/tests/multiplatform/platformClass/explicitConstructorDelegation.txt new file mode 100644 index 00000000000..6a71e5990d2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/platformClass/explicitConstructorDelegation.txt @@ -0,0 +1,17 @@ +package + +public open platform class A { + public constructor A(/*0*/ n: kotlin.Number) + public constructor A(/*0*/ s: kotlin.String) + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final platform class B : A { + public constructor B() + public constructor B(/*0*/ i: kotlin.Int) + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassMember.kt b/compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassMember.kt new file mode 100644 index 00000000000..1f8566b2101 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassMember.kt @@ -0,0 +1,24 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt +platform class Foo { + val foo: String + + fun bar(x: Int): Int +} + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt +class Foo { + val foo: String = "JVM" + + fun bar(x: Int): Int = x + 1 +} + +// MODULE: m3-js(m1-common) +// FILE: js.kt +class Foo { + val foo: String = "JS" + + fun bar(x: Int): Int = x - 1 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassMember.txt b/compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassMember.txt new file mode 100644 index 00000000000..7f610941740 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassMember.txt @@ -0,0 +1,37 @@ +// -- Module: -- +package + +public final platform class Foo { + public constructor Foo() + public final val foo: kotlin.String + public final platform fun bar(/*0*/ x: kotlin.Int): kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + + +// -- Module: -- +package + +public final class Foo { + public constructor Foo() + public final val foo: kotlin.String = "JVM" + public final fun bar(/*0*/ x: kotlin.Int): kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + + +// -- Module: -- +package + +public final class Foo { + public constructor Foo() + public final val foo: kotlin.String = "JS" + public final fun bar(/*0*/ x: kotlin.Int): kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassWithFunctionBody.kt b/compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassWithFunctionBody.kt new file mode 100644 index 00000000000..8401a252c31 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassWithFunctionBody.kt @@ -0,0 +1,29 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt +platform class Foo( + val constructorProperty: String, + constructorParameter: String +) { + init { + "no" + } + + constructor(s: String) { + "no" + } + + constructor() : this("no") + + val prop: String = "no" + + var getSet: String + get() = "no" + set(value) {} + + fun defaultArg(value: String = "no") + + fun functionWithBody(x: Int): Int { + return x + 1 + } +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassWithFunctionBody.txt b/compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassWithFunctionBody.txt new file mode 100644 index 00000000000..f3a370ca2b0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassWithFunctionBody.txt @@ -0,0 +1,15 @@ +package + +public final platform class Foo { + public constructor Foo() + public constructor Foo(/*0*/ s: kotlin.String) + public constructor Foo(/*0*/ constructorProperty: kotlin.String, /*1*/ constructorParameter: kotlin.String) + public final val constructorProperty: kotlin.String + public final var getSet: kotlin.String + public final val prop: kotlin.String = "no" + public final platform fun defaultArg(/*0*/ value: kotlin.String = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final platform fun functionWithBody(/*0*/ x: kotlin.Int): kotlin.Int + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/platformClass/simplePlatformClass.kt b/compiler/testData/diagnostics/tests/multiplatform/platformClass/simplePlatformClass.kt new file mode 100644 index 00000000000..053874029a5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/platformClass/simplePlatformClass.kt @@ -0,0 +1,12 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt +platform class Foo + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt +class Foo + +// MODULE: m3-js(m1-common) +// FILE: js.kt +class Foo diff --git a/compiler/testData/diagnostics/tests/multiplatform/platformClass/simplePlatformClass.txt b/compiler/testData/diagnostics/tests/multiplatform/platformClass/simplePlatformClass.txt new file mode 100644 index 00000000000..b5f304c8bbb --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/platformClass/simplePlatformClass.txt @@ -0,0 +1,31 @@ +// -- Module: -- +package + +public final platform class Foo { + public constructor Foo() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + + +// -- Module: -- +package + +public final class Foo { + public constructor Foo() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + + +// -- Module: -- +package + +public final class Foo { + public constructor Foo() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/platformClass/superClass.kt b/compiler/testData/diagnostics/tests/multiplatform/platformClass/superClass.kt new file mode 100644 index 00000000000..3ef1e9e4a4c --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/platformClass/superClass.kt @@ -0,0 +1,17 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +interface I +open class C +interface J + +platform class Foo : I, C, J + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt +class Foo : I, C(), J + +// MODULE: m3-js(m1-common) +// FILE: js.kt +class Foo : I, J, C() diff --git a/compiler/testData/diagnostics/tests/multiplatform/platformClass/superClass.txt b/compiler/testData/diagnostics/tests/multiplatform/platformClass/superClass.txt new file mode 100644 index 00000000000..fa5669b7261 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/platformClass/superClass.txt @@ -0,0 +1,88 @@ +// -- Module: -- +package + +public open class C { + public constructor C() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final platform class Foo : I, C, J { + public constructor Foo() + public open override /*3*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*3*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*3*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface I { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface J { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + + +// -- Module: -- +package + +public open class C { + public constructor C() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Foo : I, C, J { + public constructor Foo() + public open override /*3*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*3*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*3*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface I { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface J { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + + +// -- Module: -- +package + +public open class C { + public constructor C() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Foo : I, J, C { + public constructor Foo() + public open override /*3*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*3*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*3*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface I { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface J { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/noMultiplatformProjects.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/noMultiplatformProjects.kt new file mode 100644 index 00000000000..a488b916797 --- /dev/null +++ b/compiler/testData/diagnostics/tests/sourceCompatibility/noMultiplatformProjects.kt @@ -0,0 +1,7 @@ +platform fun foo1() +platform val bar1 = 42 +platform class Baz1 + +impl fun foo2() = 42 +impl val bar2: Int +impl interface Baz2 diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/noMultiplatformProjects.txt b/compiler/testData/diagnostics/tests/sourceCompatibility/noMultiplatformProjects.txt new file mode 100644 index 00000000000..d8334abbb0d --- /dev/null +++ b/compiler/testData/diagnostics/tests/sourceCompatibility/noMultiplatformProjects.txt @@ -0,0 +1,10 @@ +package + +public val bar2: kotlin.Int +public impl fun foo2(): kotlin.Int + +public impl interface Baz2 { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index ac0d7a749b4..bd5d7180074 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -12556,6 +12556,51 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } + @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/platformClass") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class PlatformClass extends AbstractDiagnosticsTest { + public void testAllFilesPresentInPlatformClass() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/platformClass"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("classKinds.kt") + public void testClassKinds() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/platformClass/classKinds.kt"); + doTest(fileName); + } + + @TestMetadata("explicitConstructorDelegation.kt") + public void testExplicitConstructorDelegation() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/platformClass/explicitConstructorDelegation.kt"); + doTest(fileName); + } + + @TestMetadata("platformClassMember.kt") + public void testPlatformClassMember() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassMember.kt"); + doTest(fileName); + } + + @TestMetadata("platformClassWithFunctionBody.kt") + public void testPlatformClassWithFunctionBody() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassWithFunctionBody.kt"); + doTest(fileName); + } + + @TestMetadata("simplePlatformClass.kt") + public void testSimplePlatformClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/platformClass/simplePlatformClass.kt"); + doTest(fileName); + } + + @TestMetadata("superClass.kt") + public void testSuperClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/platformClass/superClass.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -19891,6 +19936,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("noMultiplatformProjects.kt") + public void testNoMultiplatformProjects() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/noMultiplatformProjects.kt"); + doTest(fileName); + } + @TestMetadata("noTopLevelSealedInheritance.kt") public void testNoTopLevelSealedInheritance() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/noTopLevelSealedInheritance.kt");