From 0348561cd2f3e15ca86769c1fa3844ae7b66580a Mon Sep 17 00:00:00 2001 From: Leonid Stashevsky Date: Wed, 4 Oct 2017 14:03:23 +0300 Subject: [PATCH] Add annotation for default parameter value --- .../kotlin/codegen/ArgumentGenerator.kt | 25 ++++- .../codegen/CallBasedArgumentGenerator.java | 13 ++- .../codegen/ImplementationBodyCodegen.java | 6 +- .../ObjectSuperCallArgumentGenerator.kt | 11 ++ .../jetbrains/kotlin/codegen/StackValue.kt | 47 ++++++++ .../evaluate/ConstantExpressionEvaluator.kt | 8 +- .../defaultAndNamedCombination.kt | 37 +++++++ .../signatureAnnotations/defaultBoxTypes.kt | 80 ++++++++++++++ .../signatureAnnotations/defaultEnumType.kt | 42 ++++++++ .../defaultLongLiteral.kt | 48 +++++++++ .../defaultMultipleParams.kt | 43 ++++++++ .../box/signatureAnnotations/defaultNull.kt | 56 ++++++++++ .../defaultNullableBoxTypes.kt | 81 ++++++++++++++ .../signatureAnnotations/defaultOverrides.kt | 38 +++++++ .../defaultPrimitiveTypes.kt | 88 +++++++++++++++ .../defaultValueInConstructor.kt | 40 +++++++ .../defaultWithJavaBase.kt | 26 +++++ .../defaultWithKotlinBase.kt | 23 ++++ .../j+k/signatureAnnotations/defaultEnum.kt | 67 ++++++++++++ .../j+k/signatureAnnotations/defaultEnum.txt | 90 ++++++++++++++++ .../defaultLongLiteral.kt | 49 +++++++++ .../defaultLongLiteral.txt | 25 +++++ .../j+k/signatureAnnotations/defaultNull.kt | 31 ++++++ .../j+k/signatureAnnotations/defaultNull.txt | 20 ++++ .../defaultNullAndParameter.kt | 57 ++++++++++ .../defaultNullAndParameter.txt | 44 ++++++++ .../signatureAnnotations/defaultParameter.kt | 45 ++++++++ .../signatureAnnotations/defaultParameter.txt | 15 +++ .../overridesDefaultValue.kt | 100 ++++++++++++++++++ .../overridesDefaultValue.txt | 81 ++++++++++++++ .../staticMethodWithDefaultValue.kt | 17 +++ .../staticMethodWithDefaultValue.txt | 13 +++ .../ir/IrBlackBoxCodegenTestGenerated.java | 72 +++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 42 ++++++++ .../DiagnosticsUsingJavacTestGenerated.java | 42 ++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 72 +++++++++++++ .../LightAnalysisModeTestGenerated.java | 72 +++++++++++++ .../kotlin/load/java/JvmAnnotationNames.java | 2 + .../JavaCallableMemberDescriptor.java | 2 +- .../JavaClassConstructorDescriptor.java | 4 +- .../descriptors/JavaMethodDescriptor.java | 4 +- .../descriptors/JavaPropertyDescriptor.java | 2 +- .../kotlin/load/java/descriptors/util.kt | 32 ++++-- .../descriptors/LazyJavaClassMemberScope.kt | 10 +- .../typeEnhancement/signatureEnhancement.kt | 42 ++++++-- .../org/jetbrains/kotlin/load/java/utils.kt | 63 +++++++++++ .../src/org/jetbrains/kotlin/utils/numbers.kt | 25 +++++ .../src/kotlin/Annotations.kt | 14 +++ 48 files changed, 1827 insertions(+), 39 deletions(-) create mode 100644 compiler/testData/codegen/box/signatureAnnotations/defaultAndNamedCombination.kt create mode 100644 compiler/testData/codegen/box/signatureAnnotations/defaultBoxTypes.kt create mode 100644 compiler/testData/codegen/box/signatureAnnotations/defaultEnumType.kt create mode 100644 compiler/testData/codegen/box/signatureAnnotations/defaultLongLiteral.kt create mode 100644 compiler/testData/codegen/box/signatureAnnotations/defaultMultipleParams.kt create mode 100644 compiler/testData/codegen/box/signatureAnnotations/defaultNull.kt create mode 100644 compiler/testData/codegen/box/signatureAnnotations/defaultNullableBoxTypes.kt create mode 100644 compiler/testData/codegen/box/signatureAnnotations/defaultOverrides.kt create mode 100644 compiler/testData/codegen/box/signatureAnnotations/defaultPrimitiveTypes.kt create mode 100644 compiler/testData/codegen/box/signatureAnnotations/defaultValueInConstructor.kt create mode 100644 compiler/testData/codegen/box/signatureAnnotations/defaultWithJavaBase.kt create mode 100644 compiler/testData/codegen/box/signatureAnnotations/defaultWithKotlinBase.kt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultEnum.kt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultEnum.txt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultLongLiteral.kt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultLongLiteral.txt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNull.kt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNull.txt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNullAndParameter.kt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNullAndParameter.txt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultParameter.kt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultParameter.txt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesDefaultValue.kt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesDefaultValue.txt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/staticMethodWithDefaultValue.kt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/staticMethodWithDefaultValue.txt create mode 100644 core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/utils.kt create mode 100644 core/util.runtime/src/org/jetbrains/kotlin/utils/numbers.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ArgumentGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/ArgumentGenerator.kt index da8b53750a6..cff0fd13b00 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ArgumentGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ArgumentGenerator.kt @@ -17,10 +17,12 @@ package org.jetbrains.kotlin.codegen import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument +import org.jetbrains.kotlin.utils.DFS import org.jetbrains.kotlin.utils.mapToIndex class ArgumentAndDeclIndex(val arg: ResolvedValueArgument, val declIndex: Int) @@ -66,8 +68,13 @@ abstract class ArgumentGenerator { generateExpression(declIndex, argument) } is DefaultValueArgument -> { - defaultArgs.mark(declIndex) - generateDefault(declIndex, argument) + if (calleeDescriptor?.defaultValueFromJava(declIndex) == true) { + generateDefaultJava(declIndex, argument) + } + else { + defaultArgs.mark(declIndex) + generateDefault(declIndex, argument) + } } is VarargValueArgument -> { generateVararg(declIndex, argument) @@ -95,6 +102,10 @@ abstract class ArgumentGenerator { throw UnsupportedOperationException("Unsupported vararg value argument #$i: $argument") } + protected open fun generateDefaultJava(i: Int, argument: DefaultValueArgument) { + throw UnsupportedOperationException("Unsupported default java argument #$i: $argument") + } + protected open fun generateOther(i: Int, argument: ResolvedValueArgument) { throw UnsupportedOperationException("Unsupported value argument #$i: $argument") } @@ -103,3 +114,13 @@ abstract class ArgumentGenerator { throw UnsupportedOperationException("Unsupported operation") } } + +private fun CallableDescriptor.defaultValueFromJava(index: Int): Boolean = DFS.ifAny( + listOf(this), + { current -> current.original.overriddenDescriptors.map { it.original } }, + { descriptor -> + descriptor.original.overriddenDescriptors.isEmpty() && + descriptor is JavaCallableMemberDescriptor && + descriptor.valueParameters[index].declaresDefaultValue() + } +) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallBasedArgumentGenerator.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallBasedArgumentGenerator.java index 76f0d955d9b..0e022854215 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallBasedArgumentGenerator.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallBasedArgumentGenerator.java @@ -28,7 +28,7 @@ import org.jetbrains.org.objectweb.asm.Type; import java.util.List; -import static org.jetbrains.kotlin.codegen.StackValue.createDefaultValue; +import static org.jetbrains.kotlin.codegen.StackValue.*; public class CallBasedArgumentGenerator extends ArgumentGenerator { private final ExpressionCodegen codegen; @@ -76,6 +76,17 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator { callGenerator.putValueIfNeeded(valueParameterTypes.get(i), lazyVararg, ValueKind.GENERAL_VARARG, i); } + @Override + protected void generateDefaultJava(int i, @NotNull DefaultValueArgument argument) { + StackValue argumentValue = StackValueKt.findJavaDefaultArgumentValue( + valueParameters.get(i), + valueParameterTypes.get(i), + codegen.typeMapper + ); + + callGenerator.putValueIfNeeded(valueParameterTypes.get(i), argumentValue); + } + @Override protected void reorderArgumentsIfNeeded(@NotNull List actualArgsWithDeclIndex) { callGenerator.reorderArgumentsIfNeeded(actualArgsWithDeclIndex, valueParameterTypes); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index 49c1881abd6..db60016cd46 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -1467,7 +1467,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (isAnonymousObject(descriptor)) { List superValues = superParameters.subList(superIndex, superParameters.size()); - return new ObjectSuperCallArgumentGenerator(superValues, iv, offset, superConstructorCall); + return new ObjectSuperCallArgumentGenerator( + superValues, iv, + superConstructor.getValueParameters(), codegen.typeMapper, + offset, superConstructorCall + ); } else { return new CallBasedArgumentGenerator(codegen, codegen.defaultCallGenerator, superConstructor.getValueParameters(), diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ObjectSuperCallArgumentGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/ObjectSuperCallArgumentGenerator.kt index fd93e56a971..7e9cb4bc317 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ObjectSuperCallArgumentGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ObjectSuperCallArgumentGenerator.kt @@ -17,15 +17,20 @@ package org.jetbrains.kotlin.codegen import org.jetbrains.kotlin.codegen.AsmUtil.pushDefaultValueOnStack +import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ConstructorDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature +import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter internal class ObjectSuperCallArgumentGenerator( private val parameters: List, private val iv: InstructionAdapter, + private val superValueParameters: List, + private val typeMapper: KotlinTypeMapper, offset: Int, superConstructorCall: ResolvedCall ) : ArgumentGenerator() { @@ -59,6 +64,12 @@ internal class ObjectSuperCallArgumentGenerator( pushDefaultValueOnStack(type, iv) } + public override fun generateDefaultJava(i: Int, argument: DefaultValueArgument) { + val type = parameters[i].asmType + val value = superValueParameters[i].findJavaDefaultArgumentValue(type, typeMapper) + value.put(type, iv) + } + public override fun generateVararg(i: Int, argument: VarargValueArgument) { generateSuperCallArgument(i) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.kt index 799b30efd49..e6e7a6f2422 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.kt @@ -16,6 +16,16 @@ package org.jetbrains.kotlin.codegen +import org.jetbrains.kotlin.codegen.AsmUtil.unboxPrimitiveTypeOrNull +import org.jetbrains.kotlin.codegen.StackValue.* +import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.load.java.* +import org.jetbrains.kotlin.load.java.Constant +import org.jetbrains.kotlin.load.java.descriptors.NullDefaultValue +import org.jetbrains.kotlin.load.java.descriptors.StringDefaultValue +import org.jetbrains.kotlin.load.java.descriptors.getDefaultValueFromAnnotation +import org.jetbrains.kotlin.utils.DFS import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter @@ -68,3 +78,40 @@ open class OperationStackValue(resultType: Type, val lambda: (v: InstructionAdap } class FunctionCallStackValue(resultType: Type, lambda: (v: InstructionAdapter) -> Unit) : OperationStackValue(resultType, lambda) + +fun ValueParameterDescriptor.findJavaDefaultArgumentValue(targetType: Type, typeMapper: KotlinTypeMapper): StackValue { + val descriptorWithDefaultValue = DFS.dfs( + listOf(this.original), + { it.original.overriddenDescriptors.map(ValueParameterDescriptor::getOriginal) }, + object : DFS.AbstractNodeHandler() { + var result: ValueParameterDescriptor? = null + + override fun beforeChildren(current: ValueParameterDescriptor?): Boolean { + if (current?.declaresDefaultValue() == true && current.getDefaultValueFromAnnotation() != null) { + result = current + return false + } + + return true + } + + override fun result(): ValueParameterDescriptor? = result + } + ) ?: error("Should be at least one descriptor with default value: $this") + + val defaultValue = descriptorWithDefaultValue.getDefaultValueFromAnnotation() + if (defaultValue is NullDefaultValue) { + return constant(null, targetType) + } + + val value = (defaultValue as StringDefaultValue).value + val castResult = type.lexicalCastFrom(value) ?: error("Should be checked in frontend") + + return when (castResult) { + is EnumEntry -> enumEntry(castResult.descriptor, typeMapper) + is Constant -> { + val unboxedType = unboxPrimitiveTypeOrNull(targetType) ?: targetType + return coercion(constant(castResult.value, unboxedType), targetType) + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt index 4fb38f5a799..37fdf524328 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt @@ -46,6 +46,7 @@ import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.types.isError import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.util.OperatorNameConventions +import org.jetbrains.kotlin.utils.extractRadix import java.math.BigInteger import java.util.* @@ -874,11 +875,8 @@ private fun parseLong(text: String): Long? { fun substringLongSuffix(s: String) = if (hasLongSuffix(text)) s.substring(0, s.length - 1) else s fun parseLong(text: String, radix: Int) = java.lang.Long.parseLong(substringLongSuffix(text), radix) - return when { - text.startsWith("0x") || text.startsWith("0X") -> parseLong(text.substring(2), 16) - text.startsWith("0b") || text.startsWith("0B") -> parseLong(text.substring(2), 2) - else -> parseLong(text, 10) - } + val (number, radix) = extractRadix(text) + return parseLong(number, radix) } catch (e: NumberFormatException) { return null diff --git a/compiler/testData/codegen/box/signatureAnnotations/defaultAndNamedCombination.kt b/compiler/testData/codegen/box/signatureAnnotations/defaultAndNamedCombination.kt new file mode 100644 index 00000000000..9bdbda176b6 --- /dev/null +++ b/compiler/testData/codegen/box/signatureAnnotations/defaultAndNamedCombination.kt @@ -0,0 +1,37 @@ +// TARGET_BACKEND: JVM + +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; + +class A { + public int first( + @ParameterName("first") @DefaultValue("42") int a, + @ParameterName("second") @DefaultValue("1") int b + ) { + return 100 * a + b; + } +} + +// FILE: main.kt +fun box(): String { + val a = A() + if (a.first() != 100 * 42 + 1) { + return "FAIL 1" + } + + if (a.first(second = 2) != 100 * 42 + 2) { + return "FAIL 2" + } + + if (a.first(first = 2) != 100 * 2 + 1) { + return "FAIL 3" + } + + if (a.first(second = 2, first = 5) != 100 * 5 + 2) { + return "FAIL 4" + } + + return "OK" +} diff --git a/compiler/testData/codegen/box/signatureAnnotations/defaultBoxTypes.kt b/compiler/testData/codegen/box/signatureAnnotations/defaultBoxTypes.kt new file mode 100644 index 00000000000..2ea84d948b3 --- /dev/null +++ b/compiler/testData/codegen/box/signatureAnnotations/defaultBoxTypes.kt @@ -0,0 +1,80 @@ +// TARGET_BACKEND: JVM + +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; + +public class A { + + public Integer a(@DefaultValue("42") Integer arg) { + return arg; + } + + public Float b(@DefaultValue("42.5") Float arg) { + return arg; + } + + public Boolean c(@DefaultValue("true") Boolean arg) { + return arg; + } + + public Byte d(@DefaultValue("42") Byte arg) { + return arg; + } + + public Character e(@DefaultValue("o") Character arg) { + return arg; + } + + public Double f(@DefaultValue("1e12") Double arg) { + return arg; + } + + public Long g(@DefaultValue("42424242424242") Long arg) { + return arg; + } + + public Short h(@DefaultValue("123") Short arg) { + return arg; + } +} + +// FILE: test.kt +fun box(): String { + val a = A() + + if (a.a() != 42) { + return "FAIL Int: ${a.a()}" + } + + if (a.b() != 42.5f) { + return "FAIL Float: ${a.b()}" + } + + if (!a.c()) { + return "FAIL Boolean: ${a.c()}" + } + + if (a.d() != 42.toByte()) { + return "FAIL Byte: ${a.d()}" + } + + if (a.e() != 'o') { + return "FAIL Char: ${a.e()}" + } + + if (a.f() != 1e12) { + return "FAIl Double: ${a.f()}" + } + + if (a.g() != 42424242424242) { + return "FAIL Long: ${a.g()}" + } + + if (a.h() != 123.toShort()) { + return "FAIL Short: ${a.h()}" + } + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/signatureAnnotations/defaultEnumType.kt b/compiler/testData/codegen/box/signatureAnnotations/defaultEnumType.kt new file mode 100644 index 00000000000..695e3fef0d5 --- /dev/null +++ b/compiler/testData/codegen/box/signatureAnnotations/defaultEnumType.kt @@ -0,0 +1,42 @@ +// TARGET_BACKEND: JVM + +// FILE: Signs.java +// ANDROID_ANNOTATIONS + +public enum Signs { + HELLO, + WORLD; +} + +// FILE: B.kt +enum class B { + X, + Y; +} + +// FILE: A.java +import kotlin.annotations.jvm.internal.*; + +class A { + public Signs a(@DefaultValue("HELLO") Signs arg) { + return arg; + } + + public B b(@DefaultValue("Y") B arg) { + return arg; + } +} + +// FILE: test.kt +fun box(): String { + val a = A() + if (a.a() != Signs.HELLO) { + return "FAIL: enums Java" + } + + if (a.b() != B.Y) { + return "FAIL: enums Kotlin" + } + + return "OK" +} diff --git a/compiler/testData/codegen/box/signatureAnnotations/defaultLongLiteral.kt b/compiler/testData/codegen/box/signatureAnnotations/defaultLongLiteral.kt new file mode 100644 index 00000000000..7a7e1c7cf1e --- /dev/null +++ b/compiler/testData/codegen/box/signatureAnnotations/defaultLongLiteral.kt @@ -0,0 +1,48 @@ +// TARGET_BACKEND: JVM + +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; + +public class A { + public Long first(@DefaultValue("0x1F") Long value) { + return value; + } + + public Long second(@DefaultValue("0X1F") Long value) { + return value; + } + + public Long third(@DefaultValue("0b1010") Long value) { + return value; + } + + public Long fourth(@DefaultValue("0B1010") Long value) { + return value; + } +} + +// FILE: test.kt +fun box(): String { + val a = A() + + if (a.first() != 0x1F.toLong()) { + return "FAIL 1" + } + + if (a.second() != 0x1F.toLong()) { + return "FAIL 2" + } + + if (a.third() != 0b1010.toLong()) { + return "FAIL 3" + } + + if (a.fourth() != 0b1010.toLong()) { + return "FAIL 4" + } + + return "OK" +} + diff --git a/compiler/testData/codegen/box/signatureAnnotations/defaultMultipleParams.kt b/compiler/testData/codegen/box/signatureAnnotations/defaultMultipleParams.kt new file mode 100644 index 00000000000..2fedface3f7 --- /dev/null +++ b/compiler/testData/codegen/box/signatureAnnotations/defaultMultipleParams.kt @@ -0,0 +1,43 @@ +// TARGET_BACKEND: JVM + +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; + +class A { + public int first(@DefaultValue("1") int a, @DefaultValue("2") int b) { + return 100 * a + b; + } + + public int second(int a, @DefaultValue("42") int b) { + return 100 * a + b; + } +} + +// FILE: main.kt +fun box(): String { + val a = A() + + if (a.first() != 102) { + return "FAIL 1" + } + + if (a.first(2) != 202) { + return "FAIL 2" + } + + if (a.first(3, 4) != 304) { + return "FAIL 3" + } + + if (a.second(7, 8) != 708) { + return "FAIL 4" + } + + if (a.second(1) != 142) { + return "FAIL 5" + } + + return "OK" +} diff --git a/compiler/testData/codegen/box/signatureAnnotations/defaultNull.kt b/compiler/testData/codegen/box/signatureAnnotations/defaultNull.kt new file mode 100644 index 00000000000..428539d56fa --- /dev/null +++ b/compiler/testData/codegen/box/signatureAnnotations/defaultNull.kt @@ -0,0 +1,56 @@ +// TARGET_BACKEND: JVM + +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; + +public class A { + public Integer foo(@DefaultNull Integer x) { return x; } + public Integer bar(@DefaultNull Integer x) { return x; } + + public Integer baz(@DefaultValue("42") Integer x) { return x; } +} + +// FILE: AInt.java +import kotlin.annotations.jvm.internal.*; + +public interface AInt { + public Integer foo(@DefaultValue("42") Integer x); + public Integer bar(@DefaultNull Integer x); +} + +// FILE: B.java + +public class B extends A { + public Integer foo(Integer x) { return x; } +} + +// FILE: C.java +import kotlin.annotations.jvm.internal.*; + +public class C extends A { + public Integer foo(@DefaultValue("42") Integer x) { return x; } + + public Integer baz(@DefaultNull Integer x) { return x; } +} + +// FILE: D.java + +public class D extends A implements AInt { +} + +// FILE: test.kt +fun box(): String { + if (A().foo() != null) return "FAIL 0" + + if (B().foo() != null) return "FAIL 1" + if (B().bar() != null) return "FAIL 2" + + if (C().foo() != null) return "FAIL 3" + if (C().baz() != 42) return "FAIL 4" + + if (D().baz() != 42) return "FAIL 5" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/signatureAnnotations/defaultNullableBoxTypes.kt b/compiler/testData/codegen/box/signatureAnnotations/defaultNullableBoxTypes.kt new file mode 100644 index 00000000000..eec37d83f6b --- /dev/null +++ b/compiler/testData/codegen/box/signatureAnnotations/defaultNullableBoxTypes.kt @@ -0,0 +1,81 @@ +// TARGET_BACKEND: JVM + +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; +import org.jetbrains.annotations.*; + +public class A { + + public Integer a(@Nullable @DefaultValue("42") Integer arg) { + return arg; + } + + public Float b(@Nullable @DefaultValue("42.5") Float arg) { + return arg; + } + + public Boolean c(@Nullable @DefaultValue("true") Boolean arg) { + return arg; + } + + public Byte d(@Nullable @DefaultValue("42") Byte arg) { + return arg; + } + + public Character e(@Nullable @DefaultValue("o") Character arg) { + return arg; + } + + public Double f(@Nullable @DefaultValue("1e12") Double arg) { + return arg; + } + + public Long g(@Nullable @DefaultValue("42424242424242") Long arg) { + return arg; + } + + public Short h(@Nullable @DefaultValue("123") Short arg) { + return arg; + } +} + +// FILE: test.kt +fun box(): String { + val a = A() + + if (a.a() != 42) { + return "FAIL Int: ${a.a()}" + } + + if (a.b() != 42.5f) { + return "FAIL Float: ${a.b()}" + } + + if (!a.c()) { + return "FAIL Boolean: ${a.c()}" + } + + if (a.d() != 42.toByte()) { + return "FAIL Byte: ${a.d()}" + } + + if (a.e() != 'o') { + return "FAIL Char: ${a.e()}" + } + + if (a.f() != 1e12) { + return "FAIl Double: ${a.f()}" + } + + if (a.g() != 42424242424242) { + return "FAIL Long: ${a.g()}" + } + + if (a.h() != 123.toShort()) { + return "FAIL Short: ${a.h()}" + } + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/signatureAnnotations/defaultOverrides.kt b/compiler/testData/codegen/box/signatureAnnotations/defaultOverrides.kt new file mode 100644 index 00000000000..27b5d18438e --- /dev/null +++ b/compiler/testData/codegen/box/signatureAnnotations/defaultOverrides.kt @@ -0,0 +1,38 @@ +// TARGET_BACKEND: JVM + +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; + +class A { + public int first(@DefaultValue("42") int a) { + return a; + } +} + +// FILE: B.java +class B extends A { + public int first(int a) { + return a; + } +} + +// FILE: test.kt +fun box(): String { + val a = A() + val b = B() + val ab: A = B() + + if (a.first() != 42) { + return "FAIL 1" + } + if (b.first() != 42) { + return "FAIL 2" + } + if (ab.first() != 42) { + return "FAIL 4" + } + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/signatureAnnotations/defaultPrimitiveTypes.kt b/compiler/testData/codegen/box/signatureAnnotations/defaultPrimitiveTypes.kt new file mode 100644 index 00000000000..1f295ce7d7f --- /dev/null +++ b/compiler/testData/codegen/box/signatureAnnotations/defaultPrimitiveTypes.kt @@ -0,0 +1,88 @@ +// TARGET_BACKEND: JVM + +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; + +public class A { + + public int a(@DefaultValue("42") int arg) { + return arg; + } + + public float b(@DefaultValue("42.5") float arg) { + return arg; + } + + public boolean c(@DefaultValue("true") boolean arg) { + return arg; + } + + public byte d(@DefaultValue("42") byte arg) { + return arg; + } + + public char e(@DefaultValue("o") char arg) { + return arg; + } + + public double f(@DefaultValue("1e12") double arg) { + return arg; + } + + public String g(@DefaultValue("hello") String arg) { + return arg; + } + + public long h(@DefaultValue("42424242424242") long arg) { + return arg; + } + + public short i(@DefaultValue("123") short arg) { + return arg; + } +} + +// FILE: test.kt +fun box(): String { + val a = A() + + if (a.a() != 42) { + return "FAIL Int: ${a.a()}" + } + + if (a.b() != 42.5f) { + return "FAIL Float: ${a.b()}" + } + + if (!a.c()) { + return "FAIL Boolean: ${a.c()}" + } + + if (a.d() != 42.toByte()) { + return "FAIL Byte: ${a.d()}" + } + + if (a.e() != 'o') { + return "FAIL Char: ${a.e()}" + } + + if (a.f() != 1e12) { + return "FAIl Double: ${a.f()}" + } + + if (a.g() != "hello") { + return "FAIL String: ${a.g()}" + } + + if (a.h() != 42424242424242) { + return "FAIL Long: ${a.h()}" + } + + if (a.i() != 123.toShort()) { + return "FAIL Short: ${a.i()}" + } + + return "OK" +} diff --git a/compiler/testData/codegen/box/signatureAnnotations/defaultValueInConstructor.kt b/compiler/testData/codegen/box/signatureAnnotations/defaultValueInConstructor.kt new file mode 100644 index 00000000000..026dd9f49ce --- /dev/null +++ b/compiler/testData/codegen/box/signatureAnnotations/defaultValueInConstructor.kt @@ -0,0 +1,40 @@ +// TARGET_BACKEND: JVM + +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; + +public class A { + public String x; + public A(@DefaultValue("OK") String hello) { + x = hello; + } +} + +// FILE: test.kt + +fun box(): String { + val a = A() + + val b = object : A() { + } + + val c = object : A() { + fun hello() = x + } + + if (a.x != "OK") { + return "FAIL 1" + } + + if (b.x != "OK") { + return "FAIL 2" + } + + if (c.hello() != "OK") { + return "FAIL 3" + } + + return "OK" +} diff --git a/compiler/testData/codegen/box/signatureAnnotations/defaultWithJavaBase.kt b/compiler/testData/codegen/box/signatureAnnotations/defaultWithJavaBase.kt new file mode 100644 index 00000000000..b809e2b90fa --- /dev/null +++ b/compiler/testData/codegen/box/signatureAnnotations/defaultWithJavaBase.kt @@ -0,0 +1,26 @@ +// TARGET_BACKEND: JVM + +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; + +public class A { + public int x(@DefaultValue("42") int x) { + return x; + } +} + +// FILE: B.kt +class B : A() { + override fun x(x: Int): Int = x + 1 +} + +// FILE: box.kt +fun box(): String { + if (B().x() != 43) { + return "FAIL" + } + + return "OK" +} diff --git a/compiler/testData/codegen/box/signatureAnnotations/defaultWithKotlinBase.kt b/compiler/testData/codegen/box/signatureAnnotations/defaultWithKotlinBase.kt new file mode 100644 index 00000000000..e1735227023 --- /dev/null +++ b/compiler/testData/codegen/box/signatureAnnotations/defaultWithKotlinBase.kt @@ -0,0 +1,23 @@ +// TARGET_BACKEND: JVM + +// FILE: A.kt +open class A { + open fun x(x: Int = foo()) = x + private fun foo() = 42 +} + +// FILE: B.java +public class B extends A { + public int x(int i) { + return i + 1; + } +} + +// FILE: box.kt +fun box(): String { + if (B().x() != 43) { + return "FAIL" + } + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultEnum.kt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultEnum.kt new file mode 100644 index 00000000000..9acd15eee4f --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultEnum.kt @@ -0,0 +1,67 @@ +// FILE: Signs.java +// ANDROID_ANNOTATIONS + +public enum Signs { + HELLO, + WORLD; + + public static final Signs X; + public static final class NOT_ENTRY_EITHER {} +} + +// FILE: Mixed.java +public enum Mixed { + NOT_ENTRY_EITHER; + + public static final class NOT_ENTRY_EITHER {} +} + +// FILE: B.kt +enum class B { + X, + Y; +} + +// FILE: A.java +import kotlin.annotations.jvm.internal.*; + +class A { + public Signs a(@DefaultValue("HELLO") Signs arg) { + return arg; + } + + public B b(@DefaultValue("Y") B arg) { + return arg; + } + + public void foooo(@DefaultValue("ok") B arg) { + } + + public Signs bar(@DefaultValue("X") Signs arg) { + return arg; + } + + public Signs baz(@DefaultValue("NOT_ENTRY_EITHER") Signs arg) { + return arg; + } + + public Mixed bam(@DefaultValue("NOT_ENTRY_EITHER") Mixed arg) { + return arg; + } + +} + +// FILE: test.kt +fun test(){ + val a = A() + a.a() + a.a(Signs.HELLO) + a.b() + a.b(B.X) + a.foooo() + a.foooo(B.Y) + a.bar() + a.baz() + + a.bam() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultEnum.txt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultEnum.txt new file mode 100644 index 00000000000..2eca50367a9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultEnum.txt @@ -0,0 +1,90 @@ +package + +public fun test(): kotlin.Unit + +public/*package*/ open class A { + public/*package*/ constructor A() + public open fun a(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "HELLO") arg: Signs! = ...): Signs! + public open fun b(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "Y") arg: B! = ...): B! + public open fun bam(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "NOT_ENTRY_EITHER") arg: Mixed!): Mixed! + public open fun bar(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "X") arg: Signs!): Signs! + public open fun baz(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "NOT_ENTRY_EITHER") arg: Signs!): Signs! + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun foooo(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "ok") arg: B!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final enum class B : kotlin.Enum { + enum entry X + + enum entry Y + + private constructor B() + 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: B): 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): B + public final /*synthesized*/ fun values(): kotlin.Array +} + +public final enum class Mixed : kotlin.Enum { + public constructor Mixed() + 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: Mixed!): 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 + + public final class NOT_ENTRY_EITHER { + public constructor NOT_ENTRY_EITHER() + 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 + } + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): Mixed + public final /*synthesized*/ fun values(): kotlin.Array +} + +public final enum class Signs : kotlin.Enum { + enum entry HELLO + + enum entry WORLD + + public constructor Signs() + 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: Signs!): 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 + + public final class NOT_ENTRY_EITHER { + public constructor NOT_ENTRY_EITHER() + 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 + } + + // Static members + public final val X: Signs! + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): Signs + public final /*synthesized*/ fun values(): kotlin.Array +} diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultLongLiteral.kt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultLongLiteral.kt new file mode 100644 index 00000000000..f02358f1c9f --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultLongLiteral.kt @@ -0,0 +1,49 @@ +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; + +public class A { + public void first(@DefaultValue("0x1F") Long value) { + } + + public void second(@DefaultValue("0X1F") Long value) { + } + + public void third(@DefaultValue("0b1010") Long value) { + } + + public void fourth(@DefaultValue("0B1010") Long value) { + } +} + +// FILE: B.java +import kotlin.annotations.jvm.internal.*; + +public class B { + public void first(@DefaultValue("0x") Long value) { + } + + public void second(@DefaultValue("0xZZ") Long value) { + } + + public void third(@DefaultValue("0b") Long value) { + } + + public void fourth(@DefaultValue("0B1234") Long value) { + } +} + +// FILE: test.kt +fun main(a: A, b: B) { + a.first() + a.second() + a.third() + a.fourth() + + b.first() + b.second() + b.third() + b.fourth() +} + diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultLongLiteral.txt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultLongLiteral.txt new file mode 100644 index 00000000000..d5782442f9c --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultLongLiteral.txt @@ -0,0 +1,25 @@ +package + +public fun main(/*0*/ a: A, /*1*/ b: B): kotlin.Unit + +public open class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun first(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "0x1F") value: kotlin.Long! = ...): kotlin.Unit + public open fun fourth(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "0B1010") value: kotlin.Long! = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open fun second(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "0X1F") value: kotlin.Long! = ...): kotlin.Unit + public open fun third(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "0b1010") value: kotlin.Long! = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public open class B { + public constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun first(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "0x") value: kotlin.Long!): kotlin.Unit + public open fun fourth(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "0B1234") value: kotlin.Long!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open fun second(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "0xZZ") value: kotlin.Long!): kotlin.Unit + public open fun third(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "0b") value: kotlin.Long!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNull.kt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNull.kt new file mode 100644 index 00000000000..2e851602818 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNull.kt @@ -0,0 +1,31 @@ +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; + +public class A { + public void foo(@DefaultNull Integer x) {} + public void bar(@DefaultNull int x) {} +} + +// FILE: B.java +import kotlin.annotations.jvm.internal.*; + +public class B { + public void foo(@DefaultNull T t) { } +} + +// FILE: test.kt +fun test(a: A, first: B, second: B) { + a.foo() + a.foo(0) + + a.bar() + a.bar(0) + + first.foo() + first.foo(5) + + second.foo() + second.foo(5) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNull.txt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNull.txt new file mode 100644 index 00000000000..9e8e4faecc2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNull.txt @@ -0,0 +1,20 @@ +package + +public fun test(/*0*/ a: A, /*1*/ first: B, /*2*/ second: B): kotlin.Unit + +public open class A { + public constructor A() + public open fun bar(/*0*/ @kotlin.annotations.jvm.internal.DefaultNull x: kotlin.Int): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun foo(/*0*/ @kotlin.annotations.jvm.internal.DefaultNull x: kotlin.Int! = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public open class B { + public constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun foo(/*0*/ @kotlin.annotations.jvm.internal.DefaultNull t: T! = ...): kotlin.Unit + 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/j+k/signatureAnnotations/defaultNullAndParameter.kt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNullAndParameter.kt new file mode 100644 index 00000000000..c6f326e7877 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNullAndParameter.kt @@ -0,0 +1,57 @@ +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; + +public class A { + public void foo(@DefaultNull Integer i) {} + + public void bar(@DefaultNull Integer a) {} + + public void bam(@DefaultNull Integer a) {} + + public void baz(@DefaultValue("42") Integer a) {} +} + +// FILE: AInt.java +import kotlin.annotations.jvm.internal.*; + +public interface AInt { + public void foo(@DefaultValue("42") Integer i) {} + public void bar(@DefaultNull Integer a) {} +} + +// FILE: B.java +import kotlin.annotations.jvm.internal.*; + +public class B extends A { + public void foo(Integer i) {} + + public void bar(@DefaultValue("42") Integer a) {} + + public void bam(@DefaultNull @DefaultValue("42") Integer a) {} +} + +// FILE: C.java +public class C extends A implements AInt { +} + +// FILE: test.kt + +fun test(b: B, c: C) { + b.foo() + b.foo(5) + b.bar() + b.bar(5) + b.bam() + b.bam(5) + + c.foo() + c.foo(5) + c.bar() + c.bar(5) + c.bam() + c.bam(5) + c.baz() + c.baz(42) +} diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNullAndParameter.txt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNullAndParameter.txt new file mode 100644 index 00000000000..b57b5bf2d79 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNullAndParameter.txt @@ -0,0 +1,44 @@ +package + +public fun test(/*0*/ b: B, /*1*/ c: C): kotlin.Unit + +public open class A { + public constructor A() + public open fun bam(/*0*/ @kotlin.annotations.jvm.internal.DefaultNull a: kotlin.Int! = ...): kotlin.Unit + public open fun bar(/*0*/ @kotlin.annotations.jvm.internal.DefaultNull a: kotlin.Int! = ...): kotlin.Unit + public open fun baz(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "42") a: kotlin.Int! = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun foo(/*0*/ @kotlin.annotations.jvm.internal.DefaultNull i: kotlin.Int! = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface AInt { + public abstract fun bar(/*0*/ @kotlin.annotations.jvm.internal.DefaultNull a: kotlin.Int! = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun foo(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "42") i: kotlin.Int! = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public open class B : A { + public constructor B() + public open override /*1*/ fun bam(/*0*/ @kotlin.annotations.jvm.internal.DefaultNull @kotlin.annotations.jvm.internal.DefaultValue(value = "42") a: kotlin.Int! = ...): kotlin.Unit + public open override /*1*/ fun bar(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "42") a: kotlin.Int! = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun baz(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "42") a: kotlin.Int! = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun foo(/*0*/ i: kotlin.Int! = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public open class C : A, AInt { + public constructor C() + public open override /*1*/ /*fake_override*/ fun bam(/*0*/ @kotlin.annotations.jvm.internal.DefaultNull a: kotlin.Int! = ...): kotlin.Unit + public open override /*2*/ /*fake_override*/ fun bar(/*0*/ @kotlin.annotations.jvm.internal.DefaultNull a: kotlin.Int! = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun baz(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "42") a: kotlin.Int! = ...): kotlin.Unit + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun foo(/*0*/ @kotlin.annotations.jvm.internal.DefaultNull i: kotlin.Int! = ...): kotlin.Unit + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultParameter.kt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultParameter.kt new file mode 100644 index 00000000000..b3e40b48c7b --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultParameter.kt @@ -0,0 +1,45 @@ +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; + +class A { + public void first(@DefaultValue("hello") String value) { + } + + public void second(@DefaultValue("first") String a, @DefaultValue("second") String b) { + } + + public void third(@DefaultValue("first") String a, String b) { + } + + public void fourth(String first, @DefaultValue("second") String second) { + } + + public void wrong(@DefaultValue("hello") Integer i) { + } +} + + +// FILE: test.kt +fun main() { + val a = A() + + a.first() + a.first("arg") + + a.second() + a.second("arg") + a.second("first", "second") + + a.third("OK") + a.third("first", "second") + + a.fourth() + a.fourth("first") + a.fourth("first", "second") + + a.wrong() + a.wrong(42) +} + diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultParameter.txt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultParameter.txt new file mode 100644 index 00000000000..86b96afdc34 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultParameter.txt @@ -0,0 +1,15 @@ +package + +public fun main(): kotlin.Unit + +public/*package*/ open class A { + public/*package*/ constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun first(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "hello") value: kotlin.String! = ...): kotlin.Unit + public open fun fourth(/*0*/ first: kotlin.String!, /*1*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "second") second: kotlin.String! = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open fun second(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "first") a: kotlin.String! = ..., /*1*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "second") b: kotlin.String! = ...): kotlin.Unit + public open fun third(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "first") a: kotlin.String! = ..., /*1*/ b: kotlin.String!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + public open fun wrong(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "hello") i: kotlin.Int!): kotlin.Unit +} diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesDefaultValue.kt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesDefaultValue.kt new file mode 100644 index 00000000000..c92cd863e65 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesDefaultValue.kt @@ -0,0 +1,100 @@ +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; + +class A { + public void first(@DefaultValue("42") int arg) { + } +} + +// FILE: B.java +class B { + public void first(int arg) { + } +} + +// FILE: C.java +import kotlin.annotations.jvm.internal.*; + +class C extends A { + public void first(@DefaultValue("73") int arg) { + } +} + +// FILE: D.java +import kotlin.internal.*; + +class D extends B { + public void first(@DefaultValue("37") int arg) { + } +} + +// FILE: E.java +import kotlin.annotations.jvm.internal.*; + +class E extends A { + public void first(int arg) { + } +} + +// FILE: F.kt +open class F { + open fun foo(x: String = "0") { + } +} + +// FILE: G.java +class G extends F { + public void foo(String y) { + } +} + +// FILE: K.java +import kotlin.annotations.jvm.internal.*; + +public interface K { + public void foo(@DefaultValue("1") String x) { } +} + +// FILE: L.java +import kotlin.annotations.jvm.internal.*; + +public interface L { + public void foo(@DefaultValue("1") String x) { } +} + +// FILE: M.java +public class M implements K, L { + public void foo(String x) { + } +} + +// FILE: main.kt +fun main() { + val a = A() + val c = C() + val d = D() + val e = E() + + val ac: A = C() + val bd: B = D() + + a.first() + c.first() + ac.first() + + d.first() + bd.first() + + e.first() + + val g = G() + g.foo() + g.foo("ok") + + val m = M() + m.foo() + +} + diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesDefaultValue.txt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesDefaultValue.txt new file mode 100644 index 00000000000..6c1c1c5a17e --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesDefaultValue.txt @@ -0,0 +1,81 @@ +package + +public fun main(): kotlin.Unit + +public/*package*/ open class A { + public/*package*/ constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun first(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "42") arg: kotlin.Int = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public/*package*/ open class B { + public/*package*/ constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun first(/*0*/ arg: kotlin.Int): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public/*package*/ open class C : A { + public/*package*/ constructor C() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun first(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "73") arg: kotlin.Int = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public/*package*/ open class D : B { + public/*package*/ constructor D() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun first(/*0*/ @DefaultValue(value = "37") /* annotation class not found */ arg: kotlin.Int): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public/*package*/ open class E : A { + public/*package*/ constructor E() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun first(/*0*/ arg: kotlin.Int = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public open class F { + public constructor F() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun foo(/*0*/ x: kotlin.String = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public/*package*/ open class G : F { + public/*package*/ constructor G() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun foo(/*0*/ x: kotlin.String = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface K { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun foo(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "1") x: kotlin.String! = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface L { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun foo(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "1") x: kotlin.String! = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public open class M : K, L { + public constructor M() + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ fun foo(/*0*/ x: kotlin.String! = ...): kotlin.Unit + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/staticMethodWithDefaultValue.kt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/staticMethodWithDefaultValue.kt new file mode 100644 index 00000000000..6f101ae561b --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/staticMethodWithDefaultValue.kt @@ -0,0 +1,17 @@ +// IGNORE_BACKEND: JS, NATIVE + +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; + +class A { + public static String withDefault(@DefaultValue("OK") String arg) { + return arg; + } +} + +// FILE: test.kt +fun box(): String { + return A.withDefault(); +} diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/staticMethodWithDefaultValue.txt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/staticMethodWithDefaultValue.txt new file mode 100644 index 00000000000..d00162daa33 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/staticMethodWithDefaultValue.txt @@ -0,0 +1,13 @@ +package + +public fun box(): kotlin.String + +public/*package*/ open class A { + public/*package*/ constructor A() + 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 + + // Static members + public open fun withDefault(/*0*/ @kotlin.annotations.jvm.internal.DefaultValue(value = "OK") arg: kotlin.String! = ...): kotlin.String! +} diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 80fddf9ee69..301b9a4d0f5 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -18224,6 +18224,78 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/signatureAnnotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("defaultAndNamedCombination.kt") + public void testDefaultAndNamedCombination() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultAndNamedCombination.kt"); + doTest(fileName); + } + + @TestMetadata("defaultBoxTypes.kt") + public void testDefaultBoxTypes() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultBoxTypes.kt"); + doTest(fileName); + } + + @TestMetadata("defaultEnumType.kt") + public void testDefaultEnumType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultEnumType.kt"); + doTest(fileName); + } + + @TestMetadata("defaultLongLiteral.kt") + public void testDefaultLongLiteral() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultLongLiteral.kt"); + doTest(fileName); + } + + @TestMetadata("defaultMultipleParams.kt") + public void testDefaultMultipleParams() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultMultipleParams.kt"); + doTest(fileName); + } + + @TestMetadata("defaultNull.kt") + public void testDefaultNull() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultNull.kt"); + doTest(fileName); + } + + @TestMetadata("defaultNullableBoxTypes.kt") + public void testDefaultNullableBoxTypes() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultNullableBoxTypes.kt"); + doTest(fileName); + } + + @TestMetadata("defaultOverrides.kt") + public void testDefaultOverrides() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultOverrides.kt"); + doTest(fileName); + } + + @TestMetadata("defaultPrimitiveTypes.kt") + public void testDefaultPrimitiveTypes() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultPrimitiveTypes.kt"); + doTest(fileName); + } + + @TestMetadata("defaultValueInConstructor.kt") + public void testDefaultValueInConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultValueInConstructor.kt"); + doTest(fileName); + } + + @TestMetadata("defaultWithJavaBase.kt") + public void testDefaultWithJavaBase() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultWithJavaBase.kt"); + doTest(fileName); + } + + @TestMetadata("defaultWithKotlinBase.kt") + public void testDefaultWithKotlinBase() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultWithKotlinBase.kt"); + doTest(fileName); + } + @TestMetadata("reorderedParameterNames.kt") public void testReorderedParameterNames() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/reorderedParameterNames.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 317edc170a2..15064c18c99 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -13011,12 +13011,48 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/j+k/signatureAnnotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } + @TestMetadata("defaultEnum.kt") + public void testDefaultEnum() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultEnum.kt"); + doTest(fileName); + } + + @TestMetadata("defaultLongLiteral.kt") + public void testDefaultLongLiteral() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultLongLiteral.kt"); + doTest(fileName); + } + + @TestMetadata("defaultNull.kt") + public void testDefaultNull() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNull.kt"); + doTest(fileName); + } + + @TestMetadata("defaultNullAndParameter.kt") + public void testDefaultNullAndParameter() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNullAndParameter.kt"); + doTest(fileName); + } + + @TestMetadata("defaultParameter.kt") + public void testDefaultParameter() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultParameter.kt"); + doTest(fileName); + } + @TestMetadata("emptyParameterName.kt") public void testEmptyParameterName() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/emptyParameterName.kt"); doTest(fileName); } + @TestMetadata("overridesDefaultValue.kt") + public void testOverridesDefaultValue() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesDefaultValue.kt"); + doTest(fileName); + } + @TestMetadata("overridesParameterName.kt") public void testOverridesParameterName() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesParameterName.kt"); @@ -13046,6 +13082,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/stableParameterName.kt"); doTest(fileName); } + + @TestMetadata("staticMethodWithDefaultValue.kt") + public void testStaticMethodWithDefaultValue() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/staticMethodWithDefaultValue.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/diagnostics/tests/j+k/specialBuiltIns") diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index dece136a297..47b0ff19861 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -13011,12 +13011,48 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/j+k/signatureAnnotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } + @TestMetadata("defaultEnum.kt") + public void testDefaultEnum() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultEnum.kt"); + doTest(fileName); + } + + @TestMetadata("defaultLongLiteral.kt") + public void testDefaultLongLiteral() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultLongLiteral.kt"); + doTest(fileName); + } + + @TestMetadata("defaultNull.kt") + public void testDefaultNull() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNull.kt"); + doTest(fileName); + } + + @TestMetadata("defaultNullAndParameter.kt") + public void testDefaultNullAndParameter() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNullAndParameter.kt"); + doTest(fileName); + } + + @TestMetadata("defaultParameter.kt") + public void testDefaultParameter() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultParameter.kt"); + doTest(fileName); + } + @TestMetadata("emptyParameterName.kt") public void testEmptyParameterName() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/emptyParameterName.kt"); doTest(fileName); } + @TestMetadata("overridesDefaultValue.kt") + public void testOverridesDefaultValue() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesDefaultValue.kt"); + doTest(fileName); + } + @TestMetadata("overridesParameterName.kt") public void testOverridesParameterName() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesParameterName.kt"); @@ -13046,6 +13082,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/stableParameterName.kt"); doTest(fileName); } + + @TestMetadata("staticMethodWithDefaultValue.kt") + public void testStaticMethodWithDefaultValue() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/staticMethodWithDefaultValue.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/diagnostics/tests/j+k/specialBuiltIns") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 3891f05cbea..d1b2baf72eb 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -18224,6 +18224,78 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/signatureAnnotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("defaultAndNamedCombination.kt") + public void testDefaultAndNamedCombination() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultAndNamedCombination.kt"); + doTest(fileName); + } + + @TestMetadata("defaultBoxTypes.kt") + public void testDefaultBoxTypes() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultBoxTypes.kt"); + doTest(fileName); + } + + @TestMetadata("defaultEnumType.kt") + public void testDefaultEnumType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultEnumType.kt"); + doTest(fileName); + } + + @TestMetadata("defaultLongLiteral.kt") + public void testDefaultLongLiteral() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultLongLiteral.kt"); + doTest(fileName); + } + + @TestMetadata("defaultMultipleParams.kt") + public void testDefaultMultipleParams() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultMultipleParams.kt"); + doTest(fileName); + } + + @TestMetadata("defaultNull.kt") + public void testDefaultNull() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultNull.kt"); + doTest(fileName); + } + + @TestMetadata("defaultNullableBoxTypes.kt") + public void testDefaultNullableBoxTypes() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultNullableBoxTypes.kt"); + doTest(fileName); + } + + @TestMetadata("defaultOverrides.kt") + public void testDefaultOverrides() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultOverrides.kt"); + doTest(fileName); + } + + @TestMetadata("defaultPrimitiveTypes.kt") + public void testDefaultPrimitiveTypes() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultPrimitiveTypes.kt"); + doTest(fileName); + } + + @TestMetadata("defaultValueInConstructor.kt") + public void testDefaultValueInConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultValueInConstructor.kt"); + doTest(fileName); + } + + @TestMetadata("defaultWithJavaBase.kt") + public void testDefaultWithJavaBase() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultWithJavaBase.kt"); + doTest(fileName); + } + + @TestMetadata("defaultWithKotlinBase.kt") + public void testDefaultWithKotlinBase() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultWithKotlinBase.kt"); + doTest(fileName); + } + @TestMetadata("reorderedParameterNames.kt") public void testReorderedParameterNames() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/reorderedParameterNames.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index f701eac5501..9f0886b30ab 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -18224,6 +18224,78 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/signatureAnnotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("defaultAndNamedCombination.kt") + public void testDefaultAndNamedCombination() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultAndNamedCombination.kt"); + doTest(fileName); + } + + @TestMetadata("defaultBoxTypes.kt") + public void testDefaultBoxTypes() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultBoxTypes.kt"); + doTest(fileName); + } + + @TestMetadata("defaultEnumType.kt") + public void testDefaultEnumType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultEnumType.kt"); + doTest(fileName); + } + + @TestMetadata("defaultLongLiteral.kt") + public void testDefaultLongLiteral() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultLongLiteral.kt"); + doTest(fileName); + } + + @TestMetadata("defaultMultipleParams.kt") + public void testDefaultMultipleParams() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultMultipleParams.kt"); + doTest(fileName); + } + + @TestMetadata("defaultNull.kt") + public void testDefaultNull() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultNull.kt"); + doTest(fileName); + } + + @TestMetadata("defaultNullableBoxTypes.kt") + public void testDefaultNullableBoxTypes() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultNullableBoxTypes.kt"); + doTest(fileName); + } + + @TestMetadata("defaultOverrides.kt") + public void testDefaultOverrides() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultOverrides.kt"); + doTest(fileName); + } + + @TestMetadata("defaultPrimitiveTypes.kt") + public void testDefaultPrimitiveTypes() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultPrimitiveTypes.kt"); + doTest(fileName); + } + + @TestMetadata("defaultValueInConstructor.kt") + public void testDefaultValueInConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultValueInConstructor.kt"); + doTest(fileName); + } + + @TestMetadata("defaultWithJavaBase.kt") + public void testDefaultWithJavaBase() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultWithJavaBase.kt"); + doTest(fileName); + } + + @TestMetadata("defaultWithKotlinBase.kt") + public void testDefaultWithKotlinBase() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/defaultWithKotlinBase.kt"); + doTest(fileName); + } + @TestMetadata("reorderedParameterNames.kt") public void testReorderedParameterNames() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/reorderedParameterNames.kt"); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java index 8ff42214bfd..884b943dcd9 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java @@ -52,6 +52,8 @@ public final class JvmAnnotationNames { public static final FqName ENHANCED_MUTABILITY_ANNOTATION = new FqName("kotlin.jvm.internal.EnhancedMutability"); public static final FqName PARAMETER_NAME_FQ_NAME = new FqName("kotlin.annotations.jvm.internal.ParameterName"); + public static final FqName DEFAULT_VALUE_FQ_NAME = new FqName("kotlin.annotations.jvm.internal.DefaultValue"); + public static final FqName DEFAULT_NULL_FQ_NAME = new FqName("kotlin.annotations.jvm.internal.DefaultNull"); private JvmAnnotationNames() { } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaCallableMemberDescriptor.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaCallableMemberDescriptor.java index b432a322ff2..5b0f0359709 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaCallableMemberDescriptor.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaCallableMemberDescriptor.java @@ -27,7 +27,7 @@ public interface JavaCallableMemberDescriptor extends CallableMemberDescriptor { @NotNull JavaCallableMemberDescriptor enhance( @Nullable KotlinType enhancedReceiverType, - @NotNull List enhancedValueParametersTypes, + @NotNull List enhancedValueParametersData, @NotNull KotlinType enhancedReturnType ); } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaClassConstructorDescriptor.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaClassConstructorDescriptor.java index d8d3f6671e5..21a21c9fcc5 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaClassConstructorDescriptor.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaClassConstructorDescriptor.java @@ -120,7 +120,7 @@ public class JavaClassConstructorDescriptor extends ClassConstructorDescriptorIm @NotNull public JavaClassConstructorDescriptor enhance( @Nullable KotlinType enhancedReceiverType, - @NotNull List enhancedValueParametersTypes, + @NotNull List enhancedValueParametersData, @NotNull KotlinType enhancedReturnType ) { JavaClassConstructorDescriptor enhanced = createSubstitutedCopy( @@ -130,7 +130,7 @@ public class JavaClassConstructorDescriptor extends ClassConstructorDescriptorIm enhancedReceiverType, getDispatchReceiverParameter(), getTypeParameters(), - UtilKt.copyValueParameters(enhancedValueParametersTypes, getValueParameters(), enhanced), + UtilKt.copyValueParameters(enhancedValueParametersData, getValueParameters(), enhanced), enhancedReturnType, getModality(), getVisibility() diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaMethodDescriptor.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaMethodDescriptor.java index 1bd45e22610..e65c5ce87bd 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaMethodDescriptor.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaMethodDescriptor.java @@ -141,11 +141,11 @@ public class JavaMethodDescriptor extends SimpleFunctionDescriptorImpl implement @NotNull public JavaMethodDescriptor enhance( @Nullable KotlinType enhancedReceiverType, - @NotNull List enhancedValueParametersTypes, + @NotNull List enhancedValueParametersData, @NotNull KotlinType enhancedReturnType ) { List enhancedValueParameters = - UtilKt.copyValueParameters(enhancedValueParametersTypes, getValueParameters(), this); + UtilKt.copyValueParameters(enhancedValueParametersData, getValueParameters(), this); JavaMethodDescriptor enhancedMethod = (JavaMethodDescriptor) newCopyBuilder() diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaPropertyDescriptor.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaPropertyDescriptor.java index 2f6dba9b611..7356124277b 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaPropertyDescriptor.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaPropertyDescriptor.java @@ -92,7 +92,7 @@ public class JavaPropertyDescriptor extends PropertyDescriptorImpl implements Ja @Override public JavaCallableMemberDescriptor enhance( @Nullable KotlinType enhancedReceiverType, - @NotNull List enhancedValueParametersTypes, + @NotNull List enhancedValueParametersData, @NotNull KotlinType enhancedReturnType ) { JavaPropertyDescriptor enhanced = new JavaPropertyDescriptor( diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/util.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/util.kt index 0fdf25d8186..8b3907a84a8 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/util.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/util.kt @@ -32,8 +32,10 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.utils.addToStdlib.safeAs +class ValueParameterData(val type: KotlinType, val hasDefaultValue: Boolean) + fun copyValueParameters( - newValueParametersTypes: Collection, + newValueParametersTypes: Collection, oldValueParameters: Collection, newOwner: CallableDescriptor ): List { @@ -41,20 +43,18 @@ fun copyValueParameters( "Different value parameters sizes: Enhanced = ${newValueParametersTypes.size}, Old = ${oldValueParameters.size}" } - return newValueParametersTypes.zip(oldValueParameters).map { - pair -> - val (newType, oldParameter) = pair + return newValueParametersTypes.zip(oldValueParameters).map { (newParameter, oldParameter) -> ValueParameterDescriptorImpl( newOwner, - oldParameter, + null, oldParameter.index, oldParameter.annotations, oldParameter.name, - newType, - oldParameter.declaresDefaultValue(), + newParameter.type, + newParameter.hasDefaultValue, oldParameter.isCrossinline, oldParameter.isNoinline, - if (oldParameter.varargElementType != null) newOwner.module.builtIns.getArrayElementType(newType) else null, + if (oldParameter.varargElementType != null) newOwner.module.builtIns.getArrayElementType(newParameter.type) else null, oldParameter.source ) } @@ -85,3 +85,19 @@ fun ValueParameterDescriptor.getParameterNameAnnotation(): AnnotationDescriptor? return annotation } +sealed class AnnotationDefaultValue +class StringDefaultValue(val value: String) : AnnotationDefaultValue() +object NullDefaultValue : AnnotationDefaultValue() + +fun ValueParameterDescriptor.getDefaultValueFromAnnotation(): AnnotationDefaultValue? { + annotations.findAnnotation(JvmAnnotationNames.DEFAULT_VALUE_FQ_NAME) + ?.firstArgumentValue() + ?.safeAs() + ?.let { return StringDefaultValue(it) } + + if (annotations.hasAnnotation(JvmAnnotationNames.DEFAULT_NULL_FQ_NAME)) { + return NullDefaultValue + } + + return null +} diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt index a6de88b03b4..d82c268e24d 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt @@ -32,10 +32,7 @@ import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature. import org.jetbrains.kotlin.load.java.BuiltinSpecialProperties.getBuiltinSpecialPropertyGetterName import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils.resolveOverridesForNonStaticMembers import org.jetbrains.kotlin.load.java.components.TypeUsage -import org.jetbrains.kotlin.load.java.descriptors.JavaClassConstructorDescriptor -import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor -import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor -import org.jetbrains.kotlin.load.java.descriptors.copyValueParameters +import org.jetbrains.kotlin.load.java.descriptors.* import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext import org.jetbrains.kotlin.load.java.lazy.childForMethod import org.jetbrains.kotlin.load.java.lazy.resolveAnnotations @@ -50,6 +47,7 @@ import org.jetbrains.kotlin.resolve.DescriptorFactory import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.descriptorUtil.classId +import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter import org.jetbrains.kotlin.storage.NotNullLazyValue @@ -359,7 +357,9 @@ class LazyJavaClassMemberScope( }?.let { override -> override.newCopyBuilder().apply { - setValueParameters(copyValueParameters(overridden.valueParameters.map { it.type }, override.valueParameters, overridden)) + setValueParameters(copyValueParameters( + overridden.valueParameters.map { ValueParameterData(it.type, it.hasDefaultValue()) }, + override.valueParameters, overridden)) setSignatureChange() setPreserveSourceElement() }.build() diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt index d822949db78..8fe579ddc7a 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt @@ -22,9 +22,7 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.composeAnnotations import org.jetbrains.kotlin.load.java.* -import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor -import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor -import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor +import org.jetbrains.kotlin.load.java.descriptors.* import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext import org.jetbrains.kotlin.load.java.lazy.copyWithNewDefaultTypeQualifiers import org.jetbrains.kotlin.load.java.lazy.descriptors.isJavaField @@ -34,6 +32,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.resolve.descriptorUtil.firstArgumentValue import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.asFlexibleType import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.isFlexible @@ -41,7 +40,6 @@ import org.jetbrains.kotlin.types.typeUtil.isTypeParameter import org.jetbrains.kotlin.types.unwrapEnhancement import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import org.jetbrains.kotlin.utils.addToStdlib.safeAs -import java.util.* data class NullabilityQualifierWithMigrationStatus( val qualifier: NullabilityQualifier, @@ -139,9 +137,16 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati } } - val valueParameterEnhancements = annotationOwnerForMember.valueParameters.map { p -> - partsForValueParameter(p, memberContext) { it.valueParameters[p.index].type } - .enhance(predefinedEnhancementInfo?.parametersInfo?.getOrNull(p.index)) + val valueParameterEnhancements = annotationOwnerForMember.valueParameters.map { + p -> + val enhancementResult =partsForValueParameter(p, memberContext) { it.valueParameters[p.index].type } + .enhance(predefinedEnhancementInfo?.parametersInfo?.getOrNull(p.index)) + + val actualType = if (enhancementResult.wereChanges) enhancementResult.type else p.type + val hasDefaultValue = p.hasDefaultValueInAnnotation(actualType) + val wereChanges = enhancementResult.wereChanges || (hasDefaultValue != p.declaresDefaultValue()) + + ValueParameterEnhancementResult(enhancementResult.type, hasDefaultValue, wereChanges) } val returnTypeEnhancement = @@ -155,15 +160,26 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati AnnotationTypeQualifierResolver.QualifierApplicabilityType.METHOD_RETURN_TYPE ) { it.returnType!! }.enhance(predefinedEnhancementInfo?.returnTypeInfo) - if ((receiverTypeEnhancement?.wereChanges ?: false) + if ((receiverTypeEnhancement?.wereChanges == true) || returnTypeEnhancement.wereChanges || valueParameterEnhancements.any { it.wereChanges }) { @Suppress("UNCHECKED_CAST") - return this.enhance(receiverTypeEnhancement?.type, valueParameterEnhancements.map { it.type }, returnTypeEnhancement.type) as D + return this.enhance(receiverTypeEnhancement?.type, + valueParameterEnhancements.map { ValueParameterData(it.type, it.hasDefaultValue) }, returnTypeEnhancement.type) as D } return this } + private fun ValueParameterDescriptor.hasDefaultValueInAnnotation(type: KotlinType): Boolean { + val defaultValue = getDefaultValueFromAnnotation() + + return when (defaultValue) { + is StringDefaultValue -> type.lexicalCastFrom(defaultValue.value) != null + NullDefaultValue -> TypeUtils.acceptsNullable(type) + null -> declaresDefaultValue() + } && overriddenDescriptors.isEmpty() + } + private inner class SignatureParts( private val typeContainer: Annotated?, private val fromOverride: KotlinType, @@ -355,7 +371,12 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati } - private data class PartEnhancementResult(val type: KotlinType, val wereChanges: Boolean) + private open class PartEnhancementResult(val type: KotlinType, val wereChanges: Boolean) + private class ValueParameterEnhancementResult( + type: KotlinType, + val hasDefaultValue: Boolean, + wereChanges: Boolean + ) : PartEnhancementResult(type, wereChanges) private fun CallableMemberDescriptor.partsForValueParameter( // TODO: investigate if it's really can be a null (check properties' with extension overrides in Java) @@ -388,7 +409,6 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati containerApplicabilityType ) } - } private fun createJavaTypeQualifiers( diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/utils.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/utils.kt new file mode 100644 index 00000000000..1f86dadc0ad --- /dev/null +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/utils.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.load.java + +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.typeUtil.makeNotNullable +import org.jetbrains.kotlin.utils.extractRadix + +sealed class JavaDefaultValue +class EnumEntry(val descriptor: ClassDescriptor) : JavaDefaultValue() +class Constant(val value: Any) : JavaDefaultValue() + +fun KotlinType.lexicalCastFrom(value: String): JavaDefaultValue? { + val typeDescriptor = constructor.declarationDescriptor + if (typeDescriptor is ClassDescriptor && typeDescriptor.kind == ClassKind.ENUM_CLASS) { + val descriptor = typeDescriptor.unsubstitutedInnerClassesScope.getContributedClassifier( + Name.identifier(value), + NoLookupLocation.FROM_BACKEND + ) + + return if (descriptor is ClassDescriptor && descriptor.kind == ClassKind.ENUM_ENTRY) EnumEntry(descriptor) else null + } + + val type = this.makeNotNullable() + val (number, radix) = extractRadix(value) + val result: Any? = try { + when { + KotlinBuiltIns.isBoolean(type) -> value.toBoolean() + KotlinBuiltIns.isChar(type) -> value.singleOrNull() + KotlinBuiltIns.isByte(type) -> number.toByteOrNull(radix) + KotlinBuiltIns.isShort(type) -> number.toShortOrNull(radix) + KotlinBuiltIns.isInt(type) -> number.toIntOrNull(radix) + KotlinBuiltIns.isLong(type) -> number.toLongOrNull(radix) + KotlinBuiltIns.isFloat(type) -> value.toFloatOrNull() + KotlinBuiltIns.isDouble(type) -> value.toDoubleOrNull() + KotlinBuiltIns.isString(type) -> value + else -> null + } + } catch (e: IllegalArgumentException) { + null + } + + return if (result != null) Constant(result) else null +} \ No newline at end of file diff --git a/core/util.runtime/src/org/jetbrains/kotlin/utils/numbers.kt b/core/util.runtime/src/org/jetbrains/kotlin/utils/numbers.kt new file mode 100644 index 00000000000..30e872e9725 --- /dev/null +++ b/core/util.runtime/src/org/jetbrains/kotlin/utils/numbers.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.utils + +data class NumberWithRadix(val number: String, val radix: Int) + +fun extractRadix(value: String): NumberWithRadix = when { + value.startsWith("0x") || value.startsWith("0X") -> NumberWithRadix(value.substring(2), 16) + value.startsWith("0b") || value.startsWith("0B") -> NumberWithRadix(value.substring(2), 2) + else -> NumberWithRadix(value, 10) +} diff --git a/libraries/tools/android-annotations/src/kotlin/Annotations.kt b/libraries/tools/android-annotations/src/kotlin/Annotations.kt index 10cabe9f569..641e675fe5c 100644 --- a/libraries/tools/android-annotations/src/kotlin/Annotations.kt +++ b/libraries/tools/android-annotations/src/kotlin/Annotations.kt @@ -22,3 +22,17 @@ package kotlin.annotations.jvm.internal @Target(AnnotationTarget.VALUE_PARAMETER) @Retention(AnnotationRetention.BINARY) public annotation class ParameterName(val value: String) + +/** + * Default value for java method parameter. + */ +@Target(AnnotationTarget.VALUE_PARAMETER) +@Retention(AnnotationRetention.BINARY) +public annotation class DefaultValue(val value: String) + +/** + * Define that null is default value for method parameter. + */ +@Target(AnnotationTarget.VALUE_PARAMETER) +@Retention(AnnotationRetention.BINARY) +public annotation class DefaultNull