diff --git a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliLightClassGenerationSupport.java b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliLightClassGenerationSupport.java index caf9dd2ab1a..e5aa9228217 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliLightClassGenerationSupport.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliLightClassGenerationSupport.java @@ -24,19 +24,19 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiSearchScopeUtil; +import com.intellij.util.Function; import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.asJava.LightClassConstructionContext; import org.jetbrains.jet.asJava.LightClassGenerationSupport; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.psi.JetClassOrObject; import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetFile; -import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.BindingContextUtils; -import org.jetbrains.jet.lang.resolve.BindingTrace; -import org.jetbrains.jet.lang.resolve.BindingTraceContext; +import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.name.FqName; import java.util.Collection; @@ -139,4 +139,22 @@ public class CliLightClassGenerationSupport extends LightClassGenerationSupport ) { return trace.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, fqName) != null; } + + @NotNull + @Override + public Collection getSubPackages(@NotNull FqName fqn, @NotNull GlobalSearchScope scope) { + NamespaceDescriptor namespaceDescriptor = trace.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, fqn); + if (namespaceDescriptor == null) return Collections.emptyList(); + + Collection allDescriptors = namespaceDescriptor.getMemberScope().getAllDescriptors(); + return ContainerUtil.mapNotNull(allDescriptors, new Function() { + @Override + public FqName fun(DeclarationDescriptor input) { + if (input instanceof NamespaceDescriptor) { + return DescriptorUtils.getFQName(input).toSafe(); + } + return null; + } + }); + } } diff --git a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JavaElementFinder.java b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JavaElementFinder.java index 5d0ef82657c..3bd5ee350c6 100644 --- a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JavaElementFinder.java +++ b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JavaElementFinder.java @@ -16,6 +16,8 @@ package org.jetbrains.jet.asJava; +import com.google.common.base.Function; +import com.google.common.collect.Collections2; import com.google.common.collect.Sets; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; @@ -37,7 +39,10 @@ import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.util.QualifiedNamesUtil; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.WeakHashMap; import static org.jetbrains.jet.codegen.CodegenUtil.getLocalNameForObject; @@ -216,19 +221,17 @@ public class JavaElementFinder extends PsiElementFinder implements JavaPsiFacade @NotNull @Override - public PsiPackage[] getSubPackages(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { - final Collection psiFiles = collectProjectJetFiles(project, GlobalSearchScope.allScope(project)); + public PsiPackage[] getSubPackages(@NotNull PsiPackage psiPackage, @NotNull final GlobalSearchScope scope) { + FqName packageFQN = new FqName(psiPackage.getQualifiedName()); - Set answer = new HashSet(); + Collection subpackages = lightClassGenerationSupport.getSubPackages(packageFQN, scope); - for (JetFile psiFile : psiFiles) { - FqName jetRootNamespace = JetPsiUtil.getFQName(psiFile); - - final FqName subPackageFQN = QualifiedNamesUtil.plusOneSegment(new FqName(psiPackage.getQualifiedName()), jetRootNamespace); - if (subPackageFQN != null) { - answer.add(new JetLightPackage(psiManager, subPackageFQN, scope)); + Collection answer = Collections2.transform(subpackages, new Function() { + @Override + public PsiPackage apply(@Nullable FqName input) { + return new JetLightPackage(psiManager, input, scope); } - } + }); return answer.toArray(new PsiPackage[answer.size()]); } @@ -263,7 +266,7 @@ public class JavaElementFinder extends PsiElementFinder implements JavaPsiFacade @Deprecated private synchronized Collection collectProjectJetFiles(final Project project, @NotNull final GlobalSearchScope scope) { Collection cachedFiles = jetFiles.get(scope); - + if (cachedFiles == null) { cachedFiles = JetFilesProvider.getInstance(project).allInScope(scope); jetFiles.put(scope, cachedFiles); diff --git a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/LightClassGenerationSupport.java b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/LightClassGenerationSupport.java index 39410ef5462..01fe17c7da6 100644 --- a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/LightClassGenerationSupport.java +++ b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/LightClassGenerationSupport.java @@ -40,7 +40,11 @@ public abstract class LightClassGenerationSupport { public abstract Collection findClassOrObjectDeclarations(@NotNull FqName fqName, @NotNull GlobalSearchScope searchScope); /* - * Returns empty collection for absent package + * Finds files whose package declaration is exactly {@code fqName}. For example, if a file declares + * package a.b.c + * it will not be returned for fqName "a.b" + * + * If the resulting collection is empty, it means that this package has not other declarations than sub-packages */ @NotNull public abstract Collection findFilesForPackage(@NotNull FqName fqName, @NotNull GlobalSearchScope searchScope); @@ -53,4 +57,7 @@ public abstract class LightClassGenerationSupport { ); public abstract boolean packageExists(@NotNull FqName fqName, @NotNull GlobalSearchScope scope); + + @NotNull + public abstract Collection getSubPackages(@NotNull FqName fqn, @NotNull GlobalSearchScope scope); } diff --git a/idea/src/org/jetbrains/jet/plugin/caches/resolve/IDELightClassGenerationSupport.java b/idea/src/org/jetbrains/jet/plugin/caches/resolve/IDELightClassGenerationSupport.java index d9482ab61f0..f2324f2784b 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/resolve/IDELightClassGenerationSupport.java +++ b/idea/src/org/jetbrains/jet/plugin/caches/resolve/IDELightClassGenerationSupport.java @@ -16,6 +16,7 @@ package org.jetbrains.jet.plugin.caches.resolve; +import com.google.common.collect.Sets; import com.intellij.openapi.project.Project; import com.intellij.psi.search.GlobalSearchScope; import org.jetbrains.annotations.NotNull; @@ -23,13 +24,16 @@ import org.jetbrains.jet.asJava.LightClassConstructionContext; import org.jetbrains.jet.asJava.LightClassGenerationSupport; import org.jetbrains.jet.lang.psi.JetClassOrObject; import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.plugin.stubindex.JetAllPackagesIndex; import org.jetbrains.jet.plugin.stubindex.JetClassByPackageIndex; import org.jetbrains.jet.plugin.stubindex.JetFullClassNameIndex; import org.jetbrains.jet.plugin.stubindex.JetPackageDeclarationIndex; +import org.jetbrains.jet.util.QualifiedNamesUtil; import java.util.Collection; +import java.util.Set; public class IDELightClassGenerationSupport extends LightClassGenerationSupport { @@ -73,4 +77,25 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport ) { return !JetAllPackagesIndex.getInstance().get(fqName.getFqName(), project, scope).isEmpty(); } + + @NotNull + @Override + public Collection getSubPackages(@NotNull FqName fqn, @NotNull GlobalSearchScope scope) { + Collection files = JetAllPackagesIndex.getInstance().get(fqn.getFqName(), project, scope); + + Set result = Sets.newHashSet(); + for (JetFile file : files) { + FqName fqName = JetPsiUtil.getFQName(file); + + assert QualifiedNamesUtil.isSubpackageOf(fqn, fqName) : "Registered package is not a subpackage of actually declared package:\n" + + "in index: " + fqn + "\n" + + "declared: " + fqName; + FqName subpackage = QualifiedNamesUtil.plusOneSegment(fqn, fqName); + if (subpackage != null) { + result.add(subpackage); + } + } + + return result; + } }