From fd9cb59841958f43c518ef3c531172ac122e55cc Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 12 Mar 2014 15:14:37 +0400 Subject: [PATCH] TopDownAnalyzer supports lazy mode --- .../di/InjectorForTopDownAnalyzerForJvm.java | 2 + .../di/InjectorForTopDownAnalyzerBasic.java | 2 + .../jet/lang/resolve/OverrideResolver.java | 4 + .../jet/lang/resolve/TopDownAnalyzer.java | 157 ++++++++++++++++-- .../di/InjectorForTopDownAnalyzerForJs.java | 2 + 5 files changed, 156 insertions(+), 11 deletions(-) diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java index 02697b59311..def4b1835e0 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java @@ -187,6 +187,8 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly this.topDownAnalyzer.setOverloadResolver(overloadResolver); this.topDownAnalyzer.setOverrideResolver(overrideResolver); this.topDownAnalyzer.setPackageFragmentProvider(mutablePackageFragmentProvider); + this.topDownAnalyzer.setScriptHeaderResolver(scriptHeaderResolver); + this.topDownAnalyzer.setTrace(bindingTrace); this.topDownAnalyzer.setTypeHierarchyResolver(typeHierarchyResolver); javaClassFinder.setProject(project); diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java index 3c4cae111a3..e729f0aa995 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java @@ -145,6 +145,8 @@ public class InjectorForTopDownAnalyzerBasic { this.topDownAnalyzer.setOverloadResolver(overloadResolver); this.topDownAnalyzer.setOverrideResolver(overrideResolver); this.topDownAnalyzer.setPackageFragmentProvider(mutablePackageFragmentProvider); + this.topDownAnalyzer.setScriptHeaderResolver(scriptHeaderResolver); + this.topDownAnalyzer.setTrace(bindingTrace); this.topDownAnalyzer.setTypeHierarchyResolver(typeHierarchyResolver); bodyResolver.setAnnotationResolver(annotationResolver); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java index 95cf0a1d438..a543db927ac 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -61,6 +61,10 @@ public class OverrideResolver { //all created fake descriptors are stored to resolve visibility on them later generateOverridesAndDelegation(c); + check(c); + } + + public void check(@NotNull TopDownAnalysisContext c) { checkVisibility(c); checkOverrides(c); checkParameterOverridesForAllClasses(c); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 55ff4f76aa4..3f82a9ce497 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -19,30 +19,41 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.base.Predicates; import com.google.common.collect.Sets; import com.intellij.psi.PsiElement; +import kotlin.Function1; +import kotlin.KotlinPackage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.context.GlobalContext; +import org.jetbrains.jet.context.GlobalContextImpl; +import org.jetbrains.jet.di.InjectorForLazyResolve; import org.jetbrains.jet.di.InjectorForTopDownAnalyzerBasic; import org.jetbrains.jet.lang.PlatformToKotlinClassMap; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.impl.*; -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.psi.*; +import org.jetbrains.jet.lang.resolve.lazy.ResolveSession; +import org.jetbrains.jet.lang.resolve.lazy.declarations.FileBasedDeclarationProviderFactory; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; +import org.jetbrains.jet.storage.LockBasedStorageManager; import javax.inject.Inject; -import java.util.Collection; -import java.util.Collections; -import java.util.Set; +import java.util.*; public class TopDownAnalyzer { + public static boolean LAZY; + + static { + LAZY = "true".equals(System.getProperty("lazy.tda")); + } + + @NotNull + private BindingTrace trace; @NotNull private DeclarationResolver declarationResolver; @NotNull @@ -57,6 +68,13 @@ public class TopDownAnalyzer { private MutablePackageFragmentProvider packageFragmentProvider; @NotNull private BodyResolver bodyResolver; + @NotNull + private ScriptHeaderResolver scriptHeaderResolver; + + @Inject + public void setTrace(@NotNull BindingTrace trace) { + this.trace = trace; + } @Inject public void setDeclarationResolver(@NotNull DeclarationResolver declarationResolver) { @@ -93,8 +111,13 @@ public class TopDownAnalyzer { this.bodyResolver = bodyResolver; } + @Inject + public void setScriptHeaderResolver(@NotNull ScriptHeaderResolver scriptHeaderResolver) { + this.scriptHeaderResolver = scriptHeaderResolver; + } + public void doProcess( - @NotNull TopDownAnalysisContext c, + @NotNull final TopDownAnalysisContext c, @NotNull JetScope outerScope, @NotNull PackageLikeBuilder owner, @NotNull Collection declarations @@ -102,11 +125,113 @@ public class TopDownAnalyzer { // c.enableDebugOutput(); c.debug("Enter"); - typeHierarchyResolver.process(c, outerScope, owner, declarations); - declarationResolver.process(c); - overrideResolver.process(c); + if (LAZY && !c.getTopDownAnalysisParameters().isDeclaredLocally()) { + final ResolveSession resolveSession = new InjectorForLazyResolve( + declarations.iterator().next().getProject(), // TODO + new GlobalContextImpl((LockBasedStorageManager) c.getStorageManager(), c.getExceptionTracker()), // TODO + (ModuleDescriptorImpl) moduleDescriptor, // TODO + new FileBasedDeclarationProviderFactory(c.getStorageManager(), getFiles(declarations)), + trace + ).getResolveSession(); - lockScopes(c); + // fill in the context + for (PsiElement declaration : declarations) { + declaration.accept( + new JetVisitorVoid() { + private void registerDeclarations(@NotNull List declarations) { + for (JetDeclaration jetDeclaration : declarations) { + jetDeclaration.accept(this); + } + } + + private void registerScope(@Nullable JetDeclaration declaration, @NotNull JetDeclaration anchorForScope) { + if (declaration == null) return; + c.registerDeclaringScope( + declaration, + resolveSession.getScopeProvider().getResolutionScopeForDeclaration(anchorForScope) + ); + } + + @Override + public void visitDeclaration(@NotNull JetDeclaration dcl) { + throw new IllegalArgumentException("Unsupported declaration: " + dcl + " " + dcl.getText()); + } + + @Override + public void visitJetFile(@NotNull JetFile file) { + if (file.isScript()) { + JetScript script = file.getScript(); + assert script != null; + scriptHeaderResolver.processScriptHierarchy(c, script, resolveSession.getScopeProvider().getFileScope(file)); + } + else { + registerDeclarations(file.getDeclarations()); + } + } + + private void visitClassOrObject(@NotNull JetClassOrObject classOrObject) { + c.getClasses().put( + classOrObject, + (ClassDescriptorWithResolutionScopes) resolveSession.getClassDescriptor(classOrObject) + ); + registerDeclarations(classOrObject.getDeclarations()); + } + + @Override + public void visitClass(@NotNull JetClass klass) { + visitClassOrObject(klass); + } + + @Override + public void visitClassObject(@NotNull JetClassObject classObject) { + visitClassOrObject(classObject.getObjectDeclaration()); + } + + @Override + public void visitEnumEntry(@NotNull JetEnumEntry enumEntry) { + visitClassOrObject(enumEntry); + } + + @Override + public void visitObjectDeclaration(@NotNull JetObjectDeclaration declaration) { + visitClassOrObject(declaration); + } + + @Override + public void visitAnonymousInitializer(@NotNull JetClassInitializer initializer) { + registerScope(initializer, initializer); + } + + @Override + public void visitNamedFunction(@NotNull JetNamedFunction function) { + c.getFunctions().put( + function, + (SimpleFunctionDescriptor) resolveSession.resolveToDescriptor(function) + ); + registerScope(function, function); + } + + @Override + public void visitProperty(@NotNull JetProperty property) { + c.getProperties().put( + property, + (PropertyDescriptor) resolveSession.resolveToDescriptor(property) + ); + registerScope(property, property); + registerScope(property.getGetter(), property); + registerScope(property.getSetter(), property); + } + } + ); + } + overrideResolver.check(c); + } + else { + typeHierarchyResolver.process(c, outerScope, owner, declarations); + declarationResolver.process(c); + overrideResolver.process(c); + lockScopes(c); + } overloadResolver.process(c); @@ -118,6 +243,16 @@ public class TopDownAnalyzer { c.printDebugOutput(System.out); } + private static Collection getFiles(Collection declarations) { + return new LinkedHashSet(KotlinPackage.map(declarations, new Function1() { + @Nullable + @Override + public JetFile invoke(PsiElement element) { + return (JetFile) element.getContainingFile(); + } + })); + } + private void lockScopes(@NotNull TopDownAnalysisContext c) { for (ClassDescriptorWithResolutionScopes mutableClassDescriptor : c.getClasses().values()) { ((MutableClassDescriptor) mutableClassDescriptor).lockScopes(); diff --git a/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java b/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java index 70e7aa839c4..16d8fc7b982 100644 --- a/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java +++ b/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java @@ -145,6 +145,8 @@ public class InjectorForTopDownAnalyzerForJs { this.topDownAnalyzer.setOverloadResolver(overloadResolver); this.topDownAnalyzer.setOverrideResolver(overrideResolver); this.topDownAnalyzer.setPackageFragmentProvider(mutablePackageFragmentProvider); + this.topDownAnalyzer.setScriptHeaderResolver(scriptHeaderResolver); + this.topDownAnalyzer.setTrace(bindingTrace); this.topDownAnalyzer.setTypeHierarchyResolver(typeHierarchyResolver); bodyResolver.setAnnotationResolver(annotationResolver);