From 37d5c4b22373e71d44e51c499a1c872622a7fd62 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Fri, 2 Oct 2015 16:01:09 +0300 Subject: [PATCH] Allow to import members from object by name Wrap object members so they do not require dispatch receiver Hack jvm backend to make it work --- .../jetbrains/kotlin/codegen/StackValue.java | 14 +- .../kotlin/codegen/state/JetTypeMapper.java | 16 +- .../jetbrains/kotlin/diagnostics/Errors.java | 2 +- .../rendering/DefaultErrorMessages.java | 4 +- .../resolve/QualifiedExpressionResolver.kt | 18 ++- .../kotlin/resolve/importedFromObject.kt | 60 ++++++++ .../codegen/box/objects/useImportedMember.kt | 50 +++++++ .../objects/useImportedMemberFromCompanion.kt | 52 +++++++ .../importStaticMemberFromObject.kt | 30 ++++ .../imports/ImportFromCompanionObject.kt | 138 ++++++++++++++++++ .../imports/ImportFromCompanionObject.txt | 118 +++++++++++++++ .../tests/imports/ImportFromObject.kt | 116 ++++++++++++++- .../tests/imports/ImportFromObject.txt | 69 ++++++++- .../diagnostics/tests/imports/Imports.kt | 14 +- .../tests/imports/StarImportFromObject.kt | 16 +- .../diagnostics/tests/imports/WrongImport.kt | 8 +- .../diagnostics/tests/scopes/kt900-1.kt | 2 +- .../diagnostics/tests/scopes/kt900-2.kt | 6 +- .../checkers/JetDiagnosticsTestGenerated.java | 6 + .../BlackBoxCodegenTestGenerated.java | 12 ++ ...lackBoxWithStdlibCodegenTestGenerated.java | 6 + .../descriptors/FunctionDescriptor.java | 1 + 22 files changed, 713 insertions(+), 45 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/resolve/importedFromObject.kt create mode 100644 compiler/testData/codegen/box/objects/useImportedMember.kt create mode 100644 compiler/testData/codegen/box/objects/useImportedMemberFromCompanion.kt create mode 100644 compiler/testData/codegen/boxWithStdlib/platformStatic/importStaticMemberFromObject.kt create mode 100644 compiler/testData/diagnostics/tests/imports/ImportFromCompanionObject.kt create mode 100644 compiler/testData/diagnostics/tests/imports/ImportFromCompanionObject.txt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java index d2b69cb23b4..c44343d0a85 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.codegen.state.JetTypeMapper; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.psi.JetExpression; +import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor; import org.jetbrains.kotlin.resolve.annotations.AnnotationsPackage; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument; @@ -489,7 +490,8 @@ public abstract class StackValue { ) { ReceiverValue callDispatchReceiver = resolvedCall.getDispatchReceiver(); ReceiverValue callExtensionReceiver = resolvedCall.getExtensionReceiver(); - if (callDispatchReceiver.exists() || callExtensionReceiver.exists() || isLocalFunCall(callableMethod)) { + if (callDispatchReceiver.exists() || callExtensionReceiver.exists() + || isLocalFunCall(callableMethod) || isCallToMemberObjectImportedByName(resolvedCall)) { CallableDescriptor descriptor = resolvedCall.getResultingDescriptor(); ReceiverParameterDescriptor dispatchReceiverParameter = descriptor.getDispatchReceiverParameter(); ReceiverParameterDescriptor extensionReceiverParameter = descriptor.getExtensionReceiverParameter(); @@ -527,11 +529,13 @@ public abstract class StackValue { return codegen.generateReceiverValue(receiverValue); } else if (isLocalFunCall(callableMethod) && !isExtension) { - CallableDescriptor descriptor = resolvedCall.getResultingDescriptor(); - StackValue value = codegen.findLocalOrCapturedValue(descriptor.getOriginal()); + StackValue value = codegen.findLocalOrCapturedValue(resolvedCall.getResultingDescriptor().getOriginal()); assert value != null : "Local fun should be found in locals or in captured params: " + resolvedCall; return value; } + else if (isCallToMemberObjectImportedByName(resolvedCall)) { + return singleton(((ImportedFromObjectCallableDescriptor) resolvedCall.getResultingDescriptor()).getContainingObject(), codegen.typeMapper); + } } else if (receiverValue.exists()) { return receiver; @@ -539,6 +543,10 @@ public abstract class StackValue { return none(); } + private static boolean isCallToMemberObjectImportedByName(@NotNull ResolvedCall resolvedCall) { + return resolvedCall.getResultingDescriptor() instanceof ImportedFromObjectCallableDescriptor; + } + private static StackValue platformStaticCallIfPresent(@NotNull StackValue resultReceiver, @NotNull CallableDescriptor descriptor) { if (AnnotationsPackage.isPlatformStaticInObjectOrClass(descriptor)) { if (resultReceiver.canHaveSideEffects()) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java index 28d3df6a727..89f7b82563b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java @@ -47,9 +47,7 @@ import org.jetbrains.kotlin.psi.JetExpression; import org.jetbrains.kotlin.psi.JetFile; import org.jetbrains.kotlin.psi.JetFunctionLiteral; import org.jetbrains.kotlin.psi.JetFunctionLiteralExpression; -import org.jetbrains.kotlin.resolve.BindingContext; -import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; -import org.jetbrains.kotlin.resolve.DescriptorUtils; +import org.jetbrains.kotlin.resolve.*; import org.jetbrains.kotlin.resolve.annotations.AnnotationsPackage; import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; @@ -712,9 +710,11 @@ public class JetTypeMapper { } } else { - if (isStaticDeclaration(functionDescriptor) || - isStaticAccessor(functionDescriptor) || - AnnotationsPackage.isPlatformStaticInObjectOrClass(functionDescriptor)) { + boolean isStaticInvocation = (isStaticDeclaration(functionDescriptor) && + !(functionDescriptor instanceof ImportedFromObjectCallableDescriptor)) || + isStaticAccessor(functionDescriptor) || + AnnotationsPackage.isPlatformStaticInObjectOrClass(functionDescriptor); + if (isStaticInvocation) { invokeOpcode = INVOKESTATIC; } else if (isInterface) { @@ -858,6 +858,10 @@ public class JetTypeMapper { @NotNull public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, @NotNull OwnerKind kind, List valueParameters) { + if (f instanceof FunctionImportedFromObject) { + return mapSignature(((FunctionImportedFromObject) f).getFunctionFromObject()); + } + BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD); if (f instanceof ConstructorDescriptor) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 66ec1fc157a..457844a9272 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -100,7 +100,7 @@ public interface Errors { // Imports - DiagnosticFactory1 CANNOT_IMPORT_MEMBERS_FROM_SINGLETON = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 CANNOT_BE_IMPORTED = DiagnosticFactory1.create(ERROR); DiagnosticFactory0 PACKAGE_CANNOT_BE_IMPORTED = DiagnosticFactory0.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index f407e15f471..66d75bc8a49 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -147,8 +147,8 @@ public class DefaultErrorMessages { MAP.put(LABEL_NAME_CLASH, "There is more than one label with such a name in this scope"); MAP.put(EXPRESSION_EXPECTED_PACKAGE_FOUND, "Expression expected, but a package name found"); - MAP.put(CANNOT_IMPORT_MEMBERS_FROM_SINGLETON, "Cannot import members from object ''{0}''", NAME); - MAP.put(CANNOT_BE_IMPORTED, "Cannot import ''{0}'', functions and properties can be imported only from packages", TO_STRING); + MAP.put(CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON, "Cannot import-on-demand from object ''{0}''", NAME); + MAP.put(CANNOT_BE_IMPORTED, "Cannot import ''{0}'', functions and properties can be imported only from packages or objects", TO_STRING); MAP.put(PACKAGE_CANNOT_BE_IMPORTED, "Packages cannot be imported"); MAP.put(CONFLICTING_IMPORT, "Conflicting import, imported name ''{0}'' is ambiguous", STRING); MAP.put(PLATFORM_CLASS_MAPPED_TO_KOTLIN, "This class shouldn''t be used in Kotlin. Use {0} instead.", CLASSES_OR_SEPARATED); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt index 04b5f7d4c16..d1669536885 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt @@ -129,7 +129,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa val packageOrClassDescriptor = resolveToPackageOrClass(path, moduleDescriptor, trace, packageFragmentForVisibilityCheck, scopeForFirstPart = null, inImport = true) ?: return null if (packageOrClassDescriptor is ClassDescriptor && packageOrClassDescriptor.kind.isSingleton) { - trace.report(Errors.CANNOT_IMPORT_MEMBERS_FROM_SINGLETON.on(lastPart.expression, packageOrClassDescriptor)) // todo report on star + trace.report(Errors.CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON.on(lastPart.expression, packageOrClassDescriptor)) // todo report on star } return AllUnderImportsScope(packageOrClassDescriptor) } @@ -185,6 +185,15 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa val staticClassScope = packageOrClassDescriptor.staticScope descriptors.addAll(staticClassScope.getFunctions(lastName, location)) descriptors.addAll(staticClassScope.getProperties(lastName, location)) + + if (packageOrClassDescriptor.kind == ClassKind.OBJECT) { + descriptors.addAll(packageOrClassDescriptor.unsubstitutedMemberScope.getFunctions(lastName, location).map { + FunctionImportedFromObject(it) + }) + val properties = packageOrClassDescriptor.unsubstitutedMemberScope.getProperties(lastName, location) + .filterIsInstance().map { PropertyImportedFromObject(it) } + descriptors.addAll(properties) + } } else -> throw IllegalStateException("Should be class or package: $packageOrClassDescriptor") @@ -214,12 +223,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa descriptors.addAll(memberScope.getFunctions(lastName, lastPart.location)) descriptors.addAll(memberScope.getProperties(lastName, lastPart.location)) if (descriptors.isNotEmpty()) { - if (packageOrClassDescriptor.kind.isSingleton) { - trace.report(Errors.CANNOT_IMPORT_MEMBERS_FROM_SINGLETON.on(lastPart.expression, packageOrClassDescriptor)) - } - else { - trace.report(Errors.CANNOT_BE_IMPORTED.on(lastPart.expression, lastName)) - } + trace.report(Errors.CANNOT_BE_IMPORTED.on(lastPart.expression, lastName)) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/importedFromObject.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/importedFromObject.kt new file mode 100644 index 00000000000..a1756c5d3e4 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/importedFromObject.kt @@ -0,0 +1,60 @@ +/* + * 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 + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.types.TypeSubstitutor + +abstract class ImportedFromObjectCallableDescriptor(val containingObject: ClassDescriptor): CallableDescriptor + +// members imported from object should be wrapped to not require dispatch receiver +class FunctionImportedFromObject(val functionFromObject: FunctionDescriptor) : + FunctionDescriptor by functionFromObject, + ImportedFromObjectCallableDescriptor(functionFromObject.containingDeclaration as ClassDescriptor) { + override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? = null + + override fun substitute(substitutor: TypeSubstitutor) = functionFromObject.substitute(substitutor).wrap() + + override fun getOriginal() = functionFromObject.original.wrap() + + override fun copy( + newOwner: DeclarationDescriptor?, modality: Modality?, visibility: Visibility?, + kind: CallableMemberDescriptor.Kind?, copyOverrides: Boolean + ): FunctionDescriptor { + throw IllegalStateException("copy() should not be called on ${this.javaClass.simpleName}, was called for $this") + } +} + +class PropertyImportedFromObject(private val propertyFromObject: PropertyDescriptor) : + PropertyDescriptor by propertyFromObject, + ImportedFromObjectCallableDescriptor(propertyFromObject.containingDeclaration as ClassDescriptor) { + override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? = null + + override fun substitute(substitutor: TypeSubstitutor) = propertyFromObject.substitute(substitutor)?.wrap() + + override fun getOriginal() = propertyFromObject.original.wrap() + + override fun copy( + newOwner: DeclarationDescriptor?, modality: Modality?, visibility: Visibility?, + kind: CallableMemberDescriptor.Kind?, copyOverrides: Boolean + ): FunctionDescriptor { + throw IllegalStateException("copy() should not be called on ${this.javaClass.simpleName}, was called for $this") + } +} + +private fun FunctionDescriptor.wrap() = FunctionImportedFromObject(this) +private fun PropertyDescriptor.wrap() = PropertyImportedFromObject(this) \ No newline at end of file diff --git a/compiler/testData/codegen/box/objects/useImportedMember.kt b/compiler/testData/codegen/box/objects/useImportedMember.kt new file mode 100644 index 00000000000..83b806eb024 --- /dev/null +++ b/compiler/testData/codegen/box/objects/useImportedMember.kt @@ -0,0 +1,50 @@ +import C.f +import C.p +import C.ext +import C.g1 +import C.g2 +import C.fromClass +import C.fromInterface +import C.genericFromSuper + +interface I { + fun T.fromInterface(): T = this + + fun genericFromSuper(g: G) = g +} + +open class BaseClass { + val T.fromClass: T + get() = this +} + +object C: BaseClass(), I { + fun f(s: Int) = 1 + fun f(s: String) = 2 + fun Boolean.f() = 3 + + var p: Int = 4 + val Int.ext: Int + get() = 6 + + fun g1(t: T): T = t + val T.g2: T + get() = this +} + +fun box(): String { + if (f(1) != 1) return "1" + if (f("s") != 2) return "2" + if (true.f() != 3) return "3" + if (p != 4) return "4" + p = 5 + if (p != 5) return "5" + if (5.ext != 6) return "6" + if (g1("7") != "7") return "7" + if ("8".g2 != "8") return "8" + if (9.fromInterface() != 9) return "9" + if ("10".fromClass != "10") return "10" + if (genericFromSuper("11") != "11") return "11" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/objects/useImportedMemberFromCompanion.kt b/compiler/testData/codegen/box/objects/useImportedMemberFromCompanion.kt new file mode 100644 index 00000000000..9523480b86a --- /dev/null +++ b/compiler/testData/codegen/box/objects/useImportedMemberFromCompanion.kt @@ -0,0 +1,52 @@ +import Class.C.f +import Class.C.p +import Class.C.ext +import Class.C.g1 +import Class.C.g2 +import Class.C.fromClass +import Class.C.fromInterface +import Class.C.genericFromSuper + +interface I { + fun T.fromInterface(): T = this + + fun genericFromSuper(g: G) = g +} + +open class BaseClass { + val T.fromClass: T + get() = this +} + +class Class { + companion object C: BaseClass(), I { + fun f(s: Int) = 1 + fun f(s: String) = 2 + fun Boolean.f() = 3 + + var p: Int = 4 + val Int.ext: Int + get() = 6 + + fun g1(t: T): T = t + val T.g2: T + get() = this + } +} + +fun box(): String { + if (f(1) != 1) return "1" + if (f("s") != 2) return "2" + if (true.f() != 3) return "3" + if (p != 4) return "4" + p = 5 + if (p != 5) return "5" + if (5.ext != 6) return "6" + if (g1("7") != "7") return "7" + if ("8".g2 != "8") return "8" + if (9.fromInterface() != 9) return "9" + if ("10".fromClass != "10") return "10" + if (genericFromSuper("11") != "11") return "11" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithStdlib/platformStatic/importStaticMemberFromObject.kt b/compiler/testData/codegen/boxWithStdlib/platformStatic/importStaticMemberFromObject.kt new file mode 100644 index 00000000000..b9c9c1fcf20 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/platformStatic/importStaticMemberFromObject.kt @@ -0,0 +1,30 @@ +import O.p +import O.f +import C.Companion.p1 +import C.Companion.f1 + +object O { + @JvmStatic + fun f(): Int = 3 + + @JvmStatic + val p: Int = 6 +} + +class C { + companion object { + @JvmStatic + fun f1(): Int = 3 + + @JvmStatic + val p1: Int = 6 + } + +} + +fun box(): String { + if (p + f() != 9) return "fail" + if (p1 + f1() != 9) return "fail2" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/imports/ImportFromCompanionObject.kt b/compiler/testData/diagnostics/tests/imports/ImportFromCompanionObject.kt new file mode 100644 index 00000000000..e295643f313 --- /dev/null +++ b/compiler/testData/diagnostics/tests/imports/ImportFromCompanionObject.kt @@ -0,0 +1,138 @@ +// FILE: a.Kt +package a + +class C1 { + companion object O { + class A + object B + + fun bar() {} + } +} + + +class C2 { + companion object S { + + val prop: String = "" + + fun o(s: String) = Unit + fun o(i: Int) = Unit + + fun Int.ext() = Unit + var String.ext: Int + get() = 3 + set(i) { + } + + fun A(c: Int) = A() + + class A() + + fun genericFun(t: T, t2: T): T = t + } +} + +open class Base { + fun f() { + } + + fun g(t: T) { + } + + val p = 1 + val Int.ext: Int + get() = 4 +} + +interface BaseI { + fun fromI(): Int = 3 + + fun genericFromI(t: T) = t +} + +class C3 { + companion object K: Base(), BaseI { + val own: String = "" + } +} + +// FILE: b.kt +package b + +import a.C1.O.* + +fun testErroneusAllUnderImportFromObject() { + A() + B + bar() +} + +// FILE: c.kt +package c + +import a.C2.S.prop +import a.C2.S.o +import a.C2.S.ext +import a.C2.S.A +import a.C2.S.genericFun +import a.C2.S.ext as extRenamed + +fun testImportFromObjectByName() { + prop + o("a") + o(3) + 3.ext() + "".ext = 3 + val c: Int = "".ext + + 3.extRenamed() + "".extRenamed = 3 + val c2: Int = "".extRenamed + + A() + A(3) + + val a: Int = genericFun(3, 3) + val s: String = genericFun("A", "b") + val b: Boolean = genericFun(true, false) +} + +fun t(t: T): T { + return genericFun(t, t) +} + +// FILE: d.kt +package d + +import a.C2.S.prop as renamed + +fun testFunImportedFromObjectHasNoDispatchReceiver(l: a.C2.S) { + l.renamed + l.prop + renamed +} + +// FILE: e.kt + +package e + +import a.C3.K.f +import a.C3.K.g +import a.C3.K.p +import a.C3.K.own +import a.C3.K.fromI +import a.C3.K.genericFromI +import a.C3.K.ext + +fun testMembersFromSupertypes() { + f() + g("") + p + fromI() + + genericFromI(3) + genericFromI("a") + + own +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/imports/ImportFromCompanionObject.txt b/compiler/testData/diagnostics/tests/imports/ImportFromCompanionObject.txt new file mode 100644 index 00000000000..84fc9dc4bb1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/imports/ImportFromCompanionObject.txt @@ -0,0 +1,118 @@ +package + +package a { + + public open class Base { + public constructor Base() + public final val p: kotlin.Int = 1 + public final val kotlin.Int.ext: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun f(): kotlin.Unit + public final fun g(/*0*/ t: T): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public interface BaseI { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun fromI(): kotlin.Int + public open fun genericFromI(/*0*/ t: T): T + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final class C1 { + public constructor C1() + 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 + + public companion object O { + private constructor O() + public final fun bar(): kotlin.Unit + 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 + + public 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 + } + + public object B { + private constructor B() + 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 + } + } + } + + public final class C2 { + public constructor C2() + 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 + + public companion object S { + private constructor S() + public final val prop: kotlin.String = "" + public final var kotlin.String.ext: kotlin.Int + public final fun A(/*0*/ c: kotlin.Int): a.C2.S.A + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun genericFun(/*0*/ t: T, /*1*/ t2: T): T + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final fun o(/*0*/ i: kotlin.Int): kotlin.Unit + public final fun o(/*0*/ s: kotlin.String): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + public final fun kotlin.Int.ext(): kotlin.Unit + + public 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 + } + } + } + + public final class C3 { + public constructor C3() + 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 + + public companion object K : a.Base, a.BaseI { + private constructor K() + public final val own: kotlin.String = "" + public final override /*1*/ /*fake_override*/ val p: kotlin.Int + public final override /*1*/ /*fake_override*/ val kotlin.Int.ext: kotlin.Int + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun f(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun fromI(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun g(/*0*/ t: T): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun genericFromI(/*0*/ t: kotlin.Int): kotlin.Int + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String + } + } +} + +package b { + public fun testErroneusAllUnderImportFromObject(): kotlin.Unit +} + +package c { + public fun t(/*0*/ t: T): T + public fun testImportFromObjectByName(): kotlin.Unit +} + +package d { + public fun testFunImportedFromObjectHasNoDispatchReceiver(/*0*/ l: a.C2.S): kotlin.Unit +} + +package e { + public fun testMembersFromSupertypes(): kotlin.Unit +} diff --git a/compiler/testData/diagnostics/tests/imports/ImportFromObject.kt b/compiler/testData/diagnostics/tests/imports/ImportFromObject.kt index 0898d097819..7c438b4abfa 100644 --- a/compiler/testData/diagnostics/tests/imports/ImportFromObject.kt +++ b/compiler/testData/diagnostics/tests/imports/ImportFromObject.kt @@ -8,13 +8,125 @@ object O { fun bar() {} } + +object S { + + val prop: String = "" + + fun o(s: String) = Unit + fun o(i: Int) = Unit + + fun Int.ext() = Unit + var String.ext: Int + get() = 3 + set(i) { + } + + fun A(c: Int) = A() + + class A() + + fun genericFun(t: T, t2: T): T = t +} + +open class Base { + fun f() { + } + + fun g(t: T) { + } + + val p = 1 + val Int.ext: Int + get() = 4 +} + +interface BaseI { + fun fromI(): Int = 3 + + fun genericFromI(t: T) = t +} + +object K: Base(), BaseI { + val own: String = "" +} + // FILE: b.kt package b -import a.O.* +import a.O.* -fun test() { +fun testErroneusAllUnderImportFromObject() { A() B bar() +} + +// FILE: c.kt +package c + +import a.S.prop +import a.S.o +import a.S.ext +import a.S.A +import a.S.genericFun +import a.S.ext as extRenamed + +fun testImportFromObjectByName() { + prop + o("a") + o(3) + 3.ext() + "".ext = 3 + val c: Int = "".ext + + 3.extRenamed() + "".extRenamed = 3 + val c2: Int = "".extRenamed + + A() + A(3) + + val a: Int = genericFun(3, 3) + val s: String = genericFun("A", "b") + val b: Boolean = genericFun(true, false) +} + +fun t(t: T): T { + return genericFun(t, t) +} + +// FILE: d.kt +package d + +import a.S.prop as renamed + +fun testFunImportedFromObjectHasNoDispatchReceiver(l: a.S) { + l.renamed + l.prop + renamed +} + +// FILE: e.kt + +package e + +import a.K.f +import a.K.g +import a.K.p +import a.K.own +import a.K.fromI +import a.K.genericFromI +import a.K.ext + +fun testMembersFromSupertypes() { + f() + g("") + p + fromI() + + genericFromI(3) + genericFromI("a") + + own } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/imports/ImportFromObject.txt b/compiler/testData/diagnostics/tests/imports/ImportFromObject.txt index 2a6828ead49..9de40b5bf4e 100644 --- a/compiler/testData/diagnostics/tests/imports/ImportFromObject.txt +++ b/compiler/testData/diagnostics/tests/imports/ImportFromObject.txt @@ -2,6 +2,39 @@ package package a { + public open class Base { + public constructor Base() + public final val p: kotlin.Int = 1 + public final val kotlin.Int.ext: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun f(): kotlin.Unit + public final fun g(/*0*/ t: T): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public interface BaseI { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun fromI(): kotlin.Int + public open fun genericFromI(/*0*/ t: T): T + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public object K : a.Base, a.BaseI { + private constructor K() + public final val own: kotlin.String = "" + public final override /*1*/ /*fake_override*/ val p: kotlin.Int + public final override /*1*/ /*fake_override*/ val kotlin.Int.ext: kotlin.Int + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun f(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun fromI(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun g(/*0*/ t: T): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun genericFromI(/*0*/ t: kotlin.Int): kotlin.Int + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String + } + public object O { private constructor O() public final fun bar(): kotlin.Unit @@ -23,8 +56,42 @@ package a { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } } + + public object S { + private constructor S() + public final val prop: kotlin.String = "" + public final var kotlin.String.ext: kotlin.Int + public final fun A(/*0*/ c: kotlin.Int): a.S.A + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun genericFun(/*0*/ t: T, /*1*/ t2: T): T + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final fun o(/*0*/ i: kotlin.Int): kotlin.Unit + public final fun o(/*0*/ s: kotlin.String): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + public final fun kotlin.Int.ext(): kotlin.Unit + + public 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 + } + } } package b { - public fun test(): kotlin.Unit + public fun testErroneusAllUnderImportFromObject(): kotlin.Unit +} + +package c { + public fun t(/*0*/ t: T): T + public fun testImportFromObjectByName(): kotlin.Unit +} + +package d { + public fun testFunImportedFromObjectHasNoDispatchReceiver(/*0*/ l: a.S): kotlin.Unit +} + +package e { + public fun testMembersFromSupertypes(): kotlin.Unit } diff --git a/compiler/testData/diagnostics/tests/imports/Imports.kt b/compiler/testData/diagnostics/tests/imports/Imports.kt index 2621129e193..5471b1dc1b3 100644 --- a/compiler/testData/diagnostics/tests/imports/Imports.kt +++ b/compiler/testData/diagnostics/tests/imports/Imports.kt @@ -5,12 +5,12 @@ import b.B //class import b.foo //function import b.ext //extension function import b.value //property -import b.C.Companion.bar //function from companion object -import b.C.Companion.cValue //property from companion object +import b.C.Companion.bar //function from companion object +import b.C.Companion.cValue //property from companion object import b.constant.fff //function from val import b.constant.dValue //property from val import b.constant -import b.E.Companion.f //val from companion object +import b.E.Companion.f //val from companion object import smth.illegal import b.C.smth.illegal import b.bar.smth @@ -22,14 +22,14 @@ fun test(arg: B) { foo(value) arg.ext() - bar() - foo(cValue) + bar() + foo(cValue) fff(dValue) constant.fff(constant.dValue) - f.f() + f.f() } // FILE:b.kt @@ -72,7 +72,7 @@ fun bar() {} //FILE:c.kt package c -import c.C.* +import c.C.* object C { fun f() { diff --git a/compiler/testData/diagnostics/tests/imports/StarImportFromObject.kt b/compiler/testData/diagnostics/tests/imports/StarImportFromObject.kt index b8dc3285596..2a657b3f3aa 100644 --- a/compiler/testData/diagnostics/tests/imports/StarImportFromObject.kt +++ b/compiler/testData/diagnostics/tests/imports/StarImportFromObject.kt @@ -2,21 +2,21 @@ package a import a.A.* import a.A.C -import a.A.C.* -import a.A.D.* -import a.A.C.* +import a.A.C.* +import a.A.D.* +import a.A.C.* import a.A.C.G -import a.A.E.J.* -import a.A.CO.* +import a.A.E.J.* +import a.A.CO.* import a.A.CO import a.B.C.* -import a.B.C.A.* -import a.B.C.D.* +import a.B.C.A.* +import a.B.C.D.* import a.E.* import a.E.E1 -import a.E.E2.* +import a.E.E2.* class A { object C { diff --git a/compiler/testData/diagnostics/tests/imports/WrongImport.kt b/compiler/testData/diagnostics/tests/imports/WrongImport.kt index de9b830ce3b..6124b2f935a 100644 --- a/compiler/testData/diagnostics/tests/imports/WrongImport.kt +++ b/compiler/testData/diagnostics/tests/imports/WrongImport.kt @@ -61,9 +61,9 @@ import a.B.foo.barbar import a.B.bar.foo -import a.C.foo +import a.C.foo import a.C.foo.bar -import a.C.bar +import a.C.bar import a.C.bar.foo import a.C.Nested @@ -72,7 +72,7 @@ import a.D.foo.barbar import a.D.bar.foo -import a.D.Companion.foo +import a.D.Companion.foo import a.D.Companion.foo.bar -import a.D.Companion.bar +import a.D.Companion.bar import a.D.Companion.bar.foo \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/scopes/kt900-1.kt b/compiler/testData/diagnostics/tests/scopes/kt900-1.kt index ca2f36218eb..98641ea444c 100644 --- a/compiler/testData/diagnostics/tests/scopes/kt900-1.kt +++ b/compiler/testData/diagnostics/tests/scopes/kt900-1.kt @@ -2,7 +2,7 @@ package c import c.A.Companion.B -import c.M.* +import c.M.* fun foo() { val b: B = B() diff --git a/compiler/testData/diagnostics/tests/scopes/kt900-2.kt b/compiler/testData/diagnostics/tests/scopes/kt900-2.kt index c10844c7963..c89932677b3 100644 --- a/compiler/testData/diagnostics/tests/scopes/kt900-2.kt +++ b/compiler/testData/diagnostics/tests/scopes/kt900-2.kt @@ -2,9 +2,9 @@ package d //import from objects before properties resolve -import d.A.* +import d.A.* import d.M.R -import d.M.R.bar +import d.M.R.bar import d.M.T import d.M.Y @@ -12,7 +12,7 @@ var r: T = T() val y: T = Y fun f() { - bar() + bar() R.bar() B.foo() } diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index c809b13629b..d60d2dcf794 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -6627,6 +6627,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("ImportFromCompanionObject.kt") + public void testImportFromCompanionObject() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/ImportFromCompanionObject.kt"); + doTest(fileName); + } + @TestMetadata("ImportFromCurrentWithDifferentName.kt") public void testImportFromCurrentWithDifferentName() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/ImportFromCurrentWithDifferentName.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java index 060be214ebe..4d01644f344 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -5697,6 +5697,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/useAnonymousObjectAsIterator.kt"); doTest(fileName); } + + @TestMetadata("useImportedMember.kt") + public void testUseImportedMember() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/useImportedMember.kt"); + doTest(fileName); + } + + @TestMetadata("useImportedMemberFromCompanion.kt") + public void testUseImportedMemberFromCompanion() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/useImportedMemberFromCompanion.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/box/operatorConventions") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index a566ebbe515..2f47ef79962 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -2473,6 +2473,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode doTestWithStdlib(fileName); } + @TestMetadata("importStaticMemberFromObject.kt") + public void testImportStaticMemberFromObject() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformStatic/importStaticMemberFromObject.kt"); + doTestWithStdlib(fileName); + } + @TestMetadata("inline.kt") public void testInline() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformStatic/inline.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/FunctionDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/FunctionDescriptor.java index fcaed1b4889..605a0aa52ae 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/FunctionDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/FunctionDescriptor.java @@ -30,6 +30,7 @@ public interface FunctionDescriptor extends CallableMemberDescriptor { @Override FunctionDescriptor getOriginal(); + @NotNull @Override FunctionDescriptor substitute(@NotNull TypeSubstitutor substitutor);