diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java index f5481733e79..880baf4beb2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java @@ -205,6 +205,8 @@ public interface BindingContext { */ WritableSlice FUNCTION = Slices.sliceBuilder().build(); WritableSlice CONSTRUCTOR = Slices.sliceBuilder().build(); + WritableSlice> CONSTRUCTOR_RESOLVED_DELEGATION_CALL = + Slices.>sliceBuilder().build(); WritableSlice VARIABLE = Slices.sliceBuilder().build(); WritableSlice VALUE_PARAMETER = Slices.sliceBuilder().build(); WritableSlice PROPERTY_ACCESSOR = diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java index 0bea34a41af..8207fb1d078 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.lexer.JetTokens; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.calls.CallResolver; +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults; import org.jetbrains.kotlin.resolve.calls.util.CallMaker; import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant; @@ -43,9 +44,9 @@ import java.util.*; import static org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER; import static org.jetbrains.kotlin.diagnostics.Errors.*; +import static org.jetbrains.kotlin.resolve.BindingContext.CONSTRUCTOR_RESOLVED_DELEGATION_CALL; import static org.jetbrains.kotlin.resolve.BindingContext.DEFERRED_TYPE; import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE; -import static org.jetbrains.kotlin.types.TypeUtils.dependsOnTypeConstructors; public class BodyResolver { private ScriptBodyResolver scriptBodyResolverResolver; @@ -162,10 +163,15 @@ public class BodyResolver { if (call == null || call.getCalleeExpression() == null) return; JetType superClassType = DescriptorUtils.getSuperClassType(descriptor.getContainingDeclaration()); - callResolver.resolveFunctionCall( + OverloadResolutionResults results = callResolver.resolveFunctionCall( trace, scope, CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, call), - superClassType != null ? superClassType : NO_EXPECTED_TYPE, c.getOuterDataFlowInfo(), false); + superClassType != null ? superClassType : NO_EXPECTED_TYPE, + c.getOuterDataFlowInfo(), false); + + if (results.isSuccess()) { + recordConstructorDelegationCall(trace, descriptor, results.getResultingCall()); + } } public void resolveBodies(@NotNull BodiesResolveContext c) { @@ -201,6 +207,7 @@ public class BodyResolver { final ExpressionTypingServices typeInferrer = expressionTypingServices; // TODO : flow final Map supertypes = Maps.newLinkedHashMap(); + final ResolvedCall[] primaryConstructorDelegationCall = new ResolvedCall[1]; JetVisitorVoid visitor = new JetVisitorVoid() { private void recordSupertype(JetTypeReference typeReference, JetType supertype) { if (supertype == null) return; @@ -256,6 +263,13 @@ public class BodyResolver { if (classDescriptor.getKind() == ClassKind.TRAIT) { trace.report(CONSTRUCTOR_IN_TRAIT.on(elementToMark)); } + // allow only one delegating constructor + if (primaryConstructorDelegationCall[0] == null) { + primaryConstructorDelegationCall[0] = results.getResultingCall(); + } + else { + primaryConstructorDelegationCall[0] = null; + } } } else { @@ -303,9 +317,21 @@ public class BodyResolver { ? Collections.singleton(((ClassDescriptor) descriptor.getContainingDeclaration()).getTypeConstructor()) : Collections.emptySet(); + if (primaryConstructorDelegationCall[0] != null && primaryConstructor != null) { + recordConstructorDelegationCall(trace, primaryConstructor, primaryConstructorDelegationCall[0]); + } checkSupertypeList(descriptor, supertypes, parentEnum); } + private static void recordConstructorDelegationCall( + @NotNull BindingTrace trace, + @NotNull ConstructorDescriptor constructor, + @NotNull ResolvedCall call + ) { + //noinspection unchecked + trace.record(CONSTRUCTOR_RESOLVED_DELEGATION_CALL, constructor, (ResolvedCall) call); + } + // allowedFinalSupertypes typically contains a enum type of which supertypeOwner is an entry private void checkSupertypeList( @NotNull ClassDescriptor supertypeOwner,