Migrated CliLightClassGenerationSupport to package views.

This commit is contained in:
Evgeny Gerashchenko
2013-10-30 21:39:06 +04:00
parent 7e4e3e849d
commit 9d2b79c631
9 changed files with 113 additions and 47 deletions
@@ -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("<module>");
}
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<FqName> 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<DeclarationDescriptor> allDescriptors = namespaceDescriptor.getMemberScope().getAllDescriptors();
return ContainerUtil.mapNotNull(allDescriptors, new Function<DeclarationDescriptor, FqName>() {
Collection<DeclarationDescriptor> members = packageView.getMemberScope().getAllDescriptors();
return ContainerUtil.mapNotNull(members, new Function<DeclarationDescriptor, FqName>() {
@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;
}
@@ -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.<PsiFile>alwaysTrue(),
false
false,
sharedModule
);
}
}, environment.getSourceFiles()
@@ -180,19 +180,29 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
Predicate<PsiFile> filesToAnalyzeCompletely,
boolean storeContextForBodiesResolve
) {
ModuleDescriptorImpl owner = createJavaModule("<module>");
return analyzeFilesWithJavaIntegration(project, files, trace, scriptParameters, filesToAnalyzeCompletely,
storeContextForBodiesResolve, createJavaModule("<module>"));
}
public static AnalyzeExhaust analyzeFilesWithJavaIntegration(
Project project,
Collection<JetFile> files,
BindingTrace trace,
List<AnalyzerScriptParameter> scriptParameters,
Predicate<PsiFile> 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();
@@ -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<PsiPackage> result = new LinkedHashSet<PsiPackage>();
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<String, PsiPackage> packagesMap = new HashMap<String, PsiPackage>();
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()]);
}
}
@@ -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<PsiPackage> implements Java
@Override
@NotNull
public Collection<JavaPackage> getSubPackages() {
return packages(getPsi().getSubPackages());
PsiPackage psiPackage = getPsi();
return packages(new JavaPsiFacadeKotlinHacks(psiPackage.getProject()).getSubPackages(psiPackage));
}
@Override
@@ -246,9 +246,6 @@ public interface BindingContext {
Slices.<ClassDescriptor, FunctionDescriptor>sliceBuilder().build();
WritableSlice<FqName, ClassDescriptor> FQNAME_TO_CLASS_DESCRIPTOR = new BasicWritableSlice<FqName, ClassDescriptor>(DO_NOTHING, true);
@Deprecated
WritableSlice<FqName, NamespaceDescriptor> FQNAME_TO_NAMESPACE_DESCRIPTOR =
new BasicWritableSlice<FqName, NamespaceDescriptor>(DO_NOTHING);
WritableSlice<JetFile, PackageFragmentDescriptor> FILE_TO_PACKAGE_FRAGMENT = Slices.createSimpleSlice();
WritableSlice<FqName, Collection<JetFile>> PACKAGE_TO_FILES = Slices.createSimpleSlice();
@@ -45,11 +45,11 @@ public abstract class AbstractDiagnosticsTestWithEagerResolve extends AbstractJe
protected void analyzeAndCheck(File testDataFile, List<TestFile> testFiles) {
List<JetFile> jetFiles = getJetFiles(testFiles);
BindingTrace trace = CliLightClassGenerationSupport.getInstanceForCli(getProject()).getTrace();
CliLightClassGenerationSupport support = CliLightClassGenerationSupport.getInstanceForCli(getProject());
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
getProject(), jetFiles, trace,
Collections.<AnalyzerScriptParameter>emptyList(), Predicates.<PsiFile>alwaysTrue(), false).getBindingContext();
getProject(), jetFiles, support.getTrace(),
Collections.<AnalyzerScriptParameter>emptyList(), Predicates.<PsiFile>alwaysTrue(), false, support.getModule()).getBindingContext();
boolean ok = true;
@@ -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("<test module>");
CliLightClassGenerationSupport support = CliLightClassGenerationSupport.getInstanceForCli(environment.getProject());
BindingTrace trace = support.getTrace();
InjectorForTopDownAnalyzerForJvm injectorForAnalyzer = new InjectorForTopDownAnalyzerForJvm(
environment.getProject(),
new TopDownAnalysisParameters(
Predicates.<PsiFile>alwaysFalse(), false, false, Collections.<AnalyzerScriptParameter>emptyList()),
trace,
moduleDescriptor);
support.getModule());
injectorForAnalyzer.getTopDownAnalyzer().analyzeFiles(environment.getSourceFiles(), Collections.<AnalyzerScriptParameter>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);
@@ -48,37 +48,38 @@ public class LazyResolveTestUtil {
}
public static InjectorForTopDownAnalyzer getEagerInjectorForTopDownAnalyzer(JetCoreEnvironment environment) {
ModuleDescriptorImpl eagerModuleForLazy = AnalyzerFacadeForJVM.createJavaModule("<eager module for lazy>");
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.<AnalyzerScriptParameter>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.<PsiFile>alwaysTrue(), false, false, Collections.<AnalyzerScriptParameter>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<JetFile> files, JetCoreEnvironment environment) {
ModuleDescriptorImpl module = AnalyzerFacadeForJVM.createJavaModule("<test module>");
InjectorForTopDownAnalyzer injector = createInjectorForTDA(module, environment);
InjectorForTopDownAnalyzer injector = createInjectorForTDA(environment);
injector.getTopDownAnalyzer().analyzeFiles(files, Collections.<AnalyzerScriptParameter>emptyList());
return module;
return injector.getModuleDescriptor();
}
public static KotlinCodeAnalyzer resolveLazilyWithSession(List<JetFile> 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);
}