diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 81dfeedc91b..c7842d923ba 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1698,10 +1698,6 @@ public class ExpressionCodegen extends JetVisitor implem } } - //if (descriptor instanceof VariableAsFunctionDescriptor) { - // descriptor = ((VariableAsFunctionDescriptor) descriptor).getVariableDescriptor(); - //} - assert descriptor != null : "Couldn't find descriptor for '" + expression.getText() + "'"; descriptor = descriptor.getOriginal(); @@ -1738,7 +1734,7 @@ public class ExpressionCodegen extends JetVisitor implem if (descriptor instanceof ClassDescriptor) { ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; - if (classDescriptor.getKind() == ClassKind.OBJECT) { + if (classDescriptor.getKind() == ClassKind.OBJECT || classDescriptor.getKind() == ClassKind.CLASS_OBJECT) { return StackValue.singleton(classDescriptor, typeMapper); } if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.kt index 8026be85914..0a16cb89ef3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.kt @@ -28,7 +28,6 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor import org.jetbrains.jet.lang.psi.JetExpression - public fun JetReturnExpression.getTargetFunctionDescriptor(context: BindingContext): FunctionDescriptor? { val targetLabel = getTargetLabel() if (targetLabel != null) return context[LABEL_TARGET, targetLabel]?.let { context[FUNCTION, it] } 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 5741e7053c6..bf14134f706 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 @@ -30,6 +30,7 @@ import org.jetbrains.jet.lang.types.JetType; import java.util.*; import static org.jetbrains.jet.lang.resolve.LibrarySourceHacks.filterOutMembersFromLibrarySource; +import static org.jetbrains.jet.lang.resolve.descriptorUtil.DescriptorUtilPackage.getClassObjectReferenceTarget; @SuppressWarnings("unchecked") public class CallableDescriptorCollectors implements Iterable> { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/QualifierReceiver.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/QualifierReceiver.kt index a1c0d9e8746..869c0b51243 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/QualifierReceiver.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/QualifierReceiver.kt @@ -37,6 +37,7 @@ import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor import org.jetbrains.jet.lang.descriptors.impl.PackageFragmentDescriptorImpl import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext import org.jetbrains.jet.lang.psi.psiUtil.getTopmostParentQualifiedExpressionForSelector +import org.jetbrains.jet.lang.resolve.descriptorUtil.getClassObjectReferenceTarget public class QualifierReceiver( val expression: JetSimpleNameExpression, @@ -150,6 +151,13 @@ private fun QualifierReceiver.resolveReferenceTarget(selector: DeclarationDescri return packageView } + if (classifier != null && containingDeclaration is ClassDescriptor && classifier == containingDeclaration) { + return classifier + } + if (classifier is ClassDescriptor && classifier.getClassObjectDescriptor() != null) { + return classifier.getClassObjectReferenceTarget() + } + return descriptor } diff --git a/compiler/testData/diagnostics/tests/classObjects/ClassObjectVisibility.kt b/compiler/testData/diagnostics/tests/classObjects/ClassObjectVisibility.kt index c917603712c..c139c4354f3 100644 --- a/compiler/testData/diagnostics/tests/classObjects/ClassObjectVisibility.kt +++ b/compiler/testData/diagnostics/tests/classObjects/ClassObjectVisibility.kt @@ -3,6 +3,7 @@ package foo fun test() { A.d A.f + CCC CCC.classObjectVar } diff --git a/compiler/testData/resolve/ClassObjects.resolve b/compiler/testData/resolve/ClassObjects.resolve index f7574a7e1bf..014390cdace 100644 --- a/compiler/testData/resolve/ClassObjects.resolve +++ b/compiler/testData/resolve/ClassObjects.resolve @@ -1,7 +1,7 @@ package Jet86 -~A~class A { - class object { +class A { + class ~A~object { ~A.x~val x = 1 } } diff --git a/compiler/testData/resolvedCalls/invoke/invokeOnClassObject1.txt b/compiler/testData/resolvedCalls/invoke/invokeOnClassObject1.txt index 86cd5ac5ccb..8b2fa62da73 100644 --- a/compiler/testData/resolvedCalls/invoke/invokeOnClassObject1.txt +++ b/compiler/testData/resolvedCalls/invoke/invokeOnClassObject1.txt @@ -9,7 +9,7 @@ fun test() = A(1) Resolved call: -Resulting descriptor: class A +Resulting descriptor: class object Explicit receiver kind = NO_EXPLICIT_RECEIVER This object = NO_RECEIVER diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.kt b/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.kt new file mode 100644 index 00000000000..a816626db6c --- /dev/null +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.kt @@ -0,0 +1,30 @@ +/* + * 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.descriptorUtil + +import org.jetbrains.jet.lang.descriptors.ClassDescriptor +import org.jetbrains.jet.lang.descriptors.ClassKind.ENUM_ENTRY +import org.jetbrains.jet.lang.descriptors.ClassKind.ENUM_CLASS +import org.jetbrains.jet.lang.descriptors.ClassKind.OBJECT + + +public fun ClassDescriptor.getClassObjectReferenceTarget(): ClassDescriptor { + val classObjectDescriptor = getClassObjectDescriptor() + return if (classObjectDescriptor == null || hasSyntheticClassObject()) this else classObjectDescriptor +} + +public fun ClassDescriptor.hasSyntheticClassObject(): Boolean = getKind() in setOf(ENUM_ENTRY, ENUM_CLASS, OBJECT) \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java b/idea/idea-analysis/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java index 4ca2be5fb46..39533a9d826 100644 --- a/idea/idea-analysis/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java +++ b/idea/idea-analysis/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java @@ -79,27 +79,29 @@ public class JetSourceNavigationHelper { @Nullable public static JetClassOrObject getSourceClassOrObject(@NotNull JetClassOrObject decompiledClassOrObject) { if (decompiledClassOrObject instanceof JetObjectDeclaration && decompiledClassOrObject.getParent() instanceof JetClassObject) { - // class object case - - JetClass decompiledClass = PsiTreeUtil.getParentOfType(decompiledClassOrObject, JetClass.class); - assert decompiledClass != null; - - JetClass sourceClass = (JetClass) getSourceForNamedClassOrObject(decompiledClass); - if (sourceClass == null) { - return null; - } - - if (sourceClass.hasModifier(JetTokens.ENUM_KEYWORD)) { - return sourceClass; - } - - JetClassObject classObject = sourceClass.getClassObject(); - assert classObject != null; - return classObject.getObjectDeclaration(); + return getSourceClassObject((JetClassObject) decompiledClassOrObject.getParent()); } return getSourceForNamedClassOrObject(decompiledClassOrObject); } + private static JetClassOrObject getSourceClassObject(JetClassObject decompiledClassObject) { + JetClass decompiledClass = PsiTreeUtil.getParentOfType(decompiledClassObject, JetClass.class); + assert decompiledClass != null; + + JetClass sourceClass = (JetClass) getSourceForNamedClassOrObject(decompiledClass); + if (sourceClass == null) { + return null; + } + + if (sourceClass.hasModifier(JetTokens.ENUM_KEYWORD)) { + return sourceClass; + } + + JetClassObject classObject = sourceClass.getClassObject(); + assert classObject != null; + return classObject.getObjectDeclaration(); + } + @NotNull private static GlobalSearchScope createLibrarySourcesScope(@NotNull JetNamedDeclaration decompiledDeclaration) { JetFile containingFile = decompiledDeclaration.getContainingJetFile(); @@ -448,6 +450,11 @@ public class JetSourceNavigationHelper { return getSourceClassOrObject(declaration); } + @Override + public JetDeclaration visitClassObject(@NotNull JetClassObject classObject, Void data) { + return getSourceClassObject(classObject); + } + @Override public JetDeclaration visitClass(@NotNull JetClass klass, Void data) { return getSourceClassOrObject(klass); diff --git a/idea/idea-analysis/src/org/jetbrains/jet/plugin/references/referenceUtil.kt b/idea/idea-analysis/src/org/jetbrains/jet/plugin/references/referenceUtil.kt index 48a334795e9..b94e4a7374e 100644 --- a/idea/idea-analysis/src/org/jetbrains/jet/plugin/references/referenceUtil.kt +++ b/idea/idea-analysis/src/org/jetbrains/jet/plugin/references/referenceUtil.kt @@ -30,14 +30,22 @@ import org.jetbrains.jet.plugin.intentions.OperatorToFunctionIntention import org.jetbrains.jet.lang.psi.JetQualifiedExpression import org.jetbrains.jet.lang.psi.JetCallExpression import com.intellij.psi.util.PsiTreeUtil +import org.jetbrains.jet.lang.psi.JetObjectDeclaration +import org.jetbrains.jet.lang.psi.JetClassObject +import org.jetbrains.jet.lang.psi.JetClass // Navigation element of the resolved reference // For property accessor return enclosing property +// For class object return enclosing class public val PsiReference.unwrappedTargets: Set get() { fun PsiElement.adjust(): PsiElement? { val target = unwrapped - return if (target is JetPropertyAccessor) target.getParentByType(javaClass()) else target + return when { + target is JetPropertyAccessor -> target.getParentByType(javaClass()) + target is JetObjectDeclaration && target.isClassObject() -> target.getParentByType(javaClass()) + else -> target + } } return when (this) { diff --git a/idea/src/org/jetbrains/jet/plugin/findUsages/JetUsageTypeProvider.kt b/idea/src/org/jetbrains/jet/plugin/findUsages/JetUsageTypeProvider.kt index fc0992e8c16..b177bd2a734 100644 --- a/idea/src/org/jetbrains/jet/plugin/findUsages/JetUsageTypeProvider.kt +++ b/idea/src/org/jetbrains/jet/plugin/findUsages/JetUsageTypeProvider.kt @@ -26,7 +26,6 @@ import org.jetbrains.jet.lang.psi.psiUtil.* import org.jetbrains.jet.lang.resolve.BindingContext import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache import org.jetbrains.jet.plugin.JetBundle -import org.jetbrains.jet.lang.resolve.DescriptorUtils import com.intellij.psi.PsiPackage import org.jetbrains.jet.lexer.JetTokens import org.jetbrains.jet.plugin.references.JetArrayAccessReference @@ -202,11 +201,10 @@ public object JetUsageTypeProvider : UsageTypeProviderEx { val descriptor = context[BindingContext.REFERENCE_TARGET, refExpr] return when (descriptor) { - is ClassifierDescriptor -> if (DescriptorUtils.isSingleton(descriptor)) { + is ClassifierDescriptor -> when ((descriptor as? ClassDescriptor)?.getKind()) { // Treat object accesses as variables to simulate the old behaviour (when variables were created for objects) - getVariableUsageType() - } else { - getClassUsageType() + ClassKind.OBJECT, ClassKind.ENUM_ENTRY -> getVariableUsageType() + else -> getClassUsageType() } is PackageViewDescriptor -> { if (refExpr.getReference()?.resolve() is PsiPackage) getPackageUsageType() else getClassUsageType() diff --git a/idea/src/org/jetbrains/jet/plugin/imports/ImportsUtils.kt b/idea/src/org/jetbrains/jet/plugin/imports/ImportsUtils.kt index 41e6dded681..8260232041c 100644 --- a/idea/src/org/jetbrains/jet/plugin/imports/ImportsUtils.kt +++ b/idea/src/org/jetbrains/jet/plugin/imports/ImportsUtils.kt @@ -28,18 +28,18 @@ import org.jetbrains.jet.lang.psi.psiUtil.getReceiverExpression import com.intellij.psi.PsiElement import org.jetbrains.jet.lang.types.JetType +private fun DeclarationDescriptor.getImportableDescriptor() = + if (this is ConstructorDescriptor || DescriptorUtils.isClassObject(this)) getContainingDeclaration()!! else this + public val DeclarationDescriptor.importableFqName: FqName? get() { - if (this is ConstructorDescriptor) return getContainingDeclaration().importableFqName - val mayBeUnsafe = DescriptorUtils.getFqName(this) - return if (mayBeUnsafe.isSafe()) { - mayBeUnsafe.toSafe() - } - else { - null - } + val mayBeUnsafe = DescriptorUtils.getFqName(getImportableDescriptor()) + return if (mayBeUnsafe.isSafe()) mayBeUnsafe.toSafe() else null } +public val DeclarationDescriptor.importableFqNameSafe: FqName + get() = DescriptorUtils.getFqNameSafe(getImportableDescriptor()) + public fun DeclarationDescriptor.canBeReferencedViaImport(): Boolean { if (this is PackageViewDescriptor || DescriptorUtils.isTopLevelDeclaration(this)) { return true diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/extractableAnalysisUtil.kt b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/extractableAnalysisUtil.kt index d48bcac5a2a..5b191813d6f 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/extractableAnalysisUtil.kt +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/extractableAnalysisUtil.kt @@ -37,7 +37,6 @@ import org.jetbrains.jet.lang.cfg.Label import org.jetbrains.jet.plugin.refactoring.JetNameValidatorImpl import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil import org.jetbrains.jet.plugin.imports.canBeReferencedViaImport -import org.jetbrains.jet.lang.resolve.DescriptorUtils import com.intellij.psi.PsiNamedElement import org.jetbrains.jet.lang.descriptors.impl.LocalVariableDescriptor import org.jetbrains.jet.utils.DFS @@ -61,8 +60,7 @@ import org.jetbrains.jet.lang.resolve.OverridingUtil import org.jetbrains.jet.lang.resolve.bindingContextUtil.isUsedAsStatement import org.jetbrains.jet.lang.psi.psiUtil.isAncestor import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils -import org.jetbrains.jet.lang.psi.psiUtil.isFunctionLiteralOutsideParentheses -import org.jetbrains.jet.plugin.util.psiModificationUtil.moveInsideParenthesesAndReplaceWith +import org.jetbrains.jet.plugin.imports.importableFqNameSafe private val DEFAULT_FUNCTION_NAME = "myFun" private val DEFAULT_RETURN_TYPE = KotlinBuiltIns.getInstance().getUnitType() @@ -476,8 +474,7 @@ private fun ExtractionData.inferParametersInfo( info.typeParameters, info.nonDenotableTypes, false )) continue - val replacingDescriptor = (originalDescriptor as? ConstructorDescriptor)?.getContainingDeclaration() ?: originalDescriptor - info.replacementMap[refInfo.offsetInBody] = FqNameReplacement(DescriptorUtils.getFqNameSafe(replacingDescriptor)) + info.replacementMap[refInfo.offsetInBody] = FqNameReplacement(originalDescriptor.importableFqNameSafe) } else { val extractThis = hasThisReceiver || thisExpr != null diff --git a/idea/testData/libraries/navigation/usercode/ClassObject.kt b/idea/testData/libraries/navigation/usercode/ClassObject.kt index 1a610fe8ec3..02be51a6eb1 100644 --- a/idea/testData/libraries/navigation/usercode/ClassObject.kt +++ b/idea/testData/libraries/navigation/usercode/ClassObject.kt @@ -5,6 +5,5 @@ fun foo() { } // main.kt -//public class <1>WithInnerAndObject { -// class object { +// class <1>object { // fun <2>foo() { \ No newline at end of file diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java index 2aa470d019f..50031749922 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.reflect.ReflectionTypes; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.config.LibrarySourcesConfig; @@ -36,6 +37,7 @@ import org.jetbrains.k2js.translate.utils.JsAstUtils; import java.util.Map; +import static org.jetbrains.jet.lang.descriptors.ClassKind.CLASS_OBJECT; import static org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils.descriptorToDeclaration; import static org.jetbrains.k2js.translate.utils.AnnotationsUtils.*; import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.*; @@ -234,15 +236,14 @@ public final class StaticContext { return scope.declareFreshName(getSuggestedName(descriptor)); } }; - Rule constructorHasTheSameNameAsTheClass = new Rule() { + Rule constructorOrClassObjectHasTheSameNameAsTheClass = new Rule() { @Override public JsName apply(@NotNull DeclarationDescriptor descriptor) { - if (!(descriptor instanceof ConstructorDescriptor)) { - return null; + if (descriptor instanceof ConstructorDescriptor || (DescriptorUtils.isClassObject(descriptor))) { + //noinspection ConstantConditions + return getNameForDescriptor(descriptor.getContainingDeclaration()); } - ClassDescriptor containingClass = getContainingClass(descriptor); - assert containingClass != null : "Can't have constructor without a class"; - return getNameForDescriptor(containingClass); + return null; } }; @@ -324,7 +325,7 @@ public final class StaticContext { } }; addRule(namesForStandardClasses); - addRule(constructorHasTheSameNameAsTheClass); + addRule(constructorOrClassObjectHasTheSameNameAsTheClass); addRule(propertyOrPropertyAccessor); addRule(predefinedObjectsHasUnobfuscatableNames); addRule(overridingDescriptorsReferToOriginalName); @@ -469,15 +470,14 @@ public final class StaticContext { return element.getContainingFile().getUserData(LibrarySourcesConfig.EXTERNAL_MODULE_NAME); } }; - Rule constructorHaveTheSameQualifierAsTheClass = new Rule() { + Rule constructorOrClassObjectHasTheSameQualifierAsTheClass = new Rule() { @Override public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) { - if (!(descriptor instanceof ConstructorDescriptor)) { - return null; + if (descriptor instanceof ConstructorDescriptor || DescriptorUtils.isClassObject(descriptor)) { + //noinspection ConstantConditions + return getQualifierForDescriptor(descriptor.getContainingDeclaration()); } - ClassDescriptor containingClass = getContainingClass(descriptor); - assert containingClass != null : "Can't have constructor without a class"; - return getQualifierForDescriptor(containingClass); + return null; } }; Rule libraryObjectsHaveKotlinQualifier = new Rule() { @@ -504,7 +504,7 @@ public final class StaticContext { }; addRule(libraryObjectsHaveKotlinQualifier); - addRule(constructorHaveTheSameQualifierAsTheClass); + addRule(constructorOrClassObjectHasTheSameQualifierAsTheClass); addRule(standardObjectsHaveKotlinQualifier); addRule(packageLevelDeclarationsHaveEnclosingPackagesNamesAsQualifier); addRule(nativeObjectsHaveNativePartOfFullQualifier);