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 6a7a72ac5eb..c35c658b4df 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 @@ -18,7 +18,6 @@ package org.jetbrains.jet.cli.jvm.compiler; import com.google.common.base.Predicate; import com.google.common.collect.Collections2; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiClass; @@ -30,14 +29,20 @@ import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import org.jetbrains.jet.asJava.KotlinLightClassForExplicitDeclaration; 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.descriptors.ModuleDescriptorImpl; +import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor; import org.jetbrains.jet.lang.psi.*; -import org.jetbrains.jet.lang.resolve.*; +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.java.AnalyzerFacadeForJVM; import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.util.slicedmap.WritableSlice; @@ -65,6 +70,7 @@ public class CliLightClassGenerationSupport extends LightClassGenerationSupport } private BindingTrace trace; + private ModuleDescriptorImpl module; public CliLightClassGenerationSupport() { } @@ -77,9 +83,24 @@ public class CliLightClassGenerationSupport extends LightClassGenerationSupport return trace; } + @NotNull + public ModuleDescriptorImpl getModule() { + if (module == null) { + module = AnalyzerFacadeForJVM.createJavaModule(""); + } + return module; + } + + @TestOnly + public void setModule(@NotNull ModuleDescriptorImpl module) { + assert this.module == null : "module already configured: " + module; + this.module = module; + } + + @TestOnly public void newBindingTrace() { - assert ApplicationManager.getApplication().isUnitTestMode() : "Mutating project service's state shouldn't happen other than in tests"; trace = null; + module = null; } private LightClassConstructionContext analyzeRelevantCode() { @@ -163,24 +184,22 @@ public class CliLightClassGenerationSupport extends LightClassGenerationSupport } @Override - public boolean packageExists( - @NotNull FqName fqName, @NotNull GlobalSearchScope scope - ) { - return getTrace().get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, fqName) != null; + public boolean packageExists(@NotNull FqName fqName, @NotNull GlobalSearchScope scope) { + return getModule().getPackage(fqName) != null; } @NotNull @Override public Collection getSubPackages(@NotNull FqName fqn, @NotNull GlobalSearchScope scope) { - NamespaceDescriptor namespaceDescriptor = getTrace().get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, fqn); - if (namespaceDescriptor == null) return Collections.emptyList(); + PackageViewDescriptor packageView = getModule().getPackage(fqn); + if (packageView == null) return Collections.emptyList(); - Collection allDescriptors = namespaceDescriptor.getMemberScope().getAllDescriptors(); - return ContainerUtil.mapNotNull(allDescriptors, new Function() { + Collection members = packageView.getMemberScope().getAllDescriptors(); + return ContainerUtil.mapNotNull(members, new Function() { @Override - public FqName fun(DeclarationDescriptor input) { - if (input instanceof NamespaceDescriptor) { - return DescriptorUtils.getFQName(input).toSafe(); + public FqName fun(DeclarationDescriptor member) { + if (member instanceof PackageViewDescriptor) { + return ((PackageViewDescriptor) member).getFqName(); } return null; } diff --git a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java index 0057be4f0dd..bf7703d8748 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java @@ -40,6 +40,7 @@ import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.Progress; import org.jetbrains.jet.config.CommonConfigurationKeys; import org.jetbrains.jet.config.CompilerConfiguration; +import org.jetbrains.jet.lang.descriptors.ModuleDescriptorImpl; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.resolve.BindingTrace; @@ -270,14 +271,17 @@ public class KotlinToJVMBytecodeCompiler { @NotNull @Override public AnalyzeExhaust invoke() { - BindingTrace sharedTrace = CliLightClassGenerationSupport.getInstanceForCli(environment.getProject()).getTrace(); + CliLightClassGenerationSupport support = CliLightClassGenerationSupport.getInstanceForCli(environment.getProject()); + BindingTrace sharedTrace = support.getTrace(); + ModuleDescriptorImpl sharedModule = support.getModule(); return AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration( environment.getProject(), environment.getSourceFiles(), sharedTrace, environment.getConfiguration().getList(JVMConfigurationKeys.SCRIPT_PARAMETERS), Predicates.alwaysTrue(), - false + false, + sharedModule ); } }, environment.getSourceFiles() diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java index 53b044822a5..dd90d0ee96e 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java @@ -180,19 +180,29 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade { Predicate filesToAnalyzeCompletely, boolean storeContextForBodiesResolve ) { - ModuleDescriptorImpl owner = createJavaModule(""); + return analyzeFilesWithJavaIntegration(project, files, trace, scriptParameters, filesToAnalyzeCompletely, + storeContextForBodiesResolve, createJavaModule("")); + } + + public static AnalyzeExhaust analyzeFilesWithJavaIntegration( + Project project, + Collection files, + BindingTrace trace, + List scriptParameters, + Predicate filesToAnalyzeCompletely, + boolean storeContextForBodiesResolve, + ModuleDescriptorImpl module + ) { TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters( filesToAnalyzeCompletely, false, false, scriptParameters); - InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm( - project, topDownAnalysisParameters, - new ObservableBindingTrace(trace), owner); + InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm(project, topDownAnalysisParameters, trace, module); try { injector.getTopDownAnalyzer().analyzeFiles(files, scriptParameters); BodiesResolveContext bodiesResolveContext = storeContextForBodiesResolve ? new CachedBodiesResolveContext(injector.getTopDownAnalysisContext()) : null; - return AnalyzeExhaust.success(trace.getBindingContext(), bodiesResolveContext, owner); + return AnalyzeExhaust.success(trace.getBindingContext(), bodiesResolveContext, module); } finally { injector.destroy(); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPsiFacadeKotlinHacks.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPsiFacadeKotlinHacks.java index 05885ca8f89..8c9cb77369b 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPsiFacadeKotlinHacks.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPsiFacadeKotlinHacks.java @@ -20,16 +20,18 @@ import com.google.common.collect.Lists; import com.intellij.core.CoreJavaFileManager; import com.intellij.openapi.progress.ProgressIndicatorProvider; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElementFinder; -import com.intellij.psi.PsiPackage; +import com.intellij.psi.*; import com.intellij.psi.impl.JavaPsiFacadeImpl; import com.intellij.psi.impl.file.impl.JavaFileManager; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; /** * TODO Temporary class until {@link JavaPsiFacadeImpl} hacked. @@ -100,4 +102,36 @@ public class JavaPsiFacadeKotlinHacks { return null; } + public PsiPackage[] getSubPackages(@NotNull PsiPackage psiPackage) { + GlobalSearchScope scope = GlobalSearchScope.allScope(psiPackage.getProject()); + + LinkedHashSet result = new LinkedHashSet(); + for (PsiElementFinder finder : extensionPsiElementFinders) { + PsiPackage[] packages = finder.getSubPackages(psiPackage, scope); + ContainerUtil.addAll(result, packages); + } + ContainerUtil.addAll(result, getDefaultSubPackages(psiPackage, scope)); + + return result.toArray(new PsiPackage[result.size()]); + } + + private static PsiPackage[] getDefaultSubPackages(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { + Map packagesMap = new HashMap(); + String qualifiedName = psiPackage.getQualifiedName(); + for (PsiDirectory dir : psiPackage.getDirectories(scope)) { + PsiDirectory[] subDirs = dir.getSubdirectories(); + for (PsiDirectory subDir : subDirs) { + PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(subDir); + if (aPackage != null) { + String subQualifiedName = aPackage.getQualifiedName(); + if (subQualifiedName.startsWith(qualifiedName) && !packagesMap.containsKey(subQualifiedName)) { + packagesMap.put(aPackage.getQualifiedName(), aPackage); + } + } + } + } + + packagesMap.remove(qualifiedName); // avoid SOE caused by returning a package as a subpackage of itself + return packagesMap.values().toArray(new PsiPackage[packagesMap.size()]); + } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPackageImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPackageImpl.java index 36acd62af93..2fe35118b23 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPackageImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPackageImpl.java @@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve.java.structure.impl; import com.intellij.psi.PsiPackage; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.resolve.java.JavaPsiFacadeKotlinHacks; import org.jetbrains.jet.lang.resolve.java.structure.JavaClass; import org.jetbrains.jet.lang.resolve.java.structure.JavaPackage; import org.jetbrains.jet.lang.resolve.name.FqName; @@ -41,7 +42,8 @@ public class JavaPackageImpl extends JavaElementImpl implements Java @Override @NotNull public Collection getSubPackages() { - return packages(getPsi().getSubPackages()); + PsiPackage psiPackage = getPsi(); + return packages(new JavaPsiFacadeKotlinHacks(psiPackage.getProject()).getSubPackages(psiPackage)); } @Override 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 dd5df20b265..beaebe95e92 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -246,9 +246,6 @@ public interface BindingContext { Slices.sliceBuilder().build(); WritableSlice FQNAME_TO_CLASS_DESCRIPTOR = new BasicWritableSlice(DO_NOTHING, true); - @Deprecated - WritableSlice FQNAME_TO_NAMESPACE_DESCRIPTOR = - new BasicWritableSlice(DO_NOTHING); WritableSlice FILE_TO_PACKAGE_FRAGMENT = Slices.createSimpleSlice(); WritableSlice> PACKAGE_TO_FILES = Slices.createSimpleSlice(); diff --git a/compiler/tests/org/jetbrains/jet/checkers/AbstractDiagnosticsTestWithEagerResolve.java b/compiler/tests/org/jetbrains/jet/checkers/AbstractDiagnosticsTestWithEagerResolve.java index 791a7872000..1366ca544b3 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/AbstractDiagnosticsTestWithEagerResolve.java +++ b/compiler/tests/org/jetbrains/jet/checkers/AbstractDiagnosticsTestWithEagerResolve.java @@ -45,11 +45,11 @@ public abstract class AbstractDiagnosticsTestWithEagerResolve extends AbstractJe protected void analyzeAndCheck(File testDataFile, List testFiles) { List jetFiles = getJetFiles(testFiles); - BindingTrace trace = CliLightClassGenerationSupport.getInstanceForCli(getProject()).getTrace(); + CliLightClassGenerationSupport support = CliLightClassGenerationSupport.getInstanceForCli(getProject()); BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration( - getProject(), jetFiles, trace, - Collections.emptyList(), Predicates.alwaysTrue(), false).getBindingContext(); + getProject(), jetFiles, support.getTrace(), + Collections.emptyList(), Predicates.alwaysTrue(), false, support.getModule()).getBindingContext(); boolean ok = true; diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/AbstractLoadJavaTest.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/AbstractLoadJavaTest.java index 8735ad3d401..7b52277ef28 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/AbstractLoadJavaTest.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/AbstractLoadJavaTest.java @@ -142,20 +142,19 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir { JetCoreEnvironment environment = JetCoreEnvironment.createForTests(getTestRootDisposable(), configuration); // we need the same binding trace for resolve from Java and Kotlin - BindingTrace trace = CliLightClassGenerationSupport.getInstanceForCli(environment.getProject()).getTrace(); - - ModuleDescriptorImpl moduleDescriptor = AnalyzerFacadeForJVM.createJavaModule(""); + CliLightClassGenerationSupport support = CliLightClassGenerationSupport.getInstanceForCli(environment.getProject()); + BindingTrace trace = support.getTrace(); InjectorForTopDownAnalyzerForJvm injectorForAnalyzer = new InjectorForTopDownAnalyzerForJvm( environment.getProject(), new TopDownAnalysisParameters( Predicates.alwaysFalse(), false, false, Collections.emptyList()), trace, - moduleDescriptor); + support.getModule()); injectorForAnalyzer.getTopDownAnalyzer().analyzeFiles(environment.getSourceFiles(), Collections.emptyList()); - PackageViewDescriptor packageView = moduleDescriptor.getPackage(TEST_PACKAGE_FQNAME); + PackageViewDescriptor packageView = support.getModule().getPackage(TEST_PACKAGE_FQNAME); assert packageView != null : "Test namespace not found"; checkJavaPackage(expectedFile, packageView, trace.getBindingContext(), DONT_INCLUDE_METHODS_OF_OBJECT); diff --git a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveTestUtil.java b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveTestUtil.java index 315acc343d0..dda55155d1c 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveTestUtil.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveTestUtil.java @@ -48,37 +48,38 @@ public class LazyResolveTestUtil { } public static InjectorForTopDownAnalyzer getEagerInjectorForTopDownAnalyzer(JetCoreEnvironment environment) { - ModuleDescriptorImpl eagerModuleForLazy = AnalyzerFacadeForJVM.createJavaModule(""); - - InjectorForTopDownAnalyzer tdaInjectorForLazy = createInjectorForTDA(eagerModuleForLazy, environment); + InjectorForTopDownAnalyzer tdaInjectorForLazy = createInjectorForTDA(environment); // This line is required fro the 'jet' namespace to be filled in with functions tdaInjectorForLazy.getTopDownAnalyzer().analyzeFiles( Collections.singletonList(JetPsiFactory.createFile(environment.getProject(), "")), Collections.emptyList()); return tdaInjectorForLazy; } - public static InjectorForTopDownAnalyzer createInjectorForTDA(ModuleDescriptorImpl module, JetCoreEnvironment environment) { + public static InjectorForTopDownAnalyzer createInjectorForTDA(JetCoreEnvironment environment) { JetTestUtils.newTrace(environment); TopDownAnalysisParameters params = new TopDownAnalysisParameters( Predicates.alwaysTrue(), false, false, Collections.emptyList()); - BindingTrace sharedTrace = CliLightClassGenerationSupport.getInstanceForCli(environment.getProject()).getTrace(); - return new InjectorForTopDownAnalyzerForJvm(environment.getProject(), params, sharedTrace, module); + CliLightClassGenerationSupport support = CliLightClassGenerationSupport.getInstanceForCli(environment.getProject()); + BindingTrace sharedTrace = support.getTrace(); + ModuleDescriptorImpl sharedModule = support.getModule(); + return new InjectorForTopDownAnalyzerForJvm(environment.getProject(), params, sharedTrace, sharedModule); } public static ModuleDescriptor resolveEagerly(List files, JetCoreEnvironment environment) { - ModuleDescriptorImpl module = AnalyzerFacadeForJVM.createJavaModule(""); - InjectorForTopDownAnalyzer injector = createInjectorForTDA(module, environment); + InjectorForTopDownAnalyzer injector = createInjectorForTDA(environment); injector.getTopDownAnalyzer().analyzeFiles(files, Collections.emptyList()); - return module; + return injector.getModuleDescriptor(); } public static KotlinCodeAnalyzer resolveLazilyWithSession(List files, JetCoreEnvironment environment, boolean addBuiltIns) { JetTestUtils.newTrace(environment); Project project = environment.getProject(); - BindingTrace sharedTrace = CliLightClassGenerationSupport.getInstanceForCli(project).getTrace(); + CliLightClassGenerationSupport support = CliLightClassGenerationSupport.getInstanceForCli(project); + BindingTrace sharedTrace = support.getTrace(); InjectorForJavaDescriptorResolver injector = new InjectorForJavaDescriptorResolver(project, sharedTrace); + support.setModule(injector.getModule()); return AnalyzerFacadeForJVM.createLazyResolveSession(project, files, sharedTrace, injector, addBuiltIns); }