Add annotation for default parameter value
This commit is contained in:
@@ -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()
|
||||
}
|
||||
)
|
||||
|
||||
@@ -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<ArgumentAndDeclIndex> actualArgsWithDeclIndex) {
|
||||
callGenerator.reorderArgumentsIfNeeded(actualArgsWithDeclIndex, valueParameterTypes);
|
||||
|
||||
@@ -1467,7 +1467,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
if (isAnonymousObject(descriptor)) {
|
||||
List<JvmMethodParameterSignature> 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(),
|
||||
|
||||
@@ -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<JvmMethodParameterSignature>,
|
||||
private val iv: InstructionAdapter,
|
||||
private val superValueParameters: List<ValueParameterDescriptor>,
|
||||
private val typeMapper: KotlinTypeMapper,
|
||||
offset: Int,
|
||||
superConstructorCall: ResolvedCall<ConstructorDescriptor>
|
||||
) : 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)
|
||||
}
|
||||
|
||||
@@ -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<ValueParameterDescriptor, ValueParameterDescriptor?>() {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user