From 66bbddf21712b83af0a0a9670f11f096438975d4 Mon Sep 17 00:00:00 2001 From: svtk Date: Tue, 20 Dec 2011 20:14:04 +0400 Subject: [PATCH 1/2] changed imports resolve --- .../jet/lang/resolve/java/AnalyzerFacade.java | 2 +- .../jet/lang/StandardConfiguration.java | 14 +- .../jet/lang/resolve/AnalyzingUtils.java | 4 +- .../jet/lang/resolve/BindingContext.java | 2 +- .../jet/lang/resolve/DeclarationResolver.java | 1 + .../jet/lang/resolve/ImportsResolver.java | 250 ++++++++++++------ .../lang/resolve/TopDownAnalysisContext.java | 6 + .../lang/resolve/TypeHierarchyResolver.java | 4 +- .../jet/lang/resolve/calls/CallResolver.java | 6 +- .../lang/resolve/scopes/WritableScope.java | 10 +- .../resolve/scopes/WritableScopeImpl.java | 37 ++- .../scopes/WritableScopeWithImports.java | 23 +- .../resolve/scopes/WriteThroughScope.java | 14 + .../diagnostics/tests/scopes/Imports.jet | 32 +++ .../annotations/DebugInfoAnnotator.java | 2 +- .../plugin/references/JetPsiReference.java | 12 +- 16 files changed, 311 insertions(+), 108 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/scopes/Imports.jet diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacade.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacade.java index c7501b85c78..f878d443fce 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacade.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacade.java @@ -85,7 +85,7 @@ public class AnalyzerFacade { JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project); return AnalyzingUtils.analyzeNamespacesWithGivenTrace( project, - JavaBridgeConfiguration.createJavaBridgeConfiguration(project, bindingTraceContext, StandardConfiguration.createStandardConfiguration(project, semanticServices)), + JavaBridgeConfiguration.createJavaBridgeConfiguration(project, bindingTraceContext, StandardConfiguration.createStandardConfiguration(project)), declarations, filesToAnalyzeCompletely, flowDataTraceFactory, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/StandardConfiguration.java b/compiler/frontend/src/org/jetbrains/jet/lang/StandardConfiguration.java index e4ddbd8f033..30a2675b2a8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/StandardConfiguration.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/StandardConfiguration.java @@ -7,7 +7,6 @@ import org.jetbrains.jet.lang.psi.JetImportDirective; import org.jetbrains.jet.lang.psi.JetPsiFactory; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.ImportsResolver; -import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; 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 { private Project project; - private JetSemanticServices services; - public static StandardConfiguration createStandardConfiguration(Project project, JetSemanticServices services) { - return new StandardConfiguration(services, project); + public static StandardConfiguration createStandardConfiguration(Project project) { + return new StandardConfiguration(project); } - private StandardConfiguration(JetSemanticServices services, Project project) { - this.services = services; + private StandardConfiguration(Project project) { this.project = project; } @Override public void addDefaultImports(@NotNull BindingTrace trace, @NotNull WritableScope rootScope) { - TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace); JetImportDirective importDirective = JetPsiFactory.createImportDirective(project, "std.*"); - if (ImportsResolver.importNamespace(importDirective, rootScope, temporaryTrace, services)) { - temporaryTrace.commit(); - } + new ImportsResolver.ImportResolver(trace, true).processImportReference(importDirective, rootScope, rootScope); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java index 911a7d778fb..2a1ccf5ad84 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java @@ -74,9 +74,9 @@ public class AnalyzingUtils { @NotNull Configuration configuration, @NotNull Collection declarations, @NotNull Predicate filesToAnalyzeCompletely, - @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory, - @NotNull JetSemanticServices semanticServices) { + @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { BindingTraceContext bindingTraceContext = new BindingTraceContext(); + JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project); return analyzeNamespacesWithGivenTrace(project, configuration, declarations, filesToAnalyzeCompletely, flowDataTraceFactory, bindingTraceContext, semanticServices); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java index 3fa295944a8..0799347b34b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -33,7 +33,7 @@ public interface BindingContext { WritableSlice REFERENCE_TARGET = new BasicWritableSlice(DO_NOTHING); WritableSlice> RESOLVED_CALL = new BasicWritableSlice>(DO_NOTHING); - WritableSlice>> AMBIGUOUS_REFERENCE_TARGET = new BasicWritableSlice>>(DO_NOTHING); + WritableSlice> AMBIGUOUS_REFERENCE_TARGET = new BasicWritableSlice>(DO_NOTHING); WritableSlice LOOP_RANGE_ITERATOR = Slices.createSimpleSlice(); WritableSlice LOOP_RANGE_HAS_NEXT = Slices.createSimpleSlice(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java index bea45569b2c..d7d495ad416 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java @@ -29,6 +29,7 @@ public class DeclarationResolver { resolveConstructorHeaders(); resolveAnnotationStubsOnClassesAndConstructors(); resolveFunctionAndPropertyHeaders(); + context.getImportsResolver().processMembersImports(); } private void resolveConstructorHeaders() { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java index a4c30b5fb32..af23ece699e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java @@ -1,22 +1,24 @@ package org.jetbrains.jet.lang.resolve; +import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.JetSemanticServices; -import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; -import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; 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.Set; -import static org.jetbrains.jet.lang.diagnostics.Errors.UNRESOLVED_REFERENCE; -import static org.jetbrains.jet.lang.diagnostics.Errors.UNSUPPORTED; +import static org.jetbrains.jet.lang.diagnostics.Errors.*; /** * @author abreslav + * @author svtk */ public class ImportsResolver { private final TopDownAnalysisContext context; @@ -26,90 +28,188 @@ public class ImportsResolver { } 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()) { - 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 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) { - context.getConfiguration().addDefaultImports(context.getTrace(), namespaceScope); + public static class ImportResolver { + private BindingTrace trace; + private boolean firstPhase; - List importDirectives = namespace.getImportDirectives(); - for (JetImportDirective importDirective : importDirectives) { + public ImportResolver(BindingTrace trace, boolean firstPhase) { + this.trace = trace; + this.firstPhase = firstPhase; + } + + public void processImportReference(JetImportDirective importDirective, WritableScope namespaceScope, JetScope outerScope) { if (importDirective.isAbsoluteInRootNamespace()) { - context.getTrace().report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO - continue; + trace.report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO + return; } - if (importDirective.isAllUnder()) { - importNamespace(importDirective, namespaceScope, context.getTrace(), context.getSemanticServices()); + JetExpression importedReference = importDirective.getImportedReference(); + if (importedReference == null) return; + Collection descriptors; + if (importedReference instanceof JetQualifiedExpression) { + descriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) importedReference, namespaceScope); } else { - ClassifierDescriptor classifierDescriptor = null; - NamespaceDescriptor namespaceDescriptor = null; - JetSimpleNameExpression referenceExpression = null; - - JetExpression importedReference = importDirective.getImportedReference(); - if (importedReference instanceof JetDotQualifiedExpression) { - JetDotQualifiedExpression reference = (JetDotQualifiedExpression) importedReference; - JetType type = context.getSemanticServices().getTypeInferrerServices(context.getTrace()).getTypeWithNamespaces(namespaceScope, reference.getReceiverExpression()); - JetExpression selectorExpression = reference.getSelectorExpression(); - 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); + assert importedReference instanceof JetSimpleNameExpression; + JetScope scope = importDirective.isAllUnder() ? namespaceScope : outerScope; + descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) importedReference, scope); + } + if (importDirective.isAllUnder()) { + if (firstPhase) { + for (DeclarationDescriptor descriptor : descriptors) { + if (descriptor instanceof NamespaceDescriptor) { + namespaceScope.importScope(((NamespaceDescriptor) descriptor).getMemberScope()); } } } + 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 lookupDescriptorsForQualifiedExpression(@NotNull JetQualifiedExpression importedReference, @NotNull JetScope outerScope) { + JetExpression receiverExpression = importedReference.getReceiverExpression(); + Collection 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 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 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 lookupDescriptorsForSimpleNameReference(@NotNull JetSimpleNameExpression referenceExpression, @NotNull JetScope outerScope) { + List 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 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 { - assert importedReference instanceof JetSimpleNameExpression; - 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); - } + trace.report(UNRESOLVED_REFERENCE.on(referenceExpression)); } } + 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; - } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java index 31120e2c081..8b5148b0210 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java @@ -27,6 +27,7 @@ import java.util.Set; private final Configuration configuration; private final DescriptorResolver descriptorResolver; + private final ImportsResolver importsResolver; private final Map classes = Maps.newLinkedHashMap(); private final Map objects = Maps.newLinkedHashMap(); protected final Map namespaceScopes = Maps.newHashMap(); @@ -48,6 +49,7 @@ import java.util.Set; this.trace = new ObservableBindingTrace(trace); this.semanticServices = semanticServices; this.descriptorResolver = semanticServices.getClassDescriptorResolver(trace); + this.importsResolver = new ImportsResolver(this); this.analyzeCompletely = analyzeCompletely; this.configuration = configuration; this.declaredLocally = declaredLocally; @@ -100,6 +102,10 @@ import java.util.Set; return descriptorResolver; } + public ImportsResolver getImportsResolver() { + return importsResolver; + } + public Map getClasses() { return classes; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java index 5bff2b93d31..7a3efc82906 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java @@ -32,19 +32,17 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.*; */ public class TypeHierarchyResolver { private final TopDownAnalysisContext context; - private final ImportsResolver importsResolver; private LinkedList topologicalOrder; public TypeHierarchyResolver(TopDownAnalysisContext context) { this.context = context; - this.importsResolver = new ImportsResolver(context); } public void process(@NotNull JetScope outerScope, @NotNull NamespaceLike owner, @NotNull Collection declarations) { 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 resolveTypesInClassHeaders(); // Generic bounds and types in supertype lists (no expressions or constructor resolution) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 18524d28943..2401d6328e4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -259,7 +259,11 @@ public class CallResolver { @Override public void recordAmbiguity(BindingTrace trace, Collection> candidates) { - trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, candidates); + Collection descriptors = Sets.newHashSet(); + for (ResolvedCallImpl candidate : candidates) { + descriptors.add(candidate.getCandidateDescriptor()); + } + trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, descriptors); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScope.java index e0d2df9cc51..ac06875abca 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScope.java @@ -30,6 +30,10 @@ public interface WritableScope extends JetScope { void addClassifierAlias(@NotNull String name, @NotNull ClassifierDescriptor classifierDescriptor); 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); @@ -42,5 +46,9 @@ public interface WritableScope extends JetScope { 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); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java index 77bb17c3982..dd54a0cdeb9 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java @@ -68,13 +68,30 @@ public class WritableScopeImpl extends WritableScopeWithImports { } @Override - public void importNamespaceAlias(String aliasName, NamespaceDescriptor namespaceDescriptor) { + public void importNamespaceAlias(@NotNull String aliasName, @NotNull NamespaceDescriptor namespaceDescriptor) { checkMayWrite(); allDescriptors.add(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 @Override public Collection getAllDescriptors() { @@ -240,6 +257,24 @@ public class WritableScopeImpl extends WritableScopeWithImports { 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) { DeclarationDescriptor originalDescriptor = getVariableClassOrNamespaceDescriptors().get(name); if (originalDescriptor != null) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java index eb848429135..261ccd08f80 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java @@ -3,10 +3,7 @@ package org.jetbrains.jet.lang.resolve.scopes; import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; -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.descriptors.*; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import java.util.ArrayList; @@ -173,12 +170,26 @@ public abstract class WritableScopeWithImports extends JetScopeAdapter implement @Override - public void importNamespaceAlias(String aliasName, NamespaceDescriptor namespaceDescriptor) { + public void importNamespaceAlias(@NotNull String aliasName, @NotNull NamespaceDescriptor namespaceDescriptor) { checkMayWrite(); 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 public String toString() { return getClass().getSimpleName() + "@" + Integer.toHexString(System.identityHashCode(this)) + " " + debugName + " for " + getContainingDeclaration(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java index 7113b9ceaaa..31beb1efe3b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java @@ -161,6 +161,20 @@ public class WriteThroughScope extends WritableScopeWithImports { 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 public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) { checkMayWrite(); diff --git a/compiler/testData/diagnostics/tests/scopes/Imports.jet b/compiler/testData/diagnostics/tests/scopes/Imports.jet new file mode 100644 index 00000000000..508f623ccf1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/Imports.jet @@ -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(i: Int) {} + +fun B.ext() {} + +val value = 0 + +class C() { + class object { + fun bar() {} + val cValue = 1 + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/annotations/DebugInfoAnnotator.java b/idea/src/org/jetbrains/jet/plugin/annotations/DebugInfoAnnotator.java index 68aae0586f1..a75e45077a6 100644 --- a/idea/src/org/jetbrains/jet/plugin/annotations/DebugInfoAnnotator.java +++ b/idea/src/org/jetbrains/jet/plugin/annotations/DebugInfoAnnotator.java @@ -95,7 +95,7 @@ public class DebugInfoAnnotator implements Annotator { target = labelTarget.getText(); } else { - Collection> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, expression); + Collection declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, expression); if (declarationDescriptors != null) { target = "[" + declarationDescriptors.size() + " descriptors]"; } diff --git a/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java b/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java index 417506355ff..5754049dd07 100644 --- a/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java +++ b/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java @@ -81,7 +81,7 @@ public abstract class JetPsiReference implements PsiPolyVariantReference { if (psiElement != null) { return psiElement; } - Collection> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression); + Collection declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression); if (declarationDescriptors != null) return null; return file; } @@ -89,12 +89,12 @@ public abstract class JetPsiReference implements PsiPolyVariantReference { protected ResolveResult[] doMultiResolve() { JetFile file = (JetFile) getElement().getContainingFile(); BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file); - Collection> resolvedCalls = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression); - if (resolvedCalls == null) return ResolveResult.EMPTY_ARRAY; - ResolveResult[] results = new ResolveResult[resolvedCalls.size()]; + Collection declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression); + if (declarationDescriptors == null) return ResolveResult.EMPTY_ARRAY; + ResolveResult[] results = new ResolveResult[declarationDescriptors.size()]; int i = 0; - for (ResolvedCallImpl resolvedCall : resolvedCalls) { - PsiElement element = bindingContext.get(DESCRIPTOR_TO_DECLARATION, resolvedCall.getResultingDescriptor()); + for (DeclarationDescriptor descriptor : declarationDescriptors) { + PsiElement element = bindingContext.get(DESCRIPTOR_TO_DECLARATION, descriptor); if (element != null) { results[i] = new PsiElementResolveResult(element, true); i++; From c92159bb1f889cc06177227561caf4fbb0b5fe97 Mon Sep 17 00:00:00 2001 From: svtk Date: Tue, 20 Dec 2011 20:14:47 +0400 Subject: [PATCH 2/2] bug with multifile frontend tests fixed --- .../jetbrains/jet/checkers/CheckerTestUtil.java | 14 ++++++++++++++ .../jet/checkers/CheckerTestUtilTest.java | 12 +++++++++++- .../jetbrains/jet/checkers/JetDiagnosticsTest.java | 11 ++++++++++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java b/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java index 0eba8704826..b7d156c1825 100644 --- a/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java @@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory; import org.jetbrains.jet.lang.diagnostics.DiagnosticWithTextRange; 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.BindingContext; @@ -50,6 +51,7 @@ public class CheckerTestUtil { } public interface DiagnosticDiffCallbacks { + @NotNull PsiFile getFile(); void missingDiagnostic(String type, int expectedStart, int expectedEnd); void unexpectedDiagnostic(String type, int actualStart, int actualEnd); } @@ -129,6 +131,7 @@ public class CheckerTestUtil { private static void unexpectedDiagnostics(List actual, DiagnosticDiffCallbacks callbacks) { for (Diagnostic diagnostic : actual) { + if (!diagnostic.getFactory().getPsiFile(diagnostic).equals(callbacks.getFile())) continue; TextRange textRange = getTextRange(diagnostic); callbacks.unexpectedDiagnostic(diagnostic.getFactory().getName(), textRange.getStartOffset(), textRange.getEndOffset()); } @@ -136,6 +139,7 @@ public class CheckerTestUtil { private static void missingDiagnostics(DiagnosticDiffCallbacks callbacks, DiagnosedRange currentExpected) { for (String type : currentExpected.getDiagnostics()) { + if (!currentExpected.getFile().equals(callbacks.getFile())) return; callbacks.missingDiagnostic(type, currentExpected.getStart(), currentExpected.getEnd()); } } @@ -393,6 +397,7 @@ public class CheckerTestUtil { private final int start; private int end; private final Multiset diagnostics = HashMultiset.create(); + private PsiFile file; private DiagnosedRange(int start) { this.start = start; @@ -417,5 +422,14 @@ public class CheckerTestUtil { public void addDiagnostic(String diagnostic) { diagnostics.add(diagnostic); } + + public void setFile(@NotNull PsiFile file) { + this.file = file; + } + + @NotNull + public PsiFile getFile() { + return file; + } } } diff --git a/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java b/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java index eb1e3267d9f..f9e7eba1c9b 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java +++ b/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java @@ -2,6 +2,7 @@ package org.jetbrains.jet.checkers; import com.google.common.collect.Lists; import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetLiteFixture; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.diagnostics.Diagnostic; @@ -79,7 +80,7 @@ public class CheckerTestUtilTest extends JetLiteFixture { this.expected = expectedMessages; } - public void test(PsiFile psiFile) { + public void test(final @NotNull PsiFile psiFile) { BindingContext bindingContext = AnalyzerFacade.analyzeOneNamespaceWithJavaIntegration( ((JetFile) psiFile).getRootNamespace(), JetControlFlowDataTraceFactory.EMPTY); @@ -88,6 +89,9 @@ public class CheckerTestUtilTest extends JetLiteFixture { List diagnosedRanges = Lists.newArrayList(); CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges); + for (CheckerTestUtil.DiagnosedRange diagnosedRange : diagnosedRanges) { + diagnosedRange.setFile(psiFile); + } List diagnostics = CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile); Collections.sort(diagnostics, CheckerTestUtil.DIAGNOSTIC_COMPARATOR); @@ -98,6 +102,12 @@ public class CheckerTestUtilTest extends JetLiteFixture { final List actualMessages = Lists.newArrayList(); CheckerTestUtil.diagnosticsDiff(diagnosedRanges, diagnostics, new CheckerTestUtil.DiagnosticDiffCallbacks() { + @NotNull + @Override + public PsiFile getFile() { + return psiFile; + } + @Override public void missingDiagnostic(String type, int expectedStart, int expectedEnd) { String message = "Missing " + type + " at " + expectedStart + " to " + expectedEnd; diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTest.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTest.java index 464e7e6de8b..9cabe8bdd66 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTest.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTest.java @@ -52,10 +52,19 @@ public class JetDiagnosticsTest extends JetLiteFixture { expectedText = textWithMarkers; clearText = CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges); jetFile = createCheckAndReturnPsiFile(fileName, clearText); + for (CheckerTestUtil.DiagnosedRange diagnosedRange : diagnosedRanges) { + diagnosedRange.setFile(jetFile); + } } public void getActualText(BindingContext bindingContext, StringBuilder actualText) { CheckerTestUtil.diagnosticsDiff(diagnosedRanges, CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, jetFile), new CheckerTestUtil.DiagnosticDiffCallbacks() { + @NotNull + @Override + public PsiFile getFile() { + return jetFile; + } + @Override public void missingDiagnostic(String type, int expectedStart, int 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.alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY); } else { - bindingContext = AnalyzingUtils.analyzeNamespaces(getProject(), Configuration.EMPTY, namespaces, Predicates.alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY, JetSemanticServices.createSemanticServices(getProject())); + bindingContext = AnalyzingUtils.analyzeNamespaces(getProject(), Configuration.EMPTY, namespaces, Predicates.alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY); } StringBuilder actualText = new StringBuilder();