Record reference to class object directly

not to containing class descriptor
This commit is contained in:
Svetlana Isakova
2014-08-02 15:52:55 +04:00
parent 7f33ad90a6
commit 6f4c152f53
15 changed files with 105 additions and 61 deletions
@@ -1698,10 +1698,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
} }
} }
//if (descriptor instanceof VariableAsFunctionDescriptor) {
// descriptor = ((VariableAsFunctionDescriptor) descriptor).getVariableDescriptor();
//}
assert descriptor != null : "Couldn't find descriptor for '" + expression.getText() + "'"; assert descriptor != null : "Couldn't find descriptor for '" + expression.getText() + "'";
descriptor = descriptor.getOriginal(); descriptor = descriptor.getOriginal();
@@ -1738,7 +1734,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
if (descriptor instanceof ClassDescriptor) { if (descriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; ClassDescriptor classDescriptor = (ClassDescriptor) descriptor;
if (classDescriptor.getKind() == ClassKind.OBJECT) { if (classDescriptor.getKind() == ClassKind.OBJECT || classDescriptor.getKind() == ClassKind.CLASS_OBJECT) {
return StackValue.singleton(classDescriptor, typeMapper); return StackValue.singleton(classDescriptor, typeMapper);
} }
if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY) { if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY) {
@@ -28,7 +28,6 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils
import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.jet.lang.psi.JetExpression import org.jetbrains.jet.lang.psi.JetExpression
public fun JetReturnExpression.getTargetFunctionDescriptor(context: BindingContext): FunctionDescriptor? { public fun JetReturnExpression.getTargetFunctionDescriptor(context: BindingContext): FunctionDescriptor? {
val targetLabel = getTargetLabel() val targetLabel = getTargetLabel()
if (targetLabel != null) return context[LABEL_TARGET, targetLabel]?.let { context[FUNCTION, it] } if (targetLabel != null) return context[LABEL_TARGET, targetLabel]?.let { context[FUNCTION, it] }
@@ -30,6 +30,7 @@ import org.jetbrains.jet.lang.types.JetType;
import java.util.*; import java.util.*;
import static org.jetbrains.jet.lang.resolve.LibrarySourceHacks.filterOutMembersFromLibrarySource; import static org.jetbrains.jet.lang.resolve.LibrarySourceHacks.filterOutMembersFromLibrarySource;
import static org.jetbrains.jet.lang.resolve.descriptorUtil.DescriptorUtilPackage.getClassObjectReferenceTarget;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class CallableDescriptorCollectors<D extends CallableDescriptor> implements Iterable<CallableDescriptorCollector<D>> { public class CallableDescriptorCollectors<D extends CallableDescriptor> implements Iterable<CallableDescriptorCollector<D>> {
@@ -37,6 +37,7 @@ import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor
import org.jetbrains.jet.lang.descriptors.impl.PackageFragmentDescriptorImpl import org.jetbrains.jet.lang.descriptors.impl.PackageFragmentDescriptorImpl
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext
import org.jetbrains.jet.lang.psi.psiUtil.getTopmostParentQualifiedExpressionForSelector import org.jetbrains.jet.lang.psi.psiUtil.getTopmostParentQualifiedExpressionForSelector
import org.jetbrains.jet.lang.resolve.descriptorUtil.getClassObjectReferenceTarget
public class QualifierReceiver( public class QualifierReceiver(
val expression: JetSimpleNameExpression, val expression: JetSimpleNameExpression,
@@ -150,6 +151,13 @@ private fun QualifierReceiver.resolveReferenceTarget(selector: DeclarationDescri
return packageView return packageView
} }
if (classifier != null && containingDeclaration is ClassDescriptor && classifier == containingDeclaration) {
return classifier
}
if (classifier is ClassDescriptor && classifier.getClassObjectDescriptor() != null) {
return classifier.getClassObjectReferenceTarget()
}
return descriptor return descriptor
} }
@@ -3,6 +3,7 @@ package foo
fun test() { fun test() {
A.d A.d
A.<!INVISIBLE_MEMBER!>f<!> A.<!INVISIBLE_MEMBER!>f<!>
<!INVISIBLE_MEMBER!>CCC<!>
<!INVISIBLE_MEMBER!>CCC<!>.<!INVISIBLE_MEMBER!>classObjectVar<!> <!INVISIBLE_MEMBER!>CCC<!>.<!INVISIBLE_MEMBER!>classObjectVar<!>
} }
@@ -1,7 +1,7 @@
package Jet86 package Jet86
~A~class A { class A {
class object { class ~A~object {
~A.x~val x = 1 ~A.x~val x = 1
} }
} }
@@ -9,7 +9,7 @@ fun test() = <caret>A(1)
Resolved call: Resolved call:
Resulting descriptor: class A Resulting descriptor: class object
Explicit receiver kind = NO_EXPLICIT_RECEIVER Explicit receiver kind = NO_EXPLICIT_RECEIVER
This object = NO_RECEIVER This object = NO_RECEIVER
@@ -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)
@@ -79,27 +79,29 @@ public class JetSourceNavigationHelper {
@Nullable @Nullable
public static JetClassOrObject getSourceClassOrObject(@NotNull JetClassOrObject decompiledClassOrObject) { public static JetClassOrObject getSourceClassOrObject(@NotNull JetClassOrObject decompiledClassOrObject) {
if (decompiledClassOrObject instanceof JetObjectDeclaration && decompiledClassOrObject.getParent() instanceof JetClassObject) { if (decompiledClassOrObject instanceof JetObjectDeclaration && decompiledClassOrObject.getParent() instanceof JetClassObject) {
// class object case return getSourceClassObject((JetClassObject) decompiledClassOrObject.getParent());
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 getSourceForNamedClassOrObject(decompiledClassOrObject); 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 @NotNull
private static GlobalSearchScope createLibrarySourcesScope(@NotNull JetNamedDeclaration decompiledDeclaration) { private static GlobalSearchScope createLibrarySourcesScope(@NotNull JetNamedDeclaration decompiledDeclaration) {
JetFile containingFile = decompiledDeclaration.getContainingJetFile(); JetFile containingFile = decompiledDeclaration.getContainingJetFile();
@@ -448,6 +450,11 @@ public class JetSourceNavigationHelper {
return getSourceClassOrObject(declaration); return getSourceClassOrObject(declaration);
} }
@Override
public JetDeclaration visitClassObject(@NotNull JetClassObject classObject, Void data) {
return getSourceClassObject(classObject);
}
@Override @Override
public JetDeclaration visitClass(@NotNull JetClass klass, Void data) { public JetDeclaration visitClass(@NotNull JetClass klass, Void data) {
return getSourceClassOrObject(klass); return getSourceClassOrObject(klass);
@@ -30,14 +30,22 @@ import org.jetbrains.jet.plugin.intentions.OperatorToFunctionIntention
import org.jetbrains.jet.lang.psi.JetQualifiedExpression import org.jetbrains.jet.lang.psi.JetQualifiedExpression
import org.jetbrains.jet.lang.psi.JetCallExpression import org.jetbrains.jet.lang.psi.JetCallExpression
import com.intellij.psi.util.PsiTreeUtil 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 // Navigation element of the resolved reference
// For property accessor return enclosing property // For property accessor return enclosing property
// For class object return enclosing class
public val PsiReference.unwrappedTargets: Set<PsiElement> public val PsiReference.unwrappedTargets: Set<PsiElement>
get() { get() {
fun PsiElement.adjust(): PsiElement? { fun PsiElement.adjust(): PsiElement? {
val target = unwrapped val target = unwrapped
return if (target is JetPropertyAccessor) target.getParentByType(javaClass<JetProperty>()) else target return when {
target is JetPropertyAccessor -> target.getParentByType(javaClass<JetProperty>())
target is JetObjectDeclaration && target.isClassObject() -> target.getParentByType(javaClass<JetClass>())
else -> target
}
} }
return when (this) { return when (this) {
@@ -26,7 +26,6 @@ import org.jetbrains.jet.lang.psi.psiUtil.*
import org.jetbrains.jet.lang.resolve.BindingContext import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
import org.jetbrains.jet.plugin.JetBundle import org.jetbrains.jet.plugin.JetBundle
import org.jetbrains.jet.lang.resolve.DescriptorUtils
import com.intellij.psi.PsiPackage import com.intellij.psi.PsiPackage
import org.jetbrains.jet.lexer.JetTokens import org.jetbrains.jet.lexer.JetTokens
import org.jetbrains.jet.plugin.references.JetArrayAccessReference import org.jetbrains.jet.plugin.references.JetArrayAccessReference
@@ -202,11 +201,10 @@ public object JetUsageTypeProvider : UsageTypeProviderEx {
val descriptor = context[BindingContext.REFERENCE_TARGET, refExpr] val descriptor = context[BindingContext.REFERENCE_TARGET, refExpr]
return when (descriptor) { 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) // Treat object accesses as variables to simulate the old behaviour (when variables were created for objects)
getVariableUsageType() ClassKind.OBJECT, ClassKind.ENUM_ENTRY -> getVariableUsageType()
} else { else -> getClassUsageType()
getClassUsageType()
} }
is PackageViewDescriptor -> { is PackageViewDescriptor -> {
if (refExpr.getReference()?.resolve() is PsiPackage) getPackageUsageType() else getClassUsageType() if (refExpr.getReference()?.resolve() is PsiPackage) getPackageUsageType() else getClassUsageType()
@@ -28,18 +28,18 @@ import org.jetbrains.jet.lang.psi.psiUtil.getReceiverExpression
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.jet.lang.types.JetType 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? public val DeclarationDescriptor.importableFqName: FqName?
get() { get() {
if (this is ConstructorDescriptor) return getContainingDeclaration().importableFqName val mayBeUnsafe = DescriptorUtils.getFqName(getImportableDescriptor())
val mayBeUnsafe = DescriptorUtils.getFqName(this) return if (mayBeUnsafe.isSafe()) mayBeUnsafe.toSafe() else null
return if (mayBeUnsafe.isSafe()) {
mayBeUnsafe.toSafe()
}
else {
null
}
} }
public val DeclarationDescriptor.importableFqNameSafe: FqName
get() = DescriptorUtils.getFqNameSafe(getImportableDescriptor())
public fun DeclarationDescriptor.canBeReferencedViaImport(): Boolean { public fun DeclarationDescriptor.canBeReferencedViaImport(): Boolean {
if (this is PackageViewDescriptor || DescriptorUtils.isTopLevelDeclaration(this)) { if (this is PackageViewDescriptor || DescriptorUtils.isTopLevelDeclaration(this)) {
return true return true
@@ -37,7 +37,6 @@ import org.jetbrains.jet.lang.cfg.Label
import org.jetbrains.jet.plugin.refactoring.JetNameValidatorImpl import org.jetbrains.jet.plugin.refactoring.JetNameValidatorImpl
import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil
import org.jetbrains.jet.plugin.imports.canBeReferencedViaImport import org.jetbrains.jet.plugin.imports.canBeReferencedViaImport
import org.jetbrains.jet.lang.resolve.DescriptorUtils
import com.intellij.psi.PsiNamedElement import com.intellij.psi.PsiNamedElement
import org.jetbrains.jet.lang.descriptors.impl.LocalVariableDescriptor import org.jetbrains.jet.lang.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.jet.utils.DFS 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.resolve.bindingContextUtil.isUsedAsStatement
import org.jetbrains.jet.lang.psi.psiUtil.isAncestor import org.jetbrains.jet.lang.psi.psiUtil.isAncestor
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils
import org.jetbrains.jet.lang.psi.psiUtil.isFunctionLiteralOutsideParentheses import org.jetbrains.jet.plugin.imports.importableFqNameSafe
import org.jetbrains.jet.plugin.util.psiModificationUtil.moveInsideParenthesesAndReplaceWith
private val DEFAULT_FUNCTION_NAME = "myFun" private val DEFAULT_FUNCTION_NAME = "myFun"
private val DEFAULT_RETURN_TYPE = KotlinBuiltIns.getInstance().getUnitType() private val DEFAULT_RETURN_TYPE = KotlinBuiltIns.getInstance().getUnitType()
@@ -476,8 +474,7 @@ private fun ExtractionData.inferParametersInfo(
info.typeParameters, info.nonDenotableTypes, false info.typeParameters, info.nonDenotableTypes, false
)) continue )) continue
val replacingDescriptor = (originalDescriptor as? ConstructorDescriptor)?.getContainingDeclaration() ?: originalDescriptor info.replacementMap[refInfo.offsetInBody] = FqNameReplacement(originalDescriptor.importableFqNameSafe)
info.replacementMap[refInfo.offsetInBody] = FqNameReplacement(DescriptorUtils.getFqNameSafe(replacingDescriptor))
} }
else { else {
val extractThis = hasThisReceiver || thisExpr != null val extractThis = hasThisReceiver || thisExpr != null
@@ -5,6 +5,5 @@ fun foo() {
} }
// main.kt // main.kt
//public class <1>WithInnerAndObject { // class <1>object {
// class object {
// fun <2>foo() { // fun <2>foo() {
@@ -26,6 +26,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.reflect.ReflectionTypes; import org.jetbrains.jet.lang.reflect.ReflectionTypes;
import org.jetbrains.jet.lang.resolve.BindingContext; 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.jet.lang.resolve.name.FqName;
import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.config.EcmaVersion;
import org.jetbrains.k2js.config.LibrarySourcesConfig; import org.jetbrains.k2js.config.LibrarySourcesConfig;
@@ -36,6 +37,7 @@ import org.jetbrains.k2js.translate.utils.JsAstUtils;
import java.util.Map; 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.jet.lang.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
import static org.jetbrains.k2js.translate.utils.AnnotationsUtils.*; import static org.jetbrains.k2js.translate.utils.AnnotationsUtils.*;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.*; import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.*;
@@ -234,15 +236,14 @@ public final class StaticContext {
return scope.declareFreshName(getSuggestedName(descriptor)); return scope.declareFreshName(getSuggestedName(descriptor));
} }
}; };
Rule<JsName> constructorHasTheSameNameAsTheClass = new Rule<JsName>() { Rule<JsName> constructorOrClassObjectHasTheSameNameAsTheClass = new Rule<JsName>() {
@Override @Override
public JsName apply(@NotNull DeclarationDescriptor descriptor) { public JsName apply(@NotNull DeclarationDescriptor descriptor) {
if (!(descriptor instanceof ConstructorDescriptor)) { if (descriptor instanceof ConstructorDescriptor || (DescriptorUtils.isClassObject(descriptor))) {
return null; //noinspection ConstantConditions
return getNameForDescriptor(descriptor.getContainingDeclaration());
} }
ClassDescriptor containingClass = getContainingClass(descriptor); return null;
assert containingClass != null : "Can't have constructor without a class";
return getNameForDescriptor(containingClass);
} }
}; };
@@ -324,7 +325,7 @@ public final class StaticContext {
} }
}; };
addRule(namesForStandardClasses); addRule(namesForStandardClasses);
addRule(constructorHasTheSameNameAsTheClass); addRule(constructorOrClassObjectHasTheSameNameAsTheClass);
addRule(propertyOrPropertyAccessor); addRule(propertyOrPropertyAccessor);
addRule(predefinedObjectsHasUnobfuscatableNames); addRule(predefinedObjectsHasUnobfuscatableNames);
addRule(overridingDescriptorsReferToOriginalName); addRule(overridingDescriptorsReferToOriginalName);
@@ -469,15 +470,14 @@ public final class StaticContext {
return element.getContainingFile().getUserData(LibrarySourcesConfig.EXTERNAL_MODULE_NAME); return element.getContainingFile().getUserData(LibrarySourcesConfig.EXTERNAL_MODULE_NAME);
} }
}; };
Rule<JsNameRef> constructorHaveTheSameQualifierAsTheClass = new Rule<JsNameRef>() { Rule<JsNameRef> constructorOrClassObjectHasTheSameQualifierAsTheClass = new Rule<JsNameRef>() {
@Override @Override
public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) { public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) {
if (!(descriptor instanceof ConstructorDescriptor)) { if (descriptor instanceof ConstructorDescriptor || DescriptorUtils.isClassObject(descriptor)) {
return null; //noinspection ConstantConditions
return getQualifierForDescriptor(descriptor.getContainingDeclaration());
} }
ClassDescriptor containingClass = getContainingClass(descriptor); return null;
assert containingClass != null : "Can't have constructor without a class";
return getQualifierForDescriptor(containingClass);
} }
}; };
Rule<JsNameRef> libraryObjectsHaveKotlinQualifier = new Rule<JsNameRef>() { Rule<JsNameRef> libraryObjectsHaveKotlinQualifier = new Rule<JsNameRef>() {
@@ -504,7 +504,7 @@ public final class StaticContext {
}; };
addRule(libraryObjectsHaveKotlinQualifier); addRule(libraryObjectsHaveKotlinQualifier);
addRule(constructorHaveTheSameQualifierAsTheClass); addRule(constructorOrClassObjectHasTheSameQualifierAsTheClass);
addRule(standardObjectsHaveKotlinQualifier); addRule(standardObjectsHaveKotlinQualifier);
addRule(packageLevelDeclarationsHaveEnclosingPackagesNamesAsQualifier); addRule(packageLevelDeclarationsHaveEnclosingPackagesNamesAsQualifier);
addRule(nativeObjectsHaveNativePartOfFullQualifier); addRule(nativeObjectsHaveNativePartOfFullQualifier);