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
This commit is contained in:
Alexander Udalov
2018-02-06 19:16:02 +01:00
parent 22595acbfd
commit 97314d010d
7 changed files with 74 additions and 3 deletions
@@ -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) {
@@ -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
@@ -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")
@@ -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)
@@ -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() {}
@@ -0,0 +1,11 @@
-- Common --
Exit code: OK
Output:
-- JVM --
Exit code: OK
Output:
-- JVM (2) --
Exit code: OK
Output:
@@ -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)