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() + "'";
descriptor = descriptor.getOriginal();
@@ -1738,7 +1734,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> 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) {
@@ -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] }
@@ -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<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.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
}
@@ -3,6 +3,7 @@ package foo
fun test() {
A.d
A.<!INVISIBLE_MEMBER!>f<!>
<!INVISIBLE_MEMBER!>CCC<!>
<!INVISIBLE_MEMBER!>CCC<!>.<!INVISIBLE_MEMBER!>classObjectVar<!>
}
@@ -1,7 +1,7 @@
package Jet86
~A~class A {
class object {
class A {
class ~A~object {
~A.x~val x = 1
}
}
@@ -9,7 +9,7 @@ fun test() = <caret>A(1)
Resolved call:
Resulting descriptor: class A
Resulting descriptor: class object
Explicit receiver kind = NO_EXPLICIT_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
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);
@@ -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<PsiElement>
get() {
fun PsiElement.adjust(): PsiElement? {
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) {
@@ -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()
@@ -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
@@ -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
@@ -5,6 +5,5 @@ fun foo() {
}
// main.kt
//public class <1>WithInnerAndObject {
// class object {
// class <1>object {
// fun <2>foo() {
@@ -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<JsName> constructorHasTheSameNameAsTheClass = new Rule<JsName>() {
Rule<JsName> constructorOrClassObjectHasTheSameNameAsTheClass = new Rule<JsName>() {
@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<JsNameRef> constructorHaveTheSameQualifierAsTheClass = new Rule<JsNameRef>() {
Rule<JsNameRef> constructorOrClassObjectHasTheSameQualifierAsTheClass = new Rule<JsNameRef>() {
@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<JsNameRef> libraryObjectsHaveKotlinQualifier = new Rule<JsNameRef>() {
@@ -504,7 +504,7 @@ public final class StaticContext {
};
addRule(libraryObjectsHaveKotlinQualifier);
addRule(constructorHaveTheSameQualifierAsTheClass);
addRule(constructorOrClassObjectHasTheSameQualifierAsTheClass);
addRule(standardObjectsHaveKotlinQualifier);
addRule(packageLevelDeclarationsHaveEnclosingPackagesNamesAsQualifier);
addRule(nativeObjectsHaveNativePartOfFullQualifier);