Support secondary constructors in JVM backend

There is a lot of changes about closures calculating and generating.

1. As classes can have more than one constructor each of them should
have closure arguments.

2. Captured variables set is the same for all of them.

3. Within constructors bodies/delegating calls closure parameters
should be accessed through method arguments because fields may be
not initialized yet.
This commit is contained in:
Denis Zharkov
2015-02-24 19:47:16 +03:00
parent 6779e95767
commit e65382e6ec
35 changed files with 1290 additions and 39 deletions
@@ -1960,9 +1960,32 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return stackValueForLocal(descriptor, index);
}
if (context instanceof ConstructorContext) {
return lookupCapturedValueInConstructorParameters(descriptor);
}
return context.lookupInContext(descriptor, StackValue.LOCAL_0, state, false);
}
@Nullable
private StackValue lookupCapturedValueInConstructorParameters(@NotNull DeclarationDescriptor descriptor) {
StackValue parentResult = context.lookupInContext(descriptor, StackValue.LOCAL_0, state, false);
if (context.closure == null || parentResult == null) return parentResult;
int parameterOffsetInConstructor = context.closure.getCapturedParameterOffsetInConstructor(descriptor);
// when captured parameter is singleton
// see compiler/testData/codegen/box/objects/objectInLocalAnonymousObject.kt (fun local() captured in A)
if (parameterOffsetInConstructor == -1) return parentResult;
assert parentResult instanceof StackValue.Field || parentResult instanceof StackValue.FieldForSharedVar
: "Part of closure should be either Field or FieldForSharedVar";
if (parentResult instanceof StackValue.FieldForSharedVar) {
return StackValue.shared(parameterOffsetInConstructor, parentResult.type);
}
return StackValue.local(parameterOffsetInConstructor, parentResult.type);
}
private StackValue stackValueForLocal(DeclarationDescriptor descriptor, int index) {
if (descriptor instanceof VariableDescriptor) {
@@ -2207,8 +2230,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
}
final Callable callable = resolveToCallable(accessibleFunctionDescriptor(fd), superCall);
final Type returnType = typeMapper.mapReturnType(resolvedCall.getResultingDescriptor());
FunctionDescriptor accessibleFunctionDescriptor = accessibleFunctionDescriptor(fd);
final Callable callable = resolveToCallable(accessibleFunctionDescriptor, superCall);
final Type returnType = typeMapper.mapReturnType(accessibleFunctionDescriptor);
if (callable instanceof CallableMethod) {
return StackValue.functionCall(returnType, new Function1<InstructionAdapter, Unit>() {
@@ -334,7 +334,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
if (specifier instanceof JetDelegatorToSuperCall) {
if (specifier instanceof JetDelegatorToSuperClass || specifier instanceof JetDelegatorToSuperCall) {
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
assert superType != null :
String.format("No type recorded for \n---\n%s\n---\n", JetPsiUtil.getElementTextWithContext(specifier));
@@ -374,6 +374,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
try {
lookupConstructorExpressionsInClosureIfPresent();
generatePrimaryConstructor(delegationFieldsInfo);
for (ConstructorDescriptor secondaryConstructor : descriptor.getConstructors()) {
if (secondaryConstructor.isPrimary()) continue;
generateSecondaryConstructor(secondaryConstructor);
}
}
catch (CompilationException e) {
throw e;
@@ -382,7 +386,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
throw e;
}
catch (RuntimeException e) {
throw new RuntimeException("Error generating primary constructor of class " + myClass.getName() + " with kind " + kind, e);
throw new RuntimeException("Error generating constructors of class " + myClass.getName() + " with kind " + kind, e);
}
generateTraitMethods();
@@ -1097,23 +1101,33 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
private void generateSecondaryConstructor(@NotNull ConstructorDescriptor constructorDescriptor) {
ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
functionCodegen.generateMethod(OtherOrigin(myClass, constructorDescriptor), constructorDescriptor, constructorContext,
new FunctionGenerationStrategy.CodegenBased<ConstructorDescriptor>(state, constructorDescriptor) {
@Override
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
generateSecondaryConstructorImpl(callableDescriptor, codegen);
}
}
);
functionCodegen.generateDefaultIfNeeded(constructorContext, constructorDescriptor, OwnerKind.IMPLEMENTATION,
DefaultParameterValueLoader.DEFAULT, null);
}
private void generatePrimaryConstructorImpl(
@NotNull ConstructorDescriptor constructorDescriptor,
@NotNull final ExpressionCodegen codegen,
@NotNull ExpressionCodegen codegen,
@NotNull DelegationFieldsInfo fieldsInfo
) {
InstructionAdapter iv = codegen.v;
MutableClosure closure = context.closure;
if (closure != null) {
List<FieldInfo> argsFromClosure = ClosureCodegen.calculateConstructorParameters(typeMapper, closure, classAsmType);
int k = 1;
for (FieldInfo info : argsFromClosure) {
k = AsmUtil.genAssignInstanceFieldFromParam(info, k, iv);
}
}
generateClosureInitialization(iv);
generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor);
generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor,
getDelegationConstructorCall(bindingContext, constructorDescriptor));
if (isNonDefaultObject(descriptor)) {
StackValue.singleton(descriptor, typeMapper).store(StackValue.LOCAL_0, iv);
@@ -1151,17 +1165,58 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
});
}
else {
generateInitializers(new Function0<ExpressionCodegen>() {
@Override
public ExpressionCodegen invoke() {
return codegen;
}
});
generateInitializers(codegen);
}
iv.visitInsn(RETURN);
}
private void generateSecondaryConstructorImpl(
@NotNull ConstructorDescriptor constructorDescriptor,
@NotNull ExpressionCodegen codegen
) {
InstructionAdapter iv = codegen.v;
ResolvedCall<ConstructorDescriptor> constructorDelegationCall =
getDelegationConstructorCall(bindingContext, constructorDescriptor);
ConstructorDescriptor delegateConstructor = constructorDelegationCall == null ? null :
constructorDelegationCall.getResultingDescriptor();
generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor, constructorDelegationCall);
if (!isSameClassConstructor(delegateConstructor)) {
// Initialization happens only for constructors delegating to super
generateClosureInitialization(iv);
generateInitializers(codegen);
}
JetSecondaryConstructor constructor =
(JetSecondaryConstructor) DescriptorToSourceUtils.descriptorToDeclaration(constructorDescriptor);
assert constructor != null;
codegen.gen(constructor.getBodyExpression(), Type.VOID_TYPE);
iv.visitInsn(RETURN);
}
private void generateInitializers(@NotNull final ExpressionCodegen codegen) {
generateInitializers(new Function0<ExpressionCodegen>() {
@Override
public ExpressionCodegen invoke() {
return codegen;
}
});
}
private void generateClosureInitialization(@NotNull InstructionAdapter iv) {
MutableClosure closure = context.closure;
if (closure != null) {
List<FieldInfo> argsFromClosure = ClosureCodegen.calculateConstructorParameters(typeMapper, closure, classAsmType);
int k = 1;
for (FieldInfo info : argsFromClosure) {
k = AsmUtil.genAssignInstanceFieldFromParam(info, k, iv);
}
}
}
private void genSimpleSuperCall(InstructionAdapter iv) {
iv.load(0, superClassAsmType);
if (descriptor.getKind() == ClassKind.ENUM_CLASS || descriptor.getKind() == ClassKind.ENUM_ENTRY) {
@@ -1316,6 +1371,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
JetClassInitializer initializer = (JetClassInitializer) declaration;
initializer.accept(visitor);
}
else if (declaration instanceof JetSecondaryConstructor) {
JetSecondaryConstructor constructor = (JetSecondaryConstructor) declaration;
constructor.accept(visitor);
}
}
for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
@@ -1332,9 +1391,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
context.lookupInContext(superClass.getContainingDeclaration(), StackValue.LOCAL_0, state, true);
}
if (!isAnonymousObject(descriptor)) {
ResolvedCall<ConstructorDescriptor> delegationCall =
getDelegationConstructorCall(bindingContext, descriptor.getUnsubstitutedPrimaryConstructor());
ConstructorDescriptor primaryConstructor = descriptor.getUnsubstitutedPrimaryConstructor();
if (primaryConstructor != null && !isAnonymousObject(descriptor)) {
ResolvedCall<ConstructorDescriptor> delegationCall = getDelegationConstructorCall(bindingContext, primaryConstructor);
JetValueArgumentList argumentList = delegationCall != null ? delegationCall.getCall().getValueArgumentList() : null;
if (argumentList != null) {
argumentList.accept(visitor);
@@ -1415,22 +1474,54 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private void generateDelegatorToConstructorCall(
@NotNull InstructionAdapter iv,
@NotNull ExpressionCodegen codegen,
@NotNull ConstructorDescriptor constructorDescriptor
@NotNull ConstructorDescriptor constructorDescriptor,
@Nullable ResolvedCall<ConstructorDescriptor> delegationConstructorCall
) {
ResolvedCall<?> resolvedCall = getDelegationConstructorCall(bindingContext, constructorDescriptor);
if (resolvedCall == null) {
if (delegationConstructorCall == null) {
genSimpleSuperCall(iv);
return;
}
iv.load(0, OBJECT_TYPE);
ConstructorDescriptor superConstructor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor();
ConstructorDescriptor delegateConstructor = delegationConstructorCall.getResultingDescriptor();
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor);
CallableMethod delegateConstructorCallable = typeMapper.mapToCallableMethod(delegateConstructor);
CallableMethod callable = typeMapper.mapToCallableMethod(constructorDescriptor);
List<JvmMethodParameterSignature> superParameters = superCallable.getValueParameters();
List<JvmMethodParameterSignature> delegatingParameters = delegateConstructorCallable.getValueParameters();
List<JvmMethodParameterSignature> parameters = callable.getValueParameters();
ArgumentGenerator argumentGenerator;
if (isSameClassConstructor(delegateConstructor)) {
// if it's the same class constructor we should just pass all synthetic parameters
argumentGenerator =
generateThisCallImplicitArguments(iv, codegen, delegateConstructor, delegateConstructorCallable, delegatingParameters,
parameters);
}
else {
argumentGenerator =
generateSuperCallImplicitArguments(iv, codegen, constructorDescriptor, delegateConstructor, delegateConstructorCallable,
delegatingParameters,
parameters);
}
codegen.invokeMethodWithArguments(
delegateConstructorCallable, delegationConstructorCall, StackValue.none(), codegen.defaultCallGenerator, argumentGenerator);
}
private boolean isSameClassConstructor(@Nullable ConstructorDescriptor delegatingConstructor) {
return delegatingConstructor != null && delegatingConstructor.getContainingDeclaration() == descriptor;
}
@NotNull
private ArgumentGenerator generateSuperCallImplicitArguments(
@NotNull InstructionAdapter iv,
@NotNull ExpressionCodegen codegen,
@NotNull ConstructorDescriptor constructorDescriptor,
@NotNull ConstructorDescriptor superConstructor,
@NotNull CallableMethod superCallable,
@NotNull List<JvmMethodParameterSignature> superParameters,
@NotNull List<JvmMethodParameterSignature> parameters
) {
int offset = 1;
int superIndex = 0;
@@ -1469,18 +1560,47 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
offset += type.getSize();
}
ArgumentGenerator argumentGenerator;
if (isAnonymousObject(descriptor)) {
List<JvmMethodParameterSignature> superValues = superParameters.subList(superIndex, superParameters.size());
argumentGenerator = new ObjectSuperCallArgumentGenerator(superValues, iv, offset);
return new ObjectSuperCallArgumentGenerator(superValues, iv, offset);
}
else {
argumentGenerator =
new CallBasedArgumentGenerator(codegen, codegen.defaultCallGenerator, superConstructor.getValueParameters(),
return new CallBasedArgumentGenerator(codegen, codegen.defaultCallGenerator, superConstructor.getValueParameters(),
superCallable.getValueParameterTypes());
}
}
codegen.invokeMethodWithArguments(superCallable, resolvedCall, StackValue.none(), codegen.defaultCallGenerator, argumentGenerator);
@NotNull
private static ArgumentGenerator generateThisCallImplicitArguments(
@NotNull InstructionAdapter iv,
@NotNull ExpressionCodegen codegen,
@NotNull ConstructorDescriptor delegatingConstructor,
@NotNull CallableMethod delegatingCallable,
@NotNull List<JvmMethodParameterSignature> delegatingParameters,
@NotNull List<JvmMethodParameterSignature> parameters
) {
int offset = 1;
int index = 0;
for (; index < delegatingParameters.size(); index++) {
JvmMethodParameterKind delegatingKind = delegatingParameters.get(index).getKind();
if (delegatingKind == JvmMethodParameterKind.VALUE) {
assert index == parameters.size() || parameters.get(index).getKind() == JvmMethodParameterKind.VALUE:
"Delegating constructor has not enough implicit parameters";
break;
}
assert index < parameters.size() && parameters.get(index).getKind() == delegatingKind :
"Constructors of the same class should have the same set of implicit arguments";
JvmMethodParameterSignature parameter = parameters.get(index);
iv.load(offset, parameter.getAsmType());
offset += parameter.getAsmType().getSize();
}
assert index == parameters.size() || parameters.get(index).getKind() == JvmMethodParameterKind.VALUE :
"Delegating constructor has not enough parameters";
return new CallBasedArgumentGenerator(codegen, codegen.defaultCallGenerator, delegatingConstructor.getValueParameters(),
delegatingCallable.getValueParameterTypes());
}
private static class ObjectSuperCallArgumentGenerator extends ArgumentGenerator {
@@ -21,7 +21,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.types.JetType;
import org.jetbrains.org.objectweb.asm.Type;
@@ -37,6 +36,7 @@ public final class MutableClosure implements CalculatedClosure {
private boolean captureReceiver;
private Map<DeclarationDescriptor, EnclosedValueDescriptor> captureVariables;
private Map<DeclarationDescriptor, Integer> parameterOffsetInConstructor;
private List<Pair<String, Type>> recordedFields;
MutableClosure(@NotNull ClassDescriptor classDescriptor, @Nullable ClassDescriptor enclosingClass) {
@@ -114,6 +114,18 @@ public final class MutableClosure implements CalculatedClosure {
captureVariables.put(value.getDescriptor(), value);
}
public void setCapturedParameterOffsetInConstructor(DeclarationDescriptor descriptor, int offset) {
if (parameterOffsetInConstructor == null) {
parameterOffsetInConstructor = new LinkedHashMap<DeclarationDescriptor, Integer>();
}
parameterOffsetInConstructor.put(descriptor, offset);
}
public int getCapturedParameterOffsetInConstructor(DeclarationDescriptor descriptor) {
Integer result = parameterOffsetInConstructor != null ? parameterOffsetInConstructor.get(descriptor) : null;
return result != null ? result.intValue() : -1;
}
@Nullable
public ReceiverParameterDescriptor getEnclosingReceiverDescriptor() {
return enclosingFunWithReceiverDescriptor != null ? enclosingFunWithReceiverDescriptor.getExtensionReceiverParameter() : null;
@@ -59,6 +59,8 @@ public class BothSignatureWriter {
private boolean generic = false;
private int currentSignatureSize = 0;
public BothSignatureWriter(@NotNull Mode mode) {
this.signatureVisitor = new CheckSignatureAdapter(mode.asmType, signatureWriter);
}
@@ -210,6 +212,7 @@ public class BothSignatureWriter {
pop();
kotlinParameterTypes.add(new JvmMethodParameterSignature(jvmCurrentType, currentParameterKind));
currentSignatureSize += jvmCurrentType.getSize();
currentParameterKind = null;
jvmCurrentType = null;
@@ -260,6 +263,9 @@ public class BothSignatureWriter {
return new JvmMethodSignature(asmMethod, makeJavaGenericSignature(), kotlinParameterTypes);
}
public int getCurrentSignatureSize() {
return currentSignatureSize;
}
@Override
public String toString() {
@@ -23,8 +23,8 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicObjects;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.codegen.*;
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
import org.jetbrains.kotlin.codegen.binding.MutableClosure;
import org.jetbrains.kotlin.codegen.binding.PsiCodegenPredictor;
import org.jetbrains.kotlin.codegen.context.CodegenContext;
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
@@ -168,6 +168,11 @@ public class JetTypeMapper {
private Type mapReturnType(@NotNull CallableDescriptor descriptor, @Nullable BothSignatureWriter sw) {
JetType returnType = descriptor.getReturnType();
assert returnType != null : "Function has no return type: " + descriptor;
if (descriptor instanceof ConstructorDescriptor) {
return Type.VOID_TYPE;
}
if (returnType.equals(KotlinBuiltIns.getInstance().getUnitType())
&& !TypeUtils.isNullableType(returnType)
&& !(descriptor instanceof PropertyGetterDescriptor)) {
@@ -854,7 +859,7 @@ public class JetTypeMapper {
}
private void writeAdditionalConstructorParameters(@NotNull ConstructorDescriptor descriptor, @NotNull BothSignatureWriter sw) {
CalculatedClosure closure = bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration());
MutableClosure closure = bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration());
ClassDescriptor captureThis = getDispatchReceiverParameterForConstructorCall(descriptor, closure);
if (captureThis != null) {
@@ -892,14 +897,16 @@ public class JetTypeMapper {
}
if (type != null) {
closure.setCapturedParameterOffsetInConstructor(variableDescriptor, sw.getCurrentSignatureSize() + 1);
writeParameter(sw, JvmMethodParameterKind.CAPTURED_LOCAL_VARIABLE, type);
}
}
ResolvedCall<ConstructorDescriptor> superCall = getDelegationConstructorCall(bindingContext, descriptor);
// 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) {
if (classBuilderMode == ClassBuilderMode.FULL) {
ResolvedCall<ConstructorDescriptor> superCall = findFirstDelegatingSuperCall(descriptor);
if (superCall == null) return;
writeSuperConstructorCallParameters(sw, descriptor, superCall, captureThis != null);
}
}
@@ -945,6 +952,17 @@ public class JetTypeMapper {
}
}
@Nullable
private ResolvedCall<ConstructorDescriptor> findFirstDelegatingSuperCall(@NotNull ConstructorDescriptor descriptor) {
ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
while (true) {
ResolvedCall<ConstructorDescriptor> next = getDelegationConstructorCall(bindingContext, descriptor);
if (next == null) return null;
descriptor = next.getResultingDescriptor();
if (descriptor.getContainingDeclaration() != classDescriptor) return next;
}
}
@NotNull
public JvmMethodSignature mapScriptSignature(@NotNull ScriptDescriptor script, @NotNull List<ScriptDescriptor> importedScripts) {
BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
@@ -0,0 +1,24 @@
fun <R> run(block: () -> R) = block()
inline fun <R> inlineRun(block: () -> R) = block()
class Outer(val outerProp: String) {
fun foo(arg: String): String {
class Local {
val work1 = run { outerProp + arg }
val work2 = inlineRun { outerProp + arg }
val obj = object : Any() {
override fun toString() = outerProp + arg
}
override fun toString() = "${work1}#${work2}#${obj.toString()}"
}
return Local().toString()
}
}
fun box(): String {
val res = Outer("O").foo("K")
if (res != "OK#OK#OK") return "fail: $res"
return "OK"
}
@@ -0,0 +1,35 @@
var sideEffects: String = ""
class A {
var prop: String = ""
init {
sideEffects += prop + "first"
}
constructor(x: String) {
prop = x
sideEffects += "#third"
}
init {
sideEffects += prop + "#second"
}
constructor(x: Int) {
prop += "$x#int"
sideEffects += "#fourth"
}
}
fun box(): String {
val a1 = A("abc")
if (a1.prop != "abc") return "fail1: ${a1.prop}"
if (sideEffects != "first#second#third") return "fail1-sideEffects: ${sideEffects}"
sideEffects = ""
val a2 = A(123)
if (a2.prop != "123#int") return "fail2: ${a2.prop}"
if (sideEffects != "first#second#fourth") return "fail2-sideEffects: ${sideEffects}"
return "OK"
}
@@ -0,0 +1,41 @@
var sideEffects: String = ""
class A {
var prop: String = ""
init {
sideEffects += prop + "first"
}
constructor() {}
constructor(x: String): this() {
prop = x
sideEffects += "#third"
}
init {
sideEffects += prop + "#second"
}
constructor(x: Int): this(x.toString()) {
prop += "#int"
sideEffects += "#fourth"
}
}
fun box(): String {
val a1 = A("abc")
if (a1.prop != "abc") return "fail1: ${a1.prop}"
if (sideEffects != "first#second#third") return "fail1-sideEffects: ${sideEffects}"
sideEffects = ""
val a2 = A(123)
if (a2.prop != "123#int") return "fail2: ${a2.prop}"
if (sideEffects != "first#second#third#fourth") return "fail2-sideEffects: ${sideEffects}"
sideEffects = ""
val a3 = A()
if (a3.prop != "") return "fail2: ${a3.prop}"
if (sideEffects != "first#second") return "fail3-sideEffects: ${sideEffects}"
return "OK"
}
@@ -0,0 +1,39 @@
var sideEffects: String = ""
class A() {
var prop: String = ""
init {
sideEffects += prop + "first"
}
constructor(x: String): this() {
prop = x
sideEffects += "#third"
}
init {
sideEffects += prop + "#second"
}
constructor(x: Int): this(x.toString()) {
prop += "#int"
sideEffects += "#fourth"
}
}
fun box(): String {
val a1 = A("abc")
if (a1.prop != "abc") return "fail1: ${a1.prop}"
if (sideEffects != "first#second#third") return "fail1-sideEffects: ${sideEffects}"
sideEffects = ""
val a2 = A(123)
if (a2.prop != "123#int") return "fail2: ${a2.prop}"
if (sideEffects != "first#second#third#fourth") return "fail2-sideEffects: ${sideEffects}"
sideEffects = ""
val a3 = A()
if (a3.prop != "") return "fail2: ${a3.prop}"
if (sideEffects != "first#second") return "fail3-sideEffects: ${sideEffects}"
return "OK"
}
@@ -0,0 +1,53 @@
data class A1(val prop1: String) {
val prop2: String = "const2"
var prop3: String = ""
constructor(): this("default") {
prop3 = "empty"
}
constructor(x: Int): this(x.toString()) {
prop3 = "int"
}
fun f(): String = "$prop1#$prop2#$prop3"
}
data class A2 private () {
var prop1: String = ""
var prop2: String = "const2"
var prop3: String = ""
constructor(arg: String): this() {
prop1 = arg
}
constructor(x: Double): this() {
prop1 = "default"
prop3 = "empty"
}
constructor(x: Int): this(x.toString()) {
prop3 = "int"
}
fun f(): String = "$prop1#$prop2#$prop3"
}
fun box(): String {
val a1x = A1("asd")
if (a1x.f() != "asd#const2#") return "fail1: ${a1x.f()}"
if (a1x.toString() != "A1(prop1=asd)") return "fail1s: ${a1x.toString()}"
val a1y = A1()
if (a1y.f() != "default#const2#empty") return "fail2: ${a1y.f()}"
if (a1y.toString() != "A1(prop1=default)") return "fail2s: ${a1y.toString()}"
val a1z = A1(5)
if (a1z.f() != "5#const2#int") return "fail3: ${a1z.f()}"
if (a1z.toString() != "A1(prop1=5)") return "fail3s: ${a1z.toString()}"
val a2x = A2("asd")
if (a2x.f() != "asd#const2#") return "fail4: ${a2x.f()}"
val a2y = A2(123.0)
if (a2y.f() != "default#const2#empty") return "fail5: ${a2y.f()}"
val a2z = A2(5)
if (a2z.f() != "5#const2#int") return "fail6: ${a2z.f()}"
return "OK"
}
@@ -0,0 +1,34 @@
val global = "OK"
class A {
val prop: String
constructor(arg1: String = global) {
prop = arg1
}
constructor(arg1: String = global, arg2: Long) {
prop = "$arg1#$arg2"
}
constructor(arg1: String = global, argDouble: Double, arg3: Long = 1L) {
prop = "$arg1#$argDouble#$arg3"
}
}
fun box(): String {
val a1 = A()
if (a1.prop != "OK") return "fail1: ${a1.prop}"
val a2 = A("A")
if (a2.prop != "A") return "fail2: ${a2.prop}"
val a3 = A(arg2=123)
if (a3.prop != "OK#123") return "fail3: ${a3.prop}"
val a4 = A("A", arg2=123)
if (a4.prop != "A#123") return "fail4: ${a4.prop}"
val a5 = A(argDouble=23.0)
if (a5.prop != "OK#23.0#1") return "fail5: ${a5.prop}"
val a6 = A("A", argDouble=23.0)
if (a6.prop != "A#23.0#1") return "fail6: ${a6.prop}"
val a7 = A("A", arg3=2L, argDouble=23.0)
if (a7.prop != "A#23.0#2") return "fail7: ${a7.prop}"
return "OK"
}
@@ -0,0 +1,62 @@
enum class A1(val prop1: String) {
X: A1("asd")
Y: A1() {
override fun f() = super.f() + "#Y"
}
Z: A1(5)
val prop2: String = "const2"
var prop3: String = ""
constructor(): this("default") {
prop3 = "empty"
}
constructor(x: Int): this(x.toString()) {
prop3 = "int"
}
open fun f(): String = "$prop1#$prop2#$prop3"
}
enum class A2 {
val prop1: String
X: A2("asd")
Y: A2() {
override fun f() = super.f() + "#Y"
}
Z: A2(5)
val prop2: String = "const2"
var prop3: String = ""
constructor(arg: String) {
prop1 = arg
}
constructor() {
prop1 = "default"
prop3 = "empty"
}
constructor(x: Int): this(x.toString()) {
prop3 = "int"
}
open fun f(): String = "$prop1#$prop2#$prop3"
}
fun box(): String {
val a1x = A1.X
if (a1x.f() != "asd#const2#") return "fail1: ${a1x.f()}"
val a1y = A1.Y
if (a1y.f() != "default#const2#empty#Y") return "fail2: ${a1y.f()}"
val a1z = A1.Z
if (a1z.f() != "5#const2#int") return "fail3: ${a1z.f()}"
val a2x = A2.X
if (a2x.f() != "asd#const2#") return "fail4: ${a2x.f()}"
val a2y = A2.Y
if (a2y.f() != "default#const2#empty#Y") return "fail5: ${a2y.f()}"
val a2z = A2.Z
if (a2z.f() != "5#const2#int") return "fail6: ${a2z.f()}"
return "OK"
}
@@ -0,0 +1,23 @@
open class B<T>(val x: T, val y: T) {
constructor(x: T): this(x, x) {}
override fun toString() = "$x#$y"
}
class A : B<String> {
constructor(): super("default") {}
constructor(x: String): super(x, "default") {}
}
fun box(): String {
val b1 = B("1", "2").toString()
if (b1 != "1#2") return "fail1: $b1"
val b2 = B("abc").toString()
if (b2 != "abc#abc") return "fail2: $b2"
val a1 = A().toString()
if (a1 != "default#default") return "fail3: $a1"
val a2 = A("xyz").toString()
if (a2 != "xyz#default") return "fail4: $a2"
return "OK"
}
@@ -0,0 +1,79 @@
class Outer {
val outerProp: String
constructor(x: String) {
outerProp = x
}
var sideEffects = ""
inner class A1() {
var prop: String = ""
init {
sideEffects += outerProp + "#" + prop + "first"
}
constructor(x: String): this() {
prop = x + "#${outerProp}"
sideEffects += "#third"
}
init {
sideEffects += prop + "#second"
}
constructor(x: Int): this(x.toString() + "#" + outerProp) {
prop += "#int"
sideEffects += "#fourth"
}
}
inner class A2 {
var prop: String = ""
init {
sideEffects += outerProp + "#" + prop + "first"
}
constructor(x: String) {
prop = x + "#$outerProp"
sideEffects += "#third"
}
init {
sideEffects += prop + "#second"
}
constructor(x: Int) {
prop += "$x#$outerProp#int"
sideEffects += "#fourth"
}
}
}
fun box(): String {
val outer1 = Outer("propValue1")
val a1 = outer1.A1("abc")
if (a1.prop != "abc#propValue1") return "fail1: ${a1.prop}"
if (outer1.sideEffects != "propValue1#first#second#third") return "fail1-sideEffects: ${outer1.sideEffects}"
val outer2 = Outer("propValue2")
val a2 = outer2.A1(123)
if (a2.prop != "123#propValue2#propValue2#int") return "fail2: ${a2.prop}"
if (outer2.sideEffects != "propValue2#first#second#third#fourth") return "fail2-sideEffects: ${outer2.sideEffects}"
val outer3 = Outer("propValue3")
val a3 = outer3.A1()
if (a3.prop != "") return "fail2: ${a3.prop}"
if (outer3.sideEffects != "propValue3#first#second") return "fail3-sideEffects: ${outer3.sideEffects}"
val outer4 = Outer("propValue4")
val a4 = outer4.A2("abc")
if (a4.prop != "abc#propValue4") return "fail4: ${a4.prop}"
if (outer4.sideEffects != "propValue4#first#second#third") return "fail4-sideEffects: ${outer4.sideEffects}"
val outer5 = Outer("propValue5")
val a5 = outer5.A2(123)
if (a5.prop != "123#propValue5#int") return "fail5: ${a5.prop}"
if (outer5.sideEffects != "propValue5#first#second#fourth") return "fail5-sideEffects: ${outer5.sideEffects}"
return "OK"
}
@@ -0,0 +1,66 @@
class Outer {
val outerProp: String
constructor(x: String) {
outerProp = x
}
var sideEffects = ""
abstract inner class A1 {
var parentProp: String = ""
init {
sideEffects += outerProp + "#" + parentProp + "first"
}
protected constructor(x: String) {
parentProp = x + "#${outerProp}"
sideEffects += "#second#"
}
init {
sideEffects += parentProp + "#third"
}
protected constructor(x: Int): this(x.toString() + "#" + outerProp) {
parentProp += "#int"
sideEffects += "fourth#"
}
}
inner class A2 : A1 {
var prop: String = ""
init {
sideEffects += outerProp + "#" + prop + "fifth"
}
constructor(x: String): super(x + "#" + outerProp) {
prop = x + "#$outerProp"
sideEffects += "#sixth"
}
init {
sideEffects += prop + "#seventh"
}
constructor(x: Int): super(x + 1) {
prop += "$x#$outerProp#int"
sideEffects += "#eighth"
}
}
}
fun box(): String {
val outer1 = Outer("propValue1")
val a1 = outer1.A2("abc")
if (a1.parentProp != "abc#propValue1#propValue1") return "fail1: ${a1.parentProp}"
if (a1.prop != "abc#propValue1") return "fail2: ${a1.prop}"
if (outer1.sideEffects != "propValue1#first#third#second#propValue1#fifth#seventh#sixth") return "fail1-sideEffects: ${outer1.sideEffects}"
val outer2 = Outer("propValue2")
val a2 = outer2.A2(123)
if (a2.parentProp != "124#propValue2#propValue2#int") return "fail3: ${a2.parentProp}"
if (a2.prop != "123#propValue2#int") return "fail4: ${a2.prop}"
if (outer2.sideEffects != "propValue2#first#third#second#fourth#propValue2#fifth#seventh#eighth") return "fail2-sideEffects: ${outer2.sideEffects}"
return "OK"
}
@@ -0,0 +1,77 @@
open class C(val grandParentProp: String)
fun box(): String {
var sideEffects: String = ""
var parentSideEffects: String = ""
val justForUsageInClosure = 7
val justForUsageInParentClosure = "parentCaptured"
abstract class B : C {
val parentProp: String
init {
sideEffects += "minus-one#"
parentSideEffects += "1"
}
protected constructor(arg: Int): super(justForUsageInParentClosure) {
parentProp = (arg).toString()
sideEffects += "0.5#"
parentSideEffects += "#" + justForUsageInParentClosure
}
protected constructor(arg1: Int, arg2: Int): super(justForUsageInParentClosure) {
parentProp = (arg1 + arg2).toString()
sideEffects += "0.7#"
parentSideEffects += "#3"
}
init {
sideEffects += "zero#"
parentSideEffects += "#4"
}
}
class A : B {
var prop: String = ""
init {
sideEffects += prop + "first"
}
constructor(x1: Int, x2: Int): super(x1, x2) {
prop = x1.toString()
sideEffects += "#third"
}
init {
sideEffects += prop + "#second"
}
constructor(x: Int): super(justForUsageInClosure + x) {
prop += "${x}#int"
sideEffects += "#fourth"
}
constructor(): this(justForUsageInClosure) {
sideEffects += "#fifth"
}
override fun toString() = "$prop#$parentProp#$grandParentProp"
}
val a1 = A(5, 10).toString()
if (a1 != "5#15#parentCaptured") return "fail1: $a1"
if (sideEffects != "minus-one#zero#0.7#first#second#third") return "fail2: ${sideEffects}"
if (parentSideEffects != "1#4#3") return "fail3: ${parentSideEffects}"
sideEffects = ""
parentSideEffects = ""
val a2 = A(123).toString()
if (a2 != "123#int#130#parentCaptured") return "fail1: $a2"
if (sideEffects != "minus-one#zero#0.5#first#second#fourth") return "fail4: ${sideEffects}"
if (parentSideEffects != "1#4#parentCaptured") return "fail5: ${parentSideEffects}"
sideEffects = ""
parentSideEffects = ""
val a3 = A().toString()
if (a3 != "7#int#14#parentCaptured") return "fail6: $a3"
if (sideEffects != "minus-one#zero#0.5#first#second#fourth#fifth") return "fail7: ${sideEffects}"
if (parentSideEffects != "1#4#parentCaptured") return "fail8: ${parentSideEffects}"
return "OK"
}
@@ -0,0 +1,53 @@
var sideEffects: String = ""
abstract class B protected(val arg: Int) {
val parentProp: String
init {
sideEffects += "zero#"
parentProp = arg.toString()
}
}
class A(x: Boolean) : B(if (x) 1 else 2) {
var prop: String = ""
init {
sideEffects += prop + "first"
}
constructor(x: String): this(x == "abc") {
prop = x
sideEffects += "#third"
}
init {
sideEffects += prop + "#second"
}
constructor(x: Int): this(x < 0) {
prop += "${x}#int"
sideEffects += "#fourth"
}
}
fun box(): String {
val a1 = A("abc")
if (a1.prop != "abc") return "fail0: ${a1.prop}"
if (a1.parentProp != "1") return "fail1: ${a1.parentProp}"
if (a1.arg != 1) return "fail1': ${a1.arg}"
if (sideEffects != "zero#first#second#third") return "fail2: ${sideEffects}"
sideEffects = ""
val a2 = A(123)
if (a2.prop != "123#int") return "fail3: ${a2.prop}"
if (a2.parentProp != "2") return "fail4: ${a2.parentProp}"
if (a2.arg != 2) return "fail5': ${a2.arg}"
if (sideEffects != "zero#first#second#fourth") return "fail6: ${sideEffects}"
sideEffects = ""
val a3 = A(false)
if (a3.prop != "") return "fail7: ${a3.prop}"
if (a3.parentProp != "2") return "fail8: ${a3.parentProp}"
if (a3.arg != 2) return "fail9': ${a3.arg}"
if (sideEffects != "zero#first#second") return "fail10: ${sideEffects}"
return "OK"
}
@@ -0,0 +1,64 @@
var sideEffects: String = ""
abstract class B {
val parentProp: String
init {
sideEffects += "minus-one#"
}
protected constructor(arg: Int) {
parentProp = (arg).toString()
sideEffects += "0.5#"
}
protected constructor(arg1: Int, arg2: Int) {
parentProp = (arg1 + arg2).toString()
sideEffects += "0.7#"
}
init {
sideEffects += "zero#"
}
}
class A : B {
var prop: String = ""
init {
sideEffects += prop + "first"
}
constructor(x1: Int, x2: Int): super(x1, x2) {
prop = x1.toString()
sideEffects += "#third"
}
init {
sideEffects += prop + "#second"
}
constructor(x: Int): super(3 + x) {
prop += "${x}#int"
sideEffects += "#fourth"
}
constructor(): this(7) {
sideEffects += "#fifth"
}
}
fun box(): String {
val a1 = A(5, 10)
if (a1.prop != "5") return "fail0: ${a1.prop}"
if (a1.parentProp != "15") return "fail1: ${a1.parentProp}"
if (sideEffects != "minus-one#zero#0.7#first#second#third") return "fail2: ${sideEffects}"
sideEffects = ""
val a2 = A(123)
if (a2.prop != "123#int") return "fail3: ${a2.prop}"
if (a2.parentProp != "126") return "fail4: ${a2.parentProp}"
if (sideEffects != "minus-one#zero#0.5#first#second#fourth") return "fail5: ${sideEffects}"
sideEffects = ""
val a3 = A()
if (a3.prop != "7#int") return "fail6: ${a3.prop}"
if (a3.parentProp != "10") return "fail7: ${a3.parentProp}"
if (sideEffects != "minus-one#zero#0.5#first#second#fourth#fifth") return "fail8: ${sideEffects}"
return "OK"
}
@@ -0,0 +1,31 @@
fun join(x: Array<out String>): String {
var result = ""
for (i in x) {
result += i
result += "#"
}
return result
}
open class B {
val parentProp: String
constructor(vararg x: String) {
parentProp = join(x)
}
}
class A : B {
val prop: String
constructor(vararg x: String): super("0", *x, "4") {
prop = join(x)
}
}
fun box(): String {
val a1 = A("1", "2", "3")
if (a1.prop != "1#2#3#") return "fail1: ${a1.prop}"
if (a1.parentProp != "0#1#2#3#4#") return "fail2: ${a1.parentProp}"
return "OK"
}
@@ -0,0 +1,21 @@
inline fun run(block: () -> Unit) = block()
class A {
val prop: Int
constructor(arg: Boolean) {
if (arg) {
prop = 1
run { return }
throw RuntimeException("fail 0")
}
prop = 2
}
}
fun box(): String {
val a1 = A(true)
if (a1.prop != 1) return "fail1: ${a1.prop}"
val a2 = A(false)
if (a2.prop != 2) return "fail2: ${a2.prop}"
return "OK"
}
@@ -0,0 +1,18 @@
class A {
val prop: Int
constructor(arg: Boolean) {
if (arg) {
prop = 1
return
}
prop = 2
}
}
fun box(): String {
val a1 = A(true)
if (a1.prop != 1) return "fail1: ${a1.prop}"
val a2 = A(false)
if (a2.prop != 2) return "fail2: ${a2.prop}"
return "OK"
}
@@ -0,0 +1,18 @@
class A {
val prop: Int
constructor(arg: Boolean) {
if (arg) {
prop = 1
return Unit
}
prop = 2
}
}
fun box(): String {
val a1 = A(true)
if (a1.prop != 1) return "fail1: ${a1.prop}"
val a2 = A(false)
if (a2.prop != 2) return "fail2: ${a2.prop}"
return "OK"
}
@@ -0,0 +1,24 @@
package test;
public class secondaryConstructor {
private final String x;
private final String y;
public secondaryConstructor(String x, String y) {
this.x = x;
this.y = y;
}
public secondaryConstructor(String x) {
this(x, "def_y");
}
public secondaryConstructor() {
this("def_x");
}
@Override
public String toString() {
return x + "#" + y;
}
}
@@ -0,0 +1,19 @@
import test.secondaryConstructor;
class Child : secondaryConstructor {
constructor(): super() {}
constructor(x: String): super(x) {}
constructor(x: String, y: String): super(x, y) {}
}
fun box(): String {
val c1 = Child().toString()
if (c1 != "def_x#def_y") return "fail1: $c1"
val c2 = Child("abc").toString()
if (c2 != "abc#def_y") return "fail2: $c2"
val c3 = Child("abc", "def").toString()
if (c3 != "abc#def") return "fail3: $c3"
return "OK"
}
@@ -0,0 +1,11 @@
class WithGenerics {
public static String foo1() {
A<Double> x = new A<Double>("OK");
return x.toString();
}
public static String foo2() {
A<Integer> x = new A<Integer>(123);
return x.toString();
}
}
@@ -0,0 +1,20 @@
open class A<T> {
val prop: String
constructor(x: String) {
prop = x
}
constructor(x: T) {
prop = x.toString()
}
override fun toString() = prop
}
fun box(): String {
val a1 = WithGenerics.foo1()
if (a1 != "OK") return "fail1: $a1"
val a2 = WithGenerics.foo2()
if (a2 != "123") return "fail2: $a2"
return "OK"
}
@@ -0,0 +1,14 @@
class WithPrimary {
public static A test1() {
return new A("123", "abc");
}
public static A test2() {
return new A();
}
public static A test3() {
return new A("123", 456);
}
public static A test4() {
return new A(1.0);
}
}
@@ -0,0 +1,21 @@
class A(val x: String = "def_x", val y: String = "1") {
constructor(x: String, y: Int): this(x, y.toString()) {}
constructor(x: Double): this(x.toString(), "def_y") {}
override fun toString() = "$x#$y"
}
fun box(): String {
val test1 = WithPrimary.test1().toString()
if (test1 != "123#abc") return "fail1: $test1"
val test2 = WithPrimary.test2().toString()
if (test2 != "def_x#1") return "fail2: $test2"
val test3 = WithPrimary.test3().toString()
if (test3 != "123#456") return "fail3: $test3"
val test4 = WithPrimary.test4().toString()
if (test4 != "1.0#def_y") return "fail4: $test4"
return "OK"
}
@@ -0,0 +1,5 @@
public class WithVarargs {
public static String foo() {
return new A("1", "2", "3").getProp();
}
}
@@ -0,0 +1,23 @@
fun join(x: Array<out String>): String {
var result = ""
for (i in x) {
result += i
result += "#"
}
return result
}
class A {
val prop: String
constructor(vararg x: String) {
prop = join(x)
}
}
fun box(): String {
val a1 = WithVarargs.foo()
if (a1 != "1#2#3#") return "fail1: ${a1}"
return "OK"
}
@@ -0,0 +1,14 @@
class WithoutPrimary {
public static A test1() {
return new A("123", "abc");
}
public static A test2() {
return new A(null, 1, 3, null);
}
public static A test3() {
return new A("123", 456);
}
public static A test4() {
return new A(1.0);
}
}
@@ -0,0 +1,27 @@
class A {
val x: String
val y: String
constructor(x: String, y: String) {
this.x = x
this.y = y
}
constructor(x: String = "def_x", y: Int = 1): this(x, y.toString()) {}
constructor(x: Double): this(x.toString(), "def_y") {}
override fun toString() = "$x#$y"
}
fun box(): String {
val test1 = WithoutPrimary.test1().toString()
if (test1 != "123#abc") return "fail1: $test1"
val test2 = WithoutPrimary.test2().toString()
if (test2 != "def_x#1") return "fail2: $test2"
val test3 = WithoutPrimary.test3().toString()
if (test3 != "123#456") return "fail3: $test3"
val test4 = WithoutPrimary.test4().toString()
if (test4 != "1.0#def_y") return "fail4: $test4"
return "OK"
}
@@ -143,6 +143,12 @@ public class BlackBoxAgainstJavaCodegenTestGenerated extends AbstractBlackBoxCod
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/constructor/genericConstructor.kt");
doTestAgainstJava(fileName);
}
@TestMetadata("secondaryConstructor.kt")
public void testSecondaryConstructor() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/constructor/secondaryConstructor.kt");
doTestAgainstJava(fileName);
}
}
@TestMetadata("compiler/testData/codegen/boxAgainstJava/delegation")
@@ -70,6 +70,7 @@ import java.util.regex.Pattern;
BlackBoxCodegenTestGenerated.Regressions.class,
BlackBoxCodegenTestGenerated.SafeCall.class,
BlackBoxCodegenTestGenerated.SamConstructors.class,
BlackBoxCodegenTestGenerated.SecondaryConstructors.class,
BlackBoxCodegenTestGenerated.StaticFields.class,
BlackBoxCodegenTestGenerated.Strings.class,
BlackBoxCodegenTestGenerated.Super.class,
@@ -1715,6 +1716,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("subclosuresWithinInitializers.kt")
public void testSubclosuresWithinInitializers() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/closures/subclosuresWithinInitializers.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/codegen/box/closures/captureOuterProperty")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -6270,6 +6277,111 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
}
}
@TestMetadata("compiler/testData/codegen/box/secondaryConstructors")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SecondaryConstructors extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInSecondaryConstructors() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/secondaryConstructors"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("basicNoPrimaryManySinks.kt")
public void testBasicNoPrimaryManySinks() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/basicNoPrimaryManySinks.kt");
doTest(fileName);
}
@TestMetadata("basicNoPrimaryOneSink.kt")
public void testBasicNoPrimaryOneSink() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/basicNoPrimaryOneSink.kt");
doTest(fileName);
}
@TestMetadata("basicPrimary.kt")
public void testBasicPrimary() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/basicPrimary.kt");
doTest(fileName);
}
@TestMetadata("dataClasses.kt")
public void testDataClasses() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/dataClasses.kt");
doTest(fileName);
}
@TestMetadata("defaultArgs.kt")
public void testDefaultArgs() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/defaultArgs.kt");
doTest(fileName);
}
@TestMetadata("enums.kt")
public void testEnums() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/enums.kt");
doTest(fileName);
}
@TestMetadata("generics.kt")
public void testGenerics() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/generics.kt");
doTest(fileName);
}
@TestMetadata("innerClasses.kt")
public void testInnerClasses() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/innerClasses.kt");
doTest(fileName);
}
@TestMetadata("innerClassesInheritance.kt")
public void testInnerClassesInheritance() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/innerClassesInheritance.kt");
doTest(fileName);
}
@TestMetadata("localClasses.kt")
public void testLocalClasses() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/localClasses.kt");
doTest(fileName);
}
@TestMetadata("superCallPrimary.kt")
public void testSuperCallPrimary() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/superCallPrimary.kt");
doTest(fileName);
}
@TestMetadata("superCallSecondary.kt")
public void testSuperCallSecondary() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/superCallSecondary.kt");
doTest(fileName);
}
@TestMetadata("varargs.kt")
public void testVarargs() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/varargs.kt");
doTest(fileName);
}
@TestMetadata("withNonLocalReturn.kt")
public void testWithNonLocalReturn() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/withNonLocalReturn.kt");
doTest(fileName);
}
@TestMetadata("withReturn.kt")
public void testWithReturn() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/withReturn.kt");
doTest(fileName);
}
@TestMetadata("withReturnUnit.kt")
public void testWithReturnUnit() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/withReturnUnit.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/codegen/box/staticFields")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -36,6 +36,7 @@ import java.util.regex.Pattern;
BlackBoxWithJavaCodegenTestGenerated.PlatformStatic.class,
BlackBoxWithJavaCodegenTestGenerated.Properties.class,
BlackBoxWithJavaCodegenTestGenerated.Reflection.class,
BlackBoxWithJavaCodegenTestGenerated.SecondaryConstructors.class,
})
@RunWith(JUnit3RunnerWithInners.class)
public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
@@ -181,4 +182,40 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
}
@TestMetadata("compiler/testData/codegen/boxWithJava/secondaryConstructors")
@TestDataPath("$PROJECT_ROOT")
@InnerTestClasses({
})
@RunWith(JUnit3RunnerWithInners.class)
public static class SecondaryConstructors extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInSecondaryConstructors() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithJava/secondaryConstructors"), Pattern.compile("^([^\\.]+)$"), true);
}
@TestMetadata("withGenerics")
public void testWithGenerics() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/secondaryConstructors/withGenerics/");
doTestWithJava(fileName);
}
@TestMetadata("withPrimary")
public void testWithPrimary() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/secondaryConstructors/withPrimary/");
doTestWithJava(fileName);
}
@TestMetadata("withVarargs")
public void testWithVarargs() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/secondaryConstructors/withVarargs/");
doTestWithJava(fileName);
}
@TestMetadata("withoutPrimary")
public void testWithoutPrimary() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/secondaryConstructors/withoutPrimary/");
doTestWithJava(fileName);
}
}
}