From 97314d010d16f7d3895911ef7ae3d8145c53621f Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 6 Feb 2018 19:16:02 +0100 Subject: [PATCH] Serialize default argument values presence for actual declarations correctly When default argument value was present in the expected declaration, we did not correctly serialize that fact to the metadata for the actual declaration (`declaresDefaultValue` was used). Therefore, it was impossible to use that actual declaration without passing all parameter values in another module, where it was seen as a deserialized descriptor #KT-21913 --- .../calls/components/ArgumentsUtils.kt | 2 +- .../serialization/DescriptorSerializer.kt | 6 +++-- .../useDefaultArgumentsInDependency/common.kt | 9 +++++++ .../useDefaultArgumentsInDependency/jvm.kt | 9 +++++++ .../useDefaultArgumentsInDependency/jvm2.kt | 25 +++++++++++++++++++ .../output.txt | 11 ++++++++ ...MultiPlatformIntegrationTestGenerated.java | 15 +++++++++++ 7 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency/common.kt create mode 100644 compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency/jvm.kt create mode 100644 compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency/jvm2.kt create mode 100644 compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency/output.txt diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ArgumentsUtils.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ArgumentsUtils.kt index 9dc6dd787dd..fa6c6b9ed43 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ArgumentsUtils.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ArgumentsUtils.kt @@ -74,7 +74,7 @@ fun ValueParameterDescriptor.hasDefaultValue(): Boolean { ) } -private val ValueParameterDescriptor.isActualParameterWithExpectedDefault: Boolean +val ValueParameterDescriptor.isActualParameterWithExpectedDefault: Boolean get() { val function = containingDeclaration if (function is FunctionDescriptor && function.isActual) { diff --git a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt index 8e1d1b41c40..0d6bc20c253 100644 --- a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt +++ b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry import org.jetbrains.kotlin.resolve.MemberComparator import org.jetbrains.kotlin.resolve.RequireKotlinNames +import org.jetbrains.kotlin.resolve.calls.components.isActualParameterWithExpectedDefault import org.jetbrains.kotlin.resolve.checkers.KotlinVersionStringAnnotationValueChecker import org.jetbrains.kotlin.resolve.constants.EnumValue import org.jetbrains.kotlin.resolve.constants.IntValue @@ -386,9 +387,10 @@ class DescriptorSerializer private constructor( private fun valueParameter(descriptor: ValueParameterDescriptor): ProtoBuf.ValueParameter.Builder { val builder = ProtoBuf.ValueParameter.newBuilder() + val declaresDefaultValue = descriptor.declaresDefaultValue() || descriptor.isActualParameterWithExpectedDefault + val flags = Flags.getValueParameterFlags( - hasAnnotations(descriptor), descriptor.declaresDefaultValue(), - descriptor.isCrossinline, descriptor.isNoinline + hasAnnotations(descriptor), declaresDefaultValue, descriptor.isCrossinline, descriptor.isNoinline ) if (flags != builder.flags) { builder.flags = flags diff --git a/compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency/common.kt b/compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency/common.kt new file mode 100644 index 00000000000..64d7d524f9f --- /dev/null +++ b/compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency/common.kt @@ -0,0 +1,9 @@ +package lib + +expect fun foo(x: Int, y: String = "OK") + +expect class C(x: Int, y: String = "OK") + +expect annotation class Anno1(val x: Int, val y: String = "OK") + +expect annotation class Anno2(val x: Int, val y: String = "OK") diff --git a/compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency/jvm.kt b/compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency/jvm.kt new file mode 100644 index 00000000000..18c503f35ab --- /dev/null +++ b/compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency/jvm.kt @@ -0,0 +1,9 @@ +package lib + +actual fun foo(x: Int, y: String) {} + +actual class C actual constructor(x: Int, y: String) {} + +actual annotation class Anno1(actual val x: Int, actual val y: String = "OK") + +actual annotation class Anno2(actual val x: Int, actual val y: String) diff --git a/compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency/jvm2.kt b/compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency/jvm2.kt new file mode 100644 index 00000000000..f1cab59367e --- /dev/null +++ b/compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency/jvm2.kt @@ -0,0 +1,25 @@ +package usage + +import lib.* + +fun testFunction() { + foo(42) + foo(42, "OK") +} + +fun testConstructor() { + C(42) + C(42, "OK") +} + +@Anno1(42) +fun testAnno1a() {} + +@Anno1(42, "OK") +fun testAnno1b() {} + +@Anno2(42) +fun testAnno2a() {} + +@Anno2(42, "OK") +fun testAnno2b() {} diff --git a/compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency/output.txt b/compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency/output.txt new file mode 100644 index 00000000000..e2a887ac2ae --- /dev/null +++ b/compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency/output.txt @@ -0,0 +1,11 @@ +-- Common -- +Exit code: OK +Output: + +-- JVM -- +Exit code: OK +Output: + +-- JVM (2) -- +Exit code: OK +Output: diff --git a/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java index e6c70f0b4f7..87603953c0a 100644 --- a/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java @@ -190,6 +190,21 @@ public class MultiPlatformIntegrationTestGenerated extends AbstractMultiPlatform } } + @TestMetadata("compiler/testData/multiplatform/defaultArguments") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class DefaultArguments extends AbstractMultiPlatformIntegrationTest { + public void testAllFilesPresentInDefaultArguments() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/multiplatform/defaultArguments"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, true); + } + + @TestMetadata("useDefaultArgumentsInDependency") + public void testUseDefaultArgumentsInDependency() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency/"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/multiplatform/implTypeAlias") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)