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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user