KT-1579 "Can't import nested class/trait" partially: Entry can be imported, but Map.Entry in code is still unresolved

This commit is contained in:
Svetlana Isakova
2012-03-16 17:09:18 +04:00
parent ba841816c8
commit 114988ac82
15 changed files with 341 additions and 273 deletions
@@ -117,7 +117,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
v.visitOuterClass(typeMapper.mapType(container.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), null, null); v.visitOuterClass(typeMapper.mapType(container.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), null, null);
} }
for (ClassDescriptor innerClass : descriptor.getInnerClassesAndObjects()) { for (DeclarationDescriptor declarationDescriptor : descriptor.getUnsubstitutedInnerClassesScope().getAllDescriptors()) {
assert declarationDescriptor instanceof ClassDescriptor;
ClassDescriptor innerClass = (ClassDescriptor) declarationDescriptor;
// TODO: proper access // TODO: proper access
int innerClassAccess = ACC_PUBLIC; int innerClassAccess = ACC_PUBLIC;
if (innerClass.getModality() == Modality.FINAL) { if (innerClass.getModality() == Modality.FINAL) {
@@ -36,6 +36,9 @@ public interface ClassDescriptor extends ClassifierDescriptor, MemberDescriptor,
@NotNull @NotNull
JetScope getMemberScope(List<TypeProjection> typeArguments); JetScope getMemberScope(List<TypeProjection> typeArguments);
@NotNull
JetScope getUnsubstitutedInnerClassesScope();
@NotNull @NotNull
Set<ConstructorDescriptor> getConstructors(); Set<ConstructorDescriptor> getConstructors();
@@ -77,10 +80,4 @@ public interface ClassDescriptor extends ClassifierDescriptor, MemberDescriptor,
@NotNull @NotNull
ReceiverDescriptor getImplicitReceiver(); ReceiverDescriptor getImplicitReceiver();
@Nullable
ClassDescriptor getInnerClassOrObject(String name);
@NotNull
Collection<ClassDescriptor> getInnerClassesAndObjects();
} }
@@ -176,14 +176,9 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
return implicitReceiver; return implicitReceiver;
} }
@Override
public ClassDescriptor getInnerClassOrObject(String name) {
return null;
}
@NotNull @NotNull
@Override @Override
public Collection<ClassDescriptor> getInnerClassesAndObjects() { public JetScope getUnsubstitutedInnerClassesScope() {
return Collections.emptyList(); return JetScope.EMPTY;
} }
} }
@@ -20,7 +20,6 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope; import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
@@ -204,14 +203,9 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
throw new UnsupportedOperationException(); // TODO throw new UnsupportedOperationException(); // TODO
} }
@Override
public ClassDescriptor getInnerClassOrObject(String name) {
return original.getInnerClassOrObject(name);
}
@NotNull @NotNull
@Override @Override
public Collection<ClassDescriptor> getInnerClassesAndObjects() { public JetScope getUnsubstitutedInnerClassesScope() {
return original.getInnerClassesAndObjects(); return original.getUnsubstitutedInnerClassesScope();
} }
} }
@@ -23,9 +23,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.*;
import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
@@ -42,8 +40,6 @@ public class MutableClassDescriptorLite extends MutableDeclarationDescriptor imp
private List<AnnotationDescriptor> annotations = Lists.newArrayList(); private List<AnnotationDescriptor> annotations = Lists.newArrayList();
private Map<String, ClassDescriptor> innerClassesAndObjects = Maps.newHashMap();
private List<TypeParameterDescriptor> typeParameters; private List<TypeParameterDescriptor> typeParameters;
private Collection<JetType> supertypes = Lists.newArrayList(); private Collection<JetType> supertypes = Lists.newArrayList();
@@ -58,6 +54,7 @@ public class MutableClassDescriptorLite extends MutableDeclarationDescriptor imp
private final ClassKind kind; private final ClassKind kind;
private JetScope scopeForMemberLookup; private JetScope scopeForMemberLookup;
private JetScope innerClassesScope;
private ClassReceiver implicitReceiver; private ClassReceiver implicitReceiver;
@@ -109,6 +106,7 @@ public class MutableClassDescriptorLite extends MutableDeclarationDescriptor imp
public void setScopeForMemberLookup(JetScope scopeForMemberLookup) { public void setScopeForMemberLookup(JetScope scopeForMemberLookup) {
this.scopeForMemberLookup = scopeForMemberLookup; this.scopeForMemberLookup = scopeForMemberLookup;
this.innerClassesScope = new InnerClassesScopeWrapper(scopeForMemberLookup);
} }
public void createTypeConstructor() { public void createTypeConstructor() {
@@ -264,25 +262,17 @@ public class MutableClassDescriptorLite extends MutableDeclarationDescriptor imp
@Override @Override
public void addClassifierDescriptor(@NotNull MutableClassDescriptorLite classDescriptor) { public void addClassifierDescriptor(@NotNull MutableClassDescriptorLite classDescriptor) {
getScopeForMemberLookupAsWritableScope().addClassifierDescriptor(classDescriptor); getScopeForMemberLookupAsWritableScope().addClassifierDescriptor(classDescriptor);
innerClassesAndObjects.put(classDescriptor.getName(), classDescriptor);
} }
@Override
@Nullable
public ClassDescriptor getInnerClassOrObject(String name) {
return innerClassesAndObjects.get(name);
}
@Override
@NotNull @NotNull
public Collection<ClassDescriptor> getInnerClassesAndObjects() { @Override
return innerClassesAndObjects.values(); public JetScope getUnsubstitutedInnerClassesScope() {
return innerClassesScope;
} }
@Override @Override
public void addObjectDescriptor(@NotNull MutableClassDescriptorLite objectDescriptor) { public void addObjectDescriptor(@NotNull MutableClassDescriptorLite objectDescriptor) {
getScopeForMemberLookupAsWritableScope().addObjectDescriptor(objectDescriptor); getScopeForMemberLookupAsWritableScope().addObjectDescriptor(objectDescriptor);
innerClassesAndObjects.put(objectDescriptor.getName(), objectDescriptor);
} }
public void addSupertype(@NotNull JetType supertype) { public void addSupertype(@NotNull JetType supertype) {
@@ -304,7 +294,6 @@ public class MutableClassDescriptorLite extends MutableDeclarationDescriptor imp
} }
} }
public void lockScopes() { public void lockScopes() {
getScopeForMemberLookupAsWritableScope().changeLockLevel(WritableScope.LockLevel.READING); getScopeForMemberLookupAsWritableScope().changeLockLevel(WritableScope.LockLevel.READING);
if (classObjectDescriptor != null) { if (classObjectDescriptor != null) {
@@ -247,14 +247,6 @@ public class DescriptorUtils {
return null; return null;
} }
@Nullable
public static ClassDescriptor getObjectIfObjectOrClassObjectDescriptor(ClassDescriptor descriptor) {
if ((descriptor).getKind() == ClassKind.OBJECT) {
return descriptor;
}
return descriptor.getClassObjectDescriptor();
}
@NotNull @NotNull
public static JetType getFunctionExpectedReturnType(@NotNull FunctionDescriptor descriptor, @NotNull JetElement function) { public static JetType getFunctionExpectedReturnType(@NotNull FunctionDescriptor descriptor, @NotNull JetElement function) {
JetType expectedType; JetType expectedType;
@@ -21,9 +21,7 @@ import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collection;
import java.util.List; import java.util.List;
/** /**
@@ -68,26 +66,12 @@ import java.util.List;
if (descriptor instanceof NamespaceDescriptor) { if (descriptor instanceof NamespaceDescriptor) {
namespaceScope.importScope(((NamespaceDescriptor) descriptor).getMemberScope()); namespaceScope.importScope(((NamespaceDescriptor) descriptor).getMemberScope());
} }
if (firstPhase) { if (descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getKind() != ClassKind.OBJECT) {
if (descriptor instanceof ClassDescriptor) { ClassDescriptor classDescriptor = (ClassDescriptor) descriptor;
ClassDescriptor objectDescriptor = DescriptorUtils.getObjectIfObjectOrClassObjectDescriptor((ClassDescriptor) descriptor); namespaceScope.importScope(classDescriptor.getUnsubstitutedInnerClassesScope());
if (objectDescriptor != null) { ClassDescriptor classObjectDescriptor = classDescriptor.getClassObjectDescriptor();
Collection<? extends DeclarationDescriptor> innerClassesAndObjects = objectDescriptor.getInnerClassesAndObjects(); if (classObjectDescriptor != null) {
for (DeclarationDescriptor innerClassOrObject : innerClassesAndObjects) { namespaceScope.importScope(classObjectDescriptor.getUnsubstitutedInnerClassesScope());
namespaceScope.importClassifierAlias(innerClassOrObject.getName(), (ClassifierDescriptor) innerClassOrObject);
}
}
}
return;
}
if (descriptor instanceof VariableDescriptor) {
JetType type = ((VariableDescriptor) descriptor).getType();
namespaceScope.importScope(type.getMemberScope());
}
else if (descriptor instanceof ClassDescriptor) {
JetType classObjectType = ((ClassDescriptor) descriptor).getClassObjectType();
if (classObjectType != null) {
namespaceScope.importScope(classObjectType.getMemberScope());
} }
} }
} }
@@ -20,20 +20,17 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Collections2; import com.google.common.collect.Collections2;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import javax.inject.Inject;
import org.jetbrains.jet.lang.ModuleConfiguration; import org.jetbrains.jet.lang.ModuleConfiguration;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collection; import javax.inject.Inject;
import java.util.Collections; import java.util.*;
import java.util.List;
import java.util.Map;
import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*;
@@ -46,6 +43,8 @@ public class ImportsResolver {
private TopDownAnalysisContext context; private TopDownAnalysisContext context;
@NotNull @NotNull
private ModuleConfiguration configuration; private ModuleConfiguration configuration;
@NotNull
private SingleImportResolver singleImportResolver;
@Inject @Inject
public void setContext(@NotNull TopDownAnalysisContext context) { public void setContext(@NotNull TopDownAnalysisContext context) {
@@ -57,6 +56,9 @@ public class ImportsResolver {
this.configuration = configuration; this.configuration = configuration;
} }
public ImportsResolver() {
this.singleImportResolver = new SingleImportResolver();
}
public void processTypeImports() { public void processTypeImports() {
processImports(true); processImports(true);
@@ -66,9 +68,10 @@ public class ImportsResolver {
processImports(false); processImports(false);
} }
// On first phase all classes and objects are imported,
// on second phase previous imports are thrown and everything (including functions and properties at namespace level) is imported
private void processImports(boolean firstPhase) { private void processImports(boolean firstPhase) {
SingleImportResolver importResolver = new SingleImportResolver(context.getTrace(), firstPhase); TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.getTrace()); //not to trace errors of default imports
SingleImportResolver defaultImportResolver = new SingleImportResolver(TemporaryBindingTrace.create(context.getTrace()), firstPhase);//not to trace errors of default imports
for (JetFile file : context.getNamespaceDescriptors().keySet()) { for (JetFile file : context.getNamespaceDescriptors().keySet()) {
WritableScope namespaceScope = context.getNamespaceScopes().get(file); WritableScope namespaceScope = context.getNamespaceScopes().get(file);
Importer.DelayedImporter delayedImporter = new Importer.DelayedImporter(namespaceScope, firstPhase); Importer.DelayedImporter delayedImporter = new Importer.DelayedImporter(namespaceScope, firstPhase);
@@ -79,12 +82,12 @@ public class ImportsResolver {
Collection<JetImportDirective> defaultImportDirectives = Lists.newArrayList(); Collection<JetImportDirective> defaultImportDirectives = Lists.newArrayList();
configuration.addDefaultImports(namespaceScope, defaultImportDirectives); configuration.addDefaultImports(namespaceScope, defaultImportDirectives);
for (JetImportDirective defaultImportDirective : defaultImportDirectives) { for (JetImportDirective defaultImportDirective : defaultImportDirectives) {
defaultImportResolver.processImportReference(defaultImportDirective, namespaceScope, delayedImporter); singleImportResolver.processImportReference(defaultImportDirective, namespaceScope, delayedImporter, temporaryTrace, firstPhase);
} }
List<JetImportDirective> importDirectives = file.getImportDirectives(); List<JetImportDirective> importDirectives = file.getImportDirectives();
for (JetImportDirective importDirective : importDirectives) { for (JetImportDirective importDirective : importDirectives) {
Collection<? extends DeclarationDescriptor> descriptors = importResolver.processImportReference(importDirective, namespaceScope, delayedImporter); Collection<? extends DeclarationDescriptor> descriptors = singleImportResolver.processImportReference(importDirective, namespaceScope, delayedImporter, context.getTrace(), firstPhase);
if (descriptors.size() == 1) { if (descriptors.size() == 1) {
resolvedDirectives.put(importDirective, descriptors.iterator().next()); resolvedDirectives.put(importDirective, descriptors.iterator().next());
} }
@@ -162,23 +165,17 @@ public class ImportsResolver {
@NotNull JetImportDirective importDirective, @NotNull JetImportDirective importDirective,
@NotNull JetScope scope, @NotNull BindingTrace trace @NotNull JetScope scope, @NotNull BindingTrace trace
) { ) {
ImportsResolver.SingleImportResolver importResolver = new ImportsResolver.SingleImportResolver(trace, false); ImportsResolver.SingleImportResolver importResolver = new ImportsResolver.SingleImportResolver();
return importResolver.processImportReference(importDirective, scope, Importer.DO_NOTHING); return importResolver.processImportReference(importDirective, scope, Importer.DO_NOTHING, trace, false);
} }
private static class SingleImportResolver { private static class SingleImportResolver {
private final BindingTrace trace;
/* On first phase all classes and objects are imported,
on second phase previous imports are thrown and everything (including functions and properties at namespace level) is imported */
private final boolean firstPhase;
public SingleImportResolver(BindingTrace trace, boolean firstPhase) {
this.trace = trace;
this.firstPhase = firstPhase;
}
@NotNull @NotNull
public Collection<? extends DeclarationDescriptor> processImportReference(@NotNull JetImportDirective importDirective, @NotNull JetScope scope, @NotNull Importer importer) { public Collection<? extends DeclarationDescriptor> processImportReference(@NotNull JetImportDirective importDirective,
@NotNull JetScope scope,
@NotNull Importer importer,
@NotNull BindingTrace trace,
boolean firstPhase) {
if (importDirective.isAbsoluteInRootNamespace()) { if (importDirective.isAbsoluteInRootNamespace()) {
trace.report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO trace.report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO
return Collections.emptyList(); return Collections.emptyList();
@@ -190,16 +187,16 @@ public class ImportsResolver {
Collection<? extends DeclarationDescriptor> descriptors; Collection<? extends DeclarationDescriptor> descriptors;
if (importedReference instanceof JetQualifiedExpression) { if (importedReference instanceof JetQualifiedExpression) {
descriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) importedReference, scope); descriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) importedReference, scope, trace, firstPhase);
} }
else { else {
assert importedReference instanceof JetSimpleNameExpression; assert importedReference instanceof JetSimpleNameExpression;
descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) importedReference, scope, true); descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) importedReference, scope, trace, firstPhase, true);
} }
JetSimpleNameExpression referenceExpression = getLastReference(importedReference); JetSimpleNameExpression referenceExpression = getLastReference(importedReference);
if (importDirective.isAllUnder()) { if (importDirective.isAllUnder()) {
if (referenceExpression == null || !canImportMembersFrom(descriptors, referenceExpression)) { if (referenceExpression == null || !canImportMembersFrom(descriptors, referenceExpression, trace,firstPhase)) {
return Collections.emptyList(); return Collections.emptyList();
} }
@@ -223,147 +220,120 @@ public class ImportsResolver {
@NotNull @NotNull
private Collection<? extends DeclarationDescriptor> lookupDescriptorsForQualifiedExpression( private Collection<? extends DeclarationDescriptor> lookupDescriptorsForQualifiedExpression(
@NotNull JetQualifiedExpression importedReference, @NotNull JetScope outerScope) { @NotNull JetQualifiedExpression importedReference,
@NotNull JetScope outerScope,
@NotNull BindingTrace trace,
boolean firstPhase) {
JetExpression receiverExpression = importedReference.getReceiverExpression(); JetExpression receiverExpression = importedReference.getReceiverExpression();
Collection<? extends DeclarationDescriptor> declarationDescriptors; Collection<? extends DeclarationDescriptor> declarationDescriptors;
if (receiverExpression instanceof JetQualifiedExpression) { if (receiverExpression instanceof JetQualifiedExpression) {
declarationDescriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) receiverExpression, outerScope); declarationDescriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) receiverExpression, outerScope, trace, firstPhase);
} }
else { else {
assert receiverExpression instanceof JetSimpleNameExpression; assert receiverExpression instanceof JetSimpleNameExpression;
declarationDescriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) receiverExpression, outerScope, true); declarationDescriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) receiverExpression, outerScope, trace, firstPhase, true);
} }
JetExpression selectorExpression = importedReference.getSelectorExpression(); JetExpression selectorExpression = importedReference.getSelectorExpression();
if (selectorExpression instanceof JetSimpleNameExpression) { if (!(selectorExpression instanceof JetSimpleNameExpression)) return Collections.emptyList();
JetSimpleNameExpression selector = (JetSimpleNameExpression) selectorExpression;
JetSimpleNameExpression lastReference = getLastReference(receiverExpression);
if (lastReference == null || !canImportMembersFrom(declarationDescriptors, lastReference)) {
return Collections.emptyList();
}
Collection<? extends DeclarationDescriptor> result; JetSimpleNameExpression selector = (JetSimpleNameExpression) selectorExpression;
for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) { JetSimpleNameExpression lastReference = getLastReference(receiverExpression);
if (declarationDescriptor instanceof NamespaceDescriptor) { if (lastReference == null || !canImportMembersFrom(declarationDescriptors, lastReference, trace, firstPhase)) {
result = lookupDescriptorsForSimpleNameReference(selector, ((NamespaceDescriptor) declarationDescriptor).getMemberScope(), true); return Collections.emptyList();
if (!result.isEmpty()) { }
return result;
} Set<SuccessfulLookupResult> results = Sets.newHashSet();
} for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) {
if (declarationDescriptor instanceof ClassDescriptor) { if (declarationDescriptor instanceof NamespaceDescriptor) {
result = lookupObjectMembers((ClassDescriptor) declarationDescriptor, selector); addResult(results, lookupSimpleNameReference(selector, ((NamespaceDescriptor) declarationDescriptor).getMemberScope(), firstPhase, true));
if (!result.isEmpty()) { }
return result; if (declarationDescriptor instanceof ClassDescriptor) {
} addResult(results, lookupSimpleNameReference(selector, getAppropriateScope((ClassDescriptor) declarationDescriptor, firstPhase), firstPhase, false));
} ClassDescriptor classObjectDescriptor = ((ClassDescriptor) declarationDescriptor).getClassObjectDescriptor();
if (declarationDescriptor instanceof VariableDescriptor) { if (classObjectDescriptor != null) {
result = lookupVariableMembers((VariableDescriptor) declarationDescriptor, selector); addResult(results, lookupSimpleNameReference(selector, getAppropriateScope(classObjectDescriptor, firstPhase), firstPhase, false));
if (!result.isEmpty()) {
return result;
}
} }
} }
} }
if (results.isEmpty()) {
return Collections.emptyList(); return Collections.emptyList();
}
return filterAndStoreResolutionResult(results, selector, trace, firstPhase);
} }
private boolean canImportMembersFrom(@NotNull Collection<? extends DeclarationDescriptor> descriptors, @NotNull JetSimpleNameExpression reference) { private static JetScope getAppropriateScope(ClassDescriptor classDescriptor, boolean firstPhase) {
return firstPhase ? classDescriptor.getUnsubstitutedInnerClassesScope() : classDescriptor.getDefaultType().getMemberScope();
}
private static void addResult(Set<SuccessfulLookupResult> results, LookupResult result) {
if (result == LookupResult.EMPTY) return;
results.add((SuccessfulLookupResult) result);
}
private boolean canImportMembersFrom(@NotNull Collection<? extends DeclarationDescriptor> descriptors,
@NotNull JetSimpleNameExpression reference,
@NotNull BindingTrace trace,
boolean firstPhase) {
if (firstPhase) { if (firstPhase) {
return true; return true;
} }
if (descriptors.size() == 1) { if (descriptors.size() == 1) {
return canImportMembersFrom(descriptors.iterator().next(), reference, trace); return canImportMembersFrom(descriptors.iterator().next(), reference, trace, firstPhase);
} }
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace); TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace);
boolean canImport = false; boolean canImport = false;
for (DeclarationDescriptor descriptor : descriptors) { for (DeclarationDescriptor descriptor : descriptors) {
canImport |= canImportMembersFrom(descriptor, reference, temporaryTrace); canImport |= canImportMembersFrom(descriptor, reference, temporaryTrace, firstPhase);
} }
if (!canImport) { if (!canImport) {
temporaryTrace.commit(); temporaryTrace.commit();
} }
return canImport; return canImport;
} }
private boolean canImportMembersFrom(@NotNull DeclarationDescriptor descriptor, private boolean canImportMembersFrom(@NotNull DeclarationDescriptor descriptor,
@NotNull JetSimpleNameExpression reference, @NotNull JetSimpleNameExpression reference,
@NotNull BindingTrace trace) { @NotNull BindingTrace trace,
boolean firstPhase) {
assert !firstPhase; assert !firstPhase;
if (descriptor instanceof NamespaceDescriptor) { if (descriptor instanceof NamespaceDescriptor) {
return true; return true;
} }
if (descriptor instanceof ClassDescriptor) { if (descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getKind() != ClassKind.OBJECT) {
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor;
JetType classObjectType = classDescriptor.getClassObjectType();
if (classObjectType == null) {
trace.report(NO_CLASS_OBJECT.on(reference, classDescriptor));
return false;
}
return true;
}
if (descriptor instanceof VariableDescriptor && ((VariableDescriptor) descriptor).isObjectDeclaration()) {
return true; return true;
} }
trace.report(CANNOT_IMPORT_FROM_ELEMENT.on(reference, descriptor)); trace.report(CANNOT_IMPORT_FROM_ELEMENT.on(reference, descriptor));
return false; return false;
} }
@NotNull
private Collection<? extends DeclarationDescriptor> lookupObjectMembers(@NotNull ClassDescriptor classDescriptor, @NotNull JetSimpleNameExpression memberReference) {
if (firstPhase) {
ClassDescriptor objectDescriptor = DescriptorUtils.getObjectIfObjectOrClassObjectDescriptor(classDescriptor);
if (objectDescriptor == null) {
return Collections.emptyList();
}
return getInnerClassesAndObjectsByName(objectDescriptor, memberReference);
}
//on second phase class descriptor is only a descriptor for class object
JetType classObjectType = classDescriptor.getClassObjectType();
if (classObjectType == null) {
return Collections.emptyList();
}
return lookupDescriptorsForSimpleNameReference(memberReference, classObjectType.getMemberScope(), false);
}
@NotNull
private Collection<? extends DeclarationDescriptor> getInnerClassesAndObjectsByName(@NotNull ClassDescriptor classDescriptor, @NotNull JetSimpleNameExpression memberReference) {
assert classDescriptor.getKind() == ClassKind.OBJECT;
Collection<? extends DeclarationDescriptor> descriptors;
ClassDescriptor innerClass = classDescriptor.getInnerClassOrObject(memberReference.getReferencedName());
if (innerClass == null) {
return Collections.emptyList();
}
descriptors = Collections.<DeclarationDescriptor>singletonList(innerClass);
return filterResolutionResult(descriptors, memberReference, JetScope.EMPTY, false);
}
private Collection<? extends DeclarationDescriptor> lookupVariableMembers(@NotNull VariableDescriptor variableDescriptor, @NotNull JetSimpleNameExpression memberReference) {
if (firstPhase) {
return Collections.emptyList();
}
JetType variableType = variableDescriptor.getReturnType();
if (variableType == null) {
return Collections.emptyList();
}
return lookupDescriptorsForSimpleNameReference(memberReference, variableType.getMemberScope(), false);
}
@NotNull @NotNull
private Collection<? extends DeclarationDescriptor> lookupDescriptorsForSimpleNameReference( private Collection<? extends DeclarationDescriptor> lookupDescriptorsForSimpleNameReference(
@NotNull JetSimpleNameExpression referenceExpression, @NotNull JetSimpleNameExpression referenceExpression,
@NotNull JetScope outerScope, @NotNull JetScope outerScope,
@NotNull BindingTrace trace,
boolean firstPhase,
boolean namespaceLevel) {
LookupResult lookupResult = lookupSimpleNameReference(referenceExpression, outerScope, firstPhase, namespaceLevel);
if (lookupResult == LookupResult.EMPTY) return Collections.emptyList();
return filterAndStoreResolutionResult(Collections.singletonList((SuccessfulLookupResult) lookupResult), referenceExpression, trace, firstPhase);
}
private LookupResult lookupSimpleNameReference(
@NotNull JetSimpleNameExpression referenceExpression,
@NotNull JetScope outerScope,
boolean firstPhase,
boolean namespaceLevel) { boolean namespaceLevel) {
String referencedName = referenceExpression.getReferencedName(); String referencedName = referenceExpression.getReferencedName();
if (referencedName == null) { if (referencedName == null) {
return Collections.emptyList(); //to store a scope where we tried to resolve this reference
return new SuccessfulLookupResult(Collections.<DeclarationDescriptor>emptyList(), outerScope, namespaceLevel);
} }
List<DeclarationDescriptor> descriptors = Lists.newArrayList(); Set<DeclarationDescriptor> descriptors = Sets.newHashSet();
NamespaceDescriptor namespaceDescriptor = outerScope.getNamespace(referencedName); NamespaceDescriptor namespaceDescriptor = outerScope.getNamespace(referencedName);
if (namespaceDescriptor != null) { if (namespaceDescriptor != null) {
descriptors.add(namespaceDescriptor); descriptors.add(namespaceDescriptor);
@@ -386,39 +356,55 @@ public class ImportsResolver {
descriptors.add(localVariable); descriptors.add(localVariable);
} }
} }
return filterResolutionResult(descriptors, referenceExpression, outerScope, namespaceLevel); return new SuccessfulLookupResult(descriptors, outerScope, namespaceLevel);
} }
private Collection<? extends DeclarationDescriptor> filterResolutionResult( private Collection<? extends DeclarationDescriptor> filterAndStoreResolutionResult(
@NotNull Collection<? extends DeclarationDescriptor> descriptors, @NotNull Collection<SuccessfulLookupResult> lookupResults,
@NotNull JetSimpleNameExpression referenceExpression, @NotNull JetSimpleNameExpression referenceExpression,
@NotNull JetScope resolutionScope, @NotNull BindingTrace trace,
//functions and properties can be imported if namespaceLevel == true boolean firstPhase) {
boolean namespaceLevel) { //functions and properties can be imported if lookupResult.namespaceLevel == true
Collection<DeclarationDescriptor> descriptors = Sets.newLinkedHashSet();
for (SuccessfulLookupResult lookupResult : lookupResults) {
descriptors.addAll(lookupResult.descriptors);
}
if (firstPhase) { if (firstPhase) {
return Collections2.filter(descriptors, new Predicate<DeclarationDescriptor>() { return Collections2.filter(descriptors, new Predicate<DeclarationDescriptor>() {
@Override @Override
public boolean apply(@Nullable DeclarationDescriptor descriptor) { public boolean apply(@Nullable DeclarationDescriptor descriptor) {
return (descriptor instanceof ClassDescriptor) || return (descriptor instanceof ClassDescriptor) ||
(descriptor instanceof NamespaceDescriptor); (descriptor instanceof NamespaceDescriptor);
} }
}); });
} }
Collection<? extends DeclarationDescriptor> filteredDescriptors; Collection<DeclarationDescriptor> filteredDescriptors = Sets.newLinkedHashSet();
if (namespaceLevel) { for (SuccessfulLookupResult lookupResult : lookupResults) {
filteredDescriptors = descriptors; if (lookupResult.namespaceLevel) {
} filteredDescriptors.addAll(lookupResult.descriptors);
else { continue;
filteredDescriptors = Collections2.filter(descriptors, new Predicate<DeclarationDescriptor>() { }
filteredDescriptors.addAll(Collections2.filter(lookupResult.descriptors, new Predicate<DeclarationDescriptor>() {
@Override @Override
public boolean apply(@Nullable DeclarationDescriptor descriptor) { public boolean apply(@Nullable DeclarationDescriptor descriptor) {
return (descriptor instanceof NamespaceDescriptor) || return (descriptor instanceof NamespaceDescriptor) ||
(descriptor instanceof ClassDescriptor) || (descriptor instanceof ClassDescriptor) ||
(descriptor instanceof VariableDescriptor && ((VariableDescriptor) descriptor).isObjectDeclaration()); (descriptor instanceof VariableDescriptor && ((VariableDescriptor) descriptor).isObjectDeclaration());
} }
}); }));
} }
storeResolutionResult(descriptors, filteredDescriptors, referenceExpression, resolutionScope); Collection<JetScope> possibleResolutionScopes = Lists.newArrayList();
for (SuccessfulLookupResult lookupResult : lookupResults) {
if (!lookupResult.descriptors.isEmpty()) {
possibleResolutionScopes.add(lookupResult.resolutionScope);
}
}
if (possibleResolutionScopes.isEmpty()) {
for (SuccessfulLookupResult lookupResult : lookupResults) {
possibleResolutionScopes.add(lookupResult.resolutionScope);
}
}
storeResolutionResult(descriptors, filteredDescriptors, referenceExpression, possibleResolutionScopes, trace);
return filteredDescriptors; return filteredDescriptors;
} }
@@ -426,12 +412,16 @@ public class ImportsResolver {
@NotNull Collection<? extends DeclarationDescriptor> descriptors, @NotNull Collection<? extends DeclarationDescriptor> descriptors,
@NotNull Collection<? extends DeclarationDescriptor> canBeImportedDescriptors, @NotNull Collection<? extends DeclarationDescriptor> canBeImportedDescriptors,
@NotNull JetSimpleNameExpression referenceExpression, @NotNull JetSimpleNameExpression referenceExpression,
@NotNull JetScope resolutionScope) { @NotNull Collection<JetScope> possibleResolutionScopes,
@NotNull BindingTrace trace) {
assert canBeImportedDescriptors.size() <= descriptors.size(); assert canBeImportedDescriptors.size() <= descriptors.size();
assert !possibleResolutionScopes.isEmpty();
//todo completion here needs all possible resolution scopes, if there are many
JetScope resolutionScope = possibleResolutionScopes.iterator().next();
// A special case - will fill all trace information // A special case - will fill all trace information
if (resolveClassNamespaceAmbiguity(canBeImportedDescriptors, referenceExpression, resolutionScope)) { if (resolveClassNamespaceAmbiguity(canBeImportedDescriptors, referenceExpression, resolutionScope, trace)) {
return; return;
} }
@@ -451,8 +441,6 @@ public class ImportsResolver {
else if (canBeImportedDescriptors.size() == 1) { else if (canBeImportedDescriptors.size() == 1) {
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, canBeImportedDescriptors.iterator().next()); trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, canBeImportedDescriptors.iterator().next());
trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope); trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope);
} else {
// trace.report(UNRESOLVED_REFERENCE.on(referenceExpression));
} }
// Check for more information and additional errors // Check for more information and additional errors
@@ -471,9 +459,10 @@ public class ImportsResolver {
* *
* @return <code>true</code> if method has successfully resolved ambiguity * @return <code>true</code> if method has successfully resolved ambiguity
*/ */
private boolean resolveClassNamespaceAmbiguity(Collection<? extends DeclarationDescriptor> filteredDescriptors, private boolean resolveClassNamespaceAmbiguity(@NotNull Collection<? extends DeclarationDescriptor> filteredDescriptors,
JetSimpleNameExpression referenceExpression, @NotNull JetSimpleNameExpression referenceExpression,
JetScope resolutionScope) { @NotNull JetScope resolutionScope,
@NotNull BindingTrace trace) {
if (filteredDescriptors.size() == 2) { if (filteredDescriptors.size() == 2) {
NamespaceDescriptor namespaceDescriptor = null; NamespaceDescriptor namespaceDescriptor = null;
@@ -499,5 +488,21 @@ public class ImportsResolver {
return false; return false;
} }
private interface LookupResult {
LookupResult EMPTY = new LookupResult() {};
}
private static class SuccessfulLookupResult implements LookupResult {
final Collection<? extends DeclarationDescriptor> descriptors;
final JetScope resolutionScope;
final boolean namespaceLevel;
private SuccessfulLookupResult(Collection<? extends DeclarationDescriptor> descriptors, JetScope resolutionScope, boolean namespaceLevel) {
this.descriptors = descriptors;
this.resolutionScope = resolutionScope;
this.namespaceLevel = namespaceLevel;
}
}
} }
} }
@@ -0,0 +1,93 @@
/*
* Copyright 2010-2012 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.scopes;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import java.util.Collection;
import java.util.List;
/**
* @author svtk
*/
public class InnerClassesScopeWrapper extends JetScopeImpl {
private final JetScope actualScope;
public InnerClassesScopeWrapper(JetScope actualScope) {
this.actualScope = actualScope;
}
private boolean isClass(DeclarationDescriptor descriptor) {
return descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getKind() != ClassKind.OBJECT;
}
@Override
public ClassifierDescriptor getClassifier(@NotNull String name) {
ClassifierDescriptor classifier = actualScope.getClassifier(name);
if (isClass(classifier)) return classifier;
return null;
}
@NotNull
@Override
public DeclarationDescriptor getContainingDeclaration() {
return actualScope.getContainingDeclaration();
}
@NotNull
@Override
public Collection<DeclarationDescriptor> getDeclarationsByLabel(String labelName) {
Collection<DeclarationDescriptor> declarationsByLabel = actualScope.getDeclarationsByLabel(labelName);
return Collections2.filter(declarationsByLabel, new Predicate<DeclarationDescriptor>() {
@Override
public boolean apply(@Nullable DeclarationDescriptor descriptor) {
return isClass(descriptor);
}
});
}
@NotNull
@Override
public Collection<DeclarationDescriptor> getAllDescriptors() {
Collection<DeclarationDescriptor> allDescriptors = actualScope.getAllDescriptors();
return Collections2.filter(allDescriptors, new Predicate<DeclarationDescriptor>() {
@Override
public boolean apply(@Nullable DeclarationDescriptor descriptor) {
return isClass(descriptor);
}
});
}
@NotNull
@Override
public ReceiverDescriptor getImplicitReceiver() {
return actualScope.getImplicitReceiver();
}
@Override
public void getImplicitReceiversHierarchy(@NotNull List<ReceiverDescriptor> result) {
actualScope.getImplicitReceiversHierarchy(result);
}
}
@@ -70,7 +70,7 @@ fun bar() {}
//FILE:c.kt //FILE:c.kt
package c package c
import C.* import <!CANNOT_IMPORT_FROM_ELEMENT!>C<!>.*
object C { object C {
fun f() { fun f() {
@@ -79,7 +79,7 @@ object C {
} }
fun foo() { fun foo() {
if (i == 3) f() if (<!UNRESOLVED_REFERENCE!>i<!> == 3) <!UNRESOLVED_REFERENCE!>f<!>()
} }
//FILE:d.kt //FILE:d.kt
@@ -96,4 +96,4 @@ class A() {
open class B() {} open class B() {}
object C : B() {} object C : B() {}
} }
} }
@@ -0,0 +1,9 @@
//FILE:a.kt
package lib
trait WithInner {
trait Inner {
}
}
//FILE:b.kt
package user
import lib.WithInner.Inner
@@ -0,0 +1,12 @@
//FILE:a.kt
//+JDK
package a
import java.util.Map.*
fun foo(b : Entry<String, String>) = b
//FILE:b.kt
//+JDK
package b
import java.util.Map.Entry
fun bar(b : Entry<String, String>) = b
@@ -0,0 +1,24 @@
// import all members from class object
package c
import A.*
import <!CANNOT_IMPORT_FROM_ELEMENT!>M<!>.*
fun foo() {
val <!UNUSED_VARIABLE!>b<!>: B = B()
var <!UNUSED_VARIABLE!>r<!>: <!UNRESOLVED_REFERENCE!>R<!> = <!UNRESOLVED_REFERENCE!>R<!>()
}
class A() {
class object {
class B() {
class object {
}
}
}
}
object M {
fun foo() {}
class R() {}
}
@@ -0,0 +1,33 @@
package d
//import from objects before properties resolve
import <!CANNOT_IMPORT_FROM_ELEMENT!>A<!>.*
import <!CANNOT_IMPORT_FROM_ELEMENT!>M<!>.R
import <!CANNOT_IMPORT_FROM_ELEMENT!>M<!>.R.bar
import <!CANNOT_IMPORT_FROM_ELEMENT!>M<!>.T
import <!CANNOT_IMPORT_FROM_ELEMENT!>M<!>.Y
var r: T = <!UNRESOLVED_REFERENCE!>T<!>()
val y: T = <!UNRESOLVED_REFERENCE!>Y<!>
fun f() {
<!UNRESOLVED_REFERENCE!>bar<!>()
<!UNRESOLVED_REFERENCE!>R<!>.bar()
<!UNRESOLVED_REFERENCE!>B<!>.foo()
}
object M {
object R {
fun bar() {}
}
open class T() {}
object Y : T() {}
}
object A {
object B {
fun foo() {}
}
}
@@ -35,7 +35,7 @@ object N {
//FILE:b.kt //FILE:b.kt
package b package b
import N.M import <!CANNOT_IMPORT_FROM_ELEMENT!>N<!>.M
import A.P import A.P
import b.A.B import b.A.B
@@ -45,7 +45,7 @@ fun foo() {
P.foo() P.foo()
M.bar() <!UNRESOLVED_REFERENCE!>M<!>.bar()
} }
class A() { class A() {
@@ -66,65 +66,4 @@ object N {
object M { object M {
fun bar() {} fun bar() {}
} }
} }
//FILE:c.kt
// import all members from class object
package c
import A.*
import M.*
fun foo() {
val <!UNUSED_VARIABLE!>b<!>: B = B()
var <!UNUSED_VARIABLE!>r<!>: R = R()
}
class A() {
class object {
class B() {
class object {
}
}
}
}
object M {
fun foo() {}
class R() {}
}
//FILE:d.kt
package d
//import from objects before properties resolve
import A.*
import M.R
import M.R.<!CANNOT_BE_IMPORTED!>bar<!>
import M.T
import M.Y
var r: T = T()
val y: T = Y
fun f() {
<!UNRESOLVED_REFERENCE!>bar<!>()
R.bar()
B.foo()
}
object M {
object R {
fun bar() {}
}
open class T() {}
object Y : T() {}
}
object A {
object B {
fun foo() {}
}
}