diff --git a/compiler/frontend/src/org/jetbrains/kotlin/descriptors/ClassDescriptorWithResolutionScopes.java b/compiler/frontend/src/org/jetbrains/kotlin/descriptors/ClassDescriptorWithResolutionScopes.java index 0602e762abd..2ba293eb48b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/descriptors/ClassDescriptorWithResolutionScopes.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/descriptors/ClassDescriptorWithResolutionScopes.java @@ -33,6 +33,9 @@ public interface ClassDescriptorWithResolutionScopes extends ClassDescriptor { @NotNull JetScope getScopeForInitializerResolution(); + @NotNull + JetScope getScopeForSecondaryConstructorHeaderResolution(); + @NotNull JetScope getScopeForMemberLookup(); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/MutableClassDescriptor.java b/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/MutableClassDescriptor.java index c555e64c40c..3bc6a626a7a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/MutableClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/MutableClassDescriptor.java @@ -57,6 +57,7 @@ public class MutableClassDescriptor extends ClassDescriptorBase implements Class private final WritableScope scopeForMemberResolution; // This scope contains type parameters but does not contain inner classes private final WritableScope scopeForSupertypeResolution; + private final WritableScope scopeForSecondaryConstructorHeaderResolution; private WritableScope scopeForInitializers; //contains members + primary constructor value parameters + map for backing fields private JetScope scopeForMemberLookup; private final JetScope staticScope = new StaticScopeForKotlinClass(this); @@ -83,6 +84,8 @@ public class MutableClassDescriptor extends ClassDescriptorBase implements Class .changeLockLevel(WritableScope.LockLevel.BOTH); this.scopeForMemberResolution = new WritableScopeImpl(scopeForSupertypeResolution, this, redeclarationHandler, "MemberResolution") .changeLockLevel(WritableScope.LockLevel.BOTH); + this.scopeForSecondaryConstructorHeaderResolution = + new WritableScopeImpl(scopeForSupertypeResolution, this, redeclarationHandler, "SecondaryConstructorHeaderResolution "); if (kind == ClassKind.TRAIT) { setUpScopeForInitializers(this); @@ -90,6 +93,7 @@ public class MutableClassDescriptor extends ClassDescriptorBase implements Class scopeForMemberResolution.importScope(staticScope); scopeForMemberResolution.addLabeledDeclaration(this); + scopeForSecondaryConstructorHeaderResolution.importScope(staticScope); } @Nullable @@ -289,6 +293,12 @@ public class MutableClassDescriptor extends ClassDescriptorBase implements Class return getWritableScopeForInitializers(); } + @NotNull + @Override + public JetScope getScopeForSecondaryConstructorHeaderResolution() { + return scopeForSecondaryConstructorHeaderResolution; + } + private void setUpScopeForInitializers(@NotNull DeclarationDescriptor containingDeclaration) { this.scopeForInitializers = new WritableScopeImpl( scopeForMemberResolution, containingDeclaration, RedeclarationHandler.DO_NOTHING, "Initializers") diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodiesResolveContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodiesResolveContext.java index 62956fb0ded..0fb3584e9de 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodiesResolveContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodiesResolveContext.java @@ -21,10 +21,7 @@ import org.jetbrains.annotations.Mutable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.ReadOnly; import org.jetbrains.kotlin.context.GlobalContext; -import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes; -import org.jetbrains.kotlin.descriptors.PropertyDescriptor; -import org.jetbrains.kotlin.descriptors.ScriptDescriptor; -import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor; +import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; import org.jetbrains.kotlin.resolve.scopes.JetScope; @@ -50,6 +47,8 @@ public interface BodiesResolveContext extends GlobalContext { @Mutable Map getAnonymousInitializers(); @Mutable + Map getSecondaryConstructors(); + @Mutable Map getScripts(); @Mutable diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java index c5e67ac4ef1..e28c9e31f61 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java @@ -20,6 +20,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.intellij.psi.PsiElement; import com.intellij.util.containers.Queue; +import kotlin.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.*; @@ -44,6 +45,7 @@ import static org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor.NO_RE import static org.jetbrains.kotlin.diagnostics.Errors.*; 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; @@ -108,6 +110,7 @@ public class BodyResolver { resolveAnonymousInitializers(c); resolvePrimaryConstructorParameters(c); + resolveSecondaryConstructors(c); resolveFunctionBodies(c); @@ -119,6 +122,52 @@ public class BodyResolver { } } + private void resolveSecondaryConstructors(@NotNull BodiesResolveContext c) { + for (Map.Entry entry : c.getSecondaryConstructors().entrySet()) { + resolveSecondaryConstructorBody(c, entry.getKey(), entry.getValue()); + } + } + + private void resolveSecondaryConstructorBody( + @NotNull final BodiesResolveContext c, + @NotNull final JetSecondaryConstructor constructor, + @NotNull final ConstructorDescriptor descriptor + ) { + JetScope bodyDeclaringScope = c.getDeclaringScopes().apply(constructor); + assert bodyDeclaringScope != null : "Declaring scope should be registered before body resolve"; + + assert descriptor.getContainingDeclaration() instanceof ClassDescriptorWithResolutionScopes + : "When resolving body it should be class descriptor with resolution scopes"; + + ClassDescriptorWithResolutionScopes classDescriptor = (ClassDescriptorWithResolutionScopes) descriptor.getContainingDeclaration(); + + resolveFunctionBody(c, trace, constructor, descriptor, bodyDeclaringScope, + classDescriptor.getScopeForSecondaryConstructorHeaderResolution(), + new Function1() { + @Override + public Void invoke(@NotNull JetScope headerInnerScope) { + resolveSecondaryConstructorDelegationCall(c, headerInnerScope, constructor, descriptor); + return null; + } + }); + } + + private void resolveSecondaryConstructorDelegationCall( + @NotNull BodiesResolveContext c, + @NotNull JetScope scope, + @NotNull JetSecondaryConstructor constructor, + @NotNull ConstructorDescriptor descriptor + ) { + JetConstructorDelegationCall call = constructor.getDelegationCall(); + if (call == null || call.getCalleeExpression() == null) return; + JetType superClassType = DescriptorUtils.getSuperClassType(descriptor.getContainingDeclaration()); + + callResolver.resolveFunctionCall( + trace, scope, + CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, call), + superClassType != null ? superClassType : NO_EXPECTED_TYPE, c.getOuterDataFlowInfo(), false); + } + public void resolveBodies(@NotNull BodiesResolveContext c) { resolveBehaviorDeclarationBodies(c); controlFlowAnalyzer.process(c); @@ -525,7 +574,8 @@ public class BodyResolver { JetType expectedTypeForInitializer = property.getTypeReference() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE; CompileTimeConstant compileTimeInitializer = propertyDescriptor.getCompileTimeInitializer(); if (compileTimeInitializer == null) { - expressionTypingServices.getType(propertyDeclarationInnerScope, initializer, expectedTypeForInitializer, c.getOuterDataFlowInfo(), trace); + expressionTypingServices.getType(propertyDeclarationInnerScope, initializer, expectedTypeForInitializer, + c.getOuterDataFlowInfo(), trace); } } @@ -559,16 +609,35 @@ public class BodyResolver { @NotNull FunctionDescriptor functionDescriptor, @NotNull JetScope declaringScope ) { - JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(declaringScope, functionDescriptor, trace); + resolveFunctionBody(c, trace, function, functionDescriptor, declaringScope, null, null); + } + public void resolveFunctionBody( + @NotNull BodiesResolveContext c, + @NotNull BindingTrace trace, + @NotNull JetDeclarationWithBody function, + @NotNull FunctionDescriptor functionDescriptor, + @NotNull JetScope bodyDeclaringScope, + @Nullable JetScope headerDeclaringScope, + @Nullable Function1 beforeBlockBody + ) { + JetScope headerInnerScope = FunctionDescriptorUtil.getFunctionInnerScope( + headerDeclaringScope == null ? bodyDeclaringScope : headerDeclaringScope, functionDescriptor, trace); List valueParameters = function.getValueParameters(); List valueParameterDescriptors = functionDescriptor.getValueParameters(); - expressionTypingServices.resolveValueParameters(valueParameters, valueParameterDescriptors, functionInnerScope, + expressionTypingServices.resolveValueParameters(valueParameters, valueParameterDescriptors, headerInnerScope, c.getOuterDataFlowInfo(), trace); + if (beforeBlockBody != null) { + beforeBlockBody.invoke(headerInnerScope); + } + + JetScope bodyInnerScope = headerDeclaringScope == null ? headerInnerScope : + FunctionDescriptorUtil.getFunctionInnerScope(bodyDeclaringScope, functionDescriptor, trace); + if (function.hasBody()) { - expressionTypingServices.checkFunctionReturnType(functionInnerScope, function, functionDescriptor, c.getOuterDataFlowInfo(), null, trace); + expressionTypingServices.checkFunctionReturnType(bodyInnerScope, function, functionDescriptor, c.getOuterDataFlowInfo(), null, trace); } assert functionDescriptor.getReturnType() != null; diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/LazyTopDownAnalyzer.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/LazyTopDownAnalyzer.java index 460007ad3cb..3efff48b44d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/LazyTopDownAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/LazyTopDownAnalyzer.java @@ -209,7 +209,6 @@ public class LazyTopDownAnalyzer { @Override public void visitClass(@NotNull JetClass klass) { visitClassOrObject(klass); - registerPrimaryConstructorParameters(klass); } @@ -224,6 +223,15 @@ public class LazyTopDownAnalyzer { } } + @Override + public void visitSecondaryConstructor(@NotNull JetSecondaryConstructor constructor) { + c.getSecondaryConstructors().put( + constructor, + (ConstructorDescriptor) lazyDeclarationResolver.resolveToDescriptor(constructor) + ); + registerScope(c, constructor); + } + @Override public void visitEnumEntry(@NotNull JetEnumEntry enumEntry) { visitClassOrObject(enumEntry); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TopDownAnalysisContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TopDownAnalysisContext.java index df4b5bc101c..daf13e09f36 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TopDownAnalysisContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TopDownAnalysisContext.java @@ -42,6 +42,7 @@ public class TopDownAnalysisContext implements BodiesResolveContext { private final Map classes = Maps.newLinkedHashMap(); private final Map anonymousInitializers = Maps.newLinkedHashMap(); private final Set files = new LinkedHashSet(); + private final Map secondaryConstructors = Maps.newLinkedHashMap(); private final Map declaringScopes = Maps.newHashMap(); private final Map functions = Maps.newLinkedHashMap(); @@ -95,6 +96,11 @@ public class TopDownAnalysisContext implements BodiesResolveContext { return anonymousInitializers; } + @Override + public Map getSecondaryConstructors() { + return secondaryConstructors; + } + @NotNull @Override public StorageManager getStorageManager() { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java index a8c5de90d7e..7eefd6f608a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java @@ -39,8 +39,10 @@ import org.jetbrains.kotlin.resolve.calls.tasks.*; import org.jetbrains.kotlin.resolve.calls.tasks.collectors.CallableDescriptorCollectors; import org.jetbrains.kotlin.resolve.calls.util.CallMaker; import org.jetbrains.kotlin.resolve.calls.util.DelegatingCall; +import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage; import org.jetbrains.kotlin.resolve.scopes.JetScope; import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver; +import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.kotlin.types.JetType; import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext; import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices; @@ -238,7 +240,7 @@ public class CallResolver { return resolveCallForConstructor(context, (JetConstructorCalleeExpression) calleeExpression); } else if (calleeExpression instanceof JetConstructorDelegationReferenceExpression) { - return resolveCallForThisExpression(context, (JetConstructorDelegationReferenceExpression) calleeExpression); + return resolveConstructorDelegationCall(context, (JetConstructorDelegationReferenceExpression) calleeExpression); } else if (calleeExpression == null) { return checkArgumentTypesAndFail(context); @@ -288,27 +290,47 @@ public class CallResolver { return computeTasksFromCandidatesAndResolvedCall(context, functionReference, candidates, CallTransformer.FUNCTION_CALL_TRANSFORMER); } - private OverloadResolutionResults resolveCallForThisExpression( + @NotNull + private OverloadResolutionResults resolveConstructorDelegationCall( @NotNull BasicCallResolutionContext context, @NotNull JetConstructorDelegationReferenceExpression calleeExpression ) { - DeclarationDescriptor containingDeclaration = context.scope.getContainingDeclaration(); - if (containingDeclaration instanceof ConstructorDescriptor) { - containingDeclaration = containingDeclaration.getContainingDeclaration(); - } - assert containingDeclaration instanceof ClassDescriptor; + ClassDescriptor currentClassDescriptor = getClassDescriptorByConstructorContext(context); + + ClassDescriptor delegateClassDescriptor = calleeExpression.isThis() ? currentClassDescriptor : + DescriptorUtilPackage.getSuperClassOrAny(currentClassDescriptor); + Collection constructors = delegateClassDescriptor.getConstructors(); - Collection constructors = ((ClassDescriptor) containingDeclaration).getConstructors(); if (constructors.isEmpty()) { context.trace.report(NO_CONSTRUCTOR.on(CallUtilPackage.getValueArgumentListOrElement(context.call))); return checkArgumentTypesAndFail(context); } - List> candidates = - ResolutionCandidate.convertCollection(context.call, constructors); + + List> candidates = Lists.newArrayList(); + ReceiverValue constructorDispatchReceiver = !delegateClassDescriptor.isInner() ? ReceiverValue.NO_RECEIVER : + ((ClassDescriptor) delegateClassDescriptor.getContainingDeclaration()). + getThisAsReceiverParameter().getValue(); + + for (CallableDescriptor descriptor : constructors) { + candidates.add(ResolutionCandidate.create( + context.call, descriptor, constructorDispatchReceiver, ReceiverValue.NO_RECEIVER, + ExplicitReceiverKind.NO_EXPLICIT_RECEIVER + )); + } return computeTasksFromCandidatesAndResolvedCall(context, calleeExpression, candidates, CallTransformer.FUNCTION_CALL_TRANSFORMER); } + @NotNull + private static ClassDescriptor getClassDescriptorByConstructorContext(@NotNull BasicCallResolutionContext context) { + DeclarationDescriptor containingDeclaration = context.scope.getContainingDeclaration(); + if (containingDeclaration instanceof ConstructorDescriptor) { + containingDeclaration = containingDeclaration.getContainingDeclaration(); + } + assert containingDeclaration != null : "Grandparent of delegation call should be a class descriptor"; + return (ClassDescriptor) containingDeclaration; + } + public OverloadResolutionResults resolveCallWithKnownCandidate( @NotNull Call call, @NotNull TracingStrategy tracing, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/ResolutionCandidate.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/ResolutionCandidate.java index 95526653236..bb2ab33c1cf 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/ResolutionCandidate.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/ResolutionCandidate.java @@ -95,17 +95,6 @@ public class ResolutionCandidate { return explicitReceiverKind; } - @NotNull - public static List> convertCollection( - @NotNull Call call, @NotNull Collection descriptors - ) { - List> result = Lists.newArrayList(); - for (D descriptor : descriptors) { - result.add(create(call, descriptor)); - } - return result; - } - @Override public String toString() { return candidateDescriptor.toString(); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkTraitRequirements.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkTraitRequirements.kt index 2786ac6734e..4c698ccb5ef 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkTraitRequirements.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkTraitRequirements.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.psi.JetClassOrObject import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny fun checkTraitRequirements(c: Map, trace: BindingTrace) { for ((classOrObject, descriptor) in c.entrySet()) { @@ -52,21 +53,10 @@ private fun getSuperClassesReachableByClassInheritance( descriptor: ClassDescriptor, result: MutableSet = hashSetOf() ): Set { - val superClass = getSuperClass(descriptor) + val superClass = descriptor.getSuperClassOrAny() result.add(superClass) if (!KotlinBuiltIns.isAny(superClass)) { getSuperClassesReachableByClassInheritance(superClass, result) } return result } - -private fun getSuperClass(descriptor: ClassDescriptor): ClassDescriptor { - for (supertype in descriptor.getDefaultType().getConstructor().getSupertypes()) { - val superClassifier = supertype.getConstructor().getDeclarationDescriptor() - if (DescriptorUtils.isClass(superClassifier) || DescriptorUtils.isEnumClass(superClassifier)) { - return superClassifier as ClassDescriptor - } - } - return KotlinBuiltIns.getInstance().getAny() -} - diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyDeclarationResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyDeclarationResolver.java index ea126f9accc..3213bad24c7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyDeclarationResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyDeclarationResolver.java @@ -161,12 +161,25 @@ public class LazyDeclarationResolver { function.getValueParameters(); return getBindingContext().get(BindingContext.VALUE_PARAMETER, parameter); } + else if (grandFather instanceof JetSecondaryConstructor) { + ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) visitSecondaryConstructor( + (JetSecondaryConstructor) grandFather, data + ); + constructorDescriptor.getValueParameters(); + return getBindingContext().get(BindingContext.VALUE_PARAMETER, parameter); + } else { //TODO: support parameters in accessors and other places(?) return super.visitParameter(parameter, data); } } + @Override + public DeclarationDescriptor visitSecondaryConstructor(@NotNull JetSecondaryConstructor constructor, Void data) { + getClassDescriptor((JetClassOrObject) constructor.getParent().getParent()).getConstructors(); + return getBindingContext().get(BindingContext.CONSTRUCTOR, constructor); + } + @Override public DeclarationDescriptor visitProperty(@NotNull JetProperty property, Void data) { JetScope scopeForDeclaration = resolutionScopeToResolveDeclaration(property); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/AbstractPsiBasedDeclarationProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/AbstractPsiBasedDeclarationProvider.kt index 537d91b4065..79e074efb83 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/AbstractPsiBasedDeclarationProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/AbstractPsiBasedDeclarationProvider.kt @@ -38,7 +38,7 @@ public abstract class AbstractPsiBasedDeclarationProvider(storageManager: Storag val classesAndObjects = ArrayListMultimap.create() // order matters here public fun putToIndex(declaration: JetDeclaration) { - if (declaration is JetClassInitializer) return + if (declaration is JetClassInitializer || declaration is JetSecondaryConstructor) return allDeclarations.add(declaration) if (declaration is JetNamedFunction) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java index 9ace74073d9..d8ef06acf1d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java @@ -92,6 +92,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes private final NotNullLazyValue scopeForClassHeaderResolution; private final NotNullLazyValue scopeForMemberDeclarationResolution; private final NotNullLazyValue scopeForPropertyInitializerResolution; + private final NotNullLazyValue scopeForSecondaryConstructorHeaderResolution; private final NullableLazyValue forceResolveAllContents; private final boolean isDefaultObject; @@ -211,6 +212,12 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes return computeScopeForPropertyInitializerResolution(); } }); + this.scopeForSecondaryConstructorHeaderResolution = storageManager.createLazyValue(new Function0() { + @Override + public JetScope invoke() { + return computeScopeForSecondaryConstructorHeaderResolution(); + } + }); this.forceResolveAllContents = storageManager.createRecursionTolerantNullableLazyValue(new Function0() { @Override public Void invoke() { @@ -326,6 +333,23 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes scope, getScopeForMemberDeclarationResolution()); } + @NotNull + @Override + public JetScope getScopeForSecondaryConstructorHeaderResolution() { + return scopeForSecondaryConstructorHeaderResolution.invoke(); + } + + + @NotNull + private JetScope computeScopeForSecondaryConstructorHeaderResolution() { + return new ChainedScope( + this, + "ScopeForSecondaryConstructorHeaderResolution: " + getName(), + getScopeForClassHeaderResolution(), + getStaticScope() + ); + } + @NotNull @Override public JetScope getStaticScope() { diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/argumentsResolveInBodyAndDelegationCall.kt b/compiler/testData/diagnostics/tests/secondaryConstructors/argumentsResolveInBodyAndDelegationCall.kt new file mode 100644 index 00000000000..c044fad5f7f --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/argumentsResolveInBodyAndDelegationCall.kt @@ -0,0 +1,25 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +open class B(open val parentProp: Int) +val global: Int = 1 +class A : B { + val myProp: Int = 1 + override val parentProp = 1 + + constructor(x: Int, y: Int = global): super(x + y + global) { + foo(x, y, myProp) + x + y + myProp + parentProp + super.parentProp + } + constructor(x: Double, y: Int): this(x.toInt() + y, x.toInt() * y) { + foo(x.toInt(), y, myProp) + x + y + myProp + parentProp + super.parentProp + } + constructor(x: String, y: Int): super(x) { + foo(x, y, myProp) + x + y + myProp + parentProp + super.parentProp + } + constructor(x: B, y: Int = global2): this("", x) { + x.parentProp + y + myProp + parentProp + super.parentProp + } + + fun foo(x: Int, y: Int, z: Int) = x +} diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/argumentsResolveInBodyAndDelegationCall.txt b/compiler/testData/diagnostics/tests/secondaryConstructors/argumentsResolveInBodyAndDelegationCall.txt new file mode 100644 index 00000000000..638ac24c2b3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/argumentsResolveInBodyAndDelegationCall.txt @@ -0,0 +1,24 @@ +package + +internal val global: kotlin.Int = 1 + +internal final class A : B { + public constructor A(/*0*/ x: B, /*1*/ y: kotlin.Int = ...) + public constructor A(/*0*/ x: kotlin.Double, /*1*/ y: kotlin.Int) + public constructor A(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int = ...) + public constructor A(/*0*/ x: kotlin.String, /*1*/ y: kotlin.Int) + internal final val myProp: kotlin.Int = 1 + internal open override /*1*/ val parentProp: kotlin.Int = 1 + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + internal final fun foo(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int, /*2*/ z: kotlin.Int): kotlin.Int + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +internal open class B { + public constructor B(/*0*/ parentProp: kotlin.Int) + internal open val parentProp: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/constructorCallType.kt b/compiler/testData/diagnostics/tests/secondaryConstructors/constructorCallType.kt index 24414bcf36a..81bb7884051 100644 --- a/compiler/testData/diagnostics/tests/secondaryConstructors/constructorCallType.kt +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/constructorCallType.kt @@ -1,7 +1,7 @@ // !DIAGNOSTICS: -UNUSED_PARAMETER class A(x: Int) { - constructor(x: Double) {} - constructor(x: String) {} + constructor(x: Double): this(1) {} + constructor(x: String): this(1) {} } val x1: A = A(1) val x2: A = A(1.0) diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/generics.kt b/compiler/testData/diagnostics/tests/secondaryConstructors/generics.kt new file mode 100644 index 00000000000..2fe8ef6fbb1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/generics.kt @@ -0,0 +1,18 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +open class B(x: T, y: T) { + constructor(x: T): this(x, x) {} + constructor(): this(null) {} +} + +class A0 : B { + constructor() {} + constructor(x: String): super(x) {} + constructor(x: String, y: String): super(x, y) {} +} + +class A1 : B { + constructor() {} + constructor(x: R): super(x) {} + constructor(x: R, y: R): super(x, y) {} +} + diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/generics.txt b/compiler/testData/diagnostics/tests/secondaryConstructors/generics.txt new file mode 100644 index 00000000000..8540d30585e --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/generics.txt @@ -0,0 +1,28 @@ +package + +internal final class A0 : B { + public constructor A0() + public constructor A0(/*0*/ x: kotlin.String) + public constructor A0(/*0*/ x: kotlin.String, /*1*/ y: kotlin.String) + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +internal final class A1 : B { + public constructor A1() + public constructor A1(/*0*/ x: R) + public constructor A1(/*0*/ x: R, /*1*/ y: R) + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +internal open class B { + public constructor B() + public constructor B(/*0*/ x: T) + public constructor B(/*0*/ x: T, /*1*/ y: T) + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/memberAccessBeforeSuperCall.kt b/compiler/testData/diagnostics/tests/secondaryConstructors/memberAccessBeforeSuperCall.kt new file mode 100644 index 00000000000..5969772db99 --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/memberAccessBeforeSuperCall.kt @@ -0,0 +1,13 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +open class B(open val parentProperty: String) +class A : B { + val myProp: String = "" + override val parentProperty: String = "" + constructor(arg: String = myProp): super(myProp) {} + constructor(x1: String, arg: String = this.myProp): super(this.myProp) {} + constructor(x1: String, x2: String, arg: String = parentProperty): super(parentProperty) {} + constructor(x1: String, x2: String, x3: String, arg: String = super.parentProperty): super(super.parentProperty) {} + constructor(x1: String, x2: String, x3: String, x4: String, arg: String = foo(this)): super(foo(this)) {} + constructor(x1: String, x2: String, x3: String, x4: String, x5: String, arg: String = foo(this@A)): super(foo(this@A)) {} +} +fun foo(x: A) = "" diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/memberAccessBeforeSuperCall.txt b/compiler/testData/diagnostics/tests/secondaryConstructors/memberAccessBeforeSuperCall.txt new file mode 100644 index 00000000000..1b793856747 --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/memberAccessBeforeSuperCall.txt @@ -0,0 +1,25 @@ +package + +internal fun foo(/*0*/ x: A): kotlin.String + +internal final class A : B { + public constructor A(/*0*/ arg: kotlin.String = ...) + public constructor A(/*0*/ x1: kotlin.String, /*1*/ arg: kotlin.String = ...) + public constructor A(/*0*/ x1: kotlin.String, /*1*/ x2: kotlin.String, /*2*/ arg: kotlin.String = ...) + public constructor A(/*0*/ x1: kotlin.String, /*1*/ x2: kotlin.String, /*2*/ x3: kotlin.String, /*3*/ arg: kotlin.String = ...) + public constructor A(/*0*/ x1: kotlin.String, /*1*/ x2: kotlin.String, /*2*/ x3: kotlin.String, /*3*/ x4: kotlin.String, /*4*/ arg: kotlin.String = ...) + public constructor A(/*0*/ x1: kotlin.String, /*1*/ x2: kotlin.String, /*2*/ x3: kotlin.String, /*3*/ x4: kotlin.String, /*4*/ x5: kotlin.String, /*5*/ arg: kotlin.String = ...) + internal final val myProp: kotlin.String = "" + internal open override /*1*/ val parentProperty: kotlin.String = "" + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +internal open class B { + public constructor B(/*0*/ parentProperty: kotlin.String) + internal open val parentProperty: kotlin.String + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/superAnyNonEmpty.kt b/compiler/testData/diagnostics/tests/secondaryConstructors/superAnyNonEmpty.kt new file mode 100644 index 00000000000..95ba83edf37 --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/superAnyNonEmpty.kt @@ -0,0 +1,4 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +class A { + constructor(): super(1) { } +} diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/superAnyNonEmpty.txt b/compiler/testData/diagnostics/tests/secondaryConstructors/superAnyNonEmpty.txt new file mode 100644 index 00000000000..e26602fdb4d --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/superAnyNonEmpty.txt @@ -0,0 +1,8 @@ +package + +internal final class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/superSecondaryNonExisting.kt b/compiler/testData/diagnostics/tests/secondaryConstructors/superSecondaryNonExisting.kt new file mode 100644 index 00000000000..f705c3bbe72 --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/superSecondaryNonExisting.kt @@ -0,0 +1,10 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +open class B(x: Double) { + constructor(x: Int): this(1.0) {} + constructor(x: String): this(1.0) {} +} +trait C +class A : B, C { + constructor(): super(' ') { } + constructor(x: Int) { } +} diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/superSecondaryNonExisting.txt b/compiler/testData/diagnostics/tests/secondaryConstructors/superSecondaryNonExisting.txt new file mode 100644 index 00000000000..bce2636cbdf --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/superSecondaryNonExisting.txt @@ -0,0 +1,24 @@ +package + +internal final class A : B, C { + public constructor A() + public constructor A(/*0*/ x: kotlin.Int) + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + +internal open class B { + public constructor B(/*0*/ x: kotlin.Double) + public constructor B(/*0*/ x: kotlin.Int) + public constructor B(/*0*/ x: kotlin.String) + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +internal trait C { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/thisNonExisting.kt b/compiler/testData/diagnostics/tests/secondaryConstructors/thisNonExisting.kt new file mode 100644 index 00000000000..ea6583bf1ab --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/thisNonExisting.kt @@ -0,0 +1,6 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +class A { + constructor(x: Int) {} + constructor(x: String) {} + constructor(): this('a') {} +} diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/thisNonExisting.txt b/compiler/testData/diagnostics/tests/secondaryConstructors/thisNonExisting.txt new file mode 100644 index 00000000000..2abc7ee9706 --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/thisNonExisting.txt @@ -0,0 +1,10 @@ +package + +internal final class A { + public constructor A() + public constructor A(/*0*/ x: kotlin.Int) + public constructor A(/*0*/ x: kotlin.String) + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/varargsInDelegationCallToPrimary.kt b/compiler/testData/diagnostics/tests/secondaryConstructors/varargsInDelegationCallToPrimary.kt new file mode 100644 index 00000000000..2d75e8c62fd --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/varargsInDelegationCallToPrimary.kt @@ -0,0 +1,12 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +fun array(vararg x: T): Array = null!! + +open class B(vararg y: String) { + constructor(x: Int): this(x.toString(), *array("1"), "2") {} +} + +class A : B { + constructor(x: String, y: String): super(x, *array("3"), y) {} + constructor(x: String): super(x) {} + constructor(): super() {} +} diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/varargsInDelegationCallToPrimary.txt b/compiler/testData/diagnostics/tests/secondaryConstructors/varargsInDelegationCallToPrimary.txt new file mode 100644 index 00000000000..4db8600ea78 --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/varargsInDelegationCallToPrimary.txt @@ -0,0 +1,20 @@ +package + +internal fun array(/*0*/ vararg x: T /*kotlin.Array*/): kotlin.Array + +internal final class A : B { + public constructor A() + public constructor A(/*0*/ x: kotlin.String) + public constructor A(/*0*/ x: kotlin.String, /*1*/ y: kotlin.String) + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +internal open class B { + public constructor B(/*0*/ vararg y: kotlin.String /*kotlin.Array*/) + public constructor B(/*0*/ x: kotlin.Int) + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/varargsInDelegationCallToSecondary.kt b/compiler/testData/diagnostics/tests/secondaryConstructors/varargsInDelegationCallToSecondary.kt new file mode 100644 index 00000000000..9679b02f84a --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/varargsInDelegationCallToSecondary.kt @@ -0,0 +1,17 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +fun array(vararg x: T): Array = null!! + +open class B(x: Int) { + constructor(vararg y: String): this(y[0].length()) {} +} + +class A : B { + constructor(x: String, y: String): super(x, *array("q"), y) {} + constructor(x: String): super(x) {} + constructor(): super() {} +} + +val b1 = B() +val b2 = B("1", "2", "3") +val b3 = B("1", *array("2", "3"), "4") +val b4 = B(1) diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/varargsInDelegationCallToSecondary.txt b/compiler/testData/diagnostics/tests/secondaryConstructors/varargsInDelegationCallToSecondary.txt new file mode 100644 index 00000000000..780859e3679 --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/varargsInDelegationCallToSecondary.txt @@ -0,0 +1,24 @@ +package + +internal val b1: B +internal val b2: B +internal val b3: B +internal val b4: B +internal fun array(/*0*/ vararg x: T /*kotlin.Array*/): kotlin.Array + +internal final class A : B { + public constructor A() + public constructor A(/*0*/ x: kotlin.String) + public constructor A(/*0*/ x: kotlin.String, /*1*/ y: kotlin.String) + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +internal open class B { + public constructor B(/*0*/ vararg y: kotlin.String /*kotlin.Array*/) + public constructor B(/*0*/ x: kotlin.Int) + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/resolveConstructorDelegationCalls/classWithGenerics.kt b/compiler/testData/resolveConstructorDelegationCalls/classWithGenerics.kt new file mode 100644 index 00000000000..47c831fe91b --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/classWithGenerics.kt @@ -0,0 +1,4 @@ +class A { + constructor(x: T) {} + constructor(block: () -> T): this(block()) {} +} diff --git a/compiler/testData/resolveConstructorDelegationCalls/classWithGenerics.txt b/compiler/testData/resolveConstructorDelegationCalls/classWithGenerics.txt new file mode 100644 index 00000000000..129973684b5 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/classWithGenerics.txt @@ -0,0 +1,18 @@ +class A { + constructor(x: T) {} + constructor(block: () -> T): this(block()) {} +} + + +Resolved call: + +Candidate descriptor: constructor A(x: T) defined in A +Resulting descriptor: constructor A(x: T) defined in A + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +Dispatch receiver = NO_RECEIVER +Extension receiver = NO_RECEIVER + +Value arguments mapping: + +SUCCESS x : T = block() diff --git a/compiler/testData/resolveConstructorDelegationCalls/inheritanceWithGeneric.kt b/compiler/testData/resolveConstructorDelegationCalls/inheritanceWithGeneric.kt new file mode 100644 index 00000000000..caf762a0da4 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/inheritanceWithGeneric.kt @@ -0,0 +1,7 @@ +open class B { + constructor(x: T = null!!) {} +} + +class A : B { + constructor() {} +} diff --git a/compiler/testData/resolveConstructorDelegationCalls/inheritanceWithGeneric.txt b/compiler/testData/resolveConstructorDelegationCalls/inheritanceWithGeneric.txt new file mode 100644 index 00000000000..ec94411618b --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/inheritanceWithGeneric.txt @@ -0,0 +1,17 @@ +open class B { + constructor(x: T = null!!) {} +} + +class A : B { + constructor() {} +} + + +Resolved call: + +Candidate descriptor: constructor B(x: T = ...) defined in B +Resulting descriptor: constructor B(x: Int = ...) defined in B + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +Dispatch receiver = NO_RECEIVER +Extension receiver = NO_RECEIVER diff --git a/compiler/testData/resolveConstructorDelegationCalls/innerClassDelegatingPrimary.kt b/compiler/testData/resolveConstructorDelegationCalls/innerClassDelegatingPrimary.kt new file mode 100644 index 00000000000..fa09805ddba --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/innerClassDelegatingPrimary.kt @@ -0,0 +1,5 @@ +class A { + inner class B(arg: String) { + constructor (arg: Int): this("") {} + } +} diff --git a/compiler/testData/resolveConstructorDelegationCalls/innerClassDelegatingPrimary.txt b/compiler/testData/resolveConstructorDelegationCalls/innerClassDelegatingPrimary.txt new file mode 100644 index 00000000000..df805361ac2 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/innerClassDelegatingPrimary.txt @@ -0,0 +1,18 @@ +class A { + inner class B(arg: String) { + constructor (arg: Int): this("") {} + } +} + + +Resolved call: + +Resulting descriptor: constructor B(arg: String) defined in A.B + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +Dispatch receiver = Class{A} +Extension receiver = NO_RECEIVER + +Value arguments mapping: + +SUCCESS arg : String = "" diff --git a/compiler/testData/resolveConstructorDelegationCalls/innerClassDelegatingSecondary.kt b/compiler/testData/resolveConstructorDelegationCalls/innerClassDelegatingSecondary.kt new file mode 100644 index 00000000000..9e55a43f109 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/innerClassDelegatingSecondary.kt @@ -0,0 +1,6 @@ +class A { + inner class B { + constructor(x: String) {} + constructor (arg: Int): this("") {} + } +} diff --git a/compiler/testData/resolveConstructorDelegationCalls/innerClassDelegatingSecondary.txt b/compiler/testData/resolveConstructorDelegationCalls/innerClassDelegatingSecondary.txt new file mode 100644 index 00000000000..2619d2012b1 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/innerClassDelegatingSecondary.txt @@ -0,0 +1,19 @@ +class A { + inner class B { + constructor(x: String) {} + constructor (arg: Int): this("") {} + } +} + + +Resolved call: + +Resulting descriptor: constructor B(x: String) defined in A.B + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +Dispatch receiver = Class{A} +Extension receiver = NO_RECEIVER + +Value arguments mapping: + +SUCCESS x : String = "" diff --git a/compiler/testData/resolveConstructorDelegationCalls/superAnyEmpty.kt b/compiler/testData/resolveConstructorDelegationCalls/superAnyEmpty.kt new file mode 100644 index 00000000000..cb4cabbdd0c --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/superAnyEmpty.kt @@ -0,0 +1,3 @@ +class A { + constructor(): super() { } +} diff --git a/compiler/testData/resolveConstructorDelegationCalls/superAnyEmpty.txt b/compiler/testData/resolveConstructorDelegationCalls/superAnyEmpty.txt new file mode 100644 index 00000000000..5f5218f1681 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/superAnyEmpty.txt @@ -0,0 +1,12 @@ +class A { + constructor(): super() { } +} + + +Resolved call: + +Resulting descriptor: constructor Any() defined in kotlin.Any + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +Dispatch receiver = NO_RECEIVER +Extension receiver = NO_RECEIVER diff --git a/compiler/testData/resolveConstructorDelegationCalls/superAnyImplicit.kt b/compiler/testData/resolveConstructorDelegationCalls/superAnyImplicit.kt new file mode 100644 index 00000000000..c7aa546bfcb --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/superAnyImplicit.kt @@ -0,0 +1,3 @@ +class A { + constructor() { } +} diff --git a/compiler/testData/resolveConstructorDelegationCalls/superAnyImplicit.txt b/compiler/testData/resolveConstructorDelegationCalls/superAnyImplicit.txt new file mode 100644 index 00000000000..438c9402bde --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/superAnyImplicit.txt @@ -0,0 +1,12 @@ +class A { + constructor() { } +} + + +Resolved call: + +Resulting descriptor: constructor Any() defined in kotlin.Any + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +Dispatch receiver = NO_RECEIVER +Extension receiver = NO_RECEIVER diff --git a/compiler/testData/resolveConstructorDelegationCalls/superPrimary.kt b/compiler/testData/resolveConstructorDelegationCalls/superPrimary.kt new file mode 100644 index 00000000000..73106ef7960 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/superPrimary.kt @@ -0,0 +1,5 @@ +open class B(x: Int) +trait C +class A : B, C { + constructor(): super(1) { } +} diff --git a/compiler/testData/resolveConstructorDelegationCalls/superPrimary.txt b/compiler/testData/resolveConstructorDelegationCalls/superPrimary.txt new file mode 100644 index 00000000000..41fbde535fa --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/superPrimary.txt @@ -0,0 +1,18 @@ +open class B(x: Int) +trait C +class A : B, C { + constructor(): super(1) { } +} + + +Resolved call: + +Resulting descriptor: constructor B(x: Int) defined in B + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +Dispatch receiver = NO_RECEIVER +Extension receiver = NO_RECEIVER + +Value arguments mapping: + +SUCCESS x : Int = 1 diff --git a/compiler/testData/resolveConstructorDelegationCalls/superPrimaryEmpty.kt b/compiler/testData/resolveConstructorDelegationCalls/superPrimaryEmpty.kt new file mode 100644 index 00000000000..6271104ef4c --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/superPrimaryEmpty.kt @@ -0,0 +1,5 @@ +open class B +trait C +class A : B, C { + constructor(): super() { } +} diff --git a/compiler/testData/resolveConstructorDelegationCalls/superPrimaryEmpty.txt b/compiler/testData/resolveConstructorDelegationCalls/superPrimaryEmpty.txt new file mode 100644 index 00000000000..9fa46de7ad2 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/superPrimaryEmpty.txt @@ -0,0 +1,14 @@ +open class B +trait C +class A : B, C { + constructor(): super() { } +} + + +Resolved call: + +Resulting descriptor: constructor B() defined in B + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +Dispatch receiver = NO_RECEIVER +Extension receiver = NO_RECEIVER diff --git a/compiler/testData/resolveConstructorDelegationCalls/superPrimaryImplicit.kt b/compiler/testData/resolveConstructorDelegationCalls/superPrimaryImplicit.kt new file mode 100644 index 00000000000..20d6cd5b876 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/superPrimaryImplicit.kt @@ -0,0 +1,5 @@ +open class B +trait C +class A : B, C { + constructor() { } +} diff --git a/compiler/testData/resolveConstructorDelegationCalls/superPrimaryImplicit.txt b/compiler/testData/resolveConstructorDelegationCalls/superPrimaryImplicit.txt new file mode 100644 index 00000000000..4e557d66a65 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/superPrimaryImplicit.txt @@ -0,0 +1,14 @@ +open class B +trait C +class A : B, C { + constructor() { } +} + + +Resolved call: + +Resulting descriptor: constructor B() defined in B + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +Dispatch receiver = NO_RECEIVER +Extension receiver = NO_RECEIVER diff --git a/compiler/testData/resolveConstructorDelegationCalls/superSecondary.kt b/compiler/testData/resolveConstructorDelegationCalls/superSecondary.kt new file mode 100644 index 00000000000..111832c5d55 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/superSecondary.kt @@ -0,0 +1,7 @@ +open class B { + constructor(x: Int) {} +} +trait C +class A : B, C { + constructor(): super(1) { } +} diff --git a/compiler/testData/resolveConstructorDelegationCalls/superSecondary.txt b/compiler/testData/resolveConstructorDelegationCalls/superSecondary.txt new file mode 100644 index 00000000000..7ddfad21676 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/superSecondary.txt @@ -0,0 +1,20 @@ +open class B { + constructor(x: Int) {} +} +trait C +class A : B, C { + constructor(): super(1) { } +} + + +Resolved call: + +Resulting descriptor: constructor B(x: Int) defined in B + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +Dispatch receiver = NO_RECEIVER +Extension receiver = NO_RECEIVER + +Value arguments mapping: + +SUCCESS x : Int = 1 diff --git a/compiler/testData/resolveConstructorDelegationCalls/superSecondaryImplicit.kt b/compiler/testData/resolveConstructorDelegationCalls/superSecondaryImplicit.kt new file mode 100644 index 00000000000..be3bff3c20e --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/superSecondaryImplicit.kt @@ -0,0 +1,7 @@ +open class B { + constructor() {} +} +trait C +class A : B, C { + constructor() { } +} diff --git a/compiler/testData/resolveConstructorDelegationCalls/superSecondaryImplicit.txt b/compiler/testData/resolveConstructorDelegationCalls/superSecondaryImplicit.txt new file mode 100644 index 00000000000..3fb3bd10b32 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/superSecondaryImplicit.txt @@ -0,0 +1,16 @@ +open class B { + constructor() {} +} +trait C +class A : B, C { + constructor() { } +} + + +Resolved call: + +Resulting descriptor: constructor B() defined in B + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +Dispatch receiver = NO_RECEIVER +Extension receiver = NO_RECEIVER diff --git a/compiler/testData/resolveConstructorDelegationCalls/superSecondaryOverload.kt b/compiler/testData/resolveConstructorDelegationCalls/superSecondaryOverload.kt new file mode 100644 index 00000000000..509cf4f1c0c --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/superSecondaryOverload.kt @@ -0,0 +1,8 @@ +open class B(x: Double) { + constructor(x: Int) {} + constructor(x: String) {} +} +trait C +class A : B, C { + constructor(): super("abc") { } +} diff --git a/compiler/testData/resolveConstructorDelegationCalls/superSecondaryOverload.txt b/compiler/testData/resolveConstructorDelegationCalls/superSecondaryOverload.txt new file mode 100644 index 00000000000..f1e377840f0 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/superSecondaryOverload.txt @@ -0,0 +1,21 @@ +open class B(x: Double) { + constructor(x: Int) {} + constructor(x: String) {} +} +trait C +class A : B, C { + constructor(): super("abc") { } +} + + +Resolved call: + +Resulting descriptor: constructor B(x: String) defined in B + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +Dispatch receiver = NO_RECEIVER +Extension receiver = NO_RECEIVER + +Value arguments mapping: + +SUCCESS x : String = "abc" diff --git a/compiler/testData/resolveConstructorDelegationCalls/thisPrimary.kt b/compiler/testData/resolveConstructorDelegationCalls/thisPrimary.kt new file mode 100644 index 00000000000..85998b11d2a --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/thisPrimary.kt @@ -0,0 +1,3 @@ +class A(x: Int) { + constructor(): this(1) {} +} diff --git a/compiler/testData/resolveConstructorDelegationCalls/thisPrimary.txt b/compiler/testData/resolveConstructorDelegationCalls/thisPrimary.txt new file mode 100644 index 00000000000..aa973281902 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/thisPrimary.txt @@ -0,0 +1,16 @@ +class A(x: Int) { + constructor(): this(1) {} +} + + +Resolved call: + +Resulting descriptor: constructor A(x: Int) defined in A + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +Dispatch receiver = NO_RECEIVER +Extension receiver = NO_RECEIVER + +Value arguments mapping: + +SUCCESS x : Int = 1 diff --git a/compiler/testData/resolveConstructorDelegationCalls/thisPrimaryEmpty.kt b/compiler/testData/resolveConstructorDelegationCalls/thisPrimaryEmpty.kt new file mode 100644 index 00000000000..b337cbabecd --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/thisPrimaryEmpty.kt @@ -0,0 +1,3 @@ +class A() { + constructor(): this() {} +} diff --git a/compiler/testData/resolveConstructorDelegationCalls/thisPrimaryEmpty.txt b/compiler/testData/resolveConstructorDelegationCalls/thisPrimaryEmpty.txt new file mode 100644 index 00000000000..d7f16da2a34 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/thisPrimaryEmpty.txt @@ -0,0 +1,6 @@ +class A() { + constructor(): this() {} +} + + +null diff --git a/compiler/testData/resolveConstructorDelegationCalls/thisSecondary.kt b/compiler/testData/resolveConstructorDelegationCalls/thisSecondary.kt new file mode 100644 index 00000000000..9f1ef640d3f --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/thisSecondary.kt @@ -0,0 +1,4 @@ +class A { + constructor(x: Int) {} + constructor(): this(1) {} +} diff --git a/compiler/testData/resolveConstructorDelegationCalls/thisSecondary.txt b/compiler/testData/resolveConstructorDelegationCalls/thisSecondary.txt new file mode 100644 index 00000000000..2d1f9f4bb99 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/thisSecondary.txt @@ -0,0 +1,17 @@ +class A { + constructor(x: Int) {} + constructor(): this(1) {} +} + + +Resolved call: + +Resulting descriptor: constructor A(x: Int) defined in A + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +Dispatch receiver = NO_RECEIVER +Extension receiver = NO_RECEIVER + +Value arguments mapping: + +SUCCESS x : Int = 1 diff --git a/compiler/testData/resolveConstructorDelegationCalls/thisSecondaryOverload.kt b/compiler/testData/resolveConstructorDelegationCalls/thisSecondaryOverload.kt new file mode 100644 index 00000000000..b2686572e90 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/thisSecondaryOverload.kt @@ -0,0 +1,5 @@ +class A(x: Double) { + constructor(x: Int) {} + constructor(x: String) {} + constructor(): this("abc") {} +} diff --git a/compiler/testData/resolveConstructorDelegationCalls/thisSecondaryOverload.txt b/compiler/testData/resolveConstructorDelegationCalls/thisSecondaryOverload.txt new file mode 100644 index 00000000000..9fc228c15a4 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/thisSecondaryOverload.txt @@ -0,0 +1,18 @@ +class A(x: Double) { + constructor(x: Int) {} + constructor(x: String) {} + constructor(): this("abc") {} +} + + +Resolved call: + +Resulting descriptor: constructor A(x: String) defined in A + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +Dispatch receiver = NO_RECEIVER +Extension receiver = NO_RECEIVER + +Value arguments mapping: + +SUCCESS x : String = "abc" diff --git a/compiler/testData/resolveConstructorDelegationCalls/varargs.kt b/compiler/testData/resolveConstructorDelegationCalls/varargs.kt new file mode 100644 index 00000000000..c213aa26973 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/varargs.kt @@ -0,0 +1,7 @@ +open class B { + constructor(vararg x: Int) {} +} + +class A : B { + constructor(vararg x: Int): super(*x, *intArray(1, 2, 3), 4) {} +} diff --git a/compiler/testData/resolveConstructorDelegationCalls/varargs.txt b/compiler/testData/resolveConstructorDelegationCalls/varargs.txt new file mode 100644 index 00000000000..8a448c9d7c0 --- /dev/null +++ b/compiler/testData/resolveConstructorDelegationCalls/varargs.txt @@ -0,0 +1,22 @@ +open class B { + constructor(vararg x: Int) {} +} + +class A : B { + constructor(vararg x: Int): super(*x, *intArray(1, 2, 3), 4) {} +} + + +Resolved call: + +Resulting descriptor: constructor B(vararg x: Int) defined in B + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +Dispatch receiver = NO_RECEIVER +Extension receiver = NO_RECEIVER + +Value arguments mapping: + +SUCCESS x : IntArray = x +SUCCESS x : IntArray = intArray(1, 2, 3) +SUCCESS x : IntArray = 4 diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 66681ef7e3a..47b66c8fc6d 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -10397,17 +10397,65 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/secondaryConstructors"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("argumentsResolveInBodyAndDelegationCall.kt") + public void testArgumentsResolveInBodyAndDelegationCall() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/secondaryConstructors/argumentsResolveInBodyAndDelegationCall.kt"); + doTest(fileName); + } + @TestMetadata("constructorCallType.kt") public void testConstructorCallType() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/secondaryConstructors/constructorCallType.kt"); doTest(fileName); } + @TestMetadata("generics.kt") + public void testGenerics() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/secondaryConstructors/generics.kt"); + doTest(fileName); + } + + @TestMetadata("memberAccessBeforeSuperCall.kt") + public void testMemberAccessBeforeSuperCall() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/secondaryConstructors/memberAccessBeforeSuperCall.kt"); + doTest(fileName); + } + @TestMetadata("noPrimaryConstructor.kt") public void testNoPrimaryConstructor() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/secondaryConstructors/noPrimaryConstructor.kt"); doTest(fileName); } + + @TestMetadata("superAnyNonEmpty.kt") + public void testSuperAnyNonEmpty() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/secondaryConstructors/superAnyNonEmpty.kt"); + doTest(fileName); + } + + @TestMetadata("superSecondaryNonExisting.kt") + public void testSuperSecondaryNonExisting() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/secondaryConstructors/superSecondaryNonExisting.kt"); + doTest(fileName); + } + + @TestMetadata("thisNonExisting.kt") + public void testThisNonExisting() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/secondaryConstructors/thisNonExisting.kt"); + doTest(fileName); + } + + @TestMetadata("varargsInDelegationCallToPrimary.kt") + public void testVarargsInDelegationCallToPrimary() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/secondaryConstructors/varargsInDelegationCallToPrimary.kt"); + doTest(fileName); + } + + @TestMetadata("varargsInDelegationCallToSecondary.kt") + public void testVarargsInDelegationCallToSecondary() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/secondaryConstructors/varargsInDelegationCallToSecondary.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/diagnostics/tests/senselessComparison") diff --git a/compiler/tests/org/jetbrains/kotlin/resolve/calls/AbstractResolvedCallsTest.kt b/compiler/tests/org/jetbrains/kotlin/resolve/calls/AbstractResolvedCallsTest.kt index 3de44f6f4ca..309bd020bbd 100644 --- a/compiler/tests/org/jetbrains/kotlin/resolve/calls/AbstractResolvedCallsTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/resolve/calls/AbstractResolvedCallsTest.kt @@ -39,6 +39,10 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.resolve.scopes.receivers.ClassReceiver import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.psi.JetFile +import com.intellij.psi.PsiElement public abstract class AbstractResolvedCallsTest : JetLiteFixture() { override fun createEnvironment(): JetCoreEnvironment = createEnvironmentWithMockJdk(ConfigurationKind.ALL) @@ -49,10 +53,7 @@ public abstract class AbstractResolvedCallsTest : JetLiteFixture() { val jetFile = JetPsiFactory(getProject()).createFile(text.replace("", "")) val bindingContext = JvmResolveUtil.analyzeOneFileWithJavaIntegration(jetFile).bindingContext - val element = jetFile.findElementAt(text.indexOf("")) - val expression = element.getStrictParentOfType() - - val cachedCall = expression?.getParentResolvedCall(bindingContext, strict = false) + val (element, cachedCall) = buildCachedCall(bindingContext, jetFile, text) val resolvedCall = if (cachedCall !is VariableAsFunctionResolvedCall) cachedCall else if ("(" == element?.getText()) cachedCall.functionCall @@ -61,6 +62,17 @@ public abstract class AbstractResolvedCallsTest : JetLiteFixture() { val resolvedCallInfoFileName = FileUtil.getNameWithoutExtension(filePath) + ".txt" JetTestUtils.assertEqualsToFile(File(resolvedCallInfoFileName), "$text\n\n\n${resolvedCall?.renderToText()}") } + + open protected fun buildCachedCall( + bindingContext: BindingContext, jetFile: JetFile, text: String + ): Pair?> { + val element = jetFile.findElementAt(text.indexOf("")) + val expression = element.getStrictParentOfType() + + val cachedCall = expression?.getParentResolvedCall(bindingContext, strict = false) + return Pair(element, cachedCall) + } + } private fun ReceiverValue.getText() = when (this) { diff --git a/compiler/tests/org/jetbrains/kotlin/resolve/calls/AbstractResolvedConstructorDelegationCallsTests.kt b/compiler/tests/org/jetbrains/kotlin/resolve/calls/AbstractResolvedConstructorDelegationCallsTests.kt new file mode 100644 index 00000000000..b787fd20fb3 --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/resolve/calls/AbstractResolvedConstructorDelegationCallsTests.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.resolve.calls + +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.psi.JetFile +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType +import org.jetbrains.kotlin.psi.JetSecondaryConstructor +import org.jetbrains.kotlin.psi.debugText.getDebugText +import org.jetbrains.kotlin.resolve.calls.callUtil.getParentResolvedCall + + +abstract public class AbstractResolvedConstructorDelegationCallsTests : AbstractResolvedCallsTest() { + override fun buildCachedCall( + bindingContext: BindingContext, jetFile: JetFile, text: String + ): Pair?> { + val element = jetFile.findElementAt(text.indexOf("")) + val constructor = element?.getNonStrictParentOfType()!! + val delegationCall = constructor.getDelegationCall() + + val cachedCall = delegationCall.getParentResolvedCall(bindingContext, strict = false) + return Pair(delegationCall, cachedCall) + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/resolve/calls/ResolvedConstructorDelegationCallsTestsGenerated.java b/compiler/tests/org/jetbrains/kotlin/resolve/calls/ResolvedConstructorDelegationCallsTestsGenerated.java new file mode 100644 index 00000000000..7b0c002cf6a --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/resolve/calls/ResolvedConstructorDelegationCallsTestsGenerated.java @@ -0,0 +1,140 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.resolve.calls; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.InnerTestClasses; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.JetTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("compiler/testData/resolveConstructorDelegationCalls") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class ResolvedConstructorDelegationCallsTestsGenerated extends AbstractResolvedConstructorDelegationCallsTests { + public void testAllFilesPresentInResolveConstructorDelegationCalls() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/resolveConstructorDelegationCalls"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("classWithGenerics.kt") + public void testClassWithGenerics() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolveConstructorDelegationCalls/classWithGenerics.kt"); + doTest(fileName); + } + + @TestMetadata("inheritanceWithGeneric.kt") + public void testInheritanceWithGeneric() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolveConstructorDelegationCalls/inheritanceWithGeneric.kt"); + doTest(fileName); + } + + @TestMetadata("innerClassDelegatingPrimary.kt") + public void testInnerClassDelegatingPrimary() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolveConstructorDelegationCalls/innerClassDelegatingPrimary.kt"); + doTest(fileName); + } + + @TestMetadata("innerClassDelegatingSecondary.kt") + public void testInnerClassDelegatingSecondary() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolveConstructorDelegationCalls/innerClassDelegatingSecondary.kt"); + doTest(fileName); + } + + @TestMetadata("superAnyEmpty.kt") + public void testSuperAnyEmpty() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolveConstructorDelegationCalls/superAnyEmpty.kt"); + doTest(fileName); + } + + @TestMetadata("superAnyImplicit.kt") + public void testSuperAnyImplicit() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolveConstructorDelegationCalls/superAnyImplicit.kt"); + doTest(fileName); + } + + @TestMetadata("superPrimary.kt") + public void testSuperPrimary() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolveConstructorDelegationCalls/superPrimary.kt"); + doTest(fileName); + } + + @TestMetadata("superPrimaryEmpty.kt") + public void testSuperPrimaryEmpty() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolveConstructorDelegationCalls/superPrimaryEmpty.kt"); + doTest(fileName); + } + + @TestMetadata("superPrimaryImplicit.kt") + public void testSuperPrimaryImplicit() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolveConstructorDelegationCalls/superPrimaryImplicit.kt"); + doTest(fileName); + } + + @TestMetadata("superSecondary.kt") + public void testSuperSecondary() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolveConstructorDelegationCalls/superSecondary.kt"); + doTest(fileName); + } + + @TestMetadata("superSecondaryImplicit.kt") + public void testSuperSecondaryImplicit() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolveConstructorDelegationCalls/superSecondaryImplicit.kt"); + doTest(fileName); + } + + @TestMetadata("superSecondaryOverload.kt") + public void testSuperSecondaryOverload() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolveConstructorDelegationCalls/superSecondaryOverload.kt"); + doTest(fileName); + } + + @TestMetadata("thisPrimary.kt") + public void testThisPrimary() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolveConstructorDelegationCalls/thisPrimary.kt"); + doTest(fileName); + } + + @TestMetadata("thisPrimaryEmpty.kt") + public void testThisPrimaryEmpty() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolveConstructorDelegationCalls/thisPrimaryEmpty.kt"); + doTest(fileName); + } + + @TestMetadata("thisSecondary.kt") + public void testThisSecondary() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolveConstructorDelegationCalls/thisSecondary.kt"); + doTest(fileName); + } + + @TestMetadata("thisSecondaryOverload.kt") + public void testThisSecondaryOverload() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolveConstructorDelegationCalls/thisSecondaryOverload.kt"); + doTest(fileName); + } + + @TestMetadata("varargs.kt") + public void testVarargs() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/resolveConstructorDelegationCalls/varargs.kt"); + doTest(fileName); + } +} diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java index 1010bf328d0..b99d2879e1c 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java @@ -301,6 +301,18 @@ public class DescriptorUtils { return superClassDescriptors; } + @Nullable + public static JetType getSuperClassType(@NotNull ClassDescriptor classDescriptor) { + Collection superclassTypes = classDescriptor.getTypeConstructor().getSupertypes(); + for (JetType type : superclassTypes) { + ClassDescriptor superClassDescriptor = getClassDescriptorForType(type); + if (!isAny(superClassDescriptor) && superClassDescriptor.getKind() != ClassKind.TRAIT) { + return type; + } + } + return null; + } + @NotNull public static ClassDescriptor getClassDescriptorForType(@NotNull JetType type) { return getClassDescriptorForTypeConstructor(type.getConstructor()); diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt index c99a8622ba9..c6206cf41dd 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.descriptors.ClassKind.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.builtins.KotlinBuiltIns public fun ClassDescriptor.getClassObjectReferenceTarget(): ClassDescriptor = getDefaultObjectDescriptor() ?: this @@ -81,4 +82,17 @@ public val DeclarationDescriptorWithVisibility.isEffectivelyPublicApi: Boolean } return true - } \ No newline at end of file + } + +public fun ClassDescriptor.getSuperClassNotAny(): ClassDescriptor? { + for (supertype in getDefaultType().getConstructor().getSupertypes()) { + val superClassifier = supertype.getConstructor().getDeclarationDescriptor() + if (!KotlinBuiltIns.isAnyOrNullableAny(supertype) && + (DescriptorUtils.isClass(superClassifier) || DescriptorUtils.isEnumClass(superClassifier))) { + return superClassifier as ClassDescriptor + } + } + return null +} + +public fun ClassDescriptor.getSuperClassOrAny(): ClassDescriptor = getSuperClassNotAny() ?: KotlinBuiltIns.getInstance().getAny() diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 00960d82f40..1faca1cbae9 100644 --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -107,6 +107,7 @@ import org.jetbrains.kotlin.repl.AbstractReplInterpreterTest import org.jetbrains.kotlin.resolve.AbstractResolveTest import org.jetbrains.kotlin.resolve.annotation.AbstractAnnotationParameterTest import org.jetbrains.kotlin.resolve.calls.AbstractResolvedCallsTest +import org.jetbrains.kotlin.resolve.calls.AbstractResolvedConstructorDelegationCallsTests import org.jetbrains.kotlin.resolve.constants.evaluate.AbstractEvaluateExpressionTest import org.jetbrains.kotlin.resolve.constraintSystem.AbstractConstraintSystemTest import org.jetbrains.kotlin.safeDelete.AbstractJetSafeDeleteTest @@ -144,6 +145,10 @@ fun main(args: Array) { model("resolvedCalls") } + testClass(javaClass()) { + model("resolveConstructorDelegationCalls") + } + testClass(javaClass()) { model("constraintSystem", extension = "bounds") } diff --git a/idea/ide-common/src/org/jetbrains/kotlin/resolve/lazy/ElementResolver.java b/idea/ide-common/src/org/jetbrains/kotlin/resolve/lazy/ElementResolver.java index 6953e549c88..61d8682ad20 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/resolve/lazy/ElementResolver.java +++ b/idea/ide-common/src/org/jetbrains/kotlin/resolve/lazy/ElementResolver.java @@ -588,6 +588,11 @@ public abstract class ElementResolver { return Collections.emptyMap(); } + @Override + public Map getSecondaryConstructors() { + return Collections.emptyMap(); + } + @Override public Map getProperties() { return Collections.emptyMap();