Merge remote-tracking branch 'origin/master'

This commit is contained in:
James Strachan
2011-12-20 17:28:53 +00:00
19 changed files with 346 additions and 110 deletions
@@ -85,7 +85,7 @@ public class AnalyzerFacade {
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project); JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project);
return AnalyzingUtils.analyzeNamespacesWithGivenTrace( return AnalyzingUtils.analyzeNamespacesWithGivenTrace(
project, project,
JavaBridgeConfiguration.createJavaBridgeConfiguration(project, bindingTraceContext, StandardConfiguration.createStandardConfiguration(project, semanticServices)), JavaBridgeConfiguration.createJavaBridgeConfiguration(project, bindingTraceContext, StandardConfiguration.createStandardConfiguration(project)),
declarations, declarations,
filesToAnalyzeCompletely, filesToAnalyzeCompletely,
flowDataTraceFactory, flowDataTraceFactory,
@@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory; import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithTextRange; import org.jetbrains.jet.lang.diagnostics.DiagnosticWithTextRange;
import org.jetbrains.jet.lang.diagnostics.Severity; import org.jetbrains.jet.lang.diagnostics.Severity;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -50,6 +51,7 @@ public class CheckerTestUtil {
} }
public interface DiagnosticDiffCallbacks { public interface DiagnosticDiffCallbacks {
@NotNull PsiFile getFile();
void missingDiagnostic(String type, int expectedStart, int expectedEnd); void missingDiagnostic(String type, int expectedStart, int expectedEnd);
void unexpectedDiagnostic(String type, int actualStart, int actualEnd); void unexpectedDiagnostic(String type, int actualStart, int actualEnd);
} }
@@ -129,6 +131,7 @@ public class CheckerTestUtil {
private static void unexpectedDiagnostics(List<Diagnostic> actual, DiagnosticDiffCallbacks callbacks) { private static void unexpectedDiagnostics(List<Diagnostic> actual, DiagnosticDiffCallbacks callbacks) {
for (Diagnostic diagnostic : actual) { for (Diagnostic diagnostic : actual) {
if (!diagnostic.getFactory().getPsiFile(diagnostic).equals(callbacks.getFile())) continue;
TextRange textRange = getTextRange(diagnostic); TextRange textRange = getTextRange(diagnostic);
callbacks.unexpectedDiagnostic(diagnostic.getFactory().getName(), textRange.getStartOffset(), textRange.getEndOffset()); callbacks.unexpectedDiagnostic(diagnostic.getFactory().getName(), textRange.getStartOffset(), textRange.getEndOffset());
} }
@@ -136,6 +139,7 @@ public class CheckerTestUtil {
private static void missingDiagnostics(DiagnosticDiffCallbacks callbacks, DiagnosedRange currentExpected) { private static void missingDiagnostics(DiagnosticDiffCallbacks callbacks, DiagnosedRange currentExpected) {
for (String type : currentExpected.getDiagnostics()) { for (String type : currentExpected.getDiagnostics()) {
if (!currentExpected.getFile().equals(callbacks.getFile())) return;
callbacks.missingDiagnostic(type, currentExpected.getStart(), currentExpected.getEnd()); callbacks.missingDiagnostic(type, currentExpected.getStart(), currentExpected.getEnd());
} }
} }
@@ -393,6 +397,7 @@ public class CheckerTestUtil {
private final int start; private final int start;
private int end; private int end;
private final Multiset<String> diagnostics = HashMultiset.create(); private final Multiset<String> diagnostics = HashMultiset.create();
private PsiFile file;
private DiagnosedRange(int start) { private DiagnosedRange(int start) {
this.start = start; this.start = start;
@@ -417,5 +422,14 @@ public class CheckerTestUtil {
public void addDiagnostic(String diagnostic) { public void addDiagnostic(String diagnostic) {
diagnostics.add(diagnostic); diagnostics.add(diagnostic);
} }
public void setFile(@NotNull PsiFile file) {
this.file = file;
}
@NotNull
public PsiFile getFile() {
return file;
}
} }
} }
@@ -7,7 +7,6 @@ import org.jetbrains.jet.lang.psi.JetImportDirective;
import org.jetbrains.jet.lang.psi.JetPsiFactory; import org.jetbrains.jet.lang.psi.JetPsiFactory;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.ImportsResolver; import org.jetbrains.jet.lang.resolve.ImportsResolver;
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
/** /**
@@ -15,24 +14,19 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
*/ */
public class StandardConfiguration implements Configuration { public class StandardConfiguration implements Configuration {
private Project project; private Project project;
private JetSemanticServices services;
public static StandardConfiguration createStandardConfiguration(Project project, JetSemanticServices services) { public static StandardConfiguration createStandardConfiguration(Project project) {
return new StandardConfiguration(services, project); return new StandardConfiguration(project);
} }
private StandardConfiguration(JetSemanticServices services, Project project) { private StandardConfiguration(Project project) {
this.services = services;
this.project = project; this.project = project;
} }
@Override @Override
public void addDefaultImports(@NotNull BindingTrace trace, @NotNull WritableScope rootScope) { public void addDefaultImports(@NotNull BindingTrace trace, @NotNull WritableScope rootScope) {
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace);
JetImportDirective importDirective = JetPsiFactory.createImportDirective(project, "std.*"); JetImportDirective importDirective = JetPsiFactory.createImportDirective(project, "std.*");
if (ImportsResolver.importNamespace(importDirective, rootScope, temporaryTrace, services)) { new ImportsResolver.ImportResolver(trace, true).processImportReference(importDirective, rootScope, rootScope);
temporaryTrace.commit();
}
} }
@Override @Override
@@ -74,9 +74,9 @@ public class AnalyzingUtils {
@NotNull Configuration configuration, @NotNull Configuration configuration,
@NotNull Collection<? extends JetDeclaration> declarations, @NotNull Collection<? extends JetDeclaration> declarations,
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely, @NotNull Predicate<PsiFile> filesToAnalyzeCompletely,
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
@NotNull JetSemanticServices semanticServices) {
BindingTraceContext bindingTraceContext = new BindingTraceContext(); BindingTraceContext bindingTraceContext = new BindingTraceContext();
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project);
return analyzeNamespacesWithGivenTrace(project, configuration, declarations, filesToAnalyzeCompletely, flowDataTraceFactory, bindingTraceContext, semanticServices); return analyzeNamespacesWithGivenTrace(project, configuration, declarations, filesToAnalyzeCompletely, flowDataTraceFactory, bindingTraceContext, semanticServices);
} }
@@ -33,7 +33,7 @@ public interface BindingContext {
WritableSlice<JetReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET = new BasicWritableSlice<JetReferenceExpression, DeclarationDescriptor>(DO_NOTHING); WritableSlice<JetReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET = new BasicWritableSlice<JetReferenceExpression, DeclarationDescriptor>(DO_NOTHING);
WritableSlice<JetElement, ResolvedCall<? extends CallableDescriptor>> RESOLVED_CALL = new BasicWritableSlice<JetElement, ResolvedCall<? extends CallableDescriptor>>(DO_NOTHING); WritableSlice<JetElement, ResolvedCall<? extends CallableDescriptor>> RESOLVED_CALL = new BasicWritableSlice<JetElement, ResolvedCall<? extends CallableDescriptor>>(DO_NOTHING);
WritableSlice<JetReferenceExpression, Collection<? extends ResolvedCallImpl<? extends DeclarationDescriptor>>> AMBIGUOUS_REFERENCE_TARGET = new BasicWritableSlice<JetReferenceExpression, Collection<? extends ResolvedCallImpl<? extends DeclarationDescriptor>>>(DO_NOTHING); WritableSlice<JetReferenceExpression, Collection<? extends DeclarationDescriptor>> AMBIGUOUS_REFERENCE_TARGET = new BasicWritableSlice<JetReferenceExpression, Collection<? extends DeclarationDescriptor>>(DO_NOTHING);
WritableSlice<JetExpression, FunctionDescriptor> LOOP_RANGE_ITERATOR = Slices.createSimpleSlice(); WritableSlice<JetExpression, FunctionDescriptor> LOOP_RANGE_ITERATOR = Slices.createSimpleSlice();
WritableSlice<JetExpression, CallableDescriptor> LOOP_RANGE_HAS_NEXT = Slices.createSimpleSlice(); WritableSlice<JetExpression, CallableDescriptor> LOOP_RANGE_HAS_NEXT = Slices.createSimpleSlice();
@@ -29,6 +29,7 @@ public class DeclarationResolver {
resolveConstructorHeaders(); resolveConstructorHeaders();
resolveAnnotationStubsOnClassesAndConstructors(); resolveAnnotationStubsOnClassesAndConstructors();
resolveFunctionAndPropertyHeaders(); resolveFunctionAndPropertyHeaders();
context.getImportsResolver().processMembersImports();
} }
private void resolveConstructorHeaders() { private void resolveConstructorHeaders() {
@@ -1,22 +1,24 @@
package org.jetbrains.jet.lang.resolve; package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
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 org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set;
import static org.jetbrains.jet.lang.diagnostics.Errors.UNRESOLVED_REFERENCE; import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.UNSUPPORTED;
/** /**
* @author abreslav * @author abreslav
* @author svtk
*/ */
public class ImportsResolver { public class ImportsResolver {
private final TopDownAnalysisContext context; private final TopDownAnalysisContext context;
@@ -26,90 +28,188 @@ public class ImportsResolver {
} }
public void processTypeImports() { public void processTypeImports() {
processImports(true);
}
public void processMembersImports() {
processImports(false);
}
private void processImports(boolean firstPhase) {
ImportResolver importResolver = new ImportResolver(context.getTrace(), firstPhase);
for (JetNamespace jetNamespace : context.getNamespaceDescriptors().keySet()) { for (JetNamespace jetNamespace : context.getNamespaceDescriptors().keySet()) {
processImports(jetNamespace, context.getNamespaceScopes().get(jetNamespace), context.getDeclaringScopes().get(jetNamespace)); WritableScope namespaceScope = context.getNamespaceScopes().get(jetNamespace);
if (firstPhase) {
context.getConfiguration().addDefaultImports(context.getTrace(), namespaceScope);
}
List<JetImportDirective> importDirectives = jetNamespace.getImportDirectives();
for (JetImportDirective importDirective : importDirectives) {
importResolver.processImportReference(importDirective, namespaceScope, context.getDeclaringScopes().get(jetNamespace));
}
} }
} }
private void processImports(@NotNull JetNamespace namespace, @NotNull WritableScope namespaceScope, @NotNull JetScope outerScope) { public static class ImportResolver {
context.getConfiguration().addDefaultImports(context.getTrace(), namespaceScope); private BindingTrace trace;
private boolean firstPhase;
List<JetImportDirective> importDirectives = namespace.getImportDirectives(); public ImportResolver(BindingTrace trace, boolean firstPhase) {
for (JetImportDirective importDirective : importDirectives) { this.trace = trace;
this.firstPhase = firstPhase;
}
public void processImportReference(JetImportDirective importDirective, WritableScope namespaceScope, JetScope outerScope) {
if (importDirective.isAbsoluteInRootNamespace()) { if (importDirective.isAbsoluteInRootNamespace()) {
context.getTrace().report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO trace.report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO
continue; return;
} }
if (importDirective.isAllUnder()) { JetExpression importedReference = importDirective.getImportedReference();
importNamespace(importDirective, namespaceScope, context.getTrace(), context.getSemanticServices()); if (importedReference == null) return;
Collection<DeclarationDescriptor> descriptors;
if (importedReference instanceof JetQualifiedExpression) {
descriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) importedReference, namespaceScope);
} }
else { else {
ClassifierDescriptor classifierDescriptor = null; assert importedReference instanceof JetSimpleNameExpression;
NamespaceDescriptor namespaceDescriptor = null; JetScope scope = importDirective.isAllUnder() ? namespaceScope : outerScope;
JetSimpleNameExpression referenceExpression = null; descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) importedReference, scope);
}
JetExpression importedReference = importDirective.getImportedReference(); if (importDirective.isAllUnder()) {
if (importedReference instanceof JetDotQualifiedExpression) { if (firstPhase) {
JetDotQualifiedExpression reference = (JetDotQualifiedExpression) importedReference; for (DeclarationDescriptor descriptor : descriptors) {
JetType type = context.getSemanticServices().getTypeInferrerServices(context.getTrace()).getTypeWithNamespaces(namespaceScope, reference.getReceiverExpression()); if (descriptor instanceof NamespaceDescriptor) {
JetExpression selectorExpression = reference.getSelectorExpression(); namespaceScope.importScope(((NamespaceDescriptor) descriptor).getMemberScope());
if (selectorExpression != null) {
referenceExpression = (JetSimpleNameExpression) selectorExpression;
String referencedName = referenceExpression.getReferencedName();
if (type != null && referencedName != null) {
classifierDescriptor = type.getMemberScope().getClassifier(referencedName);
namespaceDescriptor = type.getMemberScope().getNamespace(referencedName);
} }
} }
} }
return;
}
JetSimpleNameExpression referenceExpression = getLastReference(importedReference);
String aliasName = importDirective.getAliasName();
if (aliasName == null) {
aliasName = referenceExpression != null ? referenceExpression.getReferencedName() : null;
}
if (aliasName == null) return;
for (DeclarationDescriptor descriptor : descriptors) {
importDeclarationAlias(namespaceScope, aliasName, descriptor);
}
}
private void importDeclarationAlias(WritableScope namespaceScope, String aliasName, DeclarationDescriptor descriptor) {
if (firstPhase) {
if (descriptor instanceof ClassifierDescriptor) {
namespaceScope.importClassifierAlias(aliasName, (ClassifierDescriptor) descriptor);
return;
}
if (descriptor instanceof NamespaceDescriptor) {
namespaceScope.importNamespaceAlias(aliasName, (NamespaceDescriptor) descriptor);
return;
}
}
if (descriptor instanceof FunctionDescriptor) {
namespaceScope.importFunctionAlias(aliasName, (FunctionDescriptor) descriptor);
return;
}
if (descriptor instanceof VariableDescriptor) {
namespaceScope.importVariableAlias(aliasName, (VariableDescriptor) descriptor);
}
}
@Nullable
private static JetSimpleNameExpression getLastReference(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;
}
@NotNull
private Collection<DeclarationDescriptor> lookupDescriptorsForQualifiedExpression(@NotNull JetQualifiedExpression importedReference, @NotNull JetScope outerScope) {
JetExpression receiverExpression = importedReference.getReceiverExpression();
Collection<DeclarationDescriptor> declarationDescriptors;
if (receiverExpression instanceof JetQualifiedExpression) {
declarationDescriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) receiverExpression, outerScope);
}
else {
assert receiverExpression instanceof JetSimpleNameExpression;
declarationDescriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) receiverExpression, outerScope);
}
for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) {
JetExpression selectorExpression = importedReference.getSelectorExpression();
assert selectorExpression instanceof JetSimpleNameExpression;
JetSimpleNameExpression selector = (JetSimpleNameExpression) selectorExpression;
if (declarationDescriptor instanceof NamespaceDescriptor) {
return lookupDescriptorsForSimpleNameReference(selector, ((NamespaceDescriptor) declarationDescriptor).getMemberScope());
}
if (declarationDescriptor instanceof ClassDescriptor) {
JetSimpleNameExpression classReference = getLastReference(receiverExpression);
if (classReference != null) {
return lookupObjectMembers(selector, classReference, (ClassDescriptor) declarationDescriptor);
}
}
if (declarationDescriptor instanceof VariableDescriptor) {
return lookupVariableMembers(selector, (VariableDescriptor) declarationDescriptor);
}
}
return Collections.emptyList();
}
@NotNull
private Collection<DeclarationDescriptor> lookupObjectMembers(@NotNull JetSimpleNameExpression memberReference, @NotNull JetSimpleNameExpression classReference, @NotNull ClassDescriptor classDescriptor) {
if (firstPhase) return Collections.emptyList();
JetType classObjectType = classDescriptor.getClassObjectType();
if (classObjectType == null || !classDescriptor.isClassObjectAValue()) {
trace.report(NO_CLASS_OBJECT.on(classReference, classDescriptor));
return Collections.emptyList();
}
return lookupDescriptorsForSimpleNameReference(memberReference, classObjectType.getMemberScope());
}
@NotNull
private Collection<DeclarationDescriptor> lookupVariableMembers(@NotNull JetSimpleNameExpression memberReference, @NotNull VariableDescriptor variableDescriptor) {
if (firstPhase) return Collections.emptyList();
JetType variableType = variableDescriptor.getReturnType();
if (variableType == null) return Collections.emptyList();
return lookupDescriptorsForSimpleNameReference(memberReference, variableType.getMemberScope());
}
@NotNull
private Collection<DeclarationDescriptor> lookupDescriptorsForSimpleNameReference(@NotNull JetSimpleNameExpression referenceExpression, @NotNull JetScope outerScope) {
List<DeclarationDescriptor> descriptors = Lists.newArrayList();
String referencedName = referenceExpression.getReferencedName();
if (referencedName != null) {
NamespaceDescriptor namespaceDescriptor = outerScope.getNamespace(referencedName);
if (namespaceDescriptor != null) descriptors.add(namespaceDescriptor);
ClassifierDescriptor classifierDescriptor = outerScope.getClassifier(referencedName);
if (classifierDescriptor != null) descriptors.add(classifierDescriptor);
Set<FunctionDescriptor> functionDescriptors = outerScope.getFunctions(referencedName);
descriptors.addAll(functionDescriptors);
VariableDescriptor variableDescriptor = outerScope.getVariable(referencedName);
if (variableDescriptor != null) descriptors.add(variableDescriptor);
}
if (!firstPhase) {
if (descriptors.size() == 1) {
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, descriptors.iterator().next());
}
else if (descriptors.size() > 1) {
trace.record(BindingContext.AMBIGUOUS_REFERENCE_TARGET, referenceExpression, descriptors);
}
else { else {
assert importedReference instanceof JetSimpleNameExpression; trace.report(UNRESOLVED_REFERENCE.on(referenceExpression));
referenceExpression = (JetSimpleNameExpression) importedReference;
String referencedName = referenceExpression.getReferencedName();
if (referencedName != null) {
classifierDescriptor = outerScope.getClassifier(referencedName);
namespaceDescriptor = outerScope.getNamespace(referencedName);
if (classifierDescriptor == null && namespaceDescriptor == null) {
context.getTrace().report(UNRESOLVED_REFERENCE.on(referenceExpression));
}
}
}
String aliasName = importDirective.getAliasName();
if (aliasName == null) {
aliasName = referenceExpression != null ? referenceExpression.getReferencedName() : null;
}
if (classifierDescriptor != null) {
context.getTrace().record(BindingContext.REFERENCE_TARGET, referenceExpression, classifierDescriptor);
if (aliasName != null) {
namespaceScope.importClassifierAlias(aliasName, classifierDescriptor);
}
}
if (namespaceDescriptor != null) {
if (classifierDescriptor == null) {
context.getTrace().record(BindingContext.REFERENCE_TARGET, referenceExpression, namespaceDescriptor);
}
if (aliasName != null) {
namespaceScope.importNamespaceAlias(aliasName, namespaceDescriptor);
}
} }
} }
return descriptors;
} }
} }
public static boolean importNamespace(JetImportDirective importDirective, WritableScope namespaceScope, @NotNull BindingTrace trace, @NotNull JetSemanticServices services) {
JetExpression importedReference = importDirective.getImportedReference();
if (importedReference != null) {
ExpressionTypingServices typeInferrerServices = services.getTypeInferrerServices(trace);
JetType type = typeInferrerServices.getTypeWithNamespaces(namespaceScope, importedReference);
if (type != null) {
namespaceScope.importScope(type.getMemberScope());
return true;
}
}
return false;
}
} }
@@ -27,6 +27,7 @@ import java.util.Set;
private final Configuration configuration; private final Configuration configuration;
private final DescriptorResolver descriptorResolver; private final DescriptorResolver descriptorResolver;
private final ImportsResolver importsResolver;
private final Map<JetClass, MutableClassDescriptor> classes = Maps.newLinkedHashMap(); private final Map<JetClass, MutableClassDescriptor> classes = Maps.newLinkedHashMap();
private final Map<JetObjectDeclaration, MutableClassDescriptor> objects = Maps.newLinkedHashMap(); private final Map<JetObjectDeclaration, MutableClassDescriptor> objects = Maps.newLinkedHashMap();
protected final Map<JetNamespace, WritableScope> namespaceScopes = Maps.newHashMap(); protected final Map<JetNamespace, WritableScope> namespaceScopes = Maps.newHashMap();
@@ -48,6 +49,7 @@ import java.util.Set;
this.trace = new ObservableBindingTrace(trace); this.trace = new ObservableBindingTrace(trace);
this.semanticServices = semanticServices; this.semanticServices = semanticServices;
this.descriptorResolver = semanticServices.getClassDescriptorResolver(trace); this.descriptorResolver = semanticServices.getClassDescriptorResolver(trace);
this.importsResolver = new ImportsResolver(this);
this.analyzeCompletely = analyzeCompletely; this.analyzeCompletely = analyzeCompletely;
this.configuration = configuration; this.configuration = configuration;
this.declaredLocally = declaredLocally; this.declaredLocally = declaredLocally;
@@ -100,6 +102,10 @@ import java.util.Set;
return descriptorResolver; return descriptorResolver;
} }
public ImportsResolver getImportsResolver() {
return importsResolver;
}
public Map<JetClass, MutableClassDescriptor> getClasses() { public Map<JetClass, MutableClassDescriptor> getClasses() {
return classes; return classes;
} }
@@ -32,19 +32,17 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.*;
*/ */
public class TypeHierarchyResolver { public class TypeHierarchyResolver {
private final TopDownAnalysisContext context; private final TopDownAnalysisContext context;
private final ImportsResolver importsResolver;
private LinkedList<MutableClassDescriptor> topologicalOrder; private LinkedList<MutableClassDescriptor> topologicalOrder;
public TypeHierarchyResolver(TopDownAnalysisContext context) { public TypeHierarchyResolver(TopDownAnalysisContext context) {
this.context = context; this.context = context;
this.importsResolver = new ImportsResolver(context);
} }
public void process(@NotNull JetScope outerScope, @NotNull NamespaceLike owner, @NotNull Collection<? extends JetDeclaration> declarations) { public void process(@NotNull JetScope outerScope, @NotNull NamespaceLike owner, @NotNull Collection<? extends JetDeclaration> declarations) {
collectNamespacesAndClassifiers(outerScope, outerScope, owner, declarations); // namespaceScopes, classes collectNamespacesAndClassifiers(outerScope, outerScope, owner, declarations); // namespaceScopes, classes
importsResolver.processTypeImports(); context.getImportsResolver().processTypeImports();
createTypeConstructors(); // create type constructors for classes and generic parameters, supertypes are not filled in createTypeConstructors(); // create type constructors for classes and generic parameters, supertypes are not filled in
resolveTypesInClassHeaders(); // Generic bounds and types in supertype lists (no expressions or constructor resolution) resolveTypesInClassHeaders(); // Generic bounds and types in supertype lists (no expressions or constructor resolution)
@@ -260,7 +260,11 @@ public class CallResolver {
@Override @Override
public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<ResolvedCallImpl<D>> candidates) { public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<ResolvedCallImpl<D>> candidates) {
trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, candidates); Collection<D> descriptors = Sets.newHashSet();
for (ResolvedCallImpl<D> candidate : candidates) {
descriptors.add(candidate.getCandidateDescriptor());
}
trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, descriptors);
} }
@Override @Override
@@ -31,6 +31,10 @@ public interface WritableScope extends JetScope {
void addNamespaceAlias(@NotNull String name, @NotNull NamespaceDescriptor namespaceDescriptor); void addNamespaceAlias(@NotNull String name, @NotNull NamespaceDescriptor namespaceDescriptor);
void addFunctionAlias(@NotNull String name, @NotNull FunctionDescriptor functionDescriptor);
void addVariableAlias(@NotNull String name, @NotNull VariableDescriptor variableDescriptor);
void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor); void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor);
@Nullable @Nullable
@@ -42,5 +46,9 @@ public interface WritableScope extends JetScope {
void importClassifierAlias(@NotNull String importedClassifierName, @NotNull ClassifierDescriptor classifierDescriptor); void importClassifierAlias(@NotNull String importedClassifierName, @NotNull ClassifierDescriptor classifierDescriptor);
void importNamespaceAlias(String aliasName, NamespaceDescriptor namespaceDescriptor); void importNamespaceAlias(@NotNull String aliasName, @NotNull NamespaceDescriptor namespaceDescriptor);
void importFunctionAlias(@NotNull String aliasName, @NotNull FunctionDescriptor functionDescriptor);
void importVariableAlias(@NotNull String aliasName, @NotNull VariableDescriptor variableDescriptor);
} }
@@ -68,13 +68,30 @@ public class WritableScopeImpl extends WritableScopeWithImports {
} }
@Override @Override
public void importNamespaceAlias(String aliasName, NamespaceDescriptor namespaceDescriptor) { public void importNamespaceAlias(@NotNull String aliasName, @NotNull NamespaceDescriptor namespaceDescriptor) {
checkMayWrite(); checkMayWrite();
allDescriptors.add(namespaceDescriptor); allDescriptors.add(namespaceDescriptor);
super.importNamespaceAlias(aliasName, namespaceDescriptor); super.importNamespaceAlias(aliasName, namespaceDescriptor);
} }
@Override
public void importFunctionAlias(@NotNull String aliasName, @NotNull FunctionDescriptor functionDescriptor) {
checkMayWrite();
addFunctionDescriptor(functionDescriptor);
super.importFunctionAlias(aliasName, functionDescriptor);
}
@Override
public void importVariableAlias(@NotNull String aliasName, @NotNull VariableDescriptor variableDescriptor) {
checkMayWrite();
addVariableDescriptor(variableDescriptor);
super.importVariableAlias(aliasName, variableDescriptor);
}
@NotNull @NotNull
@Override @Override
public Collection<DeclarationDescriptor> getAllDescriptors() { public Collection<DeclarationDescriptor> getAllDescriptors() {
@@ -240,6 +257,24 @@ public class WritableScopeImpl extends WritableScopeWithImports {
allDescriptors.add(namespaceDescriptor); allDescriptors.add(namespaceDescriptor);
} }
@Override
public void addFunctionAlias(@NotNull String name, @NotNull FunctionDescriptor functionDescriptor) {
checkMayWrite();
checkForRedeclaration(name, functionDescriptor);
getFunctionGroups().put(name, functionDescriptor);
allDescriptors.add(functionDescriptor);
}
@Override
public void addVariableAlias(@NotNull String name, @NotNull VariableDescriptor variableDescriptor) {
checkMayWrite();
checkForRedeclaration(name, variableDescriptor);
getVariableClassOrNamespaceDescriptors().put(name, variableDescriptor);
allDescriptors.add(variableDescriptor);
}
private void checkForRedeclaration(String name, DeclarationDescriptor classifierDescriptor) { private void checkForRedeclaration(String name, DeclarationDescriptor classifierDescriptor) {
DeclarationDescriptor originalDescriptor = getVariableClassOrNamespaceDescriptors().get(name); DeclarationDescriptor originalDescriptor = getVariableClassOrNamespaceDescriptors().get(name);
if (originalDescriptor != null) { if (originalDescriptor != null) {
@@ -3,10 +3,7 @@ package org.jetbrains.jet.lang.resolve.scopes;
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.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import java.util.ArrayList; import java.util.ArrayList;
@@ -173,12 +170,26 @@ public abstract class WritableScopeWithImports extends JetScopeAdapter implement
@Override @Override
public void importNamespaceAlias(String aliasName, NamespaceDescriptor namespaceDescriptor) { public void importNamespaceAlias(@NotNull String aliasName, @NotNull NamespaceDescriptor namespaceDescriptor) {
checkMayWrite(); checkMayWrite();
getCurrentIndividualImportScope().addNamespaceAlias(aliasName, namespaceDescriptor); getCurrentIndividualImportScope().addNamespaceAlias(aliasName, namespaceDescriptor);
} }
@Override
public void importFunctionAlias(@NotNull String aliasName, @NotNull FunctionDescriptor functionDescriptor) {
checkMayWrite();
getCurrentIndividualImportScope().addFunctionAlias(aliasName, functionDescriptor);
}
@Override
public void importVariableAlias(@NotNull String aliasName, @NotNull VariableDescriptor variableDescriptor) {
checkMayWrite();
getCurrentIndividualImportScope().addVariableAlias(aliasName, variableDescriptor);
}
@Override @Override
public String toString() { public String toString() {
return getClass().getSimpleName() + "@" + Integer.toHexString(System.identityHashCode(this)) + " " + debugName + " for " + getContainingDeclaration(); return getClass().getSimpleName() + "@" + Integer.toHexString(System.identityHashCode(this)) + " " + debugName + " for " + getContainingDeclaration();
@@ -161,6 +161,20 @@ public class WriteThroughScope extends WritableScopeWithImports {
writableWorker.addNamespaceAlias(name, namespaceDescriptor); writableWorker.addNamespaceAlias(name, namespaceDescriptor);
} }
@Override
public void addVariableAlias(@NotNull String name, @NotNull VariableDescriptor variableDescriptor) {
checkMayWrite();
writableWorker.addVariableAlias(name, variableDescriptor);
}
@Override
public void addFunctionAlias(@NotNull String name, @NotNull FunctionDescriptor functionDescriptor) {
checkMayWrite();
writableWorker.addFunctionAlias(name, functionDescriptor);
}
@Override @Override
public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) { public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
checkMayWrite(); checkMayWrite();
@@ -0,0 +1,32 @@
//FILE:a.kt
namespace a
import b.B //class
import b.foo //function
import b.ext //extension function
import b.value //property
import b.C.bar //function from class object
import b.C.cValue //property from class object
fun test(arg: B) {
foo(value)
arg.ext()
}
//FILE:b.kt
namespace b
class B() {}
fun foo(<!UNUSED_PARAMETER!>i<!>: Int) {}
fun B.ext() {}
val value = 0
class C() {
class object {
fun bar() {}
val cValue = 1
}
}
@@ -2,6 +2,7 @@ package org.jetbrains.jet.checkers;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetLiteFixture; import org.jetbrains.jet.JetLiteFixture;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.Diagnostic;
@@ -79,7 +80,7 @@ public class CheckerTestUtilTest extends JetLiteFixture {
this.expected = expectedMessages; this.expected = expectedMessages;
} }
public void test(PsiFile psiFile) { public void test(final @NotNull PsiFile psiFile) {
BindingContext bindingContext = AnalyzerFacade.analyzeOneNamespaceWithJavaIntegration( BindingContext bindingContext = AnalyzerFacade.analyzeOneNamespaceWithJavaIntegration(
((JetFile) psiFile).getRootNamespace(), ((JetFile) psiFile).getRootNamespace(),
JetControlFlowDataTraceFactory.EMPTY); JetControlFlowDataTraceFactory.EMPTY);
@@ -88,6 +89,9 @@ public class CheckerTestUtilTest extends JetLiteFixture {
List<CheckerTestUtil.DiagnosedRange> diagnosedRanges = Lists.newArrayList(); List<CheckerTestUtil.DiagnosedRange> diagnosedRanges = Lists.newArrayList();
CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges); CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges);
for (CheckerTestUtil.DiagnosedRange diagnosedRange : diagnosedRanges) {
diagnosedRange.setFile(psiFile);
}
List<Diagnostic> diagnostics = CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile); List<Diagnostic> diagnostics = CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile);
Collections.sort(diagnostics, CheckerTestUtil.DIAGNOSTIC_COMPARATOR); Collections.sort(diagnostics, CheckerTestUtil.DIAGNOSTIC_COMPARATOR);
@@ -98,6 +102,12 @@ public class CheckerTestUtilTest extends JetLiteFixture {
final List<String> actualMessages = Lists.newArrayList(); final List<String> actualMessages = Lists.newArrayList();
CheckerTestUtil.diagnosticsDiff(diagnosedRanges, diagnostics, new CheckerTestUtil.DiagnosticDiffCallbacks() { CheckerTestUtil.diagnosticsDiff(diagnosedRanges, diagnostics, new CheckerTestUtil.DiagnosticDiffCallbacks() {
@NotNull
@Override
public PsiFile getFile() {
return psiFile;
}
@Override @Override
public void missingDiagnostic(String type, int expectedStart, int expectedEnd) { public void missingDiagnostic(String type, int expectedStart, int expectedEnd) {
String message = "Missing " + type + " at " + expectedStart + " to " + expectedEnd; String message = "Missing " + type + " at " + expectedStart + " to " + expectedEnd;
@@ -52,10 +52,19 @@ public class JetDiagnosticsTest extends JetLiteFixture {
expectedText = textWithMarkers; expectedText = textWithMarkers;
clearText = CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges); clearText = CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges);
jetFile = createCheckAndReturnPsiFile(fileName, clearText); jetFile = createCheckAndReturnPsiFile(fileName, clearText);
for (CheckerTestUtil.DiagnosedRange diagnosedRange : diagnosedRanges) {
diagnosedRange.setFile(jetFile);
}
} }
public void getActualText(BindingContext bindingContext, StringBuilder actualText) { public void getActualText(BindingContext bindingContext, StringBuilder actualText) {
CheckerTestUtil.diagnosticsDiff(diagnosedRanges, CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, jetFile), new CheckerTestUtil.DiagnosticDiffCallbacks() { CheckerTestUtil.diagnosticsDiff(diagnosedRanges, CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, jetFile), new CheckerTestUtil.DiagnosticDiffCallbacks() {
@NotNull
@Override
public PsiFile getFile() {
return jetFile;
}
@Override @Override
public void missingDiagnostic(String type, int expectedStart, int expectedEnd) { public void missingDiagnostic(String type, int expectedStart, int expectedEnd) {
String message = "Missing " + type + DiagnosticUtils.atLocation(jetFile, new TextRange(expectedStart, expectedEnd)); String message = "Missing " + type + DiagnosticUtils.atLocation(jetFile, new TextRange(expectedStart, expectedEnd));
@@ -95,7 +104,7 @@ public class JetDiagnosticsTest extends JetLiteFixture {
bindingContext = AnalyzerFacade.analyzeNamespacesWithJavaIntegration(getProject(), namespaces, Predicates.<PsiFile>alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY); bindingContext = AnalyzerFacade.analyzeNamespacesWithJavaIntegration(getProject(), namespaces, Predicates.<PsiFile>alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY);
} }
else { else {
bindingContext = AnalyzingUtils.analyzeNamespaces(getProject(), Configuration.EMPTY, namespaces, Predicates.<PsiFile>alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY, JetSemanticServices.createSemanticServices(getProject())); bindingContext = AnalyzingUtils.analyzeNamespaces(getProject(), Configuration.EMPTY, namespaces, Predicates.<PsiFile>alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY);
} }
StringBuilder actualText = new StringBuilder(); StringBuilder actualText = new StringBuilder();
@@ -95,7 +95,7 @@ public class DebugInfoAnnotator implements Annotator {
target = labelTarget.getText(); target = labelTarget.getText();
} }
else { else {
Collection<? extends ResolvedCallImpl<? extends DeclarationDescriptor>> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, expression); Collection<? extends DeclarationDescriptor> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, expression);
if (declarationDescriptors != null) { if (declarationDescriptors != null) {
target = "[" + declarationDescriptors.size() + " descriptors]"; target = "[" + declarationDescriptors.size() + " descriptors]";
} }
@@ -81,7 +81,7 @@ public abstract class JetPsiReference implements PsiPolyVariantReference {
if (psiElement != null) { if (psiElement != null) {
return psiElement; return psiElement;
} }
Collection<? extends ResolvedCallImpl<? extends DeclarationDescriptor>> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression); Collection<? extends DeclarationDescriptor> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression);
if (declarationDescriptors != null) return null; if (declarationDescriptors != null) return null;
return file; return file;
} }
@@ -89,12 +89,12 @@ public abstract class JetPsiReference implements PsiPolyVariantReference {
protected ResolveResult[] doMultiResolve() { protected ResolveResult[] doMultiResolve() {
JetFile file = (JetFile) getElement().getContainingFile(); JetFile file = (JetFile) getElement().getContainingFile();
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file); BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
Collection<? extends ResolvedCallImpl<? extends DeclarationDescriptor>> resolvedCalls = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression); Collection<? extends DeclarationDescriptor> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression);
if (resolvedCalls == null) return ResolveResult.EMPTY_ARRAY; if (declarationDescriptors == null) return ResolveResult.EMPTY_ARRAY;
ResolveResult[] results = new ResolveResult[resolvedCalls.size()]; ResolveResult[] results = new ResolveResult[declarationDescriptors.size()];
int i = 0; int i = 0;
for (ResolvedCallImpl<? extends DeclarationDescriptor> resolvedCall : resolvedCalls) { for (DeclarationDescriptor descriptor : declarationDescriptors) {
PsiElement element = bindingContext.get(DESCRIPTOR_TO_DECLARATION, resolvedCall.getResultingDescriptor()); PsiElement element = bindingContext.get(DESCRIPTOR_TO_DECLARATION, descriptor);
if (element != null) { if (element != null) {
results[i] = new PsiElementResolveResult(element, true); results[i] = new PsiElementResolveResult(element, true);
i++; i++;