Code clean, small refactorings and tests
#KT-8987 Fixed
This commit is contained in:
@@ -16,25 +16,24 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
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.mapToIndex
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import java.util.*
|
||||
|
||||
class ArgumentAndIndex(val arg: ResolvedValueArgument, val declIndex: Int, var type: Type? = null, var reorder: Boolean = false, var tempValue: StackValue? = null)
|
||||
class ArgumentAndDeclIndex(val arg: ResolvedValueArgument, val declIndex: Int)
|
||||
|
||||
abstract class ArgumentGenerator {
|
||||
/**
|
||||
* @return a `List` of bit masks of default arguments that should be passed as last arguments to $default method, if there were
|
||||
* * any default arguments, or an empty `List` if there were none
|
||||
* *
|
||||
* any default arguments, or an empty `List` if there were none
|
||||
*
|
||||
* @see kotlin.reflect.jvm.internal.KCallableImpl.callBy
|
||||
* @param valueArgumentsByIndex
|
||||
* *
|
||||
* @param actualArgs
|
||||
*/
|
||||
open fun generate(valueArgumentsByIndex: List<ResolvedValueArgument>, actualArgs: List<ResolvedValueArgument>, codegen: ExpressionCodegen): DefaultCallMask {
|
||||
open fun generate(valueArgumentsByIndex: List<ResolvedValueArgument>, actualArgs: List<ResolvedValueArgument>): DefaultCallMask {
|
||||
//HACK: see tempVariable in ExpressionCodegen
|
||||
assert (valueArgumentsByIndex.size() == actualArgs.size())
|
||||
val actualArguments = if (actualArgs.isNotEmpty()) actualArgs else valueArgumentsByIndex
|
||||
|
||||
assert(valueArgumentsByIndex.size() == actualArguments.size()) {
|
||||
@@ -43,24 +42,23 @@ abstract class ArgumentGenerator {
|
||||
|
||||
val arg2Index = valueArgumentsByIndex.mapToIndex()
|
||||
|
||||
val actualArgsWithDeclIndex: ArrayList<ArgumentAndIndex> = ArrayList(actualArguments.filter { it !is DefaultValueArgument }.map {
|
||||
ArgumentAndIndex(it, arg2Index[it]!!)
|
||||
})
|
||||
val actualArgsWithDeclIndex = actualArguments.filter { it !is DefaultValueArgument }.map {
|
||||
ArgumentAndDeclIndex(it, arg2Index[it]!!)
|
||||
}.toArrayList()
|
||||
|
||||
valueArgumentsByIndex.withIndex().forEach {
|
||||
if (it.value is DefaultValueArgument) {
|
||||
actualArgsWithDeclIndex.add(it.index, ArgumentAndIndex(it.value, it.index))
|
||||
actualArgsWithDeclIndex.add(it.index, ArgumentAndDeclIndex(it.value, it.index))
|
||||
}
|
||||
}
|
||||
|
||||
val masks = DefaultCallMask(valueArgumentsByIndex.size())
|
||||
var orderChanged = false
|
||||
|
||||
for ((actualIndex, argumentWithDeclIndex) in actualArgsWithDeclIndex.withIndex()) {
|
||||
for (argumentWithDeclIndex in actualArgsWithDeclIndex) {
|
||||
val argument = argumentWithDeclIndex.arg
|
||||
val declIndex = argumentWithDeclIndex.declIndex
|
||||
|
||||
argumentWithDeclIndex.type = when (argument) {
|
||||
when (argument) {
|
||||
is ExpressionValueArgument -> {
|
||||
generateExpression(declIndex, argument)
|
||||
}
|
||||
@@ -75,11 +73,6 @@ abstract class ArgumentGenerator {
|
||||
generateOther(declIndex, argument)
|
||||
}
|
||||
}
|
||||
|
||||
if (actualIndex != declIndex || orderChanged) {
|
||||
orderChanged = true
|
||||
argumentWithDeclIndex.reorder = true
|
||||
}
|
||||
}
|
||||
|
||||
reorderArgumentsIfNeeded(actualArgsWithDeclIndex)
|
||||
@@ -87,23 +80,23 @@ abstract class ArgumentGenerator {
|
||||
return masks
|
||||
}
|
||||
|
||||
protected open fun generateExpression(i: Int, argument: ExpressionValueArgument): Type {
|
||||
protected open fun generateExpression(i: Int, argument: ExpressionValueArgument) {
|
||||
throw UnsupportedOperationException("Unsupported expression value argument #$i: $argument")
|
||||
}
|
||||
|
||||
protected open fun generateDefault(i: Int, argument: DefaultValueArgument): Type {
|
||||
protected open fun generateDefault(i: Int, argument: DefaultValueArgument) {
|
||||
throw UnsupportedOperationException("Unsupported default value argument #$i: $argument")
|
||||
}
|
||||
|
||||
protected open fun generateVararg(i: Int, argument: VarargValueArgument): Type {
|
||||
protected open fun generateVararg(i: Int, argument: VarargValueArgument) {
|
||||
throw UnsupportedOperationException("Unsupported vararg value argument #$i: $argument")
|
||||
}
|
||||
|
||||
protected open fun generateOther(i: Int, argument: ResolvedValueArgument): Type {
|
||||
protected open fun generateOther(i: Int, argument: ResolvedValueArgument) {
|
||||
throw UnsupportedOperationException("Unsupported value argument #$i: $argument")
|
||||
}
|
||||
|
||||
protected open fun reorderArgumentsIfNeeded(args: ArrayList<ArgumentAndIndex>) {
|
||||
protected open fun reorderArgumentsIfNeeded(args: List<ArgumentAndDeclIndex>) {
|
||||
throw UnsupportedOperationException("Unsupported operation")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.psi.ValueArgument;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.pushDefaultValueOnStack;
|
||||
@@ -54,19 +53,17 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator {
|
||||
@Override
|
||||
public DefaultCallMask generate(
|
||||
@NotNull List<? extends ResolvedValueArgument> valueArgumentsByIndex,
|
||||
@NotNull List<? extends ResolvedValueArgument> valueArgs,
|
||||
@NotNull ExpressionCodegen codegen
|
||||
@NotNull List<? extends ResolvedValueArgument> valueArgs
|
||||
) {
|
||||
boolean shouldMarkLineNumbers = this.codegen.isShouldMarkLineNumbers();
|
||||
this.codegen.setShouldMarkLineNumbers(false);
|
||||
DefaultCallMask masks = super.generate(valueArgumentsByIndex, valueArgs, codegen);
|
||||
DefaultCallMask masks = super.generate(valueArgumentsByIndex, valueArgs);
|
||||
this.codegen.setShouldMarkLineNumbers(shouldMarkLineNumbers);
|
||||
return masks;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Type generateExpression(int i, @NotNull ExpressionValueArgument argument) {
|
||||
protected void generateExpression(int i, @NotNull ExpressionValueArgument argument) {
|
||||
ValueParameterDescriptor parameter = valueParameters.get(i);
|
||||
Type type = valueParameterTypes.get(i);
|
||||
ValueArgument valueArgument = argument.getValueArgument();
|
||||
@@ -74,31 +71,26 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator {
|
||||
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
||||
assert argumentExpression != null : valueArgument.asElement().getText();
|
||||
callGenerator.genValueAndPut(parameter, argumentExpression, type, i);
|
||||
return type;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Type generateDefault(int i, @NotNull DefaultValueArgument argument) {
|
||||
protected void generateDefault(int i, @NotNull DefaultValueArgument argument) {
|
||||
ValueParameterDescriptor parameter = valueParameters.get(i);
|
||||
Type type = valueParameterTypes.get(i);
|
||||
pushDefaultValueOnStack(type, codegen.v);
|
||||
callGenerator.afterParameterPut(type, null, parameter, i);
|
||||
return type;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Type generateVararg(int i, @NotNull VarargValueArgument argument) {
|
||||
protected void generateVararg(int i, @NotNull VarargValueArgument argument) {
|
||||
ValueParameterDescriptor parameter = valueParameters.get(i);
|
||||
Type type = valueParameterTypes.get(i);
|
||||
codegen.genVarargs(argument, parameter.getType());
|
||||
callGenerator.afterParameterPut(type, null, parameter, i);
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reorderArgumentsIfNeeded(@NotNull ArrayList<ArgumentAndIndex> actualArgsWithDeclIndex) {
|
||||
callGenerator.reorderArgumentsIfNeeded(actualArgsWithDeclIndex);
|
||||
protected void reorderArgumentsIfNeeded(@NotNull List<? extends ArgumentAndDeclIndex> actualArgsWithDeclIndex) {
|
||||
callGenerator.reorderArgumentsIfNeeded(actualArgsWithDeclIndex, valueParameterTypes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@ import org.jetbrains.kotlin.psi.JetExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
abstract class CallGenerator {
|
||||
|
||||
internal class DefaultCallGenerator(private val codegen: ExpressionCodegen) : CallGenerator() {
|
||||
@@ -41,8 +39,8 @@ abstract class CallGenerator {
|
||||
}
|
||||
|
||||
override fun genCallWithoutAssertions(
|
||||
method: CallableMethod, codegen: ExpressionCodegen) {
|
||||
method.genInvokeInstruction(codegen.v)
|
||||
callableMethod: CallableMethod, codegen: ExpressionCodegen) {
|
||||
callableMethod.genInvokeInstruction(codegen.v)
|
||||
}
|
||||
|
||||
override fun afterParameterPut(
|
||||
@@ -61,7 +59,7 @@ abstract class CallGenerator {
|
||||
valueParameterDescriptor: ValueParameterDescriptor,
|
||||
argumentExpression: JetExpression,
|
||||
parameterType: Type,
|
||||
index: Int) {
|
||||
parameterIndex: Int) {
|
||||
val value = codegen.gen(argumentExpression)
|
||||
value.put(parameterType, codegen.v)
|
||||
}
|
||||
@@ -76,22 +74,23 @@ abstract class CallGenerator {
|
||||
value.put(value.type, codegen.v)
|
||||
}
|
||||
|
||||
override fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: ArrayList<ArgumentAndIndex>) {
|
||||
override fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>) {
|
||||
val mark = codegen.myFrameMap.mark()
|
||||
actualArgsWithDeclIndex.reversed().forEach {
|
||||
if (it.reorder) {
|
||||
val type = it.type!!
|
||||
it.tempValue = StackValue.local(codegen.frameMap.enterTemp(type), type)
|
||||
it.tempValue?.store(StackValue.onStack(type), codegen.v)
|
||||
}
|
||||
val reordered = actualArgsWithDeclIndex.withIndex().dropWhile {
|
||||
it.value.declIndex == it.index
|
||||
}
|
||||
|
||||
actualArgsWithDeclIndex.sortedBy { it.declIndex }.forEach {
|
||||
it.tempValue?.let {
|
||||
it.put(it.type, codegen.v)
|
||||
}
|
||||
reordered.reversed().map {
|
||||
val argumentAndDeclIndex = it.value
|
||||
val type = valueParameterTypes.get(argumentAndDeclIndex.declIndex)
|
||||
val stackValue = StackValue.local(codegen.frameMap.enterTemp(type), type)
|
||||
stackValue.store(StackValue.onStack(type), codegen.v)
|
||||
Pair(argumentAndDeclIndex.declIndex, stackValue)
|
||||
}.sortedBy {
|
||||
it.first
|
||||
}.forEach {
|
||||
it.second.put(valueParameterTypes.get(it.first), codegen.v)
|
||||
}
|
||||
|
||||
mark.dropTo()
|
||||
}
|
||||
}
|
||||
@@ -134,5 +133,5 @@ abstract class CallGenerator {
|
||||
|
||||
abstract fun putHiddenParams()
|
||||
|
||||
abstract fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: ArrayList<ArgumentAndIndex>)
|
||||
abstract fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>)
|
||||
}
|
||||
|
||||
@@ -1486,7 +1486,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
ArgumentGenerator argumentGenerator =
|
||||
new CallBasedArgumentGenerator(ExpressionCodegen.this, defaultCallGenerator, valueParameters, mappedTypes);
|
||||
|
||||
argumentGenerator.generate(valueArguments, valueArguments, ExpressionCodegen.this);
|
||||
argumentGenerator.generate(valueArguments, valueArguments);
|
||||
}
|
||||
|
||||
Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
|
||||
@@ -2455,7 +2455,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
assert valueArguments != null : "Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor();
|
||||
|
||||
List<Integer> masks =
|
||||
argumentGenerator.generate(valueArguments, new ArrayList<ResolvedValueArgument>(resolvedCall.getValueArguments().values()), this)
|
||||
argumentGenerator.generate(valueArguments, new ArrayList<ResolvedValueArgument>(resolvedCall.getValueArguments().values()))
|
||||
.toInts();
|
||||
|
||||
if (tailRecursionCodegen.isTailRecursion(resolvedCall)) {
|
||||
|
||||
@@ -1643,35 +1643,30 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
this.offset = firstValueParamOffset;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Type generateExpression(int i, @NotNull ExpressionValueArgument argument) {
|
||||
return generateSuperCallArgument(i);
|
||||
public void generateExpression(int i, @NotNull ExpressionValueArgument argument) {
|
||||
generateSuperCallArgument(i);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Type generateDefault(int i, @NotNull DefaultValueArgument argument) {
|
||||
public void generateDefault(int i, @NotNull DefaultValueArgument argument) {
|
||||
Type type = parameters.get(i).getAsmType();
|
||||
pushDefaultValueOnStack(type, iv);
|
||||
return type;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Type generateVararg(int i, @NotNull VarargValueArgument argument) {
|
||||
return generateSuperCallArgument(i);
|
||||
public void generateVararg(int i, @NotNull VarargValueArgument argument) {
|
||||
generateSuperCallArgument(i);
|
||||
}
|
||||
|
||||
private Type generateSuperCallArgument(int i) {
|
||||
private void generateSuperCallArgument(int i) {
|
||||
Type type = parameters.get(i).getAsmType();
|
||||
iv.load(offset, type);
|
||||
offset += type.getSize();
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reorderArgumentsIfNeeded(@NotNull ArrayList<ArgumentAndIndex> args) {
|
||||
protected void reorderArgumentsIfNeeded(@NotNull List<? extends ArgumentAndDeclIndex> args) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -769,7 +769,7 @@ public abstract class StackValue {
|
||||
ResolvedCall<?> call = isGetter ? resolvedGetCall : resolvedSetCall;
|
||||
StackValue newReceiver = StackValue.receiver(call, receiver, codegen, callable);
|
||||
newReceiver.put(newReceiver.type, v);
|
||||
argumentGenerator.generate(valueArguments, valueArguments, codegen);
|
||||
argumentGenerator.generate(valueArguments, valueArguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -520,8 +520,8 @@ public class InlineCodegen extends CallGenerator {
|
||||
}
|
||||
|
||||
invocationParamBuilder.markValueParametesStart();
|
||||
List<ParameterInfo> infos = invocationParamBuilder.listNotCaptured();
|
||||
recordParameterValueInLocalVal(infos.toArray(new ParameterInfo[infos.size()]));
|
||||
List<ParameterInfo> hiddenParameters = invocationParamBuilder.buildParameters().getReal();
|
||||
recordParameterValueInLocalVal(hiddenParameters.toArray(new ParameterInfo[hiddenParameters.size()]));
|
||||
}
|
||||
|
||||
public void leaveTemps() {
|
||||
@@ -772,7 +772,9 @@ public class InlineCodegen extends CallGenerator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reorderArgumentsIfNeeded(@NotNull ArrayList<ArgumentAndIndex> actualArgsWithDeclIndex) {
|
||||
public void reorderArgumentsIfNeeded(
|
||||
@NotNull List<? extends ArgumentAndDeclIndex> actualArgsWithDeclIndex, @NotNull List<? extends Type> valueParameterTypes
|
||||
) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import static org.jetbrains.kotlin.codegen.inline.LocalVarRemapper.RemapStatus.*
|
||||
|
||||
public class LocalVarRemapper {
|
||||
|
||||
private final int allParamsSize;
|
||||
private final Parameters params;
|
||||
private final int actualParamsSize;
|
||||
|
||||
@@ -38,36 +37,19 @@ public class LocalVarRemapper {
|
||||
|
||||
public LocalVarRemapper(Parameters params, int additionalShift) {
|
||||
this.additionalShift = additionalShift;
|
||||
this.allParamsSize = params.getArgsSizeOnStack();
|
||||
this.params = params;
|
||||
|
||||
remapValues = new StackValue [params.getArgsSizeOnStack()];
|
||||
Integer [] declIndexesToActual = new Integer [params.getArgsSizeOnStack()];
|
||||
Integer [] actualDeclShifts = new Integer [params.getArgsSizeOnStack()];
|
||||
|
||||
int index = 0;
|
||||
for (ParameterInfo param : params) {
|
||||
declIndexesToActual[param.declarationIndex] = index;
|
||||
index++;
|
||||
}
|
||||
|
||||
int realSize = 0;
|
||||
for (int i = 0; i < declIndexesToActual.length; i++) {
|
||||
Integer declIndexToActual = declIndexesToActual[i];
|
||||
if (declIndexToActual != null) {
|
||||
actualDeclShifts[i] = realSize;
|
||||
realSize += params.get(declIndexToActual).getType().getSize();
|
||||
}
|
||||
}
|
||||
|
||||
realSize = 0;
|
||||
for (ParameterInfo info : params) {
|
||||
Integer shift = params.getDeclarationSlot(info);
|
||||
if (!info.isSkippedOrRemapped()) {
|
||||
remapValues[actualDeclShifts[info.declarationIndex]] = StackValue.local(realSize, AsmTypes.OBJECT_TYPE);
|
||||
remapValues[shift] = StackValue.local(realSize, AsmTypes.OBJECT_TYPE);
|
||||
realSize += info.getType().getSize();
|
||||
}
|
||||
else {
|
||||
remapValues[actualDeclShifts[info.declarationIndex]] = info.isRemapped() ? info.getRemapValue() : null;
|
||||
remapValues[shift] = info.isRemapped() ? info.getRemapValue() : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,8 +59,8 @@ public class LocalVarRemapper {
|
||||
public RemapInfo doRemap(int index) {
|
||||
int remappedIndex;
|
||||
|
||||
if (index < allParamsSize) {
|
||||
ParameterInfo info = params.getByByteCodeIndex(index);
|
||||
if (index < params.getArgsSizeOnStack()) {
|
||||
ParameterInfo info = params.getParameterByDeclarationSlot(index);
|
||||
StackValue remapped = remapValues[index];
|
||||
if (info.isSkipped || remapped == null) {
|
||||
return new RemapInfo(info);
|
||||
|
||||
@@ -312,7 +312,7 @@ public class MethodInliner {
|
||||
Type[] types = Type.getArgumentTypes(node.desc);
|
||||
Type returnType = Type.getReturnType(node.desc);
|
||||
|
||||
ArrayList<Type> capturedTypes = parameters.getCapturedTypes();
|
||||
List<Type> capturedTypes = parameters.getCapturedTypes();
|
||||
Type[] allTypes = ArrayUtil.mergeArrays(types, capturedTypes.toArray(new Type[capturedTypes.size()]));
|
||||
|
||||
node.instructions.resetLabels();
|
||||
@@ -559,7 +559,7 @@ public class MethodInliner {
|
||||
|
||||
private LambdaInfo getLambdaIfExists(int varIndex) {
|
||||
if (varIndex < parameters.getArgsSizeOnStack()) {
|
||||
return parameters.getByByteCodeIndex(varIndex).getLambda();
|
||||
return parameters.getParameterByDeclarationSlot(varIndex).getLambda();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -16,24 +16,21 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import com.google.common.collect.Iterables
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import java.util.*
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
//All parameters with gaps
|
||||
class Parameters(val real: List<ParameterInfo>, val captured: List<CapturedParamInfo>) : Iterable<ParameterInfo> {
|
||||
|
||||
private val declIndexesToActual: Array<Int?>
|
||||
private val actualDeclShifts: Array<ParameterInfo?>
|
||||
private val paramToDeclByteCodeIndex: HashMap<ParameterInfo, Int> = hashMapOf()
|
||||
|
||||
public val realArgsSizeOnStack = real.fold(0, { a, v -> a + v.type.size})
|
||||
public val capturedArgsSizeOnStack = captured.fold(0, { a, v -> a + v.type.size})
|
||||
public val realArgsSizeOnStack = real.sumBy { it.type.size }
|
||||
public val capturedArgsSizeOnStack = captured.sumBy { it.type.size }
|
||||
|
||||
public val argsSizeOnStack = realArgsSizeOnStack + capturedArgsSizeOnStack
|
||||
|
||||
init {
|
||||
declIndexesToActual = arrayOfNulls<Int>(argsSizeOnStack)
|
||||
val declIndexesToActual = arrayOfNulls<Int>(argsSizeOnStack)
|
||||
withIndex().forEach { it ->
|
||||
declIndexesToActual[it.value.declarationIndex] = it.index
|
||||
}
|
||||
@@ -41,27 +38,22 @@ class Parameters(val real: List<ParameterInfo>, val captured: List<CapturedParam
|
||||
actualDeclShifts = arrayOfNulls<ParameterInfo>(argsSizeOnStack)
|
||||
var realSize = 0
|
||||
for (i in declIndexesToActual.indices) {
|
||||
val declIndexToActual = declIndexesToActual[i]
|
||||
if (declIndexToActual != null) {
|
||||
val byDeclarationIndex = getByDeclarationIndex(i)
|
||||
actualDeclShifts[realSize] = byDeclarationIndex
|
||||
realSize += byDeclarationIndex.type.size
|
||||
}
|
||||
val byDeclarationIndex = get(declIndexesToActual[i] ?: continue)
|
||||
actualDeclShifts[realSize] = byDeclarationIndex
|
||||
paramToDeclByteCodeIndex.put(byDeclarationIndex, realSize)
|
||||
realSize += byDeclarationIndex.type.size
|
||||
}
|
||||
}
|
||||
|
||||
fun getByDeclarationIndex(index: Int): ParameterInfo {
|
||||
if (index < realArgsSizeOnStack) {
|
||||
return real.get(declIndexesToActual[index]!!)
|
||||
}
|
||||
return captured.get(declIndexesToActual[index]!! - real.size())
|
||||
fun getDeclarationSlot(info : ParameterInfo): Int {
|
||||
return paramToDeclByteCodeIndex[info]!!
|
||||
}
|
||||
|
||||
fun getByByteCodeIndex(index: Int): ParameterInfo {
|
||||
fun getParameterByDeclarationSlot(index: Int): ParameterInfo {
|
||||
return actualDeclShifts[index]!!
|
||||
}
|
||||
|
||||
fun get(index: Int): ParameterInfo {
|
||||
private fun get(index: Int): ParameterInfo {
|
||||
if (index < real.size()) {
|
||||
return real.get(index)
|
||||
}
|
||||
@@ -69,26 +61,17 @@ class Parameters(val real: List<ParameterInfo>, val captured: List<CapturedParam
|
||||
}
|
||||
|
||||
override fun iterator(): Iterator<ParameterInfo> {
|
||||
return Iterables.concat(real, captured).iterator()
|
||||
return (real + captured).iterator()
|
||||
}
|
||||
|
||||
val capturedTypes: ArrayList<Type>
|
||||
get() {
|
||||
val result = ArrayList<Type>()
|
||||
for (info in captured) {
|
||||
result.add(info.getType())
|
||||
}
|
||||
return result
|
||||
val capturedTypes: List<Type>
|
||||
get() = captured.map {
|
||||
it.getType()
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun shift(capturedParams: List<CapturedParamInfo>, realSize: Int): List<CapturedParamInfo> {
|
||||
val result = ArrayList<CapturedParamInfo>()
|
||||
for (capturedParamInfo in capturedParams) {
|
||||
val newInfo = capturedParamInfo.newIndex(result.size() + realSize)
|
||||
result.add(newInfo)
|
||||
}
|
||||
return result
|
||||
return capturedParams.withIndex().map { it.value.newIndex(it.index+ realSize) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,10 +100,6 @@ class ParametersBuilder private constructor(){
|
||||
return info
|
||||
}
|
||||
|
||||
fun listNotCaptured(): List<ParameterInfo> {
|
||||
return Collections.unmodifiableList(valueAndHiddenParams)
|
||||
}
|
||||
|
||||
fun markValueParametesStart(){
|
||||
this.valueParamStart = valueAndHiddenParams.size()
|
||||
}
|
||||
@@ -118,7 +114,7 @@ class ParametersBuilder private constructor(){
|
||||
}
|
||||
|
||||
fun buildParameters(): Parameters {
|
||||
return Parameters(listNotCaptured(), Parameters.shift(listCaptured(), nextValueParameterIndex))
|
||||
return Parameters(Collections.unmodifiableList(valueAndHiddenParams), Parameters.shift(listCaptured(), nextValueParameterIndex))
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
fun box(): String {
|
||||
var invokeOrder = "";
|
||||
val expectedResult = "0_1_9"
|
||||
val expectedInvokeOrder = "1_0_9"
|
||||
var l = 1L
|
||||
var i = 0
|
||||
val captured = 9L
|
||||
|
||||
var result = test(b = {invokeOrder += "1_"; l}(), a = {invokeOrder+="0_"; i}(), c = {invokeOrder += "$captured"; "$captured"})
|
||||
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 1: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||
|
||||
invokeOrder = "";
|
||||
result = test(b = {invokeOrder += "1_"; l}(), c = {invokeOrder += "$captured"; "$captured"}, a = {invokeOrder+="0_"; i}())
|
||||
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 2: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||
|
||||
|
||||
invokeOrder = "";
|
||||
result = test(c = {invokeOrder += "$captured"; "$captured"}, b = {invokeOrder += "1_"; l}(), a = {invokeOrder+="0_"; i}())
|
||||
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 3: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||
|
||||
|
||||
invokeOrder = "";
|
||||
result = test(a = {invokeOrder+="0_"; i}(), c = {invokeOrder += "$captured"; "$captured"}, b = {invokeOrder += "1_"; l}())
|
||||
if (invokeOrder != "0_1_9" || result != expectedResult) return "fail 4: $invokeOrder != 0_1_9 or $result != $expectedResult"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun test(a: Int, b: Long, c: () -> String): String {
|
||||
return { "${a}_${b}_${c()}"} ()
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
fun box(): String {
|
||||
var invokeOrder = "";
|
||||
val expectedResult = "1.0_0_1_9"
|
||||
val expectedInvokeOrder = "1_0_9"
|
||||
var l = 1L
|
||||
var i = 0
|
||||
val captured = 9L
|
||||
|
||||
var result = 1.0.test(b = {invokeOrder += "1_"; l}(), a = {invokeOrder+="0_"; i}(), c = {invokeOrder += "$captured"; "$captured"})
|
||||
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 1: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||
|
||||
invokeOrder = "";
|
||||
result = 1.0.test(b = {invokeOrder += "1_"; l}(), c = {invokeOrder += "${captured}"; "${captured}"}, a = {invokeOrder+="0_"; i}())
|
||||
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 2: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||
|
||||
|
||||
invokeOrder = "";
|
||||
result = 1.0.test(c = {invokeOrder += "${captured}"; "${captured}"}, b = {invokeOrder += "1_"; l}(), a = {invokeOrder+="0_"; i}())
|
||||
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 3: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||
|
||||
invokeOrder = "";
|
||||
result = 1.0.test(a = {invokeOrder+="0_"; i}(), c = {invokeOrder += "${captured}"; "${captured}"}, b = {invokeOrder += "1_"; l}())
|
||||
if (invokeOrder != "0_1_9" || result != expectedResult) return "fail 4: $invokeOrder != 0_1_9 or $result != $expectedResult"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun Double.test(a: Int, b: Long, c: () -> String): String {
|
||||
return { "${this}_${a}_${b}_${c()}"} ()
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
var invokeOrder: String = ""
|
||||
|
||||
fun test(x: Double = { invokeOrder += "x"; 1.0 }(), a: String, y: Long = { invokeOrder += "y"; 1 }(), b: String): String {
|
||||
return "" + x + a + b + y;
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val funResult = test(b = { invokeOrder += "K"; "K" }(), a = { invokeOrder += "O"; "O" }())
|
||||
|
||||
if (invokeOrder != "KOxy" || funResult != "1.0OK1") return "fail: $invokeOrder != KOxy or $funResult != 1.0OK1"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
fun box(): String {
|
||||
var invokeOrder = "";
|
||||
val expectedResult = "1.0_0_1_L"
|
||||
val expectedInvokeOrder = "1_0_L"
|
||||
var l = 1L
|
||||
var i = 0
|
||||
|
||||
var result = 1.0.test(b = {invokeOrder += "1_"; l}(), a = {invokeOrder+="0_"; i}(), c = {invokeOrder += "L"; "L"})
|
||||
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 1: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||
|
||||
invokeOrder = "";
|
||||
result = 1.0.test(b = {invokeOrder += "1_"; l}(), c = {invokeOrder += "L"; "L"}, a = {invokeOrder+="0_"; i}())
|
||||
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 2: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||
|
||||
|
||||
invokeOrder = "";
|
||||
result = 1.0.test(c = {invokeOrder += "L"; "L"}, b = {invokeOrder += "1_"; l}(), a = {invokeOrder+="0_"; i}())
|
||||
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 3: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||
|
||||
|
||||
invokeOrder = "";
|
||||
result = 1.0.test(a = {invokeOrder+="0_"; i}(), c = {invokeOrder += "L"; "L"}, b = {invokeOrder += "1_"; l}())
|
||||
if (invokeOrder != "0_1_L" || result != expectedResult) return "fail 4: $invokeOrder != 0_1_L or $result != $expectedResult"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun Double.test(a: Int, b: Long, c: () -> String): String {
|
||||
return "${this}_${a}_${b}_${c()}"
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
fun box(): String {
|
||||
return Z().test()
|
||||
}
|
||||
|
||||
class Z {
|
||||
fun Double.test(a: Int, b: Long, c: () -> String): String {
|
||||
return "${this}_${a}_${b}_${c()}"
|
||||
}
|
||||
|
||||
|
||||
fun test(): String {
|
||||
var invokeOrder = "";
|
||||
val expectedResult = "1.0_0_1_L"
|
||||
val expectedInvokeOrder = "1_0_L"
|
||||
var l = 1L
|
||||
var i = 0
|
||||
|
||||
var result = 1.0.test(b = { invokeOrder += "1_"; l }(), a = { invokeOrder += "0_"; i }(), c = { invokeOrder += "L"; "L" })
|
||||
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 1: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||
|
||||
invokeOrder = "";
|
||||
result = 1.0.test(b = { invokeOrder += "1_"; l }(), c = { invokeOrder += "L"; "L" }, a = { invokeOrder += "0_"; i }())
|
||||
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 2: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||
|
||||
|
||||
invokeOrder = "";
|
||||
result = 1.0.test(c = { invokeOrder += "L"; "L" }, b = { invokeOrder += "1_"; l }(), a = { invokeOrder += "0_"; i }())
|
||||
if (invokeOrder != expectedInvokeOrder || result != expectedResult) return "fail 3: $invokeOrder != $expectedInvokeOrder or $result != $expectedResult"
|
||||
|
||||
|
||||
invokeOrder = "";
|
||||
result = 1.0.test(a = { invokeOrder += "0_"; i }(), c = { invokeOrder += "L"; "L" }, b = { invokeOrder += "1_"; l }())
|
||||
if (invokeOrder != "0_1_L" || result != expectedResult) return "fail 4: $invokeOrder != 0_1_L or $result != $expectedResult"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
fun box(): String {
|
||||
var res = "";
|
||||
var call = test(a = {res += "K"; "K"}(), b = {res+="O"; "O"}(), c = {res += "L"; "L"})
|
||||
if (res != "KOL" || call != "KOL") return "fail 1: $res != KOL or $call != KOL"
|
||||
|
||||
res = "";
|
||||
call = test(a = {res += "K"; "K"}(), c = {res += "L"; "L"}, b = {res+="O"; "O"}())
|
||||
if (res != "KOL" || call != "KOL") return "fail 2: $res != KOL or $call != KOL"
|
||||
|
||||
|
||||
res = "";
|
||||
call = test(c = {res += "L"; "L"}, a = {res += "K"; "K"}(), b = {res+="O"; "O"}())
|
||||
if (res != "KOL" || call != "KOL") return "fail 3: $res != KOL or $call != KOL"
|
||||
|
||||
return "OK"
|
||||
|
||||
}
|
||||
|
||||
fun test(a: String, b: String, c: () -> String): String {
|
||||
return a + b + c();
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
fun box(): String {
|
||||
var res = "";
|
||||
var call = Z("Z").test(a = {res += "K"; "K"}(), b = {res+="O"; "O"}(), c = {res += "L"; "L"})
|
||||
if (res != "KOL" || call != "KOLZ") return "fail 1: $res != KOL or $call != KOLZ"
|
||||
|
||||
res = "";
|
||||
call = Z("Z").test(a = {res += "K"; "K"}(), c = {res += "L"; "L"}, b = {res+="O"; "O"}())
|
||||
if (res != "KOL" || call != "KOLZ") return "fail 2: $res != KOL or $call != KOLZ"
|
||||
|
||||
|
||||
res = "";
|
||||
call = Z("Z").test(c = {res += "L"; "L"}, a = {res += "K"; "K"}(), b = {res+="O"; "O"}())
|
||||
if (res != "KOL" || call != "KOLZ") return "fail 3: $res != KOL or $call != KOLZ"
|
||||
|
||||
return "OK"
|
||||
|
||||
}
|
||||
|
||||
class Z(val p: String) {
|
||||
|
||||
fun test(a: String, b: String, c: () -> String): String {
|
||||
return a + b + c() + p;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
fun box(): String {
|
||||
var res = "";
|
||||
var call = test(b = {res += "K"; "K"}(), a = {res+="O"; "O"}(), c = {res += "L"; "L"})
|
||||
if (res != "KOL" || call != "OKL") return "fail 1: $res != KOL or $call != OKL"
|
||||
|
||||
res = "";
|
||||
call = test(b = {res += "K"; "K"}(), c = {res += "L"; "L"}, a = {res+="O"; "O"}())
|
||||
if (res != "KOL" || call != "OKL") return "fail 2: $res != KOL or $call != OKL"
|
||||
|
||||
|
||||
res = "";
|
||||
call = test(c = {res += "L"; "L"}, b = {res += "K"; "K"}(), a = {res+="O"; "O"}())
|
||||
if (res != "KOL" || call != "OKL") return "fail 3: $res != KOL or $call != OKL"
|
||||
|
||||
return "OK"
|
||||
|
||||
}
|
||||
|
||||
fun test(a: String, b: String, c: () -> String): String {
|
||||
return a + b + c();
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
fun box(): String {
|
||||
var res = "";
|
||||
var call = Z("Z").test(b = {res += "K"; "K"}(), a = {res+="O"; "O"}(), c = {res += "L"; "L"})
|
||||
if (res != "KOL" || call != "OKLZ") return "fail 1: $res != KOL or $call != OKLZ"
|
||||
|
||||
res = "";
|
||||
call = Z("Z").test(b = {res += "K"; "K"}(), c = {res += "L"; "L"}, a = {res+="O"; "O"}())
|
||||
if (res != "KOL" || call != "OKLZ") return "fail 2: $res != KOL or $call != OKLZ"
|
||||
|
||||
|
||||
res = "";
|
||||
call = Z("Z").test(c = {res += "L"; "L"}, b = {res += "K"; "K"}(), a = {res+="O"; "O"}())
|
||||
if (res != "KOL" || call != "OKLZ") return "fail 3: $res != KOL or $call != OKLZ"
|
||||
|
||||
return "OK"
|
||||
|
||||
}
|
||||
|
||||
class Z(val p: String) {
|
||||
fun test(a: String, b: String, c: () -> String): String {
|
||||
return a + b + c() + p;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class A {
|
||||
fun test(x: String?, a: String?, b: String?){}
|
||||
|
||||
fun box(): String {
|
||||
test(x = "x", b = "K", a = "O")
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
// Test argument reordering when call site argument order differs from declaration one
|
||||
// 4 LOAD
|
||||
// 2 STORE
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
class A {
|
||||
fun test(x: String? = "x", a: String?, b: String?, y: String? = "y") {
|
||||
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
test(b = "K", a = "O")
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
// Test argument reordering when call site argument order differs from declaration one
|
||||
// 12 LOAD
|
||||
// 5 STORE
|
||||
@@ -0,0 +1,12 @@
|
||||
class A {
|
||||
fun test(x: String?, a: String?, b: String?) {
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
test(x = "x", a = "O", b = "K")
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
// Test there is no argument reordering when call site argument order same as declaration one
|
||||
// 2 LOAD
|
||||
// 0 STORE
|
||||
@@ -0,0 +1,12 @@
|
||||
class A {
|
||||
fun test(x: String? = "x", a: String?, b: String?, y: String? = "y") {
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
test(a = "O", b = "K")
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
// Test there is no argument reordering when call site argument order same as declaration one
|
||||
// 9 LOAD
|
||||
// 2 STORE
|
||||
@@ -251,6 +251,39 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/bytecodeText/argumentOrder")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class ArgumentOrder extends AbstractBytecodeTextTest {
|
||||
public void testAllFilesPresentInArgumentOrder() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/argumentOrder"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("argumentReorder.kt")
|
||||
public void testArgumentReorder() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/argumentOrder/argumentReorder.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("argumentReorderWithDefault.kt")
|
||||
public void testArgumentReorderWithDefault() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/argumentOrder/argumentReorderWithDefault.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("sameOrder.kt")
|
||||
public void testSameOrder() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/argumentOrder/sameOrder.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("sameOrderWithDefault.kt")
|
||||
public void testSameOrderWithDefault() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/argumentOrder/sameOrderWithDefault.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/bytecodeText/boxingOptimization")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+54
@@ -48,6 +48,60 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/arguments.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("captured.kt")
|
||||
public void testCaptured() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/captured.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("capturedInExtension.kt")
|
||||
public void testCapturedInExtension() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/capturedInExtension.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("defaults.kt")
|
||||
public void testDefaults() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/defaults.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("extension.kt")
|
||||
public void testExtension() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/extension.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("extensionInClass.kt")
|
||||
public void testExtensionInClass() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/extensionInClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaMigration.kt")
|
||||
public void testLambdaMigration() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/lambdaMigration.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaMigrationInClass.kt")
|
||||
public void testLambdaMigrationInClass() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/lambdaMigrationInClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/simple.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simpleInClass.kt")
|
||||
public void testSimpleInClass() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/argumentOrder/simpleInClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/arrays")
|
||||
|
||||
Reference in New Issue
Block a user