LTDA: Initialize project components with resolve session after injector construction is finished

This commit is contained in:
Nikolay Krasko
2014-08-22 22:13:33 +04:00
parent 53b699d745
commit 571f3c8524
21 changed files with 263 additions and 162 deletions
@@ -18,6 +18,7 @@ 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;
@@ -29,25 +30,21 @@ 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.ModuleDescriptor;
import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.ModuleDescriptorImpl;
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.DescriptorToSourceUtils;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.TopDownAnalyzerFacadeForJVM;
import org.jetbrains.jet.lang.resolve.lazy.KotlinCodeAnalyzer;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.scopes.DescriptorKindFilter;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.util.slicedmap.ReadOnlySlice;
import org.jetbrains.jet.util.slicedmap.WritableSlice;
import java.util.Collection;
@@ -66,60 +63,40 @@ import java.util.List;
*
* To mitigate this, CliLightClassGenerationSupport hold a trace that is shared between the analyzer and JetLightClasses
*/
public class CliLightClassGenerationSupport extends LightClassGenerationSupport {
public class CliLightClassGenerationSupport extends LightClassGenerationSupport implements CodeAnalyzerInitializer {
public static CliLightClassGenerationSupport getInstanceForCli(@NotNull Project project) {
return ServiceManager.getService(project, CliLightClassGenerationSupport.class);
}
private BindingTrace trace;
private ModuleDescriptorImpl module;
private BindingContext bindingContext = null;
private ModuleDescriptor module = null;
public CliLightClassGenerationSupport() {
}
@NotNull
public BindingTrace getTrace() {
if (trace == null) {
trace = new BindingTraceContextWithoutScopeRecording();
}
return trace;
}
@NotNull
public ModuleDescriptorImpl newModule() {
assert this.module == null : "module already configured: " + module;
module = TopDownAnalyzerFacadeForJVM.createJavaModule("<shared-module-for-cli-light-classes>");
module.addDependencyOnModule(module);
module.addDependencyOnModule(KotlinBuiltIns.getInstance().getBuiltInsModule());
module.seal();
return module;
}
@NotNull
private ModuleDescriptorImpl getModule() {
if (module == null) {
return newModule();
}
return module;
}
@TestOnly
@Nullable
public ModuleDescriptorImpl getLightClassModule() {
return module;
}
@TestOnly
public void setModule(@NotNull ModuleDescriptorImpl module) {
assert this.module == null : "module already configured: " + module;
@Override
public void initialize(@NotNull BindingTrace trace, @NotNull ModuleDescriptor module, @Nullable KotlinCodeAnalyzer analyzer) {
this.bindingContext = trace.getBindingContext();
this.module = module;
if (trace instanceof CliBindingTrace) {
((CliBindingTrace) trace).setKotlinCodeAnalyzer(analyzer);
}
else {
assert ApplicationManager.getApplication().isUnitTestMode();
}
}
@TestOnly
public void newBindingTrace() {
trace = null;
module = null;
@NotNull
private BindingContext getBindingContext() {
assert bindingContext != null : "Call initialize() first";
return bindingContext;
}
@NotNull
private ModuleDescriptor getModule() {
assert module != null : "Call initialize() first";
return module;
}
@NotNull
@@ -136,13 +113,13 @@ public class CliLightClassGenerationSupport extends LightClassGenerationSupport
@NotNull
private LightClassConstructionContext getContext() {
return new LightClassConstructionContext(getTrace().getBindingContext(), getModule());
return new LightClassConstructionContext(bindingContext, getModule());
}
@NotNull
@Override
public Collection<JetClassOrObject> findClassOrObjectDeclarations(@NotNull FqName fqName, @NotNull GlobalSearchScope searchScope) {
ClassDescriptor classDescriptor = getTrace().get(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, fqName.toUnsafe());
ClassDescriptor classDescriptor = getBindingContext().get(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, fqName.toUnsafe());
if (classDescriptor != null) {
PsiElement element = DescriptorToSourceUtils.classDescriptorToDeclaration(classDescriptor);
if (element != null && PsiSearchScopeUtil.isInScope(searchScope, element)) {
@@ -174,7 +151,7 @@ public class CliLightClassGenerationSupport extends LightClassGenerationSupport
@NotNull
@Override
public Collection<JetFile> findFilesForPackage(@NotNull FqName fqName, @NotNull final GlobalSearchScope searchScope) {
Collection<JetFile> files = getTrace().get(BindingContext.PACKAGE_TO_FILES, fqName);
Collection<JetFile> files = getBindingContext().get(BindingContext.PACKAGE_TO_FILES, fqName);
if (files != null) {
return Collections2.filter(files, new Predicate<JetFile>() {
@Override
@@ -240,7 +217,13 @@ public class CliLightClassGenerationSupport extends LightClassGenerationSupport
return KotlinLightClassForExplicitDeclaration.create(classOrObject.getManager(), classOrObject);
}
public static class BindingTraceContextWithoutScopeRecording extends BindingTraceContext {
public static BindingTrace createTrace() {
return new CliBindingTrace();
}
public static class CliBindingTrace extends BindingTraceContext {
private KotlinCodeAnalyzer kotlinCodeAnalyzer;
@Override
public <K, V> void record(WritableSlice<K, V> slice, K key, V value) {
if (slice == BindingContext.RESOLUTION_SCOPE || slice == BindingContext.TYPE_RESOLUTION_SCOPE) {
@@ -252,7 +235,31 @@ public class CliLightClassGenerationSupport extends LightClassGenerationSupport
@Override
public String toString() {
return "Filtering trace for the CLI compiler: does not save scopes";
return CliBindingTrace.class.getName();
}
public void setKotlinCodeAnalyzer(KotlinCodeAnalyzer kotlinCodeAnalyzer) {
this.kotlinCodeAnalyzer = kotlinCodeAnalyzer;
}
@Override
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
V value = super.get(slice, key);
if (value == null) {
if (BindingContext.FUNCTION == slice || BindingContext.VARIABLE == slice) {
if (key instanceof JetDeclaration) {
JetDeclaration jetDeclaration = (JetDeclaration) key;
if (!JetPsiUtil.isLocal(jetDeclaration)) {
kotlinCodeAnalyzer.resolveToDescriptor(jetDeclaration);
}
}
}
return super.get(slice, key);
}
return value;
}
}
}
@@ -53,6 +53,7 @@ import org.jetbrains.jet.config.CompilerConfiguration;
import org.jetbrains.jet.lang.parsing.JetParserDefinition;
import org.jetbrains.jet.lang.parsing.JetScriptDefinitionProvider;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.CodeAnalyzerInitializer;
import org.jetbrains.jet.lang.resolve.DiagnosticsWithSuppression;
import org.jetbrains.jet.lang.resolve.kotlin.KotlinBinaryClassCache;
import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileFinderFactory;
@@ -236,6 +237,7 @@ public class JetCoreEnvironment {
CliLightClassGenerationSupport cliLightClassGenerationSupport = new CliLightClassGenerationSupport();
project.registerService(LightClassGenerationSupport.class, cliLightClassGenerationSupport);
project.registerService(CliLightClassGenerationSupport.class, cliLightClassGenerationSupport);
project.registerService(CodeAnalyzerInitializer.class, cliLightClassGenerationSupport);
Extensions.getArea(project)
.getExtensionPoint(PsiElementFinder.EP_NAME)
.registerExtension(new JavaElementFinder(project, cliLightClassGenerationSupport));
@@ -282,23 +282,24 @@ public class KotlinToJVMBytecodeCompiler {
@Nullable
private static AnalysisResult analyze(@NotNull final JetCoreEnvironment environment) {
AnalyzerWithCompilerReport analyzerWithCompilerReport = new AnalyzerWithCompilerReport(
environment.getConfiguration().get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY));
MessageCollector collector = environment.getConfiguration().get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY);
assert collector != null;
AnalyzerWithCompilerReport analyzerWithCompilerReport = new AnalyzerWithCompilerReport(collector);
analyzerWithCompilerReport.analyzeAndReport(
environment.getSourceFiles(), new Function0<AnalysisResult>() {
@NotNull
@Override
public AnalysisResult invoke() {
CliLightClassGenerationSupport support = CliLightClassGenerationSupport.getInstanceForCli(environment.getProject());
BindingTrace sharedTrace = support.getTrace();
ModuleDescriptorImpl sharedModule = support.newModule();
BindingTrace sharedTrace = CliLightClassGenerationSupport.createTrace();
ModuleDescriptorImpl analyzeModule = TopDownAnalyzerFacadeForJVM.createAnalyzeModule();
return TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
environment.getProject(),
environment.getSourceFiles(),
sharedTrace,
Predicates.<PsiFile>alwaysTrue(),
sharedModule,
analyzeModule,
environment.getConfiguration().get(JVMConfigurationKeys.MODULE_IDS),
environment.getConfiguration().get(JVMConfigurationKeys.INCREMENTAL_CACHE_PROVIDER)
);