diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index e131ae74f79..81dfeedc91b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -49,6 +49,7 @@ import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.calls.model.*; import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; +import org.jetbrains.jet.lang.resolve.calls.util.FakeCallableDescriptorForObject; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstant; import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants; @@ -1692,6 +1693,9 @@ public class ExpressionCodegen extends JetVisitor implem } receiver = StackValue.receiver(resolvedCall, receiver, this, null); descriptor = resolvedCall.getResultingDescriptor(); + if (descriptor instanceof FakeCallableDescriptorForObject) { + descriptor = ((FakeCallableDescriptorForObject) descriptor).getReferencedDescriptor(); + } } //if (descriptor instanceof VariableAsFunctionDescriptor) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java index 20ac1cb968b..4186332c8d3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java @@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsUtil; import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; +import org.jetbrains.jet.lang.resolve.calls.util.FakeCallableDescriptorForObject; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.IntegerValueConstant; import org.jetbrains.jet.lang.resolve.name.Name; @@ -81,7 +82,7 @@ public class CallExpressionResolver { JetType classObjectType = classifier.getClassObjectType(); if (classObjectType != null) { context.trace.record(REFERENCE_TARGET, expression, classifier); - JetType result = getExtendedClassObjectType(expression, classObjectType, classifier, context); + JetType result = getExtendedClassObjectType(expression, classObjectType, classifier, context.scope); checkClassObjectVisibility(classifier, expression, context); return result; } @@ -153,7 +154,7 @@ public class CallExpressionResolver { @NotNull JetSimpleNameExpression expression, @NotNull JetType classObjectType, @NotNull ClassifierDescriptor classifier, - @NotNull ResolutionContext context + @NotNull JetScope receiverScope ) { if (!isLHSOfDot(expression) || !(classifier instanceof ClassDescriptor)) { return classObjectType; @@ -170,7 +171,7 @@ public class CallExpressionResolver { scopes.add(getStaticNestedClassesScope(classDescriptor)); Name referencedName = expression.getReferencedNameAsName(); - PackageViewDescriptor packageView = context.scope.getPackage(referencedName); + PackageViewDescriptor packageView = receiverScope.getPackage(referencedName); if (packageView != null) { //for enums loaded from java binaries scopes.add(packageView.getMemberScope()); @@ -253,16 +254,23 @@ public class CallExpressionResolver { context.replaceTraceAndCache(temporaryForVariable), call, CheckValueArgumentsMode.ENABLED); OverloadResolutionResults resolutionResult = callResolver.resolveSimpleProperty(contextForVariable); + JetScope receiverScope = receiver.exists() ? receiver.getType().getMemberScope() : context.scope; if (resolutionResult.isSuccess()) { + result[0] = true; + if (resolutionResult.getResultingDescriptor() instanceof FakeCallableDescriptorForObject) { + FakeCallableDescriptorForObject fakeCallableDescriptorForObject = + (FakeCallableDescriptorForObject) resolutionResult.getResultingDescriptor(); + ClassDescriptor classDescriptor = fakeCallableDescriptorForObject.getClassDescriptor(); + context.trace.record(REFERENCE_TARGET, nameExpression, classDescriptor); + checkClassObjectVisibility(classDescriptor, nameExpression, context); + return getExtendedClassObjectType(nameExpression, fakeCallableDescriptorForObject.getType(), classDescriptor, receiverScope); + } temporaryForVariable.commit(); checkSuper(receiver, resolutionResult, context.trace, nameExpression); - result[0] = true; - return resolutionResult.isSingleResult() ? resolutionResult.getResultingDescriptor().getReturnType() : null; + return resolutionResult.getResultingDescriptor().getReturnType(); } - ExpressionTypingContext newContext = receiver.exists() - ? context.replaceScope(receiver.getType().getMemberScope()) - : context; + ExpressionTypingContext newContext = context.replaceScope(receiverScope); TemporaryTraceAndCache temporaryForPackageOrClassObject = TemporaryTraceAndCache.create( context, "trace to resolve as package or class object", nameExpression); JetType jetType = lookupPackageOrClassObject(nameExpression, newContext.replaceTraceAndCache(temporaryForPackageOrClassObject)); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/CallableDescriptorCollectors.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/CallableDescriptorCollectors.java index e40be4ea5da..5741e7053c6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/CallableDescriptorCollectors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/CallableDescriptorCollectors.java @@ -21,6 +21,7 @@ import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.calls.util.FakeCallableDescriptorForObject; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.ErrorUtils; @@ -97,6 +98,15 @@ public class CallableDescriptorCollectors implemen private static class VariableCollector implements CallableDescriptorCollector { + private static void addFakeDescriptorForObject(JetScope scope, Name name, Collection variables) { + ClassifierDescriptor classifier = scope.getClassifier(name); + if (!(classifier instanceof ClassDescriptor)) return; + JetType classObjectType = classifier.getClassObjectType(); + if (classObjectType == null) return; + + variables.add(new FakeCallableDescriptorForObject((ClassDescriptor) classifier)); + } + @NotNull @Override public Collection getNonExtensionsByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) { @@ -105,19 +115,24 @@ public class CallableDescriptorCollectors implemen return Collections.singleton(localVariable); } - LinkedHashSet variables = Sets.newLinkedHashSet(); + Set variables = Sets.newLinkedHashSet(); for (VariableDescriptor variable : scope.getProperties(name)) { if (variable.getReceiverParameter() == null) { variables.add(variable); } } + addFakeDescriptorForObject(scope, name, variables); return variables; } @NotNull @Override public Collection getMembersByName(@NotNull JetType receiverType, Name name, @NotNull BindingTrace bindingTrace) { - return receiverType.getMemberScope().getProperties(name); + JetScope memberScope = receiverType.getMemberScope(); + Collection members = Lists.newArrayList(); + members.addAll(memberScope.getProperties(name)); + addFakeDescriptorForObject(memberScope, name, members); + return members; } @NotNull @@ -141,7 +156,7 @@ public class CallableDescriptorCollectors implemen private static class PropertyCollector implements CallableDescriptorCollector { private static Collection filterProperties(Collection variableDescriptors) { - ArrayList properties = Lists.newArrayList(); + List properties = Lists.newArrayList(); for (VariableDescriptor descriptor : variableDescriptors) { if (descriptor instanceof PropertyDescriptor) { properties.add(descriptor); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java index 57dfc664345..1a26fe4c306 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java @@ -26,7 +26,6 @@ import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.Call; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetSuperExpression; -import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastUtils; import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext; import org.jetbrains.jet.lang.resolve.name.Name; @@ -280,12 +279,14 @@ public class TaskPrioritizer { @NotNull ExplicitReceiverKind explicitReceiverKind, @NotNull Call call ) { - for (D extension : descriptors) { - if (extension instanceof ConstructorDescriptor && DescriptorUtils.isStaticNestedClass(extension.getContainingDeclaration())) { - // We don't want static nested classes' constructors to be resolved with expectedThisObject + for (D descriptor : descriptors) { + if (descriptor instanceof ConstructorDescriptor && DescriptorUtils.isStaticNestedClass(descriptor.getContainingDeclaration()) + || descriptor instanceof FakeCallableDescriptorForObject) { + // We don't want static nested class constructor or class object / object (as callable) + // to be resolved with expectedThisObject continue; } - ResolutionCandidate candidate = ResolutionCandidate.create(call, extension); + ResolutionCandidate candidate = ResolutionCandidate.create(call, descriptor); candidate.setThisObject(thisObject); candidate.setReceiverArgument(receiverParameter); candidate.setExplicitReceiverKind(explicitReceiverKind); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategyImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategyImpl.java index a1dd0cd20fc..1bbc996e19d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategyImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategyImpl.java @@ -24,15 +24,14 @@ import org.jetbrains.jet.lang.psi.JetReferenceExpression; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall; +import org.jetbrains.jet.lang.resolve.calls.util.FakeCallableDescriptorForObject; import org.jetbrains.jet.lang.types.ErrorUtils; import java.util.Collection; import static org.jetbrains.jet.lang.diagnostics.Errors.UNRESOLVED_REFERENCE; import static org.jetbrains.jet.lang.diagnostics.Errors.UNRESOLVED_REFERENCE_WRONG_RECEIVER; -import static org.jetbrains.jet.lang.resolve.BindingContext.CALL; -import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; -import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL; +import static org.jetbrains.jet.lang.resolve.BindingContext.*; public class TracingStrategyImpl extends AbstractTracingStrategy { private final JetReferenceExpression reference; @@ -54,10 +53,13 @@ public class TracingStrategyImpl extends AbstractTracingStrategy { @Override public void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCall resolvedCall) { - CallableDescriptor descriptor = resolvedCall.getCandidateDescriptor(); + DeclarationDescriptor descriptor = resolvedCall.getCandidateDescriptor(); if (resolvedCall instanceof VariableAsFunctionResolvedCall) { descriptor = ((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall().getCandidateDescriptor(); } + if (descriptor instanceof FakeCallableDescriptorForObject) { + descriptor = ((FakeCallableDescriptorForObject) descriptor).getReferencedDescriptor(); + } DeclarationDescriptor storedReference = trace.get(REFERENCE_TARGET, reference); if (storedReference == null || !ErrorUtils.isError(descriptor)) { trace.record(REFERENCE_TARGET, reference, descriptor); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/util/FakeCallableDescriptorForObject.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/util/FakeCallableDescriptorForObject.kt new file mode 100644 index 00000000000..391e98f4f1f --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/util/FakeCallableDescriptorForObject.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2010-2014 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.jet.lang.resolve.calls.util + +import org.jetbrains.jet.lang.descriptors.CallableDescriptor +import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor +import org.jetbrains.jet.lang.types.JetType +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor +import java.util.Collections +import org.jetbrains.jet.lang.descriptors.ClassDescriptor +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorWithVisibility +import org.jetbrains.jet.lang.descriptors.VariableDescriptor +import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant +import org.jetbrains.jet.lang.descriptors.SourceElement +import org.jetbrains.jet.lang.descriptors.ClassKind +import org.jetbrains.jet.lang.resolve.descriptorUtil.getClassObjectReferenceTarget + +public class FakeCallableDescriptorForObject( + private val classDescriptor: ClassDescriptor +) : DeclarationDescriptorWithVisibility by classDescriptor.getClassObjectReferenceTarget(), VariableDescriptor { + + { + assert(classDescriptor.getClassObjectType() != null) { + "FakeCallableDescriptorForObject can be created only for objects, classes with class object or enum entries: $classDescriptor" + } + + } + + public fun getReferencedDescriptor(): ClassDescriptor = classDescriptor.getClassObjectReferenceTarget() + + override fun getReceiverParameter(): ReceiverParameterDescriptor? = null + + override fun getExpectedThisObject(): ReceiverParameterDescriptor? = null + + override fun getTypeParameters(): List = Collections.emptyList() + + override fun getValueParameters(): List = Collections.emptyList() + + override fun getReturnType(): JetType? = getType() + + override fun hasSynthesizedParameterNames() = false + + override fun hasStableParameterNames() = false + + override fun getOverriddenDescriptors(): Set = Collections.emptySet() + + override fun getType(): JetType = classDescriptor.getClassObjectType()!! + + override fun isVar() = false + + override fun getOriginal(): CallableDescriptor = this + + override fun getCompileTimeInitializer(): CompileTimeConstant? = null + + override fun getSource(): SourceElement = classDescriptor.getSource() +} diff --git a/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObject1.kt b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObject1.kt new file mode 100644 index 00000000000..3da9bcd33b1 --- /dev/null +++ b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObject1.kt @@ -0,0 +1,8 @@ +class A { + class object { + fun invoke(i: Int) = i + } +} + +fun box() = if (A(42) == 42) "OK" else "fail" + diff --git a/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObject2.kt b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObject2.kt new file mode 100644 index 00000000000..f31a9a39694 --- /dev/null +++ b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObject2.kt @@ -0,0 +1,11 @@ +trait B + +fun B.invoke(i: Int) = i + +class A { + class object: B { + } +} + +fun box() = if (A(42) == 42) "OK" else "fail" + diff --git a/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObjectOfNestedClass1.kt b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObjectOfNestedClass1.kt new file mode 100644 index 00000000000..6af55e75ca2 --- /dev/null +++ b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObjectOfNestedClass1.kt @@ -0,0 +1,9 @@ +class A { + class Nested { + class object { + fun invoke(i: Int) = i + } + } +} + +fun box() = if (A.Nested(42) == 42) "OK" else "fail" diff --git a/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObjectOfNestedClass2.kt b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObjectOfNestedClass2.kt new file mode 100644 index 00000000000..45116480301 --- /dev/null +++ b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObjectOfNestedClass2.kt @@ -0,0 +1,11 @@ +import A.Nested + +class A { + class Nested { + class object { + fun invoke(i: Int) = i + } + } +} + +fun box() = if (Nested(42) == 42) "OK" else "fail" diff --git a/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnEnum1.kt b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnEnum1.kt new file mode 100644 index 00000000000..4d14d3ff6c4 --- /dev/null +++ b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnEnum1.kt @@ -0,0 +1,8 @@ +enum class A { + ONE + TWO + + fun invoke(i: Int) = i +} + +fun box() = if (A.ONE(42) == 42) "OK" else "fail" diff --git a/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnEnum2.kt b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnEnum2.kt new file mode 100644 index 00000000000..af27ab1b206 --- /dev/null +++ b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnEnum2.kt @@ -0,0 +1,8 @@ +enum class A { + ONE + TWO +} + +fun A.invoke(i: Int) = i + +fun box() = if (A.ONE(42) == 42) "OK" else "fail" diff --git a/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnImportedEnum1.kt b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnImportedEnum1.kt new file mode 100644 index 00000000000..784ad24c681 --- /dev/null +++ b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnImportedEnum1.kt @@ -0,0 +1,10 @@ +import A.ONE + +enum class A { + ONE + TWO + + fun invoke(i: Int) = i +} + +fun box() = if (ONE(42) == 42) "OK" else "fail" diff --git a/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnImportedEnum2.kt b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnImportedEnum2.kt new file mode 100644 index 00000000000..08cab50069c --- /dev/null +++ b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnImportedEnum2.kt @@ -0,0 +1,10 @@ +import A.ONE + +enum class A { + ONE + TWO +} + +fun A.invoke(i: Int) = i + +fun box() = if (ONE(42) == 42) "OK" else "fail" diff --git a/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnObject1.kt b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnObject1.kt new file mode 100644 index 00000000000..d97fd73eda8 --- /dev/null +++ b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnObject1.kt @@ -0,0 +1,5 @@ +object A + +fun A.invoke(i: Int) = i + +fun box() = if (A(42) == 42) "OK" else "fail" \ No newline at end of file diff --git a/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnObject2.kt b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnObject2.kt new file mode 100644 index 00000000000..2a159deb7ab --- /dev/null +++ b/compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnObject2.kt @@ -0,0 +1,5 @@ +object A { + fun invoke(i: Int) = i +} + +fun box() = if (A(42) == 42) "OK" else "fail" \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/kt4321InvokeOnEnum.kt b/compiler/testData/diagnostics/tests/resolve/invoke/kt4321InvokeOnEnum.kt new file mode 100644 index 00000000000..3c0d7ae7326 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/invoke/kt4321InvokeOnEnum.kt @@ -0,0 +1,35 @@ +//KT-4321 invoke() on enum doesn't work + +import DOMElementTestClasses.cls2 + +// use case 1 +enum class DOMElementTestClasses { + cls1 cls2 + + fun invoke() {} +} + + +// use case 2 +trait EnumStyleClass { + fun invoke() {} +} +enum class TestClasses : EnumStyleClass { + cls +} + +// example +fun main(args: Array) { + // Kotlin: Expression 'cls1' of type 'DOMElementTestClasses' cannot be invoked as a function + DOMElementTestClasses.cls1() + + // Kotlin: Expression 'cls2' of type 'DOMElementTestClasses' cannot be invoked as a function + cls2() + + // Kotlin: Expression 'cls' of type 'TestClasses' cannot be invoked as a function + TestClasses.cls() + + // All ok + val cls = DOMElementTestClasses.cls2 + cls() +} \ No newline at end of file diff --git a/compiler/testData/resolvedCalls/invoke/invokeOnClassObject1.kt b/compiler/testData/resolvedCalls/invoke/invokeOnClassObject1.kt new file mode 100644 index 00000000000..cf448fff055 --- /dev/null +++ b/compiler/testData/resolvedCalls/invoke/invokeOnClassObject1.kt @@ -0,0 +1,7 @@ +class A { + class object { + fun invoke(i: Int) = i + } +} + +fun test() = A(1) \ No newline at end of file diff --git a/compiler/testData/resolvedCalls/invoke/invokeOnClassObject1.txt b/compiler/testData/resolvedCalls/invoke/invokeOnClassObject1.txt new file mode 100644 index 00000000000..86cd5ac5ccb --- /dev/null +++ b/compiler/testData/resolvedCalls/invoke/invokeOnClassObject1.txt @@ -0,0 +1,16 @@ +class A { + class object { + fun invoke(i: Int) = i + } +} + +fun test() = A(1) + + +Resolved call: + +Resulting descriptor: class A + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +This object = NO_RECEIVER +Receiver argument = NO_RECEIVER \ No newline at end of file diff --git a/compiler/testData/resolvedCalls/invoke/invokeOnClassObject2.kt b/compiler/testData/resolvedCalls/invoke/invokeOnClassObject2.kt new file mode 100644 index 00000000000..ecf46436df1 --- /dev/null +++ b/compiler/testData/resolvedCalls/invoke/invokeOnClassObject2.kt @@ -0,0 +1,7 @@ +class A { + class object { + fun invoke(i: Int) = i + } +} + +fun test() = A(1) \ No newline at end of file diff --git a/compiler/testData/resolvedCalls/invoke/invokeOnClassObject2.txt b/compiler/testData/resolvedCalls/invoke/invokeOnClassObject2.txt new file mode 100644 index 00000000000..d0f68b3745d --- /dev/null +++ b/compiler/testData/resolvedCalls/invoke/invokeOnClassObject2.txt @@ -0,0 +1,20 @@ +class A { + class object { + fun invoke(i: Int) = i + } +} + +fun test() = A(1) + + +Resolved call: + +Resulting descriptor: fun invoke(i: Int): Int + +Explicit receiver kind = THIS_OBJECT +This object = A {} +Receiver argument = NO_RECEIVER + +Value arguments mapping: + +SUCCESS i : Int = 1 \ No newline at end of file diff --git a/compiler/testData/resolvedCalls/invoke/invokeOnEnumEntry1.kt b/compiler/testData/resolvedCalls/invoke/invokeOnEnumEntry1.kt new file mode 100644 index 00000000000..021a2156b8c --- /dev/null +++ b/compiler/testData/resolvedCalls/invoke/invokeOnEnumEntry1.kt @@ -0,0 +1,8 @@ +enum class A { + ONE + TWO + + fun invoke(i: Int) = i +} + +fun test() = A.ONE(1) \ No newline at end of file diff --git a/compiler/testData/resolvedCalls/invoke/invokeOnEnumEntry1.txt b/compiler/testData/resolvedCalls/invoke/invokeOnEnumEntry1.txt new file mode 100644 index 00000000000..a52c5ff7e98 --- /dev/null +++ b/compiler/testData/resolvedCalls/invoke/invokeOnEnumEntry1.txt @@ -0,0 +1,17 @@ +enum class A { + ONE + TWO + + fun invoke(i: Int) = i +} + +fun test() = A.ONE(1) + + +Resolved call: + +Resulting descriptor: enum entry ONE : A + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +This object = NO_RECEIVER +Receiver argument = NO_RECEIVER \ No newline at end of file diff --git a/compiler/testData/resolvedCalls/invoke/invokeOnEnumEntry2.kt b/compiler/testData/resolvedCalls/invoke/invokeOnEnumEntry2.kt new file mode 100644 index 00000000000..03be7b30e84 --- /dev/null +++ b/compiler/testData/resolvedCalls/invoke/invokeOnEnumEntry2.kt @@ -0,0 +1,8 @@ +enum class A { + ONE + TWO + + fun invoke(i: Int) = i +} + +fun test() = A.ONE(1) \ No newline at end of file diff --git a/compiler/testData/resolvedCalls/invoke/invokeOnEnumEntry2.txt b/compiler/testData/resolvedCalls/invoke/invokeOnEnumEntry2.txt new file mode 100644 index 00000000000..7460bea668c --- /dev/null +++ b/compiler/testData/resolvedCalls/invoke/invokeOnEnumEntry2.txt @@ -0,0 +1,21 @@ +enum class A { + ONE + TWO + + fun invoke(i: Int) = i +} + +fun test() = A.ONE(1) + + +Resolved call: + +Resulting descriptor: fun invoke(i: Int): Int + +Explicit receiver kind = THIS_OBJECT +This object = ONE {A} +Receiver argument = NO_RECEIVER + +Value arguments mapping: + +SUCCESS i : Int = 1 \ No newline at end of file diff --git a/compiler/testData/resolvedCalls/invoke/invokeOnObject1.kt b/compiler/testData/resolvedCalls/invoke/invokeOnObject1.kt new file mode 100644 index 00000000000..fe25ba9a936 --- /dev/null +++ b/compiler/testData/resolvedCalls/invoke/invokeOnObject1.kt @@ -0,0 +1,5 @@ +object A { + fun invoke(i: Int) = i +} + +fun test() = A(1) \ No newline at end of file diff --git a/compiler/testData/resolvedCalls/invoke/invokeOnObject1.txt b/compiler/testData/resolvedCalls/invoke/invokeOnObject1.txt new file mode 100644 index 00000000000..94215458511 --- /dev/null +++ b/compiler/testData/resolvedCalls/invoke/invokeOnObject1.txt @@ -0,0 +1,14 @@ +object A { + fun invoke(i: Int) = i +} + +fun test() = A(1) + + +Resolved call: + +Resulting descriptor: object A + +Explicit receiver kind = NO_EXPLICIT_RECEIVER +This object = NO_RECEIVER +Receiver argument = NO_RECEIVER \ No newline at end of file diff --git a/compiler/testData/resolvedCalls/invoke/invokeOnObject2.kt b/compiler/testData/resolvedCalls/invoke/invokeOnObject2.kt new file mode 100644 index 00000000000..06148987ab2 --- /dev/null +++ b/compiler/testData/resolvedCalls/invoke/invokeOnObject2.kt @@ -0,0 +1,5 @@ +object A { + fun invoke(i: Int) = i +} + +fun test() = A(1) \ No newline at end of file diff --git a/compiler/testData/resolvedCalls/invoke/invokeOnObject2.txt b/compiler/testData/resolvedCalls/invoke/invokeOnObject2.txt new file mode 100644 index 00000000000..f2beb0d7b2a --- /dev/null +++ b/compiler/testData/resolvedCalls/invoke/invokeOnObject2.txt @@ -0,0 +1,18 @@ +object A { + fun invoke(i: Int) = i +} + +fun test() = A(1) + + +Resolved call: + +Resulting descriptor: fun invoke(i: Int): Int + +Explicit receiver kind = THIS_OBJECT +This object = A {A} +Receiver argument = NO_RECEIVER + +Value arguments mapping: + +SUCCESS i : Int = 1 \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 8520c6b6f98..4a9d66511fe 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -27,7 +27,7 @@ import java.util.regex.Pattern; /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") -@InnerTestClasses({JetDiagnosticsTestGenerated.Tests.class, JetDiagnosticsTestGenerated.Script.class, JetDiagnosticsTestGenerated.TailRecursion.class}) +@InnerTestClasses({JetDiagnosticsTestGenerated.Tests.class, JetDiagnosticsTestGenerated.Script.class, JetDiagnosticsTestGenerated.TailRecursion.class, JetDiagnosticsTestGenerated.OnObjects.class}) public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { @TestMetadata("compiler/testData/diagnostics/tests") @InnerTestClasses({Tests.Annotations.class, Tests.BackingField.class, Tests.Cast.class, Tests.CheckArguments.class, Tests.ClassObjects.class, Tests.ControlFlowAnalysis.class, Tests.ControlStructures.class, Tests.CyclicHierarchy.class, Tests.DataClasses.class, Tests.DataFlow.class, Tests.DataFlowInfoTraversal.class, Tests.DeclarationChecks.class, Tests.DelegatedProperty.class, Tests.Deparenthesize.class, Tests.DuplicateJvmSignature.class, Tests.Enum.class, Tests.Evaluate.class, Tests.Extensions.class, Tests.FunctionLiterals.class, Tests.Generics.class, Tests.Imports.class, Tests.IncompleteCode.class, Tests.Inference.class, Tests.Infos.class, Tests.Inline.class, Tests.Inner.class, Tests.J_k.class, Tests.Jdk_annotations.class, Tests.Labels.class, Tests.Library.class, Tests.Multimodule.class, Tests.NamedArguments.class, Tests.NullabilityAndAutoCasts.class, Tests.NullableTypes.class, Tests.Numbers.class, Tests.Objects.class, Tests.OperatorsOverloading.class, Tests.Overload.class, Tests.Override.class, Tests.Recovery.class, Tests.Redeclarations.class, Tests.Regressions.class, Tests.Resolve.class, Tests.Scopes.class, Tests.SenselessComparison.class, Tests.Shadowing.class, Tests.SmartCasts.class, Tests.Substitutions.class, Tests.Subtyping.class, Tests.Suppress.class, Tests.ThisAndSuper.class, Tests.TraitWithRequired.class, Tests.Typedefs.class, Tests.Unit.class, Tests.Varargs.class, Tests.When.class}) @@ -7047,6 +7047,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest("compiler/testData/diagnostics/tests/resolve/invoke/kt4204-completeNestedCallsForInvoke.kt"); } + @TestMetadata("kt4321InvokeOnEnum.kt") + public void testKt4321InvokeOnEnum() throws Exception { + doTest("compiler/testData/diagnostics/tests/resolve/invoke/kt4321InvokeOnEnum.kt"); + } + @TestMetadata("valNamedInvoke.kt") public void testValNamedInvoke() throws Exception { doTest("compiler/testData/diagnostics/tests/resolve/invoke/valNamedInvoke.kt"); @@ -8410,11 +8415,70 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { } + @TestMetadata("compiler/testData/codegen/box/functions/invoke/onObjects") + public static class OnObjects extends AbstractJetDiagnosticsTest { + public void testAllFilesPresentInOnObjects() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/functions/invoke/onObjects"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("invokeOnClassObject1.kt") + public void testInvokeOnClassObject1() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObject1.kt"); + } + + @TestMetadata("invokeOnClassObject2.kt") + public void testInvokeOnClassObject2() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObject2.kt"); + } + + @TestMetadata("invokeOnClassObjectOfNestedClass1.kt") + public void testInvokeOnClassObjectOfNestedClass1() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObjectOfNestedClass1.kt"); + } + + @TestMetadata("invokeOnClassObjectOfNestedClass2.kt") + public void testInvokeOnClassObjectOfNestedClass2() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObjectOfNestedClass2.kt"); + } + + @TestMetadata("invokeOnEnum1.kt") + public void testInvokeOnEnum1() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnEnum1.kt"); + } + + @TestMetadata("invokeOnEnum2.kt") + public void testInvokeOnEnum2() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnEnum2.kt"); + } + + @TestMetadata("invokeOnImportedEnum1.kt") + public void testInvokeOnImportedEnum1() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnImportedEnum1.kt"); + } + + @TestMetadata("invokeOnImportedEnum2.kt") + public void testInvokeOnImportedEnum2() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnImportedEnum2.kt"); + } + + @TestMetadata("invokeOnObject1.kt") + public void testInvokeOnObject1() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnObject1.kt"); + } + + @TestMetadata("invokeOnObject2.kt") + public void testInvokeOnObject2() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnObject2.kt"); + } + + } + public static Test suite() { TestSuite suite = new TestSuite("JetDiagnosticsTestGenerated"); suite.addTest(Tests.innerSuite()); suite.addTestSuite(Script.class); suite.addTestSuite(TailRecursion.class); + suite.addTestSuite(OnObjects.class); return suite; } } diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index 5578c4d01d4..c9b44291f98 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -2672,6 +2672,7 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } @TestMetadata("compiler/testData/codegen/box/functions/invoke") + @InnerTestClasses({Invoke.OnObjects.class}) public static class Invoke extends AbstractBlackBoxCodegenTest { public void testAllFilesPresentInInvoke() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/functions/invoke"), Pattern.compile("^(.+)\\.kt$"), true); @@ -2732,6 +2733,70 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/functions/invoke/kt3822invokeOnThis.kt"); } + @TestMetadata("compiler/testData/codegen/box/functions/invoke/onObjects") + public static class OnObjects extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInOnObjects() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/functions/invoke/onObjects"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("invokeOnClassObject1.kt") + public void testInvokeOnClassObject1() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObject1.kt"); + } + + @TestMetadata("invokeOnClassObject2.kt") + public void testInvokeOnClassObject2() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObject2.kt"); + } + + @TestMetadata("invokeOnClassObjectOfNestedClass1.kt") + public void testInvokeOnClassObjectOfNestedClass1() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObjectOfNestedClass1.kt"); + } + + @TestMetadata("invokeOnClassObjectOfNestedClass2.kt") + public void testInvokeOnClassObjectOfNestedClass2() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnClassObjectOfNestedClass2.kt"); + } + + @TestMetadata("invokeOnEnum1.kt") + public void testInvokeOnEnum1() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnEnum1.kt"); + } + + @TestMetadata("invokeOnEnum2.kt") + public void testInvokeOnEnum2() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnEnum2.kt"); + } + + @TestMetadata("invokeOnImportedEnum1.kt") + public void testInvokeOnImportedEnum1() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnImportedEnum1.kt"); + } + + @TestMetadata("invokeOnImportedEnum2.kt") + public void testInvokeOnImportedEnum2() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnImportedEnum2.kt"); + } + + @TestMetadata("invokeOnObject1.kt") + public void testInvokeOnObject1() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnObject1.kt"); + } + + @TestMetadata("invokeOnObject2.kt") + public void testInvokeOnObject2() throws Exception { + doTest("compiler/testData/codegen/box/functions/invoke/onObjects/invokeOnObject2.kt"); + } + + } + + public static Test innerSuite() { + TestSuite suite = new TestSuite("Invoke"); + suite.addTestSuite(Invoke.class); + suite.addTestSuite(OnObjects.class); + return suite; + } } @TestMetadata("compiler/testData/codegen/box/functions/localFunctions") @@ -2993,7 +3058,7 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public static Test innerSuite() { TestSuite suite = new TestSuite("Functions"); suite.addTestSuite(Functions.class); - suite.addTestSuite(Invoke.class); + suite.addTest(Invoke.innerSuite()); suite.addTestSuite(LocalFunctions.class); suite.addTestSuite(TailRecursion.class); return suite; diff --git a/compiler/tests/org/jetbrains/jet/resolve/calls/ResolvedCallsTestGenerated.java b/compiler/tests/org/jetbrains/jet/resolve/calls/ResolvedCallsTestGenerated.java index 0f4ce70f465..8dde061ea55 100644 --- a/compiler/tests/org/jetbrains/jet/resolve/calls/ResolvedCallsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/resolve/calls/ResolvedCallsTestGenerated.java @@ -314,6 +314,36 @@ public class ResolvedCallsTestGenerated extends AbstractResolvedCallsTest { doTest("compiler/testData/resolvedCalls/invoke/implicitReceiverForInvoke.kt"); } + @TestMetadata("invokeOnClassObject1.kt") + public void testInvokeOnClassObject1() throws Exception { + doTest("compiler/testData/resolvedCalls/invoke/invokeOnClassObject1.kt"); + } + + @TestMetadata("invokeOnClassObject2.kt") + public void testInvokeOnClassObject2() throws Exception { + doTest("compiler/testData/resolvedCalls/invoke/invokeOnClassObject2.kt"); + } + + @TestMetadata("invokeOnEnumEntry1.kt") + public void testInvokeOnEnumEntry1() throws Exception { + doTest("compiler/testData/resolvedCalls/invoke/invokeOnEnumEntry1.kt"); + } + + @TestMetadata("invokeOnEnumEntry2.kt") + public void testInvokeOnEnumEntry2() throws Exception { + doTest("compiler/testData/resolvedCalls/invoke/invokeOnEnumEntry2.kt"); + } + + @TestMetadata("invokeOnObject1.kt") + public void testInvokeOnObject1() throws Exception { + doTest("compiler/testData/resolvedCalls/invoke/invokeOnObject1.kt"); + } + + @TestMetadata("invokeOnObject2.kt") + public void testInvokeOnObject2() throws Exception { + doTest("compiler/testData/resolvedCalls/invoke/invokeOnObject2.kt"); + } + @TestMetadata("receiverArgumentAsReceiverForInvoke.kt") public void testReceiverArgumentAsReceiverForInvoke() throws Exception { doTest("compiler/testData/resolvedCalls/invoke/receiverArgumentAsReceiverForInvoke.kt"); diff --git a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/CallableDescriptor.java b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/CallableDescriptor.java index 4e8fc5a1d40..53853b1eb0f 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/CallableDescriptor.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/CallableDescriptor.java @@ -32,6 +32,7 @@ public interface CallableDescriptor extends DeclarationDescriptorWithVisibility, @Nullable ReceiverParameterDescriptor getExpectedThisObject(); + @KotlinSignature("fun getTypeParameters(): List") @NotNull List getTypeParameters(); @@ -48,6 +49,7 @@ public interface CallableDescriptor extends DeclarationDescriptorWithVisibility, @Override CallableDescriptor substitute(@NotNull TypeSubstitutor substitutor); + @KotlinSignature("fun getValueParameters(): List") @NotNull List getValueParameters(); diff --git a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt index 10f0f118977..d3e528afcf1 100644 --- a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt @@ -128,6 +128,7 @@ fun main(args: Array) { model("diagnostics/tests") model("diagnostics/tests/script", extension = "kts") model("codegen/box/functions/tailRecursion") + model("codegen/box/functions/invoke/onObjects") } testClass(javaClass()) {