LTDA: Fix REPL and make it work with lazy resolve
This commit is contained in:
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.cli.jvm.repl
|
||||
|
||||
import org.jetbrains.jet.lang.resolve.lazy.declarations.PackageMemberDeclarationProvider
|
||||
import org.jetbrains.jet.lang.resolve.name.Name
|
||||
import org.jetbrains.jet.lang.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration
|
||||
|
||||
open class DelegatePackageMemberDeclarationProvider(var delegate: PackageMemberDeclarationProvider) : PackageMemberDeclarationProvider {
|
||||
// Can't use Kotlin delegate feature because of inability to change delegate object in runtime (KT-5870)
|
||||
|
||||
override fun getAllDeclaredSubPackages() = delegate.getAllDeclaredSubPackages()
|
||||
|
||||
override fun getPackageFiles() = delegate.getPackageFiles()
|
||||
|
||||
override fun getDeclarations(kindFilter: DescriptorKindFilter,
|
||||
nameFilter: (Name) -> Boolean) = delegate.getDeclarations(kindFilter, nameFilter)
|
||||
|
||||
override fun getFunctionDeclarations(name: Name) = delegate.getFunctionDeclarations(name)
|
||||
|
||||
override fun getPropertyDeclarations(name: Name) = delegate.getPropertyDeclarations(name)
|
||||
|
||||
override fun getClassOrObjectDeclarations(name: Name) = delegate.getClassOrObjectDeclarations(name)
|
||||
}
|
||||
@@ -27,7 +27,9 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiFileFactory;
|
||||
import com.intellij.psi.impl.PsiFileFactoryImpl;
|
||||
import com.intellij.psi.search.ProjectScope;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import kotlin.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.OutputFile;
|
||||
@@ -41,26 +43,25 @@ import org.jetbrains.jet.codegen.CompilationErrorHandler;
|
||||
import org.jetbrains.jet.codegen.KotlinCodegenFacade;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.config.CompilerConfiguration;
|
||||
import org.jetbrains.jet.context.ContextPackage;
|
||||
import org.jetbrains.jet.context.GlobalContextImpl;
|
||||
import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJvm;
|
||||
import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.impl.CompositePackageFragmentProvider;
|
||||
import org.jetbrains.jet.lang.descriptors.impl.ModuleDescriptorImpl;
|
||||
import org.jetbrains.jet.lang.descriptors.impl.PackageLikeBuilderDummy;
|
||||
import org.jetbrains.jet.lang.parsing.JetParserDefinition;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetScript;
|
||||
import org.jetbrains.jet.lang.resolve.*;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
import org.jetbrains.jet.lang.resolve.java.TopDownAnalyzerFacadeForJVM;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.declarations.*;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.plugin.JetLanguage;
|
||||
import org.jetbrains.jet.storage.ExceptionTracker;
|
||||
import org.jetbrains.jet.storage.LockBasedStorageManager;
|
||||
import org.jetbrains.jet.utils.UtilsPackage;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
@@ -92,8 +93,10 @@ public class ReplInterpreter {
|
||||
private final PsiFileFactoryImpl psiFileFactory;
|
||||
private final BindingTraceContext trace;
|
||||
private final ModuleDescriptorImpl module;
|
||||
|
||||
private final TopDownAnalysisContext topDownAnalysisContext;
|
||||
private final TopDownAnalyzer topDownAnalyzer;
|
||||
private final LazyTopDownAnalyzer topDownAnalyzer;
|
||||
private final ScriptMutableDeclarationProviderFactory scriptDeclarationFactory;
|
||||
|
||||
public ReplInterpreter(@NotNull Disposable disposable, @NotNull CompilerConfiguration configuration) {
|
||||
JetCoreEnvironment environment = JetCoreEnvironment.createForProduction(disposable, configuration);
|
||||
@@ -101,20 +104,41 @@ public class ReplInterpreter {
|
||||
this.psiFileFactory = (PsiFileFactoryImpl) PsiFileFactory.getInstance(project);
|
||||
this.trace = new BindingTraceContext();
|
||||
this.module = TopDownAnalyzerFacadeForJVM.createJavaModule("<repl>");
|
||||
TopDownAnalysisParameters topDownAnalysisParameters = TopDownAnalysisParameters.createForLocalDeclarations(
|
||||
new LockBasedStorageManager(),
|
||||
new ExceptionTracker(), // dummy
|
||||
Predicates.<PsiFile>alwaysTrue()
|
||||
|
||||
GlobalContextImpl context = ContextPackage.GlobalContext();
|
||||
|
||||
TopDownAnalysisParameters topDownAnalysisParameters = TopDownAnalysisParameters.createForLazy(
|
||||
context.getStorageManager(),
|
||||
context.getExceptionTracker(),
|
||||
Predicates.<PsiFile>alwaysTrue(),
|
||||
false,
|
||||
true
|
||||
);
|
||||
|
||||
// FIXME: Make it work for lazy resolve
|
||||
InjectorForTopDownAnalyzerForJvm injector = null;
|
||||
scriptDeclarationFactory = new ScriptMutableDeclarationProviderFactory();
|
||||
|
||||
InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm(
|
||||
project,
|
||||
context,
|
||||
trace,
|
||||
module,
|
||||
ProjectScope.getAllScope(project),
|
||||
scriptDeclarationFactory
|
||||
);
|
||||
|
||||
this.topDownAnalysisContext = new TopDownAnalysisContext(topDownAnalysisParameters);
|
||||
this.topDownAnalyzer = null;
|
||||
this.topDownAnalyzer = injector.getLazyTopDownAnalyzer();
|
||||
|
||||
this.topDownAnalyzer.getCodeAnalyzer().getScopeProvider().setAdditionalFileScopesProvider(new Function1<JetFile, JetScope>() {
|
||||
@Override
|
||||
public JetScope invoke(JetFile file) {
|
||||
return lastLineScope;
|
||||
}
|
||||
});
|
||||
|
||||
module.initialize(new CompositePackageFragmentProvider(
|
||||
Arrays.asList(
|
||||
topDownAnalyzer.getPackageFragmentProvider(),
|
||||
injector.getResolveSession().getPackageFragmentProvider(),
|
||||
injector.getJavaDescriptorResolver().getPackageFragmentProvider()
|
||||
)
|
||||
));
|
||||
@@ -322,33 +346,23 @@ public class ReplInterpreter {
|
||||
|
||||
@Nullable
|
||||
private ScriptDescriptor doAnalyze(@NotNull JetFile psiFile, @NotNull MessageCollector messageCollector) {
|
||||
WritableScope scope = new WritableScopeImpl(
|
||||
JetScope.Empty.INSTANCE$, module,
|
||||
new TraceBasedRedeclarationHandler(trace), "Root scope in analyzePackage"
|
||||
);
|
||||
scriptDeclarationFactory.setDelegateFactory(
|
||||
new FileBasedDeclarationProviderFactory(topDownAnalysisContext.getStorageManager(), Collections.singletonList(psiFile)));
|
||||
|
||||
scope.changeLockLevel(WritableScope.LockLevel.BOTH);
|
||||
TopDownAnalysisContext context = topDownAnalyzer.analyzeDeclarations(
|
||||
topDownAnalysisContext.getTopDownAnalysisParameters(),
|
||||
Collections.singletonList(psiFile));
|
||||
|
||||
// Import a scope that contains all top-level packages that come from dependencies
|
||||
// This makes the packages visible at all, does not import themselves
|
||||
scope.importScope(module.getPackage(FqName.ROOT).getMemberScope());
|
||||
|
||||
if (lastLineScope != null) {
|
||||
scope.importScope(lastLineScope);
|
||||
if (trace.get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, psiFile) == null) {
|
||||
trace.record(BindingContext.FILE_TO_PACKAGE_FRAGMENT, psiFile, topDownAnalyzer.getCodeAnalyzer().getPackageFragment(FqName.ROOT));
|
||||
}
|
||||
|
||||
scope.changeLockLevel(WritableScope.LockLevel.READING);
|
||||
|
||||
// dummy builder is used because "root" is module descriptor,
|
||||
// packages added to module explicitly in
|
||||
topDownAnalyzer.doProcess(topDownAnalysisContext, scope, new PackageLikeBuilderDummy(), Collections.singletonList(psiFile));
|
||||
|
||||
boolean hasErrors = AnalyzerWithCompilerReport.reportDiagnostics(trace.getBindingContext().getDiagnostics(), messageCollector);
|
||||
if (hasErrors) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ScriptDescriptor scriptDescriptor = topDownAnalysisContext.getScripts().get(psiFile.getScript());
|
||||
ScriptDescriptor scriptDescriptor = context.getScripts().get(psiFile.getScript());
|
||||
lastLineScope = trace.get(BindingContext.SCRIPT_SCOPE, scriptDescriptor);
|
||||
if (lastLineScope == null) {
|
||||
throw new IllegalStateException("last line scope is not initialized");
|
||||
@@ -398,4 +412,53 @@ public class ReplInterpreter {
|
||||
);
|
||||
}
|
||||
|
||||
private static class ScriptMutableDeclarationProviderFactory implements DeclarationProviderFactory {
|
||||
private DeclarationProviderFactory delegateFactory;
|
||||
private AdaptablePackageMemberDeclarationProvider rootPackageProvider;
|
||||
|
||||
public void setDelegateFactory(DeclarationProviderFactory delegateFactory) {
|
||||
this.delegateFactory = delegateFactory;
|
||||
|
||||
PackageMemberDeclarationProvider provider = delegateFactory.getPackageMemberDeclarationProvider(FqName.ROOT);
|
||||
if (rootPackageProvider == null) {
|
||||
assert provider != null;
|
||||
rootPackageProvider = new AdaptablePackageMemberDeclarationProvider(provider);
|
||||
}
|
||||
else {
|
||||
rootPackageProvider.addDelegateProvider(provider);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ClassMemberDeclarationProvider getClassMemberDeclarationProvider(@NotNull JetClassLikeInfo classLikeInfo) {
|
||||
return delegateFactory.getClassMemberDeclarationProvider(classLikeInfo);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PackageMemberDeclarationProvider getPackageMemberDeclarationProvider(@NotNull FqName packageFqName) {
|
||||
if (packageFqName.isRoot()) {
|
||||
return rootPackageProvider;
|
||||
}
|
||||
|
||||
return this.delegateFactory.getPackageMemberDeclarationProvider(packageFqName);
|
||||
}
|
||||
|
||||
public static class AdaptablePackageMemberDeclarationProvider extends DelegatePackageMemberDeclarationProvider {
|
||||
@NotNull
|
||||
private PackageMemberDeclarationProvider delegateProvider;
|
||||
|
||||
public AdaptablePackageMemberDeclarationProvider(@NotNull PackageMemberDeclarationProvider delegateProvider) {
|
||||
super(delegateProvider);
|
||||
this.delegateProvider = delegateProvider;
|
||||
}
|
||||
|
||||
public void addDelegateProvider(PackageMemberDeclarationProvider provider) {
|
||||
delegateProvider = new CombinedPackageMemberDeclarationProvider(Lists.newArrayList(provider, delegateProvider));
|
||||
|
||||
setDelegate(delegateProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user