From a71ea5c6db0cf6d0f55b9f6a39e3eea78c0e7601 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 16 Nov 2012 17:15:24 +0400 Subject: [PATCH] EA-39003 - ISE: ResolveSession.resolveToDescriptor Lokking up classes and objects by PSI element, rather than by name --- .../resolve/lazy/AbstractLazyMemberScope.java | 46 +++++++++++-------- .../AbstractPsiBasedDeclarationProvider.java | 9 ++-- .../resolve/lazy/DeclarationProvider.java | 5 +- ...EmptyPackageMemberDeclarationProvider.java | 5 +- .../jet/lang/resolve/lazy/ResolveSession.java | 24 ++++++---- .../resolve/lazy/ResolveSessionUtils.java | 36 ++++++++++++--- .../jet/plugin/caches/JetShortNamesCache.java | 6 ++- .../AbstractStubDeclarationProvider.java | 7 ++- .../completion/basic/ClassRedeclaration1.kt | 9 ++++ .../completion/basic/ClassRedeclaration2.kt | 9 ++++ .../completion/basic/ObjectRedeclaration1.kt | 9 ++++ .../completion/basic/ObjectRedeclaration2.kt | 9 ++++ .../completion/JetBasicCompletionTest.java | 16 +++++++ 13 files changed, 143 insertions(+), 47 deletions(-) create mode 100644 idea/testData/completion/basic/ClassRedeclaration1.kt create mode 100644 idea/testData/completion/basic/ClassRedeclaration2.kt create mode 100644 idea/testData/completion/basic/ObjectRedeclaration1.kt create mode 100644 idea/testData/completion/basic/ObjectRedeclaration2.kt diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/AbstractLazyMemberScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/AbstractLazyMemberScope.java index eba9365281d..8713b954327 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/AbstractLazyMemberScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/AbstractLazyMemberScope.java @@ -65,21 +65,27 @@ public abstract class AbstractLazyMemberScope classOrObjectDeclarations = declarationProvider.getClassOrObjectDeclarations(name); + if (classOrObjectDeclarations.isEmpty()) return null; - // TODO: when enum entries with constructors are dropped, replace with declaresObjectOrEnumConstant() - if (object != declaresObjectOrEnumConstant(classOrObjectDeclaration)) return null; + ClassDescriptor result = null; - ClassDescriptor classDescriptor = new LazyClassDescriptor(resolveSession, thisDescriptor, name, - JetClassInfoUtil.createClassLikeInfo(classOrObjectDeclaration)); + for (JetClassOrObject classOrObjectDeclaration : classOrObjectDeclarations) { - cache.put(name, classDescriptor); - if (!object) { - allDescriptors.add(classDescriptor); + // TODO: when enum entries with constructors are dropped, replace with declaresObjectOrEnumConstant() + if (object != declaresObjectOrEnumConstant(classOrObjectDeclaration)) continue; + + ClassDescriptor classDescriptor = new LazyClassDescriptor(resolveSession, thisDescriptor, name, + JetClassInfoUtil.createClassLikeInfo(classOrObjectDeclaration)); + + cache.put(name, classDescriptor); + if (!object) { + allDescriptors.add(classDescriptor); + } + + result = classDescriptor; } - - return classDescriptor; + return result; } private static boolean declaresObjectOrEnumConstant(JetClassOrObject declaration) { @@ -149,15 +155,17 @@ public abstract class AbstractLazyMemberScope classOrObjectDeclarations = declarationProvider.getClassOrObjectDeclarations(name); + for (JetClassOrObject classOrObjectDeclaration : classOrObjectDeclarations) { + if (declaresObjectOrEnumConstant(classOrObjectDeclaration)) { + ClassDescriptor classifier = getObjectDescriptor(name); + if (classifier == null) { + throw new IllegalStateException("Object declaration " + name + " found in the DeclarationProvider " + declarationProvider + " but not in the scope " + this); + } + VariableDescriptor propertyDescriptor = resolveSession.getInjector().getDescriptorResolver() + .resolveObjectDeclaration(thisDescriptor, classOrObjectDeclaration, classifier, resolveSession.getTrace()); + result.add(propertyDescriptor); } - VariableDescriptor propertyDescriptor = resolveSession.getInjector().getDescriptorResolver() - .resolveObjectDeclaration(thisDescriptor, classOrObjectDeclaration, classifier, resolveSession.getTrace()); - result.add(propertyDescriptor); } getNonDeclaredProperties(name, result); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/AbstractPsiBasedDeclarationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/AbstractPsiBasedDeclarationProvider.java index 3da46ff4be8..dabbfe90672 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/AbstractPsiBasedDeclarationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/AbstractPsiBasedDeclarationProvider.java @@ -16,16 +16,16 @@ package org.jetbrains.jet.lang.resolve.lazy; +import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.HashMultimap; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.name.Name; +import java.util.Collection; import java.util.List; -import java.util.Map; /** * @author abreslav @@ -34,7 +34,7 @@ public abstract class AbstractPsiBasedDeclarationProvider implements Declaration private final List allDeclarations = Lists.newArrayList(); private final Multimap functions = HashMultimap.create(); private final Multimap properties = HashMultimap.create(); - private final Map classesAndObjects = Maps.newHashMap(); + private final Multimap classesAndObjects = ArrayListMultimap.create(); // order matters here private boolean indexCreated = false; @@ -92,8 +92,9 @@ public abstract class AbstractPsiBasedDeclarationProvider implements Declaration return Lists.newArrayList(properties.get(name)); } + @NotNull @Override - public JetClassOrObject getClassOrObjectDeclaration(@NotNull Name name) { + public Collection getClassOrObjectDeclarations(@NotNull Name name) { createIndex(); return classesAndObjects.get(name); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/DeclarationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/DeclarationProvider.java index 52982f91b7e..5262b578712 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/DeclarationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/DeclarationProvider.java @@ -17,7 +17,6 @@ package org.jetbrains.jet.lang.resolve.lazy; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.psi.JetClassOrObject; import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetNamedFunction; @@ -39,6 +38,6 @@ public interface DeclarationProvider { @NotNull Collection getPropertyDeclarations(@NotNull Name name); - @Nullable - JetClassOrObject getClassOrObjectDeclaration(@NotNull Name name); + @NotNull + Collection getClassOrObjectDeclarations(@NotNull Name name); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/EmptyPackageMemberDeclarationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/EmptyPackageMemberDeclarationProvider.java index c2363278804..1b6c8eb792e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/EmptyPackageMemberDeclarationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/EmptyPackageMemberDeclarationProvider.java @@ -64,8 +64,9 @@ public class EmptyPackageMemberDeclarationProvider implements PackageMemberDecla return Collections.emptyList(); } + @NotNull @Override - public JetClassOrObject getClassOrObjectDeclaration(@NotNull Name name) { - return null; + public Collection getClassOrObjectDeclarations(@NotNull Name name) { + return Collections.emptyList(); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java index 4722b9dfc60..a3c5885cdb4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java @@ -28,10 +28,7 @@ import org.jetbrains.jet.di.InjectorForLazyResolve; import org.jetbrains.jet.lang.ModuleConfiguration; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; -import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.BindingTrace; -import org.jetbrains.jet.lang.resolve.BindingTraceContext; -import org.jetbrains.jet.lang.resolve.ObservableBindingTrace; +import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; import org.jetbrains.jet.lang.resolve.name.Name; @@ -158,14 +155,23 @@ public class ResolveSession { JetScope resolutionScope = getInjector().getScopeProvider().getResolutionScopeForDeclaration(classOrObject); Name name = classOrObject.getNameAsName(); assert name != null : "Name is null for " + classOrObject + " " + classOrObject.getText(); - ClassifierDescriptor classifier = resolutionScope.getClassifier(name); - if (classifier == null) { - classifier = resolutionScope.getObjectDescriptor(name); + + // Why not use the result here. Because it may be that there is a redeclaration: + // class A {} class A { fun foo(): A} + // and if we find teh class by name only, we may b-not get the right one. + // This call is only needed to make sure the classes are written to trace + resolutionScope.getClassifier(name); + DeclarationDescriptor declaration = getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject); + + if (declaration == null) { + // Why not use the result here. See the comment + resolutionScope.getObjectDescriptor(name); + declaration = getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject); } - if (classifier == null) { + if (declaration == null) { throw new IllegalArgumentException("Could not find a classifier for " + classOrObject + " " + classOrObject.getText()); } - return (ClassDescriptor) classifier; + return (ClassDescriptor) declaration; } /*package*/ LazyClassDescriptor getClassObjectDescriptor(JetClassObject classObject) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSessionUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSessionUtils.java index e9b37743feb..6615d31964a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSessionUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSessionUtils.java @@ -308,7 +308,20 @@ public class ResolveSessionUtils { return null; } - public static Collection getClassDescriptorsByFqName(@NotNull ResolveSession resolveSession, @NotNull FqName fqName) { + @NotNull + public static Collection getClassDescriptorsByFqName( + @NotNull ResolveSession resolveSession, + @NotNull FqName fqName + ) { + return getClassOrObjectDescriptorsByFqName(resolveSession, fqName, false); + } + + @NotNull + public static Collection getClassOrObjectDescriptorsByFqName( + @NotNull ResolveSession resolveSession, + @NotNull FqName fqName, + boolean includeObjectDeclarations + ) { if (fqName.isRoot()) { return Collections.emptyList(); } @@ -320,7 +333,8 @@ public class ResolveSessionUtils { NamespaceDescriptor packageDescriptor = resolveSession.getPackageDescriptorByFqName(packageFqName); if (packageDescriptor != null) { FqName classInPackagePath = new FqName(QualifiedNamesUtil.tail(packageFqName, fqName)); - Collection descriptors = getClassDescriptorsByFqName(packageDescriptor, classInPackagePath); + Collection descriptors = getClassOrObjectDescriptorsByFqName(packageDescriptor, classInPackagePath, + includeObjectDeclarations); classDescriptors.addAll(descriptors); } @@ -335,7 +349,11 @@ public class ResolveSessionUtils { return classDescriptors; } - private static Collection getClassDescriptorsByFqName(NamespaceDescriptor packageDescriptor, FqName path) { + private static Collection getClassOrObjectDescriptorsByFqName( + NamespaceDescriptor packageDescriptor, + FqName path, + boolean includeObjectDeclarations + ) { if (path.isRoot()) { return Collections.emptyList(); } @@ -358,14 +376,20 @@ public class ResolveSessionUtils { } Name shortName = path.shortName(); - Collection resultClassDescriptors = Lists.newArrayList(); + Collection resultClassifierDescriptors = Lists.newArrayList(); for (JetScope scope : scopes) { ClassifierDescriptor classifier = scope.getClassifier(shortName); if (classifier instanceof ClassDescriptor) { - resultClassDescriptors.add((ClassDescriptor) classifier); + resultClassifierDescriptors.add((ClassDescriptor) classifier); + } + if (includeObjectDeclarations) { + ClassDescriptor objectDescriptor = scope.getObjectDescriptor(shortName); + if (objectDescriptor != null) { + resultClassifierDescriptors.add(objectDescriptor); + } } } - return resultClassDescriptors; + return resultClassifierDescriptors; } } diff --git a/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java b/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java index bc6bdbec48f..ce828ef251a 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java +++ b/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java @@ -158,7 +158,9 @@ public class JetShortNamesCache extends PsiShortNamesCache { Collection topObjects = JetTopLevelShortObjectNameIndex.getInstance().get(name, project, scope); for (JetObjectDeclaration objectDeclaration : topObjects) { - result.add(resolveSession.getClassDescriptor(objectDeclaration)); + FqName fqName = JetPsiUtil.getFQName(objectDeclaration); + assert fqName != null : "Local object declaration in JetTopLevelShortObjectNameIndex:" + objectDeclaration.getText(); + result.addAll(ResolveSessionUtils.getClassOrObjectDescriptorsByFqName(resolveSession, fqName, true)); } for (PsiClass psiClass : JetFromJavaDescriptorHelper @@ -166,7 +168,7 @@ public class JetShortNamesCache extends PsiShortNamesCache { String qualifiedName = psiClass.getQualifiedName(); if (qualifiedName != null) { FqName fqName = new FqName(qualifiedName); - result.addAll(ResolveSessionUtils.getClassDescriptorsByFqName(resolveSession, fqName)); + result.addAll(ResolveSessionUtils.getClassOrObjectDescriptorsByFqName(resolveSession, fqName, true)); } } diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/resolve/AbstractStubDeclarationProvider.java b/idea/src/org/jetbrains/jet/plugin/stubindex/resolve/AbstractStubDeclarationProvider.java index 28e619a28a9..8305bc202a6 100644 --- a/idea/src/org/jetbrains/jet/plugin/stubindex/resolve/AbstractStubDeclarationProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/stubindex/resolve/AbstractStubDeclarationProvider.java @@ -22,6 +22,8 @@ import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.resolve.lazy.DeclarationProvider; import org.jetbrains.jet.lang.resolve.name.Name; +import java.util.Collection; +import java.util.Collections; import java.util.List; /** @@ -34,9 +36,10 @@ public abstract class AbstractStubDeclarationProvider implements DeclarationProv return null; } + @NotNull @Override - public JetClassOrObject getClassOrObjectDeclaration(@NotNull Name name) { + public Collection getClassOrObjectDeclarations(@NotNull Name name) { // TODO: - return null; + return Collections.emptyList(); } } diff --git a/idea/testData/completion/basic/ClassRedeclaration1.kt b/idea/testData/completion/basic/ClassRedeclaration1.kt new file mode 100644 index 00000000000..7c203a21ca9 --- /dev/null +++ b/idea/testData/completion/basic/ClassRedeclaration1.kt @@ -0,0 +1,9 @@ +class A { + fun f() : A +} + +class A { + fun f() : A +} + +// EXIST: A \ No newline at end of file diff --git a/idea/testData/completion/basic/ClassRedeclaration2.kt b/idea/testData/completion/basic/ClassRedeclaration2.kt new file mode 100644 index 00000000000..3432ee1fa20 --- /dev/null +++ b/idea/testData/completion/basic/ClassRedeclaration2.kt @@ -0,0 +1,9 @@ +class A { + fun f() : A +} + +class A { + fun f() : A +} + +// EXIST: A \ No newline at end of file diff --git a/idea/testData/completion/basic/ObjectRedeclaration1.kt b/idea/testData/completion/basic/ObjectRedeclaration1.kt new file mode 100644 index 00000000000..878e9978c3d --- /dev/null +++ b/idea/testData/completion/basic/ObjectRedeclaration1.kt @@ -0,0 +1,9 @@ +object A { + fun f() : S +} + +object A { + fun f() : S +} + +// EXIST: String \ No newline at end of file diff --git a/idea/testData/completion/basic/ObjectRedeclaration2.kt b/idea/testData/completion/basic/ObjectRedeclaration2.kt new file mode 100644 index 00000000000..414eb30ff14 --- /dev/null +++ b/idea/testData/completion/basic/ObjectRedeclaration2.kt @@ -0,0 +1,9 @@ +object A { + fun f() : S +} + +object A { + fun f() : S +} + +// EXIST: String \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java b/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java index 3d6192f2791..31a6d6f54df 100644 --- a/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java +++ b/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java @@ -269,6 +269,22 @@ public class JetBasicCompletionTest extends JetCompletionTestBase { doTest(); } + public void testClassRedeclaration1() { + doTest(); + } + + public void testClassRedeclaration2() { + doTest(); + } + + public void testObjectRedeclaration1() { + doTest(); + } + + public void testObjectRedeclaration2() { + doTest(); + } + @NotNull @Override protected String getTestDataPath() {