diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 385b8501e8d..5a635ad616e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -570,7 +570,8 @@ public interface Errors { enum BadNamedArgumentsTarget { NON_KOTLIN_FUNCTION, - INVOKE_ON_FUNCTION_TYPE + INVOKE_ON_FUNCTION_TYPE, + HEADER_CLASS_MEMBER, } DiagnosticFactory0 VARARG_OUTSIDE_PARENTHESES = 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 2ff04b8f5ad..f904adbcc36 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -207,6 +207,8 @@ public class DefaultErrorMessages { return "non-Kotlin functions"; case INVOKE_ON_FUNCTION_TYPE: return "function types"; + case HEADER_CLASS_MEMBER: + return "members of header classes"; default: throw new AssertionError(target); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ValueArgumentsToParametersMapper.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ValueArgumentsToParametersMapper.java index b9eec8abd4b..ab9cd269501 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ValueArgumentsToParametersMapper.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ValueArgumentsToParametersMapper.java @@ -23,9 +23,7 @@ import kotlin.collections.CollectionsKt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor; -import org.jetbrains.kotlin.descriptors.CallableDescriptor; -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor; -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; +import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.diagnostics.Diagnostic; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; @@ -42,8 +40,7 @@ import java.util.Map; import java.util.Set; import static org.jetbrains.kotlin.diagnostics.Errors.*; -import static org.jetbrains.kotlin.diagnostics.Errors.BadNamedArgumentsTarget.INVOKE_ON_FUNCTION_TYPE; -import static org.jetbrains.kotlin.diagnostics.Errors.BadNamedArgumentsTarget.NON_KOTLIN_FUNCTION; +import static org.jetbrains.kotlin.diagnostics.Errors.BadNamedArgumentsTarget.*; import static org.jetbrains.kotlin.resolve.BindingContext.REFERENCE_TARGET; import static org.jetbrains.kotlin.resolve.calls.ValueArgumentsToParametersMapper.Status.*; @@ -189,11 +186,19 @@ public class ValueArgumentsToParametersMapper { KtSimpleNameExpression nameReference = argumentName.getReferenceExpression(); KtPsiUtilKt.checkReservedYield(nameReference, candidateCall.getTrace()); - if (!candidate.hasStableParameterNames() && nameReference != null) { - report(NAMED_ARGUMENTS_NOT_ALLOWED.on( - nameReference, - candidate instanceof FunctionInvokeDescriptor ? INVOKE_ON_FUNCTION_TYPE : NON_KOTLIN_FUNCTION - )); + if (nameReference != null) { + if (candidate instanceof MemberDescriptor && ((MemberDescriptor) candidate).isHeader() && + candidate.getContainingDeclaration() instanceof ClassDescriptor) { + // We do not allow named arguments for members of header classes until we're able to use both + // headers and platform definitions when compiling platform code + report(NAMED_ARGUMENTS_NOT_ALLOWED.on(nameReference, HEADER_CLASS_MEMBER)); + } + else if (!candidate.hasStableParameterNames()) { + report(NAMED_ARGUMENTS_NOT_ALLOWED.on( + nameReference, + candidate instanceof FunctionInvokeDescriptor ? INVOKE_ON_FUNCTION_TYPE : NON_KOTLIN_FUNCTION + )); + } } if (candidate.hasStableParameterNames() && nameReference != null && diff --git a/compiler/testData/diagnostics/tests/multiplatform/namedArguments.kt b/compiler/testData/diagnostics/tests/multiplatform/namedArguments.kt new file mode 100644 index 00000000000..5320224993e --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/namedArguments.kt @@ -0,0 +1,36 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +header class Foo(zzz: Int) { + constructor(aaa: Boolean) + + fun f1(xxx: String): String +} + +header fun f2(xxx: Int) + +fun testCommon() { + Foo(zzz = 0) + val f = Foo(aaa = true) + f.f1(xxx = "") + f2(xxx = 42) +} + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt + +impl class Foo(val aaa: Boolean) { + impl constructor(zzz: Int) : this(zzz == 0) + + impl fun f1(xxx: String) = xxx +} + +impl fun f2(xxx: Int) {} + +fun testPlatform() { + Foo(zzz = 0) + val f = Foo(aaa = true) + f.f1(xxx = "") + f2(xxx = 42) +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/namedArguments.txt b/compiler/testData/diagnostics/tests/multiplatform/namedArguments.txt new file mode 100644 index 00000000000..274db482bdd --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/namedArguments.txt @@ -0,0 +1,32 @@ +// -- Module: -- +package + +public header fun f2(/*0*/ xxx: kotlin.Int): kotlin.Unit +public fun testCommon(): kotlin.Unit + +public final header class Foo { + public constructor Foo(/*0*/ aaa: kotlin.Boolean) + public constructor Foo(/*0*/ zzz: kotlin.Int) + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final header fun f1(/*0*/ xxx: kotlin.String): kotlin.String + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + + +// -- Module: -- +package + +public impl fun f2(/*0*/ xxx: kotlin.Int): kotlin.Unit +public fun testCommon(): kotlin.Unit +public fun testPlatform(): kotlin.Unit + +public final impl class Foo { + public constructor Foo(/*0*/ aaa: kotlin.Boolean) + public constructor Foo(/*0*/ zzz: kotlin.Int) + public final val aaa: kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final impl fun f1(/*0*/ xxx: kotlin.String): kotlin.String + 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 f2a1878f8ba..fb90878b0c7 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -13120,6 +13120,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("namedArguments.kt") + public void testNamedArguments() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/namedArguments.kt"); + doTest(fileName); + } + @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/enum") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)