diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 71e39a3e737..72b187d39b2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1328,7 +1328,7 @@ public class ExpressionCodegen extends JetVisitor implem ConstructorDescriptor constructorDescriptor = bindingContext.get(CONSTRUCTOR, expression.getObjectDeclaration()); assert constructorDescriptor != null : "Unresolved constructor: " + expression.getText(); - CallableMethod constructor = typeMapper.mapToCallableMethod(constructorDescriptor); + JvmMethodSignature constructor = typeMapper.mapSignature(constructorDescriptor); Type type = typeMapper.mapType(constructorDescriptor.getContainingDeclaration()); @@ -1339,12 +1339,27 @@ public class ExpressionCodegen extends JetVisitor implem ResolvedCall superCall = closure.getSuperCall(); if (superCall != null) { + // For an anonymous object, we should also generate all non-default arguments that it captures for its super call ConstructorDescriptor superConstructor = superCall.getResultingDescriptor(); - List valueArguments = superCall.getValueArgumentsByIndex(); - assert valueArguments != null : "Failed to arrange value arguments by index: " + superConstructor; - ArgumentGenerator argumentGenerator = - new CallBasedArgumentGenerator(this, defaultCallGenerator, superConstructor.getValueParameters(), - typeMapper.mapToCallableMethod(superConstructor).getValueParameterTypes()); + List superValueParameters = superConstructor.getValueParameters(); + int params = superValueParameters.size(); + List superMappedTypes = typeMapper.mapToCallableMethod(superConstructor).getValueParameterTypes(); + assert superMappedTypes.size() >= params : String.format("Incorrect number of mapped parameters vs arguments: %d < %d for %s", + superMappedTypes.size(), params, constructorDescriptor); + + List valueArguments = new ArrayList(params); + List valueParameters = new ArrayList(params); + List mappedTypes = new ArrayList(params); + for (ValueParameterDescriptor parameter : superValueParameters) { + ResolvedValueArgument argument = superCall.getValueArguments().get(parameter); + if (!(argument instanceof DefaultValueArgument)) { + valueArguments.add(argument); + valueParameters.add(parameter); + mappedTypes.add(superMappedTypes.get(parameter.getIndex())); + } + } + ArgumentGenerator argumentGenerator = new CallBasedArgumentGenerator(this, defaultCallGenerator, valueParameters, mappedTypes); + argumentGenerator.generate(valueArguments); } @@ -1352,7 +1367,11 @@ public class ExpressionCodegen extends JetVisitor implem return StackValue.onStack(type); } - public void pushClosureOnStack(@Nullable CalculatedClosure closure, boolean ignoreThisAndReceiver, @NotNull CallGenerator callGenerator) { + public void pushClosureOnStack( + @Nullable CalculatedClosure closure, + boolean ignoreThisAndReceiver, + @NotNull CallGenerator callGenerator + ) { if (closure == null) return; int paramIndex = 0; @@ -1381,6 +1400,12 @@ public class ExpressionCodegen extends JetVisitor implem StackValue capturedVar = entry.getValue().getOuterValue(this); callGenerator.putCapturedValueOnStack(capturedVar, sharedVarType, paramIndex++); } + + ResolvedCall superCall = closure.getSuperCall(); + if (superCall != null) { + MutableClosure superClosure = bindingContext.get(CLOSURE, superCall.getResultingDescriptor().getContainingDeclaration()); + pushClosureOnStack(superClosure, ignoreThisAndReceiver, callGenerator); + } } private StackValue generateBlock(List statements, boolean lastStatementIsExpression) { @@ -2133,7 +2158,7 @@ public class ExpressionCodegen extends JetVisitor implem invokeMethodWithArguments(callableMethod, resolvedCall, receiver, callGenerator, argumentGenerator); } - private void invokeMethodWithArguments( + public void invokeMethodWithArguments( @NotNull CallableMethod callableMethod, @NotNull ResolvedCall resolvedCall, @NotNull StackValue receiver, diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 0f370098435..ad590649820 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -393,7 +393,7 @@ public class FunctionCodegen extends ParentCodegenAware { private static boolean needIndexForVar(JvmMethodParameterKind kind) { return kind == JvmMethodParameterKind.CAPTURED_LOCAL_VARIABLE || kind == JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL || - kind == JvmMethodParameterKind.SUPER_OF_ANONYMOUS_CALL_PARAM; + kind == JvmMethodParameterKind.SUPER_CALL_PARAM; } public static void endVisit(MethodVisitor mv, @Nullable String description, @Nullable PsiElement method) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 4dfde28cf1d..c074f56ee9b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -26,7 +26,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.backend.common.CodegenUtil; import org.jetbrains.jet.backend.common.DataClassMethodGenerator; -import org.jetbrains.jet.codegen.binding.CalculatedClosure; import org.jetbrains.jet.codegen.binding.CodegenBinding; import org.jetbrains.jet.codegen.binding.MutableClosure; import org.jetbrains.jet.codegen.bridges.BridgesPackage; @@ -47,7 +46,10 @@ import org.jetbrains.jet.lang.resolve.DeclarationResolver; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.bindingContextUtil.BindingContextUtilPackage; import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil; +import org.jetbrains.jet.lang.resolve.calls.model.DefaultValueArgument; +import org.jetbrains.jet.lang.resolve.calls.model.ExpressionValueArgument; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; +import org.jetbrains.jet.lang.resolve.calls.model.VarargValueArgument; import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants; import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames; @@ -73,6 +75,7 @@ import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver; import static org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils.descriptorToDeclaration; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*; +import static org.jetbrains.jet.lang.resolve.bindingContextUtil.BindingContextUtilPackage.getResolvedCallWithAssert; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*; import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass; import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.DelegationToTraitImpl; @@ -1446,20 +1449,17 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) { - if (specifier != superCall) { - if (specifier instanceof JetDelegatorByExpressionSpecifier) { - JetExpression delegateExpression = ((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression(); - assert delegateExpression != null; - delegateExpression.accept(visitor); - } + if (specifier instanceof JetDelegatorByExpressionSpecifier) { + JetExpression delegateExpression = ((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression(); + assert delegateExpression != null; + delegateExpression.accept(visitor); } - else { - if (superCall instanceof JetDelegatorToSuperCall) { - JetValueArgumentList argumentList = ((JetDelegatorToSuperCall) superCall).getValueArgumentList(); - if (argumentList != null) { - argumentList.accept(visitor); - } - } + } + + if (superCall instanceof JetDelegatorToSuperCall && !isAnonymousObject(descriptor)) { + JetValueArgumentList argumentList = ((JetDelegatorToSuperCall) superCall).getValueArgumentList(); + if (argumentList != null) { + argumentList.accept(visitor); } } } @@ -1550,51 +1550,96 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } private void generateDelegatorToConstructorCall( - InstructionAdapter iv, ExpressionCodegen codegen, - ConstructorDescriptor constructorDescriptor + @NotNull InstructionAdapter iv, + @NotNull ExpressionCodegen codegen, + @NotNull ConstructorDescriptor constructorDescriptor ) { - ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration(); - iv.load(0, OBJECT_TYPE); - if (classDecl.getKind() == ClassKind.ENUM_CLASS || classDecl.getKind() == ClassKind.ENUM_ENTRY) { - iv.load(1, OBJECT_TYPE); - iv.load(2, Type.INT_TYPE); - } - - ResolvedCall resolvedCall = BindingContextUtilPackage.getResolvedCallWithAssert(superCall, bindingContext); + ResolvedCall resolvedCall = getResolvedCallWithAssert(superCall, bindingContext); ConstructorDescriptor superConstructor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor(); - //noinspection SuspiciousMethodCalls - CalculatedClosure closureForSuper = bindingContext.get(CLOSURE, superConstructor.getContainingDeclaration()); - if (closureForSuper != null && closureForSuper.getCaptureThis() != null) { - iv.load(((ConstructorFrameMap) codegen.myFrameMap).getOuterThisIndex(), OBJECT_TYPE); + CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor); + CallableMethod callable = typeMapper.mapToCallableMethod(constructorDescriptor); + + List superParameters = superCallable.getValueParameters(); + List parameters = callable.getValueParameters(); + + int offset = 1; + int superIndex = 0; + + // Here we match all the super constructor parameters except those with kind VALUE to the derived constructor parameters, push + // them all onto the stack and update "offset" variable so that in the end it points to the slot of the first VALUE argument + for (JvmMethodParameterSignature parameter : parameters) { + if (superIndex >= superParameters.size()) break; + + JvmMethodParameterKind kind = parameter.getKind(); + Type type = parameter.getAsmType(); + + // Stop when we reach the actual value parameters present in the code; they will be generated via ResolvedCall below + if (superParameters.get(superIndex).getKind() == JvmMethodParameterKind.VALUE && + kind == JvmMethodParameterKind.SUPER_CALL_PARAM) { + break; + } + + if (kind == JvmMethodParameterKind.SUPER_CALL_PARAM || kind == JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL || + (kind == JvmMethodParameterKind.OUTER && superConstructor.getContainingDeclaration().isInner())) { + iv.load(offset, type); + superIndex++; + } + + offset += type.getSize(); } - CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor); - + ArgumentGenerator argumentGenerator; if (isAnonymousObject(descriptor) && superCall instanceof JetDelegatorToSuperCall) { - int nextVar = findFirstSuperArgument(typeMapper.mapToCallableMethod(constructorDescriptor)); - for (Type t : superCallable.getAsmMethod().getArgumentTypes()) { - iv.load(nextVar, t); - nextVar += t.getSize(); - } - superCallable.invokeWithNotNullAssertion(codegen.v, state, resolvedCall); + List superValues = superParameters.subList(superIndex, superParameters.size()); + argumentGenerator = new ObjectSuperCallArgumentGenerator(superValues, iv, offset); } else { - codegen.invokeMethodWithArguments(superCallable, resolvedCall, StackValue.none()); + argumentGenerator = + new CallBasedArgumentGenerator(codegen, codegen.defaultCallGenerator, superConstructor.getValueParameters(), + superCallable.getValueParameterTypes()); } + + codegen.invokeMethodWithArguments(superCallable, resolvedCall, StackValue.none(), codegen.defaultCallGenerator, argumentGenerator); } - private static int findFirstSuperArgument(@NotNull CallableMethod method) { - int i = 0; - for (JvmMethodParameterSignature type : method.getValueParameters()) { - if (type.getKind() == JvmMethodParameterKind.SUPER_OF_ANONYMOUS_CALL_PARAM) { - return i + 1; // because of this - } - i += type.getAsmType().getSize(); + private static class ObjectSuperCallArgumentGenerator extends ArgumentGenerator { + private final List parameters; + private final InstructionAdapter iv; + private int offset; + + public ObjectSuperCallArgumentGenerator( + @NotNull List superParameters, + @NotNull InstructionAdapter iv, + int firstValueParamOffset + ) { + this.parameters = superParameters; + this.iv = iv; + this.offset = firstValueParamOffset; + } + + @Override + public void generateExpression(int i, @NotNull ExpressionValueArgument argument) { + generateSuperCallArgument(i); + } + + @Override + public void generateDefault(int i, @NotNull DefaultValueArgument argument) { + pushDefaultValueOnStack(parameters.get(i).getAsmType(), iv); + } + + @Override + public void generateVararg(int i, @NotNull VarargValueArgument argument) { + generateSuperCallArgument(i); + } + + private void generateSuperCallArgument(int i) { + Type type = parameters.get(i).getAsmType(); + iv.load(offset, type); + offset += type.getSize(); } - return -1; } @Override @@ -1602,7 +1647,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (declaration instanceof JetEnumEntry) { String name = declaration.getName(); assert name != null : "Enum entry has no name: " + declaration.getText(); - String desc = "L" + classAsmType.getInternalName() + ";"; + String desc = classAsmType.getDescriptor(); ClassDescriptor entryDescriptor = bindingContext.get(BindingContext.CLASS, declaration); v.newField(OtherOrigin(declaration, entryDescriptor), ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL, name, desc, null, null); myEnumConstants.add((JetEnumEntry) declaration); @@ -1663,7 +1708,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { throw new UnsupportedOperationException("unsupported type of enum constant initializer: " + specifier); } - ResolvedCall resolvedCall = BindingContextUtilPackage.getResolvedCallWithAssert(specifier, bindingContext); + ResolvedCall resolvedCall = getResolvedCallWithAssert(specifier, bindingContext); CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) resolvedCall.getResultingDescriptor()); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java index 1b1b52da899..6d52e05603b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java @@ -34,7 +34,9 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.OverrideResolver; +import org.jetbrains.jet.lang.resolve.calls.model.DefaultValueArgument; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; +import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.StringValue; import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants; @@ -784,9 +786,50 @@ public class JetTypeMapper { } ResolvedCall superCall = closure.getSuperCall(); - if (superCall != null && isAnonymousObject(descriptor.getContainingDeclaration())) { - for (JvmMethodParameterSignature parameter : mapSignature(superCall.getResultingDescriptor()).getValueParameters()) { - writeParameter(sw, JvmMethodParameterKind.SUPER_OF_ANONYMOUS_CALL_PARAM, parameter.getAsmType()); + // We may generate a slightly wrong signature for a local class / anonymous object in light classes mode but we don't care, + // because such classes are not accessible from the outside world + if (superCall != null && classBuilderMode == ClassBuilderMode.FULL) { + writeSuperConstructorCallParameters(sw, descriptor, superCall, captureThis != null); + } + } + + private void writeSuperConstructorCallParameters( + @NotNull BothSignatureWriter sw, + @NotNull ConstructorDescriptor descriptor, + @NotNull ResolvedCall superCall, + boolean hasOuter + ) { + ConstructorDescriptor superDescriptor = superCall.getResultingDescriptor(); + List valueArguments = superCall.getValueArgumentsByIndex(); + assert valueArguments != null : "Failed to arrange value arguments by index: " + superDescriptor; + + List parameters = mapSignature(superDescriptor).getValueParameters(); + + int params = parameters.size(); + int args = valueArguments.size(); + + // Mapped parameters should consist of captured values plus all of valueArguments + assert params >= args : + String.format("Incorrect number of mapped parameters vs arguments: %d < %d for %s", params, args, descriptor); + + // Include all captured values, i.e. those parameters for which there are no resolved value arguments + for (int i = 0; i < params - args; i++) { + JvmMethodParameterSignature parameter = parameters.get(i); + JvmMethodParameterKind kind = parameter.getKind(); + if (kind == JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL) continue; + if (hasOuter && kind == JvmMethodParameterKind.OUTER) continue; + + writeParameter(sw, JvmMethodParameterKind.SUPER_CALL_PARAM, parameter.getAsmType()); + } + + if (isAnonymousObject(descriptor.getContainingDeclaration())) { + // For anonymous objects, also add all real non-default value arguments passed to the super constructor + for (int i = 0; i < args; i++) { + ResolvedValueArgument valueArgument = valueArguments.get(i); + JvmMethodParameterSignature parameter = parameters.get(params - args + i); + if (!(valueArgument instanceof DefaultValueArgument)) { + writeParameter(sw, JvmMethodParameterKind.SUPER_CALL_PARAM, parameter.getAsmType()); + } } } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/jvmSignature/JvmMethodParameterKind.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/jvmSignature/JvmMethodParameterKind.java index 7e8408ab18f..530b9302109 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/jvmSignature/JvmMethodParameterKind.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/jvmSignature/JvmMethodParameterKind.java @@ -23,7 +23,7 @@ public enum JvmMethodParameterKind { RECEIVER, CAPTURED_LOCAL_VARIABLE, ENUM_NAME_OR_ORDINAL, - SUPER_OF_ANONYMOUS_CALL_PARAM; + SUPER_CALL_PARAM; public boolean isSkippedInGenericSignature() { return this == OUTER || this == ENUM_NAME_OR_ORDINAL; diff --git a/compiler/testData/codegen/box/superConstructorCall/deepInnerHierarchy.kt b/compiler/testData/codegen/box/superConstructorCall/deepInnerHierarchy.kt new file mode 100644 index 00000000000..08efa14a7ff --- /dev/null +++ b/compiler/testData/codegen/box/superConstructorCall/deepInnerHierarchy.kt @@ -0,0 +1,13 @@ +open class A(val s: String) { + open inner class B(s: String): A(s) + + open inner class C(s: String, additional: Double): B(s) + + open inner class D(other: Int, another: Long, s: String) : C(s, another.toDouble()) + + open inner class E : D(0, 42L, "OK") + + inner class F : E() +} + +fun box(): String = A("Fail").F().s diff --git a/compiler/testData/codegen/box/superConstructorCall/deepLocalHierarchy.kt b/compiler/testData/codegen/box/superConstructorCall/deepLocalHierarchy.kt new file mode 100644 index 00000000000..51a059cb0a3 --- /dev/null +++ b/compiler/testData/codegen/box/superConstructorCall/deepLocalHierarchy.kt @@ -0,0 +1,17 @@ +fun box(): String { + open trait L1 { + fun foo(): String + } + + open class L2(val s: String) : L1 { + override fun foo() = s + } + + open class L3(unused: Double, value: String = "OK") : L2(value) + + open class L4(i: Int, j: Long, z: Boolean, l: L3) : L3(3.14) + + class L5 : L4(0, 0L, false, L3(2.71, "Fail")) + + return L5().foo() +} diff --git a/compiler/testData/codegen/box/superConstructorCall/innerExtendsOuter.kt b/compiler/testData/codegen/box/superConstructorCall/innerExtendsOuter.kt new file mode 100644 index 00000000000..e90ccb30a21 --- /dev/null +++ b/compiler/testData/codegen/box/superConstructorCall/innerExtendsOuter.kt @@ -0,0 +1,14 @@ +// When inner class extends its outer, there are two instances of the outer present in the inner: +// the enclosing one and the one in the super call. +// Here we test that symbols are resolved to the instance created via the super call. +// This differs from Java, so this test may change when we revisit code generation of inner classes + +open class Outer(vararg val chars: Char) { + open inner class Inner(val s: String): Outer(s[0], s[1]) { + fun concat() = java.lang.String.valueOf(chars) + } + + fun value() = Inner("OK").concat() +} + +fun box() = Outer('F', 'a', 'i', 'l').value() diff --git a/compiler/testData/codegen/box/superConstructorCall/localExtendsLocalWithClosure.kt b/compiler/testData/codegen/box/superConstructorCall/localExtendsLocalWithClosure.kt new file mode 100644 index 00000000000..f24ed933d5c --- /dev/null +++ b/compiler/testData/codegen/box/superConstructorCall/localExtendsLocalWithClosure.kt @@ -0,0 +1,11 @@ +fun box(): String { + val result = "OK" + + open class Local(val ok: Boolean) { + fun result() = if (ok) result else "Fail" + } + + class Derived : Local(true) + + return Derived().result() +} diff --git a/compiler/testData/codegen/box/superConstructorCall/localWithClosureExtendsLocalWithClosure.kt b/compiler/testData/codegen/box/superConstructorCall/localWithClosureExtendsLocalWithClosure.kt new file mode 100644 index 00000000000..b2bb6dbd67a --- /dev/null +++ b/compiler/testData/codegen/box/superConstructorCall/localWithClosureExtendsLocalWithClosure.kt @@ -0,0 +1,16 @@ +fun box(): String { + val three = 3 + + open class Local(val one: Int) { + open fun value() = "$three$one" + } + + val four = 4 + + class Derived(val two: Int) : Local(1) { + override fun value() = super.value() + "$four$two" + } + + val result = Derived(2).value() + return if (result == "3142") "OK" else "Fail: $result" +} diff --git a/compiler/testData/codegen/box/superConstructorCall/objectExtendsClassDefaultArgument.kt b/compiler/testData/codegen/box/superConstructorCall/objectExtendsClassDefaultArgument.kt new file mode 100644 index 00000000000..298b0ec9162 --- /dev/null +++ b/compiler/testData/codegen/box/superConstructorCall/objectExtendsClassDefaultArgument.kt @@ -0,0 +1,9 @@ +// KT-3581 + +open class A(val result: String = "OK") { +} + +fun box(): String { + val a = object : A() {} + return a.result +} diff --git a/compiler/testData/codegen/box/superConstructorCall/objectExtendsClassVararg.kt b/compiler/testData/codegen/box/superConstructorCall/objectExtendsClassVararg.kt new file mode 100644 index 00000000000..b0bb4aed5d1 --- /dev/null +++ b/compiler/testData/codegen/box/superConstructorCall/objectExtendsClassVararg.kt @@ -0,0 +1,8 @@ +open class SomeClass(val some: Double, val other: Int, vararg val args: String) { + fun result() = args[1] +} + +fun box(): String { + return object : SomeClass(3.14, 42, "No", "OK", "Yes") { + }.result() +} diff --git a/compiler/testData/codegen/box/superConstructorCall/objectExtendsInner.kt b/compiler/testData/codegen/box/superConstructorCall/objectExtendsInner.kt new file mode 100644 index 00000000000..f02f1d4edc1 --- /dev/null +++ b/compiler/testData/codegen/box/superConstructorCall/objectExtendsInner.kt @@ -0,0 +1,12 @@ +class A { + open inner class Inner(val result: String) + + fun box(): String { + val o = object : Inner("OK") { + fun ok() = result + } + return o.ok() + } +} + +fun box() = A().box() diff --git a/compiler/testData/codegen/box/superConstructorCall/objectExtendsInnerDefaultArgument.kt b/compiler/testData/codegen/box/superConstructorCall/objectExtendsInnerDefaultArgument.kt new file mode 100644 index 00000000000..c94d6ab49ca --- /dev/null +++ b/compiler/testData/codegen/box/superConstructorCall/objectExtendsInnerDefaultArgument.kt @@ -0,0 +1,12 @@ +class A { + open inner class Inner(val result: String = "OK", val int: Int) + + fun box(): String { + val o = object : Inner(int = 0) { + fun ok() = result + } + return o.ok() + } +} + +fun box() = A().box() diff --git a/compiler/testData/codegen/box/superConstructorCall/objectExtendsInnerOfLocalVarargAndDefault.kt b/compiler/testData/codegen/box/superConstructorCall/objectExtendsInnerOfLocalVarargAndDefault.kt new file mode 100644 index 00000000000..eef3131ae2b --- /dev/null +++ b/compiler/testData/codegen/box/superConstructorCall/objectExtendsInnerOfLocalVarargAndDefault.kt @@ -0,0 +1,17 @@ +fun box(): String { + val capture = "oh" + + class Local { + val captured = capture + + open inner class Inner(val d: Double = -1.0, val s: String, vararg val y: Int) { + open fun result() = "Fail" + } + + val obj = object : Inner(s = "OK") { + override fun result() = s + } + } + + return Local().obj.result() +} diff --git a/compiler/testData/codegen/box/superConstructorCall/objectExtendsInnerOfLocalWithCapture.kt b/compiler/testData/codegen/box/superConstructorCall/objectExtendsInnerOfLocalWithCapture.kt new file mode 100644 index 00000000000..b4fb7a47cee --- /dev/null +++ b/compiler/testData/codegen/box/superConstructorCall/objectExtendsInnerOfLocalWithCapture.kt @@ -0,0 +1,15 @@ +fun box(): String { + class Local { + open inner class Inner(val s: String) { + open fun result() = "Fail" + } + + val realResult = "OK" + + val obj = object : Inner(realResult) { + override fun result() = s + } + } + + return Local().obj.result() +} diff --git a/compiler/testData/codegen/box/superConstructorCall/objectExtendsLocalCaptureInSuperCall.kt b/compiler/testData/codegen/box/superConstructorCall/objectExtendsLocalCaptureInSuperCall.kt new file mode 100644 index 00000000000..35bb545eb82 --- /dev/null +++ b/compiler/testData/codegen/box/superConstructorCall/objectExtendsLocalCaptureInSuperCall.kt @@ -0,0 +1,11 @@ +open class A(val s: String) + +fun box(): String { + class B { + val result = "OK" + + val f = object : A(result) {}.s + } + + return B().f +} diff --git a/compiler/testData/codegen/box/superConstructorCall/objectExtendsLocalWithClosure.kt b/compiler/testData/codegen/box/superConstructorCall/objectExtendsLocalWithClosure.kt new file mode 100644 index 00000000000..834b1e5d824 --- /dev/null +++ b/compiler/testData/codegen/box/superConstructorCall/objectExtendsLocalWithClosure.kt @@ -0,0 +1,14 @@ +fun box(): String { + val d = 42.0 + val c = 'C' + + open class Local(val l: Long) { + fun foo(): Boolean = d == 42.0 && c == 'C' && l == 239L + } + + if (object : Local(239L) { + fun bar(): Boolean = foo() + }.bar()) return "OK" + + return "Fail" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index a6864d1e91f..683c65b6b78 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -31,7 +31,7 @@ import org.jetbrains.jet.codegen.generated.AbstractBlackBoxCodegenTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") @TestMetadata("compiler/testData/codegen/box") -@InnerTestClasses({BlackBoxCodegenTestGenerated.Arrays.class, BlackBoxCodegenTestGenerated.BinaryOp.class, BlackBoxCodegenTestGenerated.Bridges.class, BlackBoxCodegenTestGenerated.BuiltinStubMethods.class, BlackBoxCodegenTestGenerated.Casts.class, BlackBoxCodegenTestGenerated.Classes.class, BlackBoxCodegenTestGenerated.Closures.class, BlackBoxCodegenTestGenerated.Constants.class, BlackBoxCodegenTestGenerated.ControlStructures.class, BlackBoxCodegenTestGenerated.DefaultArguments.class, BlackBoxCodegenTestGenerated.DelegatedProperty.class, BlackBoxCodegenTestGenerated.Elvis.class, BlackBoxCodegenTestGenerated.Enum.class, BlackBoxCodegenTestGenerated.ExclExcl.class, BlackBoxCodegenTestGenerated.ExtensionFunctions.class, BlackBoxCodegenTestGenerated.ExtensionProperties.class, BlackBoxCodegenTestGenerated.FakeOverride.class, BlackBoxCodegenTestGenerated.FieldRename.class, BlackBoxCodegenTestGenerated.Finally.class, BlackBoxCodegenTestGenerated.Functions.class, BlackBoxCodegenTestGenerated.InnerNested.class, BlackBoxCodegenTestGenerated.Instructions.class, BlackBoxCodegenTestGenerated.Intrinsics.class, BlackBoxCodegenTestGenerated.Labels.class, BlackBoxCodegenTestGenerated.LocalClasses.class, BlackBoxCodegenTestGenerated.MultiDecl.class, BlackBoxCodegenTestGenerated.Objects.class, BlackBoxCodegenTestGenerated.OperatorConventions.class, BlackBoxCodegenTestGenerated.Package.class, BlackBoxCodegenTestGenerated.PrimitiveTypes.class, BlackBoxCodegenTestGenerated.Properties.class, BlackBoxCodegenTestGenerated.Reflection.class, BlackBoxCodegenTestGenerated.Regressions.class, BlackBoxCodegenTestGenerated.SafeCall.class, BlackBoxCodegenTestGenerated.SamConstructors.class, BlackBoxCodegenTestGenerated.Strings.class, BlackBoxCodegenTestGenerated.Super.class, BlackBoxCodegenTestGenerated.ToArray.class, BlackBoxCodegenTestGenerated.Traits.class, BlackBoxCodegenTestGenerated.TypeInfo.class, BlackBoxCodegenTestGenerated.TypeMapping.class, BlackBoxCodegenTestGenerated.UnaryOp.class, BlackBoxCodegenTestGenerated.Unit.class, BlackBoxCodegenTestGenerated.Vararg.class, BlackBoxCodegenTestGenerated.When.class}) +@InnerTestClasses({BlackBoxCodegenTestGenerated.Arrays.class, BlackBoxCodegenTestGenerated.BinaryOp.class, BlackBoxCodegenTestGenerated.Bridges.class, BlackBoxCodegenTestGenerated.BuiltinStubMethods.class, BlackBoxCodegenTestGenerated.Casts.class, BlackBoxCodegenTestGenerated.Classes.class, BlackBoxCodegenTestGenerated.Closures.class, BlackBoxCodegenTestGenerated.Constants.class, BlackBoxCodegenTestGenerated.ControlStructures.class, BlackBoxCodegenTestGenerated.DefaultArguments.class, BlackBoxCodegenTestGenerated.DelegatedProperty.class, BlackBoxCodegenTestGenerated.Elvis.class, BlackBoxCodegenTestGenerated.Enum.class, BlackBoxCodegenTestGenerated.ExclExcl.class, BlackBoxCodegenTestGenerated.ExtensionFunctions.class, BlackBoxCodegenTestGenerated.ExtensionProperties.class, BlackBoxCodegenTestGenerated.FakeOverride.class, BlackBoxCodegenTestGenerated.FieldRename.class, BlackBoxCodegenTestGenerated.Finally.class, BlackBoxCodegenTestGenerated.Functions.class, BlackBoxCodegenTestGenerated.InnerNested.class, BlackBoxCodegenTestGenerated.Instructions.class, BlackBoxCodegenTestGenerated.Intrinsics.class, BlackBoxCodegenTestGenerated.Labels.class, BlackBoxCodegenTestGenerated.LocalClasses.class, BlackBoxCodegenTestGenerated.MultiDecl.class, BlackBoxCodegenTestGenerated.Objects.class, BlackBoxCodegenTestGenerated.OperatorConventions.class, BlackBoxCodegenTestGenerated.Package.class, BlackBoxCodegenTestGenerated.PrimitiveTypes.class, BlackBoxCodegenTestGenerated.Properties.class, BlackBoxCodegenTestGenerated.Reflection.class, BlackBoxCodegenTestGenerated.Regressions.class, BlackBoxCodegenTestGenerated.SafeCall.class, BlackBoxCodegenTestGenerated.SamConstructors.class, BlackBoxCodegenTestGenerated.Strings.class, BlackBoxCodegenTestGenerated.Super.class, BlackBoxCodegenTestGenerated.SuperConstructorCall.class, BlackBoxCodegenTestGenerated.ToArray.class, BlackBoxCodegenTestGenerated.Traits.class, BlackBoxCodegenTestGenerated.TypeInfo.class, BlackBoxCodegenTestGenerated.TypeMapping.class, BlackBoxCodegenTestGenerated.UnaryOp.class, BlackBoxCodegenTestGenerated.Unit.class, BlackBoxCodegenTestGenerated.Vararg.class, BlackBoxCodegenTestGenerated.When.class}) public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testAllFilesPresentInBox() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/box"), Pattern.compile("^(.+)\\.kt$"), true); @@ -4826,6 +4826,79 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } + @TestMetadata("compiler/testData/codegen/box/superConstructorCall") + public static class SuperConstructorCall extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInSuperConstructorCall() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/box/superConstructorCall"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("deepInnerHierarchy.kt") + public void testDeepInnerHierarchy() throws Exception { + doTest("compiler/testData/codegen/box/superConstructorCall/deepInnerHierarchy.kt"); + } + + @TestMetadata("deepLocalHierarchy.kt") + public void testDeepLocalHierarchy() throws Exception { + doTest("compiler/testData/codegen/box/superConstructorCall/deepLocalHierarchy.kt"); + } + + @TestMetadata("innerExtendsOuter.kt") + public void testInnerExtendsOuter() throws Exception { + doTest("compiler/testData/codegen/box/superConstructorCall/innerExtendsOuter.kt"); + } + + @TestMetadata("localExtendsLocalWithClosure.kt") + public void testLocalExtendsLocalWithClosure() throws Exception { + doTest("compiler/testData/codegen/box/superConstructorCall/localExtendsLocalWithClosure.kt"); + } + + @TestMetadata("localWithClosureExtendsLocalWithClosure.kt") + public void testLocalWithClosureExtendsLocalWithClosure() throws Exception { + doTest("compiler/testData/codegen/box/superConstructorCall/localWithClosureExtendsLocalWithClosure.kt"); + } + + @TestMetadata("objectExtendsClassDefaultArgument.kt") + public void testObjectExtendsClassDefaultArgument() throws Exception { + doTest("compiler/testData/codegen/box/superConstructorCall/objectExtendsClassDefaultArgument.kt"); + } + + @TestMetadata("objectExtendsClassVararg.kt") + public void testObjectExtendsClassVararg() throws Exception { + doTest("compiler/testData/codegen/box/superConstructorCall/objectExtendsClassVararg.kt"); + } + + @TestMetadata("objectExtendsInner.kt") + public void testObjectExtendsInner() throws Exception { + doTest("compiler/testData/codegen/box/superConstructorCall/objectExtendsInner.kt"); + } + + @TestMetadata("objectExtendsInnerDefaultArgument.kt") + public void testObjectExtendsInnerDefaultArgument() throws Exception { + doTest("compiler/testData/codegen/box/superConstructorCall/objectExtendsInnerDefaultArgument.kt"); + } + + @TestMetadata("objectExtendsInnerOfLocalVarargAndDefault.kt") + public void testObjectExtendsInnerOfLocalVarargAndDefault() throws Exception { + doTest("compiler/testData/codegen/box/superConstructorCall/objectExtendsInnerOfLocalVarargAndDefault.kt"); + } + + @TestMetadata("objectExtendsInnerOfLocalWithCapture.kt") + public void testObjectExtendsInnerOfLocalWithCapture() throws Exception { + doTest("compiler/testData/codegen/box/superConstructorCall/objectExtendsInnerOfLocalWithCapture.kt"); + } + + @TestMetadata("objectExtendsLocalCaptureInSuperCall.kt") + public void testObjectExtendsLocalCaptureInSuperCall() throws Exception { + doTest("compiler/testData/codegen/box/superConstructorCall/objectExtendsLocalCaptureInSuperCall.kt"); + } + + @TestMetadata("objectExtendsLocalWithClosure.kt") + public void testObjectExtendsLocalWithClosure() throws Exception { + doTest("compiler/testData/codegen/box/superConstructorCall/objectExtendsLocalWithClosure.kt"); + } + + } + @TestMetadata("compiler/testData/codegen/box/toArray") public static class ToArray extends AbstractBlackBoxCodegenTest { public void testAllFilesPresentInToArray() throws Exception { @@ -5335,6 +5408,7 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { suite.addTestSuite(SamConstructors.class); suite.addTestSuite(Strings.class); suite.addTestSuite(Super.class); + suite.addTestSuite(SuperConstructorCall.class); suite.addTestSuite(ToArray.class); suite.addTest(Traits.innerSuite()); suite.addTestSuite(TypeInfo.class);