# KT-1579 Fixed Can't import nested class/trait

This commit is contained in:
Svetlana Isakova
2012-03-27 15:15:15 +04:00
parent fe9d5ddf89
commit f7cfb36f62
26 changed files with 548 additions and 516 deletions
@@ -35,6 +35,7 @@ import org.jetbrains.jet.lang.resolve.AnnotationResolver;
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lang.resolve.TypeResolver;
import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver;
import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver;
import org.jetbrains.jet.lang.resolve.ImportsResolver;
import org.jetbrains.jet.lang.resolve.DelegationResolver;
@@ -89,6 +90,7 @@ public class InjectorForTopDownAnalyzerForJvm {
CallResolver callResolver = new CallResolver();
ExpressionTypingServices expressionTypingServices = new ExpressionTypingServices();
TypeResolver typeResolver = new TypeResolver();
QualifiedExpressionResolver qualifiedExpressionResolver = new QualifiedExpressionResolver();
OverloadingConflictResolver overloadingConflictResolver = new OverloadingConflictResolver();
ImportsResolver importsResolver = new ImportsResolver();
DelegationResolver delegationResolver = new DelegationResolver();
@@ -161,9 +163,11 @@ public class InjectorForTopDownAnalyzerForJvm {
typeResolver.setAnnotationResolver(annotationResolver);
typeResolver.setDescriptorResolver(descriptorResolver);
typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver);
importsResolver.setConfiguration(javaBridgeConfiguration);
importsResolver.setContext(topDownAnalysisContext);
importsResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver);
importsResolver.setTrace(observableBindingTrace);
delegationResolver.setContext(topDownAnalysisContext);
@@ -63,11 +63,11 @@ public class JavaBridgeConfiguration implements ModuleConfiguration {
@Override
public void addDefaultImports(@NotNull WritableScope rootScope, @NotNull Collection<JetImportDirective> directives) {
public void addDefaultImports(@NotNull Collection<JetImportDirective> directives) {
for (ImportPath importPath : DEFAULT_JAVA_IMPORTS) {
directives.add(JetPsiFactory.createImportDirective(project, importPath));
}
delegateConfiguration.addDefaultImports(rootScope, directives);
delegateConfiguration.addDefaultImports(directives);
}
@Override
@@ -23,6 +23,7 @@ import org.jetbrains.jet.lang.resolve.calls.CallResolver;
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
import org.jetbrains.jet.lang.resolve.AnnotationResolver;
import org.jetbrains.jet.lang.resolve.TypeResolver;
import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver;
import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
@@ -42,6 +43,7 @@ public class InjectorForMacros {
DescriptorResolver descriptorResolver = new DescriptorResolver();
AnnotationResolver annotationResolver = new AnnotationResolver();
TypeResolver typeResolver = new TypeResolver();
QualifiedExpressionResolver qualifiedExpressionResolver = new QualifiedExpressionResolver();
OverloadingConflictResolver overloadingConflictResolver = new OverloadingConflictResolver();
this.expressionTypingServices.setCallResolver(callResolver);
@@ -63,6 +65,7 @@ public class InjectorForMacros {
typeResolver.setAnnotationResolver(annotationResolver);
typeResolver.setDescriptorResolver(descriptorResolver);
typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver);
}
@@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.resolve.AnnotationResolver;
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lang.resolve.TypeResolver;
import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver;
import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver;
import org.jetbrains.jet.lang.resolve.ImportsResolver;
import org.jetbrains.jet.lang.resolve.DelegationResolver;
@@ -84,6 +85,7 @@ public class InjectorForTopDownAnalyzerBasic {
CallResolver callResolver = new CallResolver();
ExpressionTypingServices expressionTypingServices = new ExpressionTypingServices();
TypeResolver typeResolver = new TypeResolver();
QualifiedExpressionResolver qualifiedExpressionResolver = new QualifiedExpressionResolver();
OverloadingConflictResolver overloadingConflictResolver = new OverloadingConflictResolver();
ImportsResolver importsResolver = new ImportsResolver();
DelegationResolver delegationResolver = new DelegationResolver();
@@ -148,9 +150,11 @@ public class InjectorForTopDownAnalyzerBasic {
typeResolver.setAnnotationResolver(annotationResolver);
typeResolver.setDescriptorResolver(descriptorResolver);
typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver);
importsResolver.setConfiguration(moduleConfiguration);
importsResolver.setContext(topDownAnalysisContext);
importsResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver);
importsResolver.setTrace(observableBindingTrace);
delegationResolver.setContext(topDownAnalysisContext);
@@ -49,7 +49,7 @@ public class DefaultModuleConfiguration implements ModuleConfiguration {
}
@Override
public void addDefaultImports(@NotNull WritableScope rootScope, @NotNull Collection<JetImportDirective> directives) {
public void addDefaultImports(@NotNull Collection<JetImportDirective> directives) {
for (ImportPath defaultJetImport : DEFAULT_JET_IMPORTS) {
directives.add(JetPsiFactory.createImportDirective(project, defaultJetImport));
}
@@ -30,7 +30,7 @@ import java.util.Collection;
public interface ModuleConfiguration {
ModuleConfiguration EMPTY = new ModuleConfiguration() {
@Override
public void addDefaultImports(@NotNull WritableScope rootScope, @NotNull Collection<JetImportDirective> directives) {
public void addDefaultImports(@NotNull Collection<JetImportDirective> directives) {
}
@Override
@@ -39,7 +39,7 @@ public interface ModuleConfiguration {
};
void addDefaultImports(@NotNull WritableScope rootScope, @NotNull Collection<JetImportDirective> directives);
void addDefaultImports(@NotNull Collection<JetImportDirective> directives);
/**
*
@@ -274,4 +274,29 @@ public class JetPsiUtil {
}
}
@Nullable
public static String getAliasName(@NotNull JetImportDirective importDirective) {
String aliasName = importDirective.getAliasName();
JetExpression importedReference = importDirective.getImportedReference();
if (importedReference == null) {
return null;
}
JetSimpleNameExpression referenceExpression = getLastReference(importedReference);
if (aliasName == null) {
aliasName = referenceExpression != null ? referenceExpression.getReferencedName() : null;
}
return aliasName;
}
@Nullable
public static JetSimpleNameExpression getLastReference(@NotNull JetExpression importedReference) {
if (importedReference instanceof JetDotQualifiedExpression) {
JetExpression selectorExpression = ((JetDotQualifiedExpression)importedReference).getSelectorExpression();
return (selectorExpression instanceof JetSimpleNameExpression) ? (JetSimpleNameExpression)selectorExpression : null;
}
if (importedReference instanceof JetSimpleNameExpression) {
return (JetSimpleNameExpression)importedReference;
}
return null;
}
}
@@ -45,11 +45,9 @@ import java.util.List;
class StandardImporter implements Importer {
private final WritableScope namespaceScope;
private final boolean firstPhase;
public StandardImporter(WritableScope namespaceScope, boolean firstPhase) {
public StandardImporter(WritableScope namespaceScope) {
this.namespaceScope = namespaceScope;
this.firstPhase = firstPhase;
}
@Override
@@ -96,8 +94,8 @@ import java.util.List;
class DelayedImporter extends StandardImporter {
private final List<Pair<DeclarationDescriptor, String>> imports = Lists.newArrayList();
public DelayedImporter(@NotNull WritableScope namespaceScope, boolean firstPhase) {
super(namespaceScope, firstPhase);
public DelayedImporter(@NotNull WritableScope namespaceScope) {
super(namespaceScope);
}
@Override
@@ -16,23 +16,25 @@
package org.jetbrains.jet.lang.resolve;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.ModuleConfiguration;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import javax.inject.Inject;
import java.util.*;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.USELESS_HIDDEN_IMPORT;
import static org.jetbrains.jet.lang.diagnostics.Errors.USELESS_SIMPLE_IMPORT;
/**
* @author abreslav
@@ -44,7 +46,7 @@ public class ImportsResolver {
@NotNull
private ModuleConfiguration configuration;
@NotNull
private SingleImportResolver singleImportResolver;
private QualifiedExpressionResolver qualifiedExpressionResolver;
@NotNull
private ObservableBindingTrace trace;
@@ -63,8 +65,9 @@ public class ImportsResolver {
this.trace = trace;
}
public ImportsResolver() {
this.singleImportResolver = new SingleImportResolver();
@Inject
public void setQualifiedExpressionResolver(@NotNull QualifiedExpressionResolver qualifiedExpressionResolver) {
this.qualifiedExpressionResolver = qualifiedExpressionResolver;
}
public void processTypeImports() {
@@ -75,67 +78,40 @@ public class ImportsResolver {
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 onlyClasses) {
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace); //not to trace errors of default imports
for (JetFile file : context.getNamespaceDescriptors().keySet()) {
//JetScope rootScope = context.getRootScope();
WritableScope namespaceScope = context.getNamespaceScopes().get(file);
Importer.DelayedImporter delayedImporter = new Importer.DelayedImporter(namespaceScope, firstPhase);
if (!firstPhase) {
Importer.DelayedImporter delayedImporter = new Importer.DelayedImporter(namespaceScope);
if (!onlyClasses) {
namespaceScope.clearImports();
}
Map<JetImportDirective, DeclarationDescriptor> resolvedDirectives = Maps.newHashMap();
Collection<JetImportDirective> defaultImportDirectives = Lists.newArrayList();
configuration.addDefaultImports(namespaceScope, defaultImportDirectives);
configuration.addDefaultImports(defaultImportDirectives);
for (JetImportDirective defaultImportDirective : defaultImportDirectives) {
singleImportResolver.processImportReference(defaultImportDirective, namespaceScope, delayedImporter, temporaryTrace, firstPhase);
qualifiedExpressionResolver.processImportReference(defaultImportDirective, namespaceScope, delayedImporter, temporaryTrace, onlyClasses);
}
List<JetImportDirective> importDirectives = file.getImportDirectives();
for (JetImportDirective importDirective : importDirectives) {
Collection<? extends DeclarationDescriptor> descriptors = singleImportResolver.processImportReference(importDirective, namespaceScope, delayedImporter, trace, firstPhase);
Collection<? extends DeclarationDescriptor> descriptors =
qualifiedExpressionResolver.processImportReference(importDirective, namespaceScope, delayedImporter, trace, onlyClasses);
if (descriptors.size() == 1) {
resolvedDirectives.put(importDirective, descriptors.iterator().next());
}
}
delayedImporter.processImports();
if (firstPhase) {
continue;
}
for (JetImportDirective importDirective : importDirectives) {
reportUselessImport(importDirective, namespaceScope, resolvedDirectives);
if (!onlyClasses) {
for (JetImportDirective importDirective : importDirectives) {
reportUselessImport(importDirective, namespaceScope, resolvedDirectives);
}
}
}
}
@Nullable
private static JetSimpleNameExpression getLastReference(@NotNull JetExpression importedReference) {
if (importedReference instanceof JetDotQualifiedExpression) {
JetDotQualifiedExpression reference = (JetDotQualifiedExpression) importedReference;
JetExpression selectorExpression = reference.getSelectorExpression();
return (selectorExpression != null) ? (JetSimpleNameExpression) selectorExpression : null;
}
assert importedReference instanceof JetSimpleNameExpression;
return (JetSimpleNameExpression) importedReference;
}
@Nullable
private static String getAliasName(@NotNull JetImportDirective importDirective) {
String aliasName = importDirective.getAliasName();
JetExpression importedReference = importDirective.getImportedReference();
if (importedReference == null) {
return null;
}
JetSimpleNameExpression referenceExpression = getLastReference(importedReference);
if (aliasName == null) {
aliasName = referenceExpression != null ? referenceExpression.getReferencedName() : null;
}
return aliasName;
}
private void reportUselessImport(@NotNull JetImportDirective importDirective,
@NotNull WritableScope namespaceScope,
@NotNull Map<JetImportDirective, DeclarationDescriptor> resolvedDirectives) {
@@ -144,7 +120,7 @@ public class ImportsResolver {
if (importedReference == null || !resolvedDirectives.containsKey(importDirective)) {
return;
}
String aliasName = getAliasName(importDirective);
String aliasName = JetPsiUtil.getAliasName(importDirective);
if (aliasName == null) {
return;
}
@@ -163,353 +139,10 @@ public class ImportsResolver {
if (isResolved != null && isResolved != wasResolved) {
trace.report(USELESS_HIDDEN_IMPORT.on(importedReference));
}
if (!importDirective.isAllUnder() && importedReference instanceof JetSimpleNameExpression && importDirective.getAliasName() == null) {
if (!importDirective.isAllUnder() &&
importedReference instanceof JetSimpleNameExpression &&
importDirective.getAliasName() == null) {
trace.report(USELESS_SIMPLE_IMPORT.on(importedReference));
}
}
public static Collection<? extends DeclarationDescriptor> analyseImportReference(
@NotNull JetImportDirective importDirective,
@NotNull JetScope scope, @NotNull BindingTrace trace
) {
ImportsResolver.SingleImportResolver importResolver = new ImportsResolver.SingleImportResolver();
return importResolver.processImportReference(importDirective, scope, Importer.DO_NOTHING, trace, false);
}
private static class SingleImportResolver {
@NotNull
public Collection<? extends DeclarationDescriptor> processImportReference(@NotNull JetImportDirective importDirective,
@NotNull JetScope scope,
@NotNull Importer importer,
@NotNull BindingTrace trace,
boolean firstPhase) {
if (importDirective.isAbsoluteInRootNamespace()) {
trace.report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO
return Collections.emptyList();
}
JetExpression importedReference = importDirective.getImportedReference();
if (importedReference == null) {
return Collections.emptyList();
}
Collection<? extends DeclarationDescriptor> descriptors;
if (importedReference instanceof JetQualifiedExpression) {
descriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) importedReference, scope, trace, firstPhase);
}
else {
assert importedReference instanceof JetSimpleNameExpression;
descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) importedReference, scope, trace, firstPhase, true);
}
JetSimpleNameExpression referenceExpression = getLastReference(importedReference);
if (importDirective.isAllUnder()) {
if (referenceExpression == null || !canImportMembersFrom(descriptors, referenceExpression, trace,firstPhase)) {
return Collections.emptyList();
}
for (DeclarationDescriptor descriptor : descriptors) {
importer.addAllUnderImport(descriptor);
}
return Collections.emptyList();
}
String aliasName = getAliasName(importDirective);
if (aliasName == null) {
return Collections.emptyList();
}
for (DeclarationDescriptor descriptor : descriptors) {
importer.addAliasImport(descriptor, aliasName);
}
return descriptors;
}
@NotNull
private Collection<? extends DeclarationDescriptor> lookupDescriptorsForQualifiedExpression(
@NotNull JetQualifiedExpression importedReference,
@NotNull JetScope outerScope,
@NotNull BindingTrace trace,
boolean firstPhase) {
JetExpression receiverExpression = importedReference.getReceiverExpression();
Collection<? extends DeclarationDescriptor> declarationDescriptors;
if (receiverExpression instanceof JetQualifiedExpression) {
declarationDescriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) receiverExpression, outerScope, trace, firstPhase);
}
else {
assert receiverExpression instanceof JetSimpleNameExpression;
declarationDescriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) receiverExpression, outerScope, trace, firstPhase, true);
}
JetExpression selectorExpression = importedReference.getSelectorExpression();
if (!(selectorExpression instanceof JetSimpleNameExpression)) return Collections.emptyList();
JetSimpleNameExpression selector = (JetSimpleNameExpression) selectorExpression;
JetSimpleNameExpression lastReference = getLastReference(receiverExpression);
if (lastReference == null || !canImportMembersFrom(declarationDescriptors, lastReference, trace, firstPhase)) {
return Collections.emptyList();
}
Set<SuccessfulLookupResult> results = Sets.newHashSet();
for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) {
if (declarationDescriptor instanceof NamespaceDescriptor) {
addResult(results, lookupSimpleNameReference(selector, ((NamespaceDescriptor) declarationDescriptor).getMemberScope(), firstPhase, true));
}
if (declarationDescriptor instanceof ClassDescriptor) {
addResult(results, lookupSimpleNameReference(selector, getAppropriateScope((ClassDescriptor) declarationDescriptor, firstPhase), firstPhase, false));
ClassDescriptor classObjectDescriptor = ((ClassDescriptor) declarationDescriptor).getClassObjectDescriptor();
if (classObjectDescriptor != null) {
addResult(results, lookupSimpleNameReference(selector, getAppropriateScope(classObjectDescriptor, firstPhase), firstPhase, false));
}
}
}
if (results.isEmpty()) {
return Collections.emptyList();
}
return filterAndStoreResolutionResult(results, selector, trace, firstPhase);
}
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) {
return true;
}
if (descriptors.size() == 1) {
return canImportMembersFrom(descriptors.iterator().next(), reference, trace, firstPhase);
}
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace);
boolean canImport = false;
for (DeclarationDescriptor descriptor : descriptors) {
canImport |= canImportMembersFrom(descriptor, reference, temporaryTrace, firstPhase);
}
if (!canImport) {
temporaryTrace.commit();
}
return canImport;
}
private boolean canImportMembersFrom(@NotNull DeclarationDescriptor descriptor,
@NotNull JetSimpleNameExpression reference,
@NotNull BindingTrace trace,
boolean firstPhase) {
assert !firstPhase;
if (descriptor instanceof NamespaceDescriptor) {
return true;
}
if (descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getKind() != ClassKind.OBJECT) {
return true;
}
trace.report(CANNOT_IMPORT_FROM_ELEMENT.on(reference, descriptor));
return false;
}
@NotNull
private Collection<? extends DeclarationDescriptor> lookupDescriptorsForSimpleNameReference(
@NotNull JetSimpleNameExpression referenceExpression,
@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) {
String referencedName = referenceExpression.getReferencedName();
if (referencedName == null) {
//to store a scope where we tried to resolve this reference
return new SuccessfulLookupResult(Collections.<DeclarationDescriptor>emptyList(), outerScope, namespaceLevel);
}
Set<DeclarationDescriptor> descriptors = Sets.newHashSet();
NamespaceDescriptor namespaceDescriptor = outerScope.getNamespace(referencedName);
if (namespaceDescriptor != null) {
descriptors.add(namespaceDescriptor);
}
ClassifierDescriptor classifierDescriptor = outerScope.getClassifier(referencedName);
if (classifierDescriptor != null) {
descriptors.add(classifierDescriptor);
}
if (firstPhase) {
descriptors.add(outerScope.getObjectDescriptor(referencedName));
}
else {
descriptors.addAll(outerScope.getFunctions(referencedName));
descriptors.addAll(outerScope.getProperties(referencedName));
VariableDescriptor localVariable = outerScope.getLocalVariable(referencedName);
if (localVariable != null) {
descriptors.add(localVariable);
}
}
return new SuccessfulLookupResult(descriptors, outerScope, namespaceLevel);
}
private Collection<? extends DeclarationDescriptor> filterAndStoreResolutionResult(
@NotNull Collection<SuccessfulLookupResult> lookupResults,
@NotNull JetSimpleNameExpression referenceExpression,
@NotNull BindingTrace trace,
boolean firstPhase) {
//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) {
return Collections2.filter(descriptors, new Predicate<DeclarationDescriptor>() {
@Override
public boolean apply(@Nullable DeclarationDescriptor descriptor) {
return (descriptor instanceof ClassDescriptor) ||
(descriptor instanceof NamespaceDescriptor);
}
});
}
Collection<DeclarationDescriptor> filteredDescriptors = Sets.newLinkedHashSet();
for (SuccessfulLookupResult lookupResult : lookupResults) {
if (lookupResult.namespaceLevel) {
filteredDescriptors.addAll(lookupResult.descriptors);
continue;
}
filteredDescriptors.addAll(Collections2.filter(lookupResult.descriptors, new Predicate<DeclarationDescriptor>() {
@Override
public boolean apply(@Nullable DeclarationDescriptor descriptor) {
return (descriptor instanceof NamespaceDescriptor) ||
(descriptor instanceof ClassDescriptor) ||
(descriptor instanceof VariableDescriptor && ((VariableDescriptor) descriptor).isObjectDeclaration());
}
}));
}
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;
}
private void storeResolutionResult(
@NotNull Collection<? extends DeclarationDescriptor> descriptors,
@NotNull Collection<? extends DeclarationDescriptor> canBeImportedDescriptors,
@NotNull JetSimpleNameExpression referenceExpression,
@NotNull Collection<JetScope> possibleResolutionScopes,
@NotNull BindingTrace trace) {
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
if (resolveClassNamespaceAmbiguity(canBeImportedDescriptors, referenceExpression, resolutionScope, trace)) {
return;
}
// Simple case of no descriptors
if (descriptors.isEmpty()) {
trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope);
trace.report(UNRESOLVED_REFERENCE.on(referenceExpression));
return;
}
// Decide if expression has resolved reference
if (descriptors.size() == 1) {
assert canBeImportedDescriptors.size() <= 1;
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, descriptors.iterator().next());
trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope);
}
else if (canBeImportedDescriptors.size() == 1) {
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, canBeImportedDescriptors.iterator().next());
trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope);
}
// Check for more information and additional errors
if (canBeImportedDescriptors.isEmpty()) {
assert descriptors.size() >= 1;
trace.report(CANNOT_BE_IMPORTED.on(referenceExpression, descriptors.iterator().next()));
}
else if (canBeImportedDescriptors.size() > 1) {
trace.record(BindingContext.AMBIGUOUS_REFERENCE_TARGET, referenceExpression, descriptors);
}
}
/**
* This method tries to resolve descriptors ambiguity between class descriptor and namespace descriptor for the same class.
* It's ok choose class for expression reference resolution.
*
* @return <code>true</code> if method has successfully resolved ambiguity
*/
private boolean resolveClassNamespaceAmbiguity(@NotNull Collection<? extends DeclarationDescriptor> filteredDescriptors,
@NotNull JetSimpleNameExpression referenceExpression,
@NotNull JetScope resolutionScope,
@NotNull BindingTrace trace) {
if (filteredDescriptors.size() == 2) {
NamespaceDescriptor namespaceDescriptor = null;
ClassDescriptor classDescriptor = null;
for (DeclarationDescriptor filteredDescriptor : filteredDescriptors) {
if (filteredDescriptor instanceof NamespaceDescriptor) {
namespaceDescriptor = (NamespaceDescriptor) filteredDescriptor;
}
else if (filteredDescriptor instanceof ClassDescriptor) {
classDescriptor = (ClassDescriptor) filteredDescriptor;
}
}
if (namespaceDescriptor != null && classDescriptor != null) {
if (DescriptorUtils.getFQName(namespaceDescriptor).equals(DescriptorUtils.getFQName(classDescriptor))) {
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classDescriptor);
trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope);
return true;
}
}
}
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,428 @@
/*
* 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;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
/**
* @author svtk
*/
public class QualifiedExpressionResolver {
@NotNull
public Collection<? extends DeclarationDescriptor> analyseImportReference(@NotNull JetImportDirective importDirective,
@NotNull JetScope scope,
@NotNull BindingTrace trace) {
return processImportReference(importDirective, scope, Importer.DO_NOTHING, trace, false);
}
@NotNull
public Collection<? extends DeclarationDescriptor> processImportReference(@NotNull JetImportDirective importDirective,
@NotNull JetScope scope,
@NotNull Importer importer,
@NotNull BindingTrace trace,
boolean onlyClasses) {
if (importDirective.isAbsoluteInRootNamespace()) {
trace.report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO
return Collections.emptyList();
}
JetExpression importedReference = importDirective.getImportedReference();
if (importedReference == null) {
return Collections.emptyList();
}
Collection<? extends DeclarationDescriptor> descriptors;
if (importedReference instanceof JetQualifiedExpression) {
//store result only when we find all descriptors, not only classes on the second phase
descriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression)importedReference, scope, trace, onlyClasses, !onlyClasses);
}
else {
assert importedReference instanceof JetSimpleNameExpression;
descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression)importedReference, scope, trace, onlyClasses, true, !onlyClasses);
}
JetSimpleNameExpression referenceExpression = JetPsiUtil.getLastReference(importedReference);
if (importDirective.isAllUnder()) {
if (referenceExpression == null || !canImportMembersFrom(descriptors, referenceExpression, trace, onlyClasses)) {
return Collections.emptyList();
}
for (DeclarationDescriptor descriptor : descriptors) {
importer.addAllUnderImport(descriptor);
}
return Collections.emptyList();
}
String aliasName = JetPsiUtil.getAliasName(importDirective);
if (aliasName == null) {
return Collections.emptyList();
}
for (DeclarationDescriptor descriptor : descriptors) {
importer.addAliasImport(descriptor, aliasName);
}
return descriptors;
}
private boolean canImportMembersFrom(@NotNull Collection<? extends DeclarationDescriptor> descriptors,
@NotNull JetSimpleNameExpression reference,
@NotNull BindingTrace trace,
boolean onlyClasses) {
if (onlyClasses) {
return true;
}
if (descriptors.size() == 1) {
return canImportMembersFrom(descriptors.iterator().next(), reference, trace, onlyClasses);
}
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace);
boolean canImport = false;
for (DeclarationDescriptor descriptor : descriptors) {
canImport |= canImportMembersFrom(descriptor, reference, temporaryTrace, onlyClasses);
}
if (!canImport) {
temporaryTrace.commit();
}
return canImport;
}
private boolean canImportMembersFrom(@NotNull DeclarationDescriptor descriptor,
@NotNull JetSimpleNameExpression reference,
@NotNull BindingTrace trace,
boolean onlyClasses) {
assert !onlyClasses;
if (descriptor instanceof NamespaceDescriptor) {
return true;
}
if (descriptor instanceof ClassDescriptor && ((ClassDescriptor)descriptor).getKind() != ClassKind.OBJECT) {
return true;
}
trace.report(CANNOT_IMPORT_FROM_ELEMENT.on(reference, descriptor));
return false;
}
@NotNull
public Collection<? extends DeclarationDescriptor> lookupDescriptorsForUserType(@NotNull JetUserType userType,
@NotNull JetScope outerScope,
@NotNull BindingTrace trace) {
if (userType.isAbsoluteInRootNamespace()) {
trace.report(Errors.UNSUPPORTED.on(userType, "package"));
return Collections.emptyList();
}
JetSimpleNameExpression referenceExpression = userType.getReferenceExpression();
if (referenceExpression == null) {
return Collections.emptyList();
}
JetUserType qualifier = userType.getQualifier();
if (qualifier == null) {
return lookupDescriptorsForSimpleNameReference(referenceExpression, outerScope, trace, true, false, true);
}
Collection<? extends DeclarationDescriptor> declarationDescriptors = lookupDescriptorsForUserType(qualifier, outerScope, trace);
return lookupSelectorDescriptors(referenceExpression, declarationDescriptors, trace, true, true);
}
@NotNull
public Collection<? extends DeclarationDescriptor> lookupDescriptorsForQualifiedExpression(@NotNull JetQualifiedExpression importedReference,
@NotNull JetScope outerScope,
@NotNull BindingTrace trace,
boolean onlyClasses,
boolean storeResult) {
JetExpression receiverExpression = importedReference.getReceiverExpression();
Collection<? extends DeclarationDescriptor> declarationDescriptors;
if (receiverExpression instanceof JetQualifiedExpression) {
declarationDescriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression)receiverExpression, outerScope, trace, onlyClasses, storeResult);
}
else {
assert receiverExpression instanceof JetSimpleNameExpression;
declarationDescriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression)receiverExpression, outerScope, trace, onlyClasses, true, storeResult);
}
JetExpression selectorExpression = importedReference.getSelectorExpression();
if (!(selectorExpression instanceof JetSimpleNameExpression)) {
return Collections.emptyList();
}
JetSimpleNameExpression selector = (JetSimpleNameExpression)selectorExpression;
JetSimpleNameExpression lastReference = JetPsiUtil.getLastReference(receiverExpression);
if (lastReference == null || !canImportMembersFrom(declarationDescriptors, lastReference, trace, onlyClasses)) {
return Collections.emptyList();
}
return lookupSelectorDescriptors(selector, declarationDescriptors, trace, onlyClasses, storeResult);
}
@NotNull
private Collection<? extends DeclarationDescriptor> lookupSelectorDescriptors(@NotNull JetSimpleNameExpression selector,
@NotNull Collection<? extends DeclarationDescriptor> declarationDescriptors,
@NotNull BindingTrace trace,
boolean onlyClasses,
boolean storeResult) {
Set<SuccessfulLookupResult> results = Sets.newHashSet();
for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) {
if (declarationDescriptor instanceof NamespaceDescriptor) {
addResult(results, lookupSimpleNameReference(selector, ((NamespaceDescriptor)declarationDescriptor).getMemberScope(), onlyClasses, true));
}
if (declarationDescriptor instanceof ClassDescriptor) {
addResult(results, lookupSimpleNameReference(selector, getAppropriateScope((ClassDescriptor)declarationDescriptor, onlyClasses), onlyClasses, false));
ClassDescriptor classObjectDescriptor = ((ClassDescriptor)declarationDescriptor).getClassObjectDescriptor();
if (classObjectDescriptor != null) {
addResult(results, lookupSimpleNameReference(selector, getAppropriateScope(classObjectDescriptor, onlyClasses), onlyClasses, false));
}
}
}
return filterAndStoreResolutionResult(results, selector, trace, onlyClasses, storeResult);
}
@NotNull
private JetScope getAppropriateScope(@NotNull ClassDescriptor classDescriptor, boolean onlyClasses) {
return onlyClasses ? classDescriptor.getUnsubstitutedInnerClassesScope() : classDescriptor.getDefaultType().getMemberScope();
}
private void addResult(@NotNull Set<SuccessfulLookupResult> results, @NotNull LookupResult result) {
if (result == LookupResult.EMPTY) return;
results.add((SuccessfulLookupResult)result);
}
@NotNull
public Collection<? extends DeclarationDescriptor> lookupDescriptorsForSimpleNameReference(@NotNull JetSimpleNameExpression referenceExpression,
@NotNull JetScope outerScope,
@NotNull BindingTrace trace,
boolean onlyClasses,
boolean namespaceLevel,
boolean storeResult) {
LookupResult lookupResult = lookupSimpleNameReference(referenceExpression, outerScope, onlyClasses, namespaceLevel);
if (lookupResult == LookupResult.EMPTY) return Collections.emptyList();
return filterAndStoreResolutionResult(Collections.singletonList((SuccessfulLookupResult)lookupResult), referenceExpression, trace,
onlyClasses, storeResult);
}
@NotNull
private LookupResult lookupSimpleNameReference(@NotNull JetSimpleNameExpression referenceExpression,
@NotNull JetScope outerScope,
boolean onlyClasses,
boolean namespaceLevel) {
String referencedName = referenceExpression.getReferencedName();
if (referencedName == null) {
//to store a scope where we tried to resolve this reference
return new SuccessfulLookupResult(Collections.<DeclarationDescriptor>emptyList(), outerScope, namespaceLevel);
}
Set<DeclarationDescriptor> descriptors = Sets.newHashSet();
NamespaceDescriptor namespaceDescriptor = outerScope.getNamespace(referencedName);
if (namespaceDescriptor != null) {
descriptors.add(namespaceDescriptor);
}
ClassifierDescriptor classifierDescriptor = outerScope.getClassifier(referencedName);
if (classifierDescriptor != null) {
descriptors.add(classifierDescriptor);
}
if (onlyClasses) {
ClassDescriptor objectDescriptor = outerScope.getObjectDescriptor(referencedName);
if (objectDescriptor != null) {
descriptors.add(objectDescriptor);
}
}
else {
descriptors.addAll(outerScope.getFunctions(referencedName));
descriptors.addAll(outerScope.getProperties(referencedName));
VariableDescriptor localVariable = outerScope.getLocalVariable(referencedName);
if (localVariable != null) {
descriptors.add(localVariable);
}
}
return new SuccessfulLookupResult(descriptors, outerScope, namespaceLevel);
}
@NotNull
private Collection<? extends DeclarationDescriptor> filterAndStoreResolutionResult(@NotNull Collection<SuccessfulLookupResult> lookupResults,
@NotNull JetSimpleNameExpression referenceExpression,
@NotNull BindingTrace trace,
boolean onlyClasses,
boolean storeResult) {
if (lookupResults.isEmpty()) {
return Collections.emptyList();
}
Collection<DeclarationDescriptor> descriptors = Sets.newLinkedHashSet();
for (SuccessfulLookupResult lookupResult : lookupResults) {
descriptors.addAll(lookupResult.descriptors);
}
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);
}
}
Collection<DeclarationDescriptor> filteredDescriptors;
if (onlyClasses) {
filteredDescriptors = Collections2.filter(descriptors, new Predicate<DeclarationDescriptor>() {
@Override
public boolean apply(@Nullable DeclarationDescriptor descriptor) {
return (descriptor instanceof ClassifierDescriptor) ||
(descriptor instanceof NamespaceDescriptor);
}
});
}
else {
filteredDescriptors = Sets.newLinkedHashSet();
//functions and properties can be imported if lookupResult.namespaceLevel == true
for (SuccessfulLookupResult lookupResult : lookupResults) {
if (lookupResult.namespaceLevel) {
filteredDescriptors.addAll(lookupResult.descriptors);
continue;
}
filteredDescriptors.addAll(Collections2.filter(lookupResult.descriptors, new Predicate<DeclarationDescriptor>() {
@Override
public boolean apply(@Nullable DeclarationDescriptor descriptor) {
return (descriptor instanceof NamespaceDescriptor) ||
(descriptor instanceof ClassifierDescriptor) ||
(descriptor instanceof VariableDescriptor && ((VariableDescriptor)descriptor).isObjectDeclaration());
}
}));
}
}
if (storeResult) {
storeResolutionResult(descriptors, filteredDescriptors, referenceExpression, possibleResolutionScopes, trace);
}
return filteredDescriptors;
}
private void storeResolutionResult(@NotNull Collection<? extends DeclarationDescriptor> descriptors,
@NotNull Collection<? extends DeclarationDescriptor> canBeImportedDescriptors,
@NotNull JetSimpleNameExpression referenceExpression,
@NotNull Collection<JetScope> possibleResolutionScopes,
@NotNull BindingTrace trace) {
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
if (resolveClassNamespaceAmbiguity(canBeImportedDescriptors, referenceExpression, resolutionScope, trace)) {
return;
}
// Simple case of no descriptors
if (descriptors.isEmpty()) {
trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope);
trace.report(UNRESOLVED_REFERENCE.on(referenceExpression));
return;
}
// Decide if expression has resolved reference
if (descriptors.size() == 1) {
assert canBeImportedDescriptors.size() <= 1;
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, descriptors.iterator().next());
trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope);
}
else if (canBeImportedDescriptors.size() == 1) {
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, canBeImportedDescriptors.iterator().next());
trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope);
}
// Check for more information and additional errors
if (canBeImportedDescriptors.isEmpty()) {
assert descriptors.size() >= 1;
trace.report(CANNOT_BE_IMPORTED.on(referenceExpression, descriptors.iterator().next()));
}
else if (canBeImportedDescriptors.size() > 1) {
trace.record(BindingContext.AMBIGUOUS_REFERENCE_TARGET, referenceExpression, descriptors);
}
}
/**
* This method tries to resolve descriptors ambiguity between class descriptor and namespace descriptor for the same class.
* It's ok choose class for expression reference resolution.
*
* @return <code>true</code> if method has successfully resolved ambiguity
*/
private boolean resolveClassNamespaceAmbiguity(@NotNull Collection<? extends DeclarationDescriptor> filteredDescriptors,
@NotNull JetSimpleNameExpression referenceExpression,
@NotNull JetScope resolutionScope,
@NotNull BindingTrace trace) {
if (filteredDescriptors.size() == 2) {
NamespaceDescriptor namespaceDescriptor = null;
ClassDescriptor classDescriptor = null;
for (DeclarationDescriptor filteredDescriptor : filteredDescriptors) {
if (filteredDescriptor instanceof NamespaceDescriptor) {
namespaceDescriptor = (NamespaceDescriptor)filteredDescriptor;
}
else if (filteredDescriptor instanceof ClassDescriptor) {
classDescriptor = (ClassDescriptor)filteredDescriptor;
}
}
if (namespaceDescriptor != null && classDescriptor != null) {
if (DescriptorUtils.getFQName(namespaceDescriptor).equals(DescriptorUtils.getFQName(classDescriptor))) {
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classDescriptor);
trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope);
return true;
}
}
}
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;
}
}
}
@@ -18,10 +18,7 @@ package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
@@ -32,11 +29,11 @@ import org.jetbrains.jet.util.lazy.LazyValue;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
/**
* @author abreslav
@@ -45,6 +42,7 @@ public class TypeResolver {
private AnnotationResolver annotationResolver;
private DescriptorResolver descriptorResolver;
private QualifiedExpressionResolver qualifiedExpressionResolver;
@Inject
public void setDescriptorResolver(DescriptorResolver descriptorResolver) {
@@ -56,6 +54,11 @@ public class TypeResolver {
this.annotationResolver = annotationResolver;
}
@Inject
public void setQualifiedExpressionResolver(QualifiedExpressionResolver qualifiedExpressionResolver) {
this.qualifiedExpressionResolver = qualifiedExpressionResolver;
}
@NotNull
public JetType resolveType(@NotNull final JetScope scope, @NotNull final JetTypeReference typeReference, BindingTrace trace, boolean checkBounds) {
JetType cachedType = trace.getBindingContext().get(BindingContext.TYPE, typeReference);
@@ -267,90 +270,13 @@ public class TypeResolver {
@Nullable
public ClassifierDescriptor resolveClass(JetScope scope, JetUserType userType, BindingTrace trace) {
ClassifierDescriptor classifierDescriptor = resolveClassWithoutErrorReporting(scope, userType, trace);
if (classifierDescriptor == null) {
trace.report(UNRESOLVED_REFERENCE.on(userType.getReferenceExpression()));
}
else {
trace.record(REFERENCE_TARGET, userType.getReferenceExpression(), classifierDescriptor);
}
return classifierDescriptor;
}
@Nullable
private ClassifierDescriptor resolveClassWithoutErrorReporting(JetScope scope, JetUserType userType, BindingTrace trace) {
JetSimpleNameExpression expression = userType.getReferenceExpression();
if (expression == null) {
return null;
}
String referencedName = expression.getReferencedName();
if (referencedName == null) {
return null;
}
ClassifierDescriptor classifierDescriptor;
if (userType.isAbsoluteInRootNamespace()) {
classifierDescriptor = JetModuleUtil.getRootNamespaceType(userType).getMemberScope().getClassifier(referencedName);
trace.record(BindingContext.RESOLUTION_SCOPE, userType.getReferenceExpression(),
JetModuleUtil.getRootNamespaceType(userType).getMemberScope());
}
else {
JetUserType qualifier = userType.getQualifier();
if (qualifier != null) {
scope = resolveClassLookupScope(scope, qualifier, trace);
}
if (scope == null) {
return ErrorUtils.getErrorClass();
}
classifierDescriptor = scope.getClassifier(referencedName);
trace.record(BindingContext.RESOLUTION_SCOPE, userType.getReferenceExpression(), scope);
}
return classifierDescriptor;
}
@Nullable
private JetScope resolveClassLookupScope(JetScope scope, JetUserType userType, BindingTrace trace) {
ClassifierDescriptor classifierDescriptor = resolveClassWithoutErrorReporting(scope, userType, trace);
if (classifierDescriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) classifierDescriptor;
JetType classObjectType = classDescriptor.getClassObjectType();
if (classObjectType != null) {
return classObjectType.getMemberScope();
Collection<? extends DeclarationDescriptor> descriptors = qualifiedExpressionResolver
.lookupDescriptorsForUserType(userType, scope, trace);
for (DeclarationDescriptor descriptor : descriptors) {
if (descriptor instanceof ClassifierDescriptor) {
return (ClassifierDescriptor) descriptor;
}
}
NamespaceDescriptor namespaceDescriptor = resolveNamespace(scope, userType, trace);
if (namespaceDescriptor == null) {
trace.report(UNRESOLVED_REFERENCE.on(userType.getReferenceExpression()));
return null;
}
return namespaceDescriptor.getMemberScope();
return null;
}
@Nullable
private NamespaceDescriptor resolveNamespace(JetScope scope, JetUserType userType, BindingTrace trace) {
if (userType.isAbsoluteInRootNamespace()) {
return resolveNamespace(JetModuleUtil.getRootNamespaceType(userType).getMemberScope(), userType, trace);
}
JetUserType qualifier = userType.getQualifier();
NamespaceDescriptor namespace;
if (qualifier != null) {
NamespaceDescriptor domain = resolveNamespace(scope, qualifier, trace);
if (domain == null) {
return null;
}
namespace = domain.getMemberScope().getNamespace(userType.getReferencedName());
}
else {
namespace = scope.getNamespace(userType.getReferencedName());
}
if (namespace != null) {
trace.record(BindingContext.REFERENCE_TARGET, userType.getReferenceExpression(), namespace);
}
return namespace;
}
}
@@ -183,7 +183,7 @@ public class ExpressionTypingUtils {
JetImportDirective importDirective = JetPsiFactory.createImportDirective(project, callableFQN.getFqName());
Collection<? extends DeclarationDescriptor> declarationDescriptors = ImportsResolver.analyseImportReference(importDirective, scope, new BindingTraceContext());
Collection<? extends DeclarationDescriptor> declarationDescriptors = new QualifiedExpressionResolver().analyseImportReference(importDirective, scope, new BindingTraceContext());
List<CallableDescriptor> callableExtensionDescriptors = new ArrayList<CallableDescriptor>();
ReceiverDescriptor receiverDescriptor = new ExpressionReceiver(receiverExpression, receiverType);
@@ -8,7 +8,7 @@ package n
// FILE: f.kt
abstract class XXX() {
abstract val a : Int
abstract val a1 : package.<!UNRESOLVED_REFERENCE!>Int<!>
abstract val a1 : <!UNSUPPORTED!>package.Int<!>
abstract val a2 : n.B
abstract val a3 : (A)
abstract val a31 : (n.B)
@@ -50,4 +50,4 @@ abstract class YYY() {
abstract val a17 : ((a : Int) -> Int).(a : Int) -> Int
abstract val a18 : (a : Int) -> ((a : Int) -> Int)
abstract val a19 : (b : (a : Int) -> Int) -> Int
}
}
@@ -1,5 +1,5 @@
package a
import A as ER
import a.A as ER
class A()
@@ -70,7 +70,7 @@ fun bar() {}
//FILE:c.kt
package c
import <!CANNOT_IMPORT_FROM_ELEMENT!>C<!>.*
import c.<!CANNOT_IMPORT_FROM_ELEMENT!>C<!>.*
object C {
fun f() {
@@ -85,8 +85,8 @@ fun foo() {
//FILE:d.kt
package d
import A.B
import A.C
import d.A.B
import d.A.C
val b : B = B()
val c : B = C
@@ -1,5 +1,5 @@
package a
import <!USELESS_SIMPLE_IMPORT!>B<!>
import <!USELESS_SIMPLE_IMPORT!>a<!>
object B {}
@@ -1,3 +1,4 @@
//KT-1579 Can't import nested class/trait
//FILE:a.kt
package lib
trait WithInner {
@@ -4,9 +4,17 @@ 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
//FILE:c.kt
//+JDK
package c
import java.util.Map
fun fff(b: Map.Entry<String, String>) = b
@@ -1,8 +1,8 @@
// import all members from class object
package c
import A.*
import <!CANNOT_IMPORT_FROM_ELEMENT!>M<!>.*
import c.A.*
import c.<!CANNOT_IMPORT_FROM_ELEMENT!>M<!>.*
fun foo() {
val <!UNUSED_VARIABLE!>b<!>: B = B()
@@ -2,11 +2,11 @@ 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
import d.<!CANNOT_IMPORT_FROM_ELEMENT!>A<!>.*
import d.<!CANNOT_IMPORT_FROM_ELEMENT!>M<!>.R
import d.<!CANNOT_IMPORT_FROM_ELEMENT!>M<!>.R.bar
import d.<!CANNOT_IMPORT_FROM_ELEMENT!>M<!>.T
import d.<!CANNOT_IMPORT_FROM_ELEMENT!>M<!>.Y
var r: T = <!UNRESOLVED_REFERENCE!>T<!>()
val y: T = <!UNRESOLVED_REFERENCE!>Y<!>
@@ -35,8 +35,8 @@ object N {
//FILE:b.kt
package b
import <!CANNOT_IMPORT_FROM_ELEMENT!>N<!>.M
import A.P
import b.<!CANNOT_IMPORT_FROM_ELEMENT!>N<!>.M
import b.A.P
import b.A.B
fun foo() {
@@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.resolve.calls.CallResolver;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.resolve.AnnotationResolver;
import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver;
import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
@@ -48,6 +49,7 @@ public class InjectorForTests {
this.jetStandardLibrary = JetStandardLibrary.getInstance();
this.project = project;
AnnotationResolver annotationResolver = new AnnotationResolver();
QualifiedExpressionResolver qualifiedExpressionResolver = new QualifiedExpressionResolver();
OverloadingConflictResolver overloadingConflictResolver = new OverloadingConflictResolver();
this.descriptorResolver.setAnnotationResolver(annotationResolver);
@@ -61,6 +63,7 @@ public class InjectorForTests {
this.typeResolver.setAnnotationResolver(annotationResolver);
this.typeResolver.setDescriptorResolver(descriptorResolver);
this.typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver);
this.callResolver.setDescriptorResolver(descriptorResolver);
this.callResolver.setExpressionTypingServices(expressionTypingServices);
@@ -175,7 +175,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
FqName functionFQN = JetFromJavaDescriptorHelper.getJetTopLevelDeclarationFQN(method);
if (functionFQN != null) {
JetImportDirective importDirective = JetPsiFactory.createImportDirective(project, new ImportPath(functionFQN, false));
Collection<? extends DeclarationDescriptor> declarationDescriptors = ImportsResolver.analyseImportReference(importDirective, jetScope, new BindingTraceContext());
Collection<? extends DeclarationDescriptor> declarationDescriptors = new QualifiedExpressionResolver().analyseImportReference(importDirective, jetScope, new BindingTraceContext());
for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) {
if (declarationDescriptor instanceof FunctionDescriptor) {
result.add((FunctionDescriptor) declarationDescriptor);
+1 -1
View File
@@ -12,7 +12,7 @@ fun test(<warning>l</warning> : java.util.List<Int>) {
val <warning>y</warning> : java.util.List<Int>
val <warning>b</warning> : java.lang.Object
val <warning>a</warning> : util.List<Int>
val <warning>z</warning> : java.<error>utils</error>.List<Int>
val <warning>z</warning> : java.<error>utils</error>.<error>List</error><Int>
val <warning>f</warning> : java.io.File? = null
@@ -2,5 +2,5 @@ package Test
import <caret>
// EXIST: java, javax, reflect
// EXIST: java, javax
// ABSENT: Array, Integer
@@ -135,8 +135,7 @@ public final class AnalyzerFacadeForJS {
}
@Override
public void addDefaultImports(@NotNull WritableScope rootScope,
@NotNull Collection<JetImportDirective> directives) {
public void addDefaultImports(@NotNull Collection<JetImportDirective> directives) {
directives.add(JetPsiFactory.createImportDirective(project, new ImportPath("js.*")));
directives.add(JetPsiFactory.createImportDirective(project, new ImportPath(JetStandardClasses.STANDARD_CLASSES_FQNAME, true)));
}