diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 03f3588fd78..72f6561a9da 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1869,7 +1869,7 @@ public class ExpressionCodegen extends JetVisitor implem DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); boolean isBackingFieldInAnotherClass = AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor); - boolean isStatic = containingDeclaration instanceof PackageFragmentDescriptor; + boolean isStatic = DescriptorUtils.isStaticDeclaration(propertyDescriptor); boolean isSuper = superExpression != null; boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java index 775124279a8..f289b5c8b23 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java @@ -443,7 +443,9 @@ public class JetTypeMapper { thisClass = mapClass(currentOwner); } else { - if (isAccessor(functionDescriptor) || isPlatformStaticInObject(functionDescriptor)) { + if (isStaticDeclaration(functionDescriptor) || + isAccessor(functionDescriptor) || + isPlatformStaticInObject(functionDescriptor)) { invokeOpcode = INVOKESTATIC; } else if (isInterface) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt index e6448f65644..10c57f24702 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt @@ -47,7 +47,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet if (descriptor.isVar()) { return false } - if (DescriptorUtils.isClassObject(descriptor.getContainingDeclaration()) || DescriptorUtils.isTopLevelDeclaration(descriptor)) { + if (DescriptorUtils.isClassObject(descriptor.getContainingDeclaration()) || DescriptorUtils.isStaticDeclaration(descriptor)) { val returnType = descriptor.getType() return KotlinBuiltIns.getInstance().isPrimitiveType(returnType) || KotlinBuiltIns.getInstance().getStringType() == returnType } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/Importer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/Importer.java index 5139293fb84..eb61abb0d21 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/Importer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/Importer.java @@ -86,12 +86,13 @@ public interface Importer { } protected void importAllUnderDeclaration(@NotNull DeclarationDescriptor descriptor, @NotNull PlatformToKotlinClassMap platformToKotlinClassMap) { - List scopesToImport = new ArrayList(2); + List scopesToImport = new ArrayList(3); if (descriptor instanceof PackageViewDescriptor) { scopesToImport.add(((PackageViewDescriptor) descriptor).getMemberScope()); } else if (descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getKind() != ClassKind.OBJECT) { ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; + scopesToImport.add(classDescriptor.getStaticScope()); scopesToImport.add(classDescriptor.getUnsubstitutedInnerClassesScope()); ClassDescriptor classObjectDescriptor = classDescriptor.getClassObjectDescriptor(); if (classObjectDescriptor != null) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/QualifiedExpressionResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/QualifiedExpressionResolver.java index eb684e95213..c01092a5067 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/QualifiedExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/QualifiedExpressionResolver.java @@ -21,6 +21,7 @@ import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import kotlin.jvm.KotlinSignature; +import org.jetbrains.annotations.Mutable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; @@ -232,35 +233,42 @@ public class QualifiedExpressionResolver { @NotNull LookupMode lookupMode, boolean storeResult ) { - Set results = Sets.newHashSet(); + Set results = Sets.newLinkedHashSet(); for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) { if (declarationDescriptor instanceof PackageViewDescriptor) { addResult(results, lookupSimpleNameReference(selector, ((PackageViewDescriptor) declarationDescriptor).getMemberScope(), lookupMode, true)); } if (declarationDescriptor instanceof ClassDescriptor) { - addResult(results, lookupSimpleNameReference(selector, getAppropriateScope((ClassDescriptor) declarationDescriptor, - lookupMode), lookupMode, false)); - ClassDescriptor classObjectDescriptor = ((ClassDescriptor) declarationDescriptor).getClassObjectDescriptor(); - if (classObjectDescriptor != null) { - addResult(results, lookupSimpleNameReference(selector, getAppropriateScope(classObjectDescriptor, lookupMode), - lookupMode, false)); - } + addResultsForClass(results, selector, lookupMode, (ClassDescriptor) declarationDescriptor); } } return filterAndStoreResolutionResult(results, selector, trace, scopeToCheckVisibility, lookupMode, storeResult); } - @NotNull - private static JetScope getAppropriateScope(@NotNull ClassDescriptor classDescriptor, @NotNull LookupMode lookupMode) { - return lookupMode == LookupMode.ONLY_CLASSES - ? classDescriptor.getUnsubstitutedInnerClassesScope() - : classDescriptor.getDefaultType().getMemberScope(); + private static void addResultsForClass( + @NotNull @Mutable Set results, + @NotNull JetSimpleNameExpression selector, + @NotNull LookupMode lookupMode, + @NotNull ClassDescriptor descriptor + ) { + JetScope scope = lookupMode == LookupMode.ONLY_CLASSES + ? descriptor.getUnsubstitutedInnerClassesScope() + : descriptor.getDefaultType().getMemberScope(); + addResult(results, lookupSimpleNameReference(selector, scope, lookupMode, false)); + + addResult(results, lookupSimpleNameReference(selector, descriptor.getStaticScope(), lookupMode, true)); + + ClassDescriptor classObject = descriptor.getClassObjectDescriptor(); + if (classObject != null) { + addResultsForClass(results, selector, lookupMode, classObject); + } } private static void addResult(@NotNull Set results, @NotNull LookupResult result) { - if (result == LookupResult.EMPTY) return; - results.add((SuccessfulLookupResult) result); + if (result != LookupResult.EMPTY) { + results.add((SuccessfulLookupResult) result); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/Qualifier.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/Qualifier.kt index 7d9053b4b25..198bc316a39 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/Qualifier.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/Qualifier.kt @@ -16,13 +16,10 @@ package org.jetbrains.jet.lang.resolve.scopes.receivers +import org.jetbrains.jet.lang.descriptors.* import org.jetbrains.jet.lang.types.JetType -import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor import org.jetbrains.jet.lang.resolve.scopes.JetScope -import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor import org.jetbrains.jet.lang.psi.JetSimpleNameExpression -import org.jetbrains.jet.lang.descriptors.ClassDescriptor -import org.jetbrains.jet.lang.descriptors.ClassKind import org.jetbrains.jet.lang.resolve.DescriptorUtils import org.jetbrains.jet.lang.resolve.DescriptorUtils.getFqName import org.jetbrains.jet.lang.resolve.name.Name @@ -30,17 +27,13 @@ import org.jetbrains.jet.lang.resolve.scopes.ChainedScope import java.util.ArrayList import org.jetbrains.jet.utils.addIfNotNull import org.jetbrains.jet.lang.resolve.BindingContext.* -import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor import org.jetbrains.jet.lang.diagnostics.Errors.* -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor -import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext import org.jetbrains.jet.lang.psi.psiUtil.getTopmostParentQualifiedExpressionForSelector import org.jetbrains.jet.lang.resolve.descriptorUtil.getClassObjectReferenceTarget import org.jetbrains.jet.lang.psi.JetExpression import org.jetbrains.jet.lang.resolve.bindingContextUtil.recordScopeAndDataFlowInfo import kotlin.properties.Delegates -import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor public trait Qualifier { @@ -81,18 +74,22 @@ class QualifierReceiver ( classifier?.getClassObjectType()?.let { ExpressionReceiver(referenceExpression, it) } ?: ReceiverValue.NO_RECEIVER fun getNestedClassesAndPackageMembersScope(): JetScope { - val scopes = ArrayList(3) - - val classObjectDescriptor = (classifier as? ClassDescriptor)?.getClassObjectDescriptor() - if (classObjectDescriptor != null) { - // non-static members are resolved through class object receiver - scopes.add(DescriptorUtils.getStaticNestedClassesScope(classObjectDescriptor)) - } + val scopes = ArrayList(4) scopes.addIfNotNull(packageView?.getMemberScope()) - if (classifier is ClassDescriptor && classifier.getKind() != ClassKind.ENUM_ENTRY) { - scopes.add(DescriptorUtils.getStaticNestedClassesScope(classifier)) + if (classifier is ClassDescriptor) { + scopes.add(classifier.getStaticScope()) + + val classObjectDescriptor = classifier.getClassObjectDescriptor() + if (classObjectDescriptor != null) { + // non-static members are resolved through class object receiver + scopes.add(DescriptorUtils.getStaticNestedClassesScope(classObjectDescriptor)) + } + + if (classifier.getKind() != ClassKind.ENUM_ENTRY) { + scopes.add(DescriptorUtils.getStaticNestedClassesScope(classifier)) + } } return ChainedScope(descriptor, "Static scope for " + name + " as package or class or object", *scopes.copyToArray()) diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaClassMemberScope.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaClassMemberScope.kt index d03b26c200d..30705b74323 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaClassMemberScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaClassMemberScope.kt @@ -68,6 +68,7 @@ public class LazyJavaClassMemberScope( emptyOrSingletonList(createDefaultConstructor()) } } + override fun computeNonDeclaredFunctions(result: MutableCollection, name: Name) { val functionsFromSupertypes = getFunctionsFromSupertypes(name, getContainingDeclaration()) result.addAll(DescriptorResolverUtils.resolveOverrides(name, functionsFromSupertypes, result, getContainingDeclaration(), c.errorReporter)) @@ -237,6 +238,9 @@ public class LazyJavaClassMemberScope( } } + override fun getExpectedThisObject(): ReceiverParameterDescriptor? = + DescriptorUtils.getExpectedThisObjectIfNeeded(getContainingDeclaration()) + override fun getClassifier(name: Name): ClassifierDescriptor? = nestedClasses(name) override fun getAllClassNames(): Collection = nestedClassIndex().keySet() + enumEntryIndex().keySet() diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt index 4c270e2c84d..8eef948db5b 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt @@ -43,7 +43,6 @@ import java.util.LinkedHashSet import org.jetbrains.jet.lang.types.JetType import org.jetbrains.jet.lang.resolve.java.descriptor.JavaPropertyDescriptor import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorImpl -import java.util.Collections import org.jetbrains.jet.lang.resolve.java.resolver.ExternalSignatureResolver import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils import org.jetbrains.jet.utils.* @@ -58,7 +57,7 @@ public abstract class LazyJavaMemberScope( // when computing getAllPackageNames() we ask the JavaPsiFacade for all subpackages of foo // it, in turn, asks JavaElementFinder for subpackages of Kotlin package foo, which calls getAllPackageNames() recursively // when on recursive call we return an empty collection, recursion collapses gracefully - Collections.emptyList() + listOf() ) override fun getContainingDeclaration() = _containingDeclaration @@ -71,6 +70,8 @@ public abstract class LazyJavaMemberScope( protected abstract fun computeNonDeclaredFunctions(result: MutableCollection, name: Name) + protected abstract fun getExpectedThisObject(): ReceiverParameterDescriptor? + private val _functions = c.storageManager.createMemoizedFunction { (name: Name): Collection -> @@ -138,7 +139,7 @@ public abstract class LazyJavaMemberScope( functionDescriptorImpl.initialize( effectiveSignature.getReceiverType(), - DescriptorUtils.getExpectedThisObjectIfNeeded(_containingDeclaration), + getExpectedThisObject(), effectiveSignature.getTypeParameters(), effectiveSignature.getValueParameters(), effectiveSignature.getReturnType(), @@ -256,7 +257,7 @@ public abstract class LazyJavaMemberScope( c.externalSignatureResolver.reportSignatureErrors(propertyDescriptor, signatureErrors) } - propertyDescriptor.setType(effectiveSignature.getReturnType(), Collections.emptyList(), DescriptorUtils.getExpectedThisObjectIfNeeded(getContainingDeclaration()), null : JetType?) + propertyDescriptor.setType(effectiveSignature.getReturnType(), listOf(), getExpectedThisObject(), null : JetType?) if (DescriptorUtils.shouldRecordInitializerForProperty(propertyDescriptor, propertyDescriptor.getType())) { propertyDescriptor.setCompileTimeInitializer( diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaStaticScope.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaStaticScope.kt index bb103ac974d..279465d0c56 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaStaticScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaStaticScope.kt @@ -44,6 +44,8 @@ public abstract class LazyJavaStaticScope( protected val fqName: FqName = DescriptorUtils.getFqName(descriptor).toSafe() + override fun getExpectedThisObject() = null + protected fun computeMemberIndexForSamConstructors(delegate: MemberIndex): MemberIndex = object : MemberIndex by delegate { override fun getAllMethodNames(): Collection { val jClass = c.findClassInJava(fqName).jClass diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index e07f12a7f83..1e06e1fe9fd 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -107,10 +107,6 @@ public class DescriptorUtils { return getFqName(containingDeclaration).child(descriptor.getName()); } - public static boolean isTopLevelDeclaration(@NotNull DeclarationDescriptor descriptor) { - return descriptor.getContainingDeclaration() instanceof PackageFragmentDescriptor; - } - @Nullable private static DeclarationDescriptor getContainingDeclarationSkippingClassObjects(@NotNull DeclarationDescriptor descriptor) { DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); @@ -127,6 +123,22 @@ public class DescriptorUtils { return getFqNameFromTopLevelClass(containingDeclaration).child(name); } + public static boolean isTopLevelDeclaration(@NotNull DeclarationDescriptor descriptor) { + return descriptor.getContainingDeclaration() instanceof PackageFragmentDescriptor; + } + + /** + * @return true iff this is a top-level declaration or a class member with no expected "this" object (e.g. static members in Java, + * values() and valueOf() methods of enum classes, etc.) + */ + public static boolean isStaticDeclaration(@NotNull CallableDescriptor descriptor) { + if (descriptor instanceof ConstructorDescriptor) return false; + + DeclarationDescriptor container = descriptor.getContainingDeclaration(); + return container instanceof PackageFragmentDescriptor || + (container instanceof ClassDescriptor && descriptor.getExpectedThisObject() == null); + } + // WARNING! Don't use this method in JVM backend, use JvmCodegenUtil.isCallInsideSameModuleAsDeclared() instead. // The latter handles compilation against compiled part of our module correctly. public static boolean areInSameModule(@NotNull DeclarationDescriptor first, @NotNull DeclarationDescriptor second) { diff --git a/idea/idea-analysis/src/org/jetbrains/jet/plugin/highlighter/PropertiesHighlightingVisitor.java b/idea/idea-analysis/src/org/jetbrains/jet/plugin/highlighter/PropertiesHighlightingVisitor.java index 6e31054abd6..9f28acd619c 100644 --- a/idea/idea-analysis/src/org/jetbrains/jet/plugin/highlighter/PropertiesHighlightingVisitor.java +++ b/idea/idea-analysis/src/org/jetbrains/jet/plugin/highlighter/PropertiesHighlightingVisitor.java @@ -77,21 +77,22 @@ class PropertiesHighlightingVisitor extends AfterAnalysisHighlightingVisitor { super.visitParameter(parameter); } - private void highlightProperty(@NotNull PsiElement elementToHighlight, + private void highlightProperty( + @NotNull PsiElement elementToHighlight, @NotNull PropertyDescriptor descriptor, - boolean withBackingField) { - boolean inPackage = DescriptorUtils.isTopLevelDeclaration(descriptor); - JetPsiChecker.highlightName(holder, elementToHighlight, - inPackage ? JetHighlightingColors.PACKAGE_PROPERTY : JetHighlightingColors.INSTANCE_PROPERTY + boolean withBackingField + ) { + boolean isStatic = DescriptorUtils.isStaticDeclaration(descriptor); + JetPsiChecker.highlightName( + holder, elementToHighlight, + isStatic ? JetHighlightingColors.PACKAGE_PROPERTY : JetHighlightingColors.INSTANCE_PROPERTY ); if (descriptor.getReceiverParameter() != null) { JetPsiChecker.highlightName(holder, elementToHighlight, JetHighlightingColors.EXTENSION_PROPERTY); } if (withBackingField) { - holder.createInfoAnnotation( - elementToHighlight, - "This property has a backing field") - .setTextAttributes(JetHighlightingColors.PROPERTY_WITH_BACKING_FIELD); + holder.createInfoAnnotation(elementToHighlight, "This property has a backing field") + .setTextAttributes(JetHighlightingColors.PROPERTY_WITH_BACKING_FIELD); } } } diff --git a/idea/src/org/jetbrains/jet/plugin/imports/ImportsUtils.kt b/idea/src/org/jetbrains/jet/plugin/imports/ImportsUtils.kt index d7225f072a1..5616b315312 100644 --- a/idea/src/org/jetbrains/jet/plugin/imports/ImportsUtils.kt +++ b/idea/src/org/jetbrains/jet/plugin/imports/ImportsUtils.kt @@ -39,7 +39,9 @@ public val DeclarationDescriptor.importableFqNameSafe: FqName get() = DescriptorUtils.getFqNameSafe(getImportableDescriptor()) public fun DeclarationDescriptor.canBeReferencedViaImport(): Boolean { - if (this is PackageViewDescriptor || DescriptorUtils.isTopLevelDeclaration(this)) { + if (this is PackageViewDescriptor || + DescriptorUtils.isTopLevelDeclaration(this) || + (this is CallableDescriptor && DescriptorUtils.isStaticDeclaration(this))) { return true } val parent = getContainingDeclaration()!!