From fecc98af8c20aa27f07abb82786ef8e34bc3767e Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 14 Mar 2012 21:47:29 +0400 Subject: [PATCH] more DI in top down analysis --- .../resolve/java/AnalyzerFacadeForJVM.java | 3 +- .../jet/di/InjectorForTopDownAnalyzer.java | 31 +++- .../jet/lang/resolve/AnalyzingUtils.java | 52 +----- .../jet/lang/resolve/BodyResolver.java | 9 +- .../jet/lang/resolve/ControlFlowAnalyzer.java | 10 +- .../jet/lang/resolve/OverrideResolver.java | 8 +- .../lang/resolve/TopDownAnalysisContext.java | 48 ++---- .../resolve/TopDownAnalysisParameters.java | 64 +++++++ .../jet/lang/resolve/TopDownAnalyzer.java | 156 +++++++++++++++--- .../jet/di/AllInjectorsGenerator.java | 3 +- .../k2js/analyze/AnalyzerFacadeForJS.java | 3 +- 11 files changed, 265 insertions(+), 122 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisParameters.java 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 bbffcbb5381..b749b40d63d 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 @@ -145,7 +145,7 @@ public class AnalyzerFacadeForJVM { public static BindingContext analyzeFilesWithJavaIntegration(Project project, Collection files, Predicate filesToAnalyzeCompletely, JetControlFlowDataTraceFactory flowDataTraceFactory) { BindingTraceContext bindingTraceContext = new BindingTraceContext(); - return AnalyzingUtils.analyzeFilesWithGivenTrace( + AnalyzingUtils.analyzeFilesWithGivenTrace( project, JavaBridgeConfiguration.createJavaBridgeConfiguration(project, bindingTraceContext, DefaultModuleConfiguration.createStandardConfiguration(project)), files, @@ -153,6 +153,7 @@ public class AnalyzerFacadeForJVM { flowDataTraceFactory, bindingTraceContext ); + return bindingTraceContext.getBindingContext(); } public static BindingContext shallowAnalyzeFiles(Collection files) { diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzer.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzer.java index 6a81e0c4885..ebc497c2867 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzer.java @@ -18,12 +18,13 @@ package org.jetbrains.jet.di; import org.jetbrains.jet.lang.resolve.TopDownAnalyzer; +import org.jetbrains.jet.lang.resolve.TopDownAnalysisContext; import org.jetbrains.jet.lang.resolve.BodyResolver; import org.jetbrains.jet.lang.resolve.ControlFlowAnalyzer; import org.jetbrains.jet.lang.resolve.DeclarationsChecker; import org.jetbrains.jet.lang.resolve.DescriptorResolver; import com.intellij.openapi.project.Project; -import org.jetbrains.jet.lang.resolve.TopDownAnalysisContext; +import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters; import org.jetbrains.jet.lang.ModuleConfiguration; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; @@ -39,7 +40,7 @@ import org.jetbrains.jet.lang.resolve.OverloadResolver; import org.jetbrains.jet.lang.resolve.OverrideResolver; import org.jetbrains.jet.lang.resolve.TypeHierarchyResolver; import com.intellij.openapi.project.Project; -import org.jetbrains.jet.lang.resolve.TopDownAnalysisContext; +import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters; import org.jetbrains.jet.lang.ModuleConfiguration; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; @@ -49,25 +50,29 @@ import org.jetbrains.annotations.NotNull; public class InjectorForTopDownAnalyzer { private TopDownAnalyzer topDownAnalyzer; + private TopDownAnalysisContext topDownAnalysisContext; private BodyResolver bodyResolver; private ControlFlowAnalyzer controlFlowAnalyzer; private DeclarationsChecker declarationsChecker; private DescriptorResolver descriptorResolver; private final Project project; + private final TopDownAnalysisParameters topDownAnalysisParameters; public InjectorForTopDownAnalyzer( @NotNull Project project, - @NotNull TopDownAnalysisContext topDownAnalysisContext, + @NotNull TopDownAnalysisParameters topDownAnalysisParameters, @NotNull ModuleConfiguration moduleConfiguration, @NotNull ModuleDescriptor moduleDescriptor, JetControlFlowDataTraceFactory jetControlFlowDataTraceFactory ) { this.topDownAnalyzer = new TopDownAnalyzer(); + this.topDownAnalysisContext = new TopDownAnalysisContext(); this.bodyResolver = new BodyResolver(); this.controlFlowAnalyzer = new ControlFlowAnalyzer(); this.declarationsChecker = new DeclarationsChecker(); this.descriptorResolver = new DescriptorResolver(); this.project = project; + this.topDownAnalysisParameters = topDownAnalysisParameters; DeclarationResolver declarationResolver = new DeclarationResolver(); AnnotationResolver annotationResolver = new AnnotationResolver(); CallResolver callResolver = new CallResolver(); @@ -80,19 +85,30 @@ public class InjectorForTopDownAnalyzer { OverrideResolver overrideResolver = new OverrideResolver(); TypeHierarchyResolver typeHierarchyResolver = new TypeHierarchyResolver(); + this.topDownAnalyzer.setBodyResolver(bodyResolver); + this.topDownAnalyzer.setConfiguration(moduleConfiguration); + this.topDownAnalyzer.setContext(topDownAnalysisContext); + this.topDownAnalyzer.setControlFlowAnalyzer(controlFlowAnalyzer); this.topDownAnalyzer.setDeclarationResolver(declarationResolver); + this.topDownAnalyzer.setDeclarationsChecker(declarationsChecker); this.topDownAnalyzer.setDelegationResolver(delegationResolver); + this.topDownAnalyzer.setModuleDescriptor(moduleDescriptor); this.topDownAnalyzer.setOverloadResolver(overloadResolver); this.topDownAnalyzer.setOverrideResolver(overrideResolver); + this.topDownAnalyzer.setTopDownAnalysisParameters(topDownAnalysisParameters); this.topDownAnalyzer.setTypeHierarchyResolver(typeHierarchyResolver); + this.topDownAnalysisContext.setTopDownAnalysisParameters(topDownAnalysisParameters); + this.bodyResolver.setCallResolver(callResolver); this.bodyResolver.setContext(topDownAnalysisContext); this.bodyResolver.setDescriptorResolver(descriptorResolver); this.bodyResolver.setExpressionTypingServices(expressionTypingServices); + this.bodyResolver.setTopDownAnalysisParameters(topDownAnalysisParameters); this.controlFlowAnalyzer.setContext(topDownAnalysisContext); this.controlFlowAnalyzer.setFlowDataTraceFactory(jetControlFlowDataTraceFactory); + this.controlFlowAnalyzer.setTopDownAnalysisParameters(topDownAnalysisParameters); this.declarationsChecker.setContext(topDownAnalysisContext); @@ -129,6 +145,7 @@ public class InjectorForTopDownAnalyzer { overloadResolver.setContext(topDownAnalysisContext); overrideResolver.setContext(topDownAnalysisContext); + overrideResolver.setTopDownAnalysisParameters(topDownAnalysisParameters); typeHierarchyResolver.setConfiguration(moduleConfiguration); typeHierarchyResolver.setContext(topDownAnalysisContext); @@ -142,6 +159,10 @@ public class InjectorForTopDownAnalyzer { return this.topDownAnalyzer; } + public TopDownAnalysisContext getTopDownAnalysisContext() { + return this.topDownAnalysisContext; + } + public BodyResolver getBodyResolver() { return this.bodyResolver; } @@ -162,4 +183,8 @@ public class InjectorForTopDownAnalyzer { return this.project; } + public TopDownAnalysisParameters getTopDownAnalysisParameters() { + return this.topDownAnalysisParameters; + } + } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java index 72e0dc4b142..15de36d5efd 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java @@ -17,7 +17,6 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.base.Predicate; -import com.google.common.collect.Lists; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; @@ -26,16 +25,10 @@ import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.ModuleConfiguration; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; -import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.DiagnosticHolder; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.psi.JetFile; -import org.jetbrains.jet.lang.resolve.scopes.JetScope; -import org.jetbrains.jet.lang.resolve.scopes.JetScopeAdapter; -import org.jetbrains.jet.lang.resolve.scopes.WritableScope; -import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; -import org.jetbrains.jet.lang.types.lang.JetStandardLibrary; import java.util.ArrayList; import java.util.Collection; @@ -91,10 +84,11 @@ public class AnalyzingUtils { @NotNull Predicate filesToAnalyzeCompletely, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { BindingTraceContext bindingTraceContext = new BindingTraceContext(); - return analyzeFilesWithGivenTrace(project, configuration, files, filesToAnalyzeCompletely, flowDataTraceFactory, bindingTraceContext); + analyzeFilesWithGivenTrace(project, configuration, files, filesToAnalyzeCompletely, flowDataTraceFactory, bindingTraceContext); + return bindingTraceContext.getBindingContext(); } - public static BindingContext analyzeFilesWithGivenTrace( + public static void analyzeFilesWithGivenTrace( @NotNull Project project, @NotNull final ModuleConfiguration configuration, @NotNull Collection files, @@ -102,45 +96,7 @@ public class AnalyzingUtils { @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory, @NotNull BindingTraceContext bindingTraceContext) { - final ModuleDescriptor owner = new ModuleDescriptor(""); - - final WritableScope scope = new WritableScopeImpl( - JetScope.EMPTY, owner, - new TraceBasedRedeclarationHandler(bindingTraceContext)).setDebugName("Root scope in analyzeNamespace"); - scope.changeLockLevel(WritableScope.LockLevel.BOTH); - - // Import the lang package - scope.importScope(JetStandardLibrary.getInstance().getLibraryScope()); - - // Import a scope that contains all top-level namespaces that come from dependencies - // This makes the namespaces visible at all, does not import themselves - scope.importScope(new JetScopeAdapter(JetScope.EMPTY) { - @Override - public NamespaceDescriptor getNamespace(@NotNull String name) { - // Is it a top-level namespace coming from the dependencies? - NamespaceDescriptor topLevelNamespaceFromConfiguration = configuration.getTopLevelNamespace(name); - if (topLevelNamespaceFromConfiguration != null) { - return topLevelNamespaceFromConfiguration; - } - // Should be null, we are delegating to EMPTY - return super.getNamespace(name); - } - - @NotNull - @Override - public Collection getAllDescriptors() { - List allDescriptors = Lists.newArrayList(); - configuration.addAllTopLevelNamespacesTo(allDescriptors); - return allDescriptors; - } - }); - - // dummy builder is used because "root" is module descriptor, - // namespaces added to module explicitly in - TopDownAnalyzer.process(project, bindingTraceContext, scope, - new NamespaceLikeBuilderDummy(), owner, files, filesToAnalyzeCompletely, flowDataTraceFactory, configuration); - - return bindingTraceContext.getBindingContext(); + TopDownAnalyzer.doAnalyzeFilesWithGivenTrace(project, configuration, files, filesToAnalyzeCompletely, flowDataTraceFactory, bindingTraceContext); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java index 27c40da7679..d58bb5051a2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -55,6 +55,8 @@ public class BodyResolver { @NotNull private TopDownAnalysisContext context; @NotNull + private TopDownAnalysisParameters topDownAnalysisParameters; + @NotNull private DescriptorResolver descriptorResolver; @NotNull private ExpressionTypingServices expressionTypingServices; @@ -67,6 +69,11 @@ public class BodyResolver { this.context = context; } + @Inject + public void setTopDownAnalysisParameters(@NotNull TopDownAnalysisParameters topDownAnalysisParameters) { + this.topDownAnalysisParameters = topDownAnalysisParameters; + } + @Inject public void setDescriptorResolver(@NotNull DescriptorResolver descriptorResolver) { this.descriptorResolver = descriptorResolver; @@ -97,7 +104,7 @@ public class BodyResolver { resolveSecondaryConstructorBodies(); resolveFunctionBodies(); - if (!context.isDeclaredLocally()) { + if (!topDownAnalysisParameters.isDeclaredLocally()) { computeDeferredTypes(); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ControlFlowAnalyzer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ControlFlowAnalyzer.java index 02f4992869a..73ff41c9d91 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ControlFlowAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ControlFlowAnalyzer.java @@ -35,10 +35,16 @@ import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; * @author svtk */ public class ControlFlowAnalyzer { + private TopDownAnalysisParameters topDownAnalysisParameters; private TopDownAnalysisContext context; private JetControlFlowDataTraceFactory flowDataTraceFactory; + @Inject + public void setTopDownAnalysisParameters(TopDownAnalysisParameters topDownAnalysisParameters) { + this.topDownAnalysisParameters = topDownAnalysisParameters; + } + @Inject public void setContext(TopDownAnalysisContext context) { this.context = context; @@ -83,7 +89,7 @@ public class ControlFlowAnalyzer { private void checkClassOrObject(JetClassOrObject klass) { // A pseudocode of class initialization corresponds to a class JetFlowInformationProvider flowInformationProvider = new JetFlowInformationProvider((JetDeclaration) klass, (JetExpression) klass, flowDataTraceFactory, context.getTrace()); - flowInformationProvider.markUninitializedVariables((JetElement) klass, context.isDeclaredLocally()); + flowInformationProvider.markUninitializedVariables((JetElement) klass, topDownAnalysisParameters.isDeclaredLocally()); } private void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor) { @@ -107,7 +113,7 @@ public class ControlFlowAnalyzer { // Property accessor is checked through initialization of a class check (at 'checkClassOrObject') boolean isPropertyAccessor = function instanceof JetPropertyAccessor; - flowInformationProvider.markUninitializedVariables(function.asElement(), context.isDeclaredLocally() || isPropertyAccessor); + flowInformationProvider.markUninitializedVariables(function.asElement(), topDownAnalysisParameters.isDeclaredLocally() || isPropertyAccessor); flowInformationProvider.markUnusedVariables(function.asElement()); 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 ee65768f7f6..32dd8aa3269 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -45,6 +45,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.DELEGATED; public class OverrideResolver { private TopDownAnalysisContext context; + private TopDownAnalysisParameters topDownAnalysisParameters; @Inject @@ -52,6 +53,11 @@ public class OverrideResolver { this.context = context; } + @Inject + public void setTopDownAnalysisParameters(TopDownAnalysisParameters topDownAnalysisParameters) { + this.topDownAnalysisParameters = topDownAnalysisParameters; + } + public void process() { @@ -213,7 +219,7 @@ public class OverrideResolver { } protected void checkOverridesInAClass(MutableClassDescriptor classDescriptor, JetClassOrObject klass) { - if (context.analyzingBootstrapLibrary()) return; + if (topDownAnalysisParameters.isAnalyzingBootstrapLibrary()) return; // Check overrides for internal consistency for (CallableMemberDescriptor member : classDescriptor.getCallableMembers()) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java index a8d5ba80b44..1f9e86986b5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java @@ -32,6 +32,7 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; +import javax.inject.Inject; import java.io.PrintStream; import java.util.Map; import java.util.Set; @@ -41,7 +42,7 @@ import java.util.Set; */ public class TopDownAnalysisContext { - private final ObservableBindingTrace trace; + private ObservableBindingTrace trace; private final Map classes = Maps.newLinkedHashMap(); private final Map objects = Maps.newLinkedHashMap(); @@ -54,40 +55,19 @@ public class TopDownAnalysisContext { private final Map properties = Maps.newLinkedHashMap(); private final Set primaryConstructorParameterProperties = Sets.newHashSet(); - private final Predicate analyzeCompletely; - private StringBuilder debugOutput; - private final boolean analyzingBootstrapLibrary; - private boolean declaredLocally; - private final InjectorForTopDownAnalyzer injector; - public TopDownAnalysisContext( - final Project project, - final BindingTrace trace, - Predicate analyzeCompletely, - @NotNull final ModuleConfiguration configuration, - @NotNull final ModuleDescriptor moduleDescriptor, - boolean declaredLocally, - boolean analyzingBootstrapLibrary, - @Nullable final JetControlFlowDataTraceFactory jetControlFlowDataTraceFactory) { + private TopDownAnalysisParameters topDownAnalysisParameters; - if (analyzingBootstrapLibrary == (jetControlFlowDataTraceFactory != null)) { - throw new IllegalStateException( - "jetControlFlowDataTraceFactory must not be passed when analyzingBootstrapLibrary and vice versa"); - } - - this.injector = new InjectorForTopDownAnalyzer(project, this, configuration, moduleDescriptor, jetControlFlowDataTraceFactory); - - this.trace = new ObservableBindingTrace(trace); - this.analyzeCompletely = analyzeCompletely; - this.declaredLocally = declaredLocally; - this.analyzingBootstrapLibrary = analyzingBootstrapLibrary; + @Inject + public void setTopDownAnalysisParameters(TopDownAnalysisParameters topDownAnalysisParameters) { + this.topDownAnalysisParameters = topDownAnalysisParameters; + this.trace = new ObservableBindingTrace(topDownAnalysisParameters.getTrace()); } - public InjectorForTopDownAnalyzer getInjector() { - return injector; - } + + public void debug(Object message) { if (debugOutput != null) { @@ -107,13 +87,9 @@ public class TopDownAnalysisContext { } } - public boolean analyzingBootstrapLibrary() { - return analyzingBootstrapLibrary; - } - public boolean completeAnalysisNeeded(@NotNull PsiElement element) { PsiFile containingFile = element.getContainingFile(); - boolean result = containingFile != null && analyzeCompletely.apply(containingFile); + boolean result = containingFile != null && topDownAnalysisParameters.getAnalyzeCompletely().apply(containingFile); if (!result) { debug(containingFile); } @@ -161,8 +137,4 @@ public class TopDownAnalysisContext { return functions; } - public boolean isDeclaredLocally() { - return declaredLocally; - } - } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisParameters.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisParameters.java new file mode 100644 index 00000000000..3f1d5340d60 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisParameters.java @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2012 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.lang.resolve; + +import com.google.common.base.Predicate; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; + +/** + * Various junk that cannot be placed into context (yet). + * + * @author Stepan Koltsov + */ +public class TopDownAnalysisParameters { + @NotNull + private final Predicate analyzeCompletely; + private final boolean analyzingBootstrapLibrary; + private final boolean declaredLocally; + @NotNull + private final BindingTrace trace; + + public TopDownAnalysisParameters( + @NotNull Predicate analyzeCompletely, + boolean analyzingBootstrapLibrary, + boolean declaredLocally, + @NotNull BindingTrace trace) { + this.analyzeCompletely = analyzeCompletely; + this.analyzingBootstrapLibrary = analyzingBootstrapLibrary; + this.declaredLocally = declaredLocally; + this.trace = trace; + } + + @NotNull + public Predicate getAnalyzeCompletely() { + return analyzeCompletely; + } + + public boolean isAnalyzingBootstrapLibrary() { + return analyzingBootstrapLibrary; + } + + public boolean isDeclaredLocally() { + return declaredLocally; + } + + @NotNull + public BindingTrace getTrace() { + return trace; + } +} 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 c61e5e1eee8..408fc93b1b5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -18,10 +18,12 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.base.Predicate; import com.google.common.base.Predicates; +import com.google.common.collect.Lists; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.di.InjectorForTopDownAnalyzer; import org.jetbrains.jet.lang.ModuleConfiguration; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.*; @@ -29,8 +31,11 @@ import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetObjectDeclaration; import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.JetScopeAdapter; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lang.types.lang.JetStandardClasses; +import org.jetbrains.jet.lang.types.lang.JetStandardLibrary; import javax.inject.Inject; import java.util.ArrayList; @@ -53,7 +58,18 @@ public class TopDownAnalyzer { private OverrideResolver overrideResolver; @NotNull private OverloadResolver overloadResolver; + @NotNull + private TopDownAnalysisParameters topDownAnalysisParameters; + @NotNull + private TopDownAnalysisContext context; + @NotNull + private ModuleConfiguration configuration; + @NotNull + private ModuleDescriptor moduleDescriptor; + private BodyResolver bodyResolver; + private ControlFlowAnalyzer controlFlowAnalyzer; + private DeclarationsChecker declarationsChecker; @Inject public void setDeclarationResolver(@NotNull DeclarationResolver declarationResolver) { @@ -80,23 +96,45 @@ public class TopDownAnalyzer { this.overloadResolver = overloadResolver; } + @Inject + public void setTopDownAnalysisParameters(@NotNull TopDownAnalysisParameters topDownAnalysisParameters) { + this.topDownAnalysisParameters = topDownAnalysisParameters; + } + + @Inject + public void setContext(@NotNull TopDownAnalysisContext context) { + this.context = context; + } + + @Inject + public void setConfiguration(@NotNull ModuleConfiguration configuration) { + this.configuration = configuration; + } + + @Inject + public void setModuleDescriptor(@NotNull ModuleDescriptor moduleDescriptor) { + this.moduleDescriptor = moduleDescriptor; + } + + @Inject + public void setBodyResolver(BodyResolver bodyResolver) { + this.bodyResolver = bodyResolver; + } + + @Inject + public void setControlFlowAnalyzer(ControlFlowAnalyzer controlFlowAnalyzer) { + this.controlFlowAnalyzer = controlFlowAnalyzer; + } + + @Inject + public void setDeclarationsChecker(DeclarationsChecker declarationsChecker) { + this.declarationsChecker = declarationsChecker; + } + + public static void process( - @NotNull Project project, - @NotNull BindingTrace trace, - @NotNull JetScope outerScope, - @NotNull NamespaceLikeBuilder owner, - @NotNull ModuleDescriptor moduleDescriptor, - @NotNull Collection files, - @NotNull Predicate analyzeCompletely, - @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory, - @NotNull ModuleConfiguration configuration - ) { - process(project, trace, outerScope, moduleDescriptor, owner, files, analyzeCompletely, flowDataTraceFactory, configuration, false); - } - - private static void process( @NotNull Project project, @NotNull BindingTrace trace, @NotNull JetScope outerScope, @@ -107,13 +145,17 @@ public class TopDownAnalyzer { @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory, @NotNull ModuleConfiguration configuration, boolean declaredLocally) { - TopDownAnalysisContext context = new TopDownAnalysisContext(project, trace, analyzeCompletely, configuration, moduleDescriptor, declaredLocally, false, flowDataTraceFactory); - context.getInjector().getTopDownAnalyzer().doProcess(context, outerScope, owner, declarations); + + TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(analyzeCompletely, false, declaredLocally, trace); + + InjectorForTopDownAnalyzer injector = new InjectorForTopDownAnalyzer(project, topDownAnalysisParameters, configuration, moduleDescriptor, flowDataTraceFactory); + + injector.getTopDownAnalyzer().doProcess(outerScope, owner, declarations); } - private void doProcess( - TopDownAnalysisContext context, JetScope outerScope, + public void doProcess( + JetScope outerScope, NamespaceLikeBuilder owner, Collection declarations) { // context.enableDebugOutput(); @@ -124,14 +166,14 @@ public class TopDownAnalyzer { delegationResolver.process(); overrideResolver.process(); - lockScopes(context); + lockScopes(); overloadResolver.process(); - if (!context.analyzingBootstrapLibrary()) { - context.getInjector().getBodyResolver().resolveBehaviorDeclarationBodies(); - context.getInjector().getControlFlowAnalyzer().process(); - context.getInjector().getDeclarationsChecker().process(); + if (!topDownAnalysisParameters.isAnalyzingBootstrapLibrary()) { + bodyResolver.resolveBehaviorDeclarationBodies(); + controlFlowAnalyzer.process(); + declarationsChecker.process(); } context.debug("Exit"); @@ -139,7 +181,7 @@ public class TopDownAnalyzer { } - private static void lockScopes(TopDownAnalysisContext context) { + private void lockScopes() { for (MutableClassDescriptor mutableClassDescriptor : context.getClasses().values()) { mutableClassDescriptor.lockScopes(); } @@ -157,7 +199,17 @@ public class TopDownAnalyzer { @NotNull WritableScope outerScope, @NotNull NamespaceDescriptorImpl standardLibraryNamespace, @NotNull List files) { - TopDownAnalysisContext context = new TopDownAnalysisContext(project, trace, Predicates.alwaysFalse(), ModuleConfiguration.EMPTY, JetStandardClasses.FAKE_STANDARD_CLASSES_MODULE, false, true, null); + + TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(Predicates.alwaysFalse(), true, false, trace); + InjectorForTopDownAnalyzer injector = new InjectorForTopDownAnalyzer( + project, topDownAnalysisParameters, ModuleConfiguration.EMPTY, + JetStandardClasses.FAKE_STANDARD_CLASSES_MODULE, null); + + injector.getTopDownAnalyzer().doProcessStandardLibraryNamespace(outerScope, standardLibraryNamespace, files); + } + + private void doProcessStandardLibraryNamespace( + WritableScope outerScope, NamespaceDescriptorImpl standardLibraryNamespace, List files) { ArrayList toAnalyze = new ArrayList(); for(JetFile file : files) { context.getNamespaceDescriptors().put(file, standardLibraryNamespace); @@ -166,7 +218,7 @@ public class TopDownAnalyzer { } // context.getDeclaringScopes().put(file, outerScope); - context.getInjector().getTopDownAnalyzer().doProcess(context, outerScope, standardLibraryNamespace, toAnalyze); + doProcess(outerScope, standardLibraryNamespace, toAnalyze); } public static void processObject( @@ -213,6 +265,58 @@ public class TopDownAnalyzer { }, Collections.singletonList(object), Predicates.equalTo(object.getContainingFile()), JetControlFlowDataTraceFactory.EMPTY, ModuleConfiguration.EMPTY, true); } + + public static void doAnalyzeFilesWithGivenTrace(Project project, final ModuleConfiguration configuration, Collection files, Predicate filesToAnalyzeCompletely, JetControlFlowDataTraceFactory flowDataTraceFactory, BindingTraceContext bindingTraceContext) { + final ModuleDescriptor owner = new ModuleDescriptor(""); + + TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters( + filesToAnalyzeCompletely, false, false, bindingTraceContext); + + InjectorForTopDownAnalyzer injector = new InjectorForTopDownAnalyzer( + project, topDownAnalysisParameters, configuration, owner, flowDataTraceFactory); + + + injector.getTopDownAnalyzer().doAnalyzeFilesWithGivenTrance2(files); + } + + private void doAnalyzeFilesWithGivenTrance2(Collection files) { + final WritableScope scope = new WritableScopeImpl( + JetScope.EMPTY, moduleDescriptor, + new TraceBasedRedeclarationHandler(topDownAnalysisParameters.getTrace())).setDebugName("Root scope in analyzeNamespace"); + scope.changeLockLevel(WritableScope.LockLevel.BOTH); + + // Import the lang package + scope.importScope(JetStandardLibrary.getInstance().getLibraryScope()); + + // Import a scope that contains all top-level namespaces that come from dependencies + // This makes the namespaces visible at all, does not import themselves + scope.importScope(new JetScopeAdapter(JetScope.EMPTY) { + @Override + public NamespaceDescriptor getNamespace(@NotNull String name) { + // Is it a top-level namespace coming from the dependencies? + NamespaceDescriptor topLevelNamespaceFromConfiguration = configuration.getTopLevelNamespace(name); + if (topLevelNamespaceFromConfiguration != null) { + return topLevelNamespaceFromConfiguration; + } + // Should be null, we are delegating to EMPTY + return super.getNamespace(name); + } + + @NotNull + @Override + public Collection getAllDescriptors() { + List allDescriptors = Lists.newArrayList(); + configuration.addAllTopLevelNamespacesTo(allDescriptors); + return allDescriptors; + } + }); + + // dummy builder is used because "root" is module descriptor, + // namespaces added to module explicitly in + doProcess(scope, new NamespaceLikeBuilderDummy(), files); + } + + } diff --git a/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java b/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java index 6c9477b1b06..02f5966e5a2 100644 --- a/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java +++ b/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java @@ -45,6 +45,7 @@ public class AllInjectorsGenerator { // Fields generator.addPublicField(TopDownAnalyzer.class); + generator.addPublicField(TopDownAnalysisContext.class); generator.addPublicField(BodyResolver.class); generator.addPublicField(ControlFlowAnalyzer.class); generator.addPublicField(DeclarationsChecker.class); @@ -52,7 +53,7 @@ public class AllInjectorsGenerator { // Parameters generator.addPublicParameter(Project.class); - generator.addParameter(TopDownAnalysisContext.class); + generator.addPublicParameter(TopDownAnalysisParameters.class); generator.addParameter(ModuleConfiguration.class); generator.addParameter(ModuleDescriptor.class); generator.addParameter(JetControlFlowDataTraceFactory.class, false); diff --git a/js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacadeForJS.java b/js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacadeForJS.java index ebed36ccbd6..a001856ead0 100644 --- a/js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacadeForJS.java +++ b/js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacadeForJS.java @@ -94,7 +94,7 @@ public final class AnalyzerFacadeForJS { public static BindingContext analyzeNamespace(@NotNull JetFile file) { BindingTraceContext bindingTraceContext = new BindingTraceContext(); Project project = file.getProject(); - return AnalyzingUtils.analyzeFilesWithGivenTrace( + AnalyzingUtils.analyzeFilesWithGivenTrace( project, JsConfiguration.jsLibConfiguration(project), Collections.singletonList(file), @@ -102,6 +102,7 @@ public final class AnalyzerFacadeForJS { JetControlFlowDataTraceFactory.EMPTY, bindingTraceContext ); + return bindingTraceContext.getBindingContext(); } private static final class JsConfiguration implements ModuleConfiguration {