001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.lang.resolve;
018
019 import com.google.common.base.Predicates;
020 import com.intellij.openapi.project.Project;
021 import com.intellij.psi.PsiElement;
022 import com.intellij.psi.PsiFile;
023 import org.jetbrains.annotations.NotNull;
024 import org.jetbrains.jet.di.InjectorForTopDownAnalyzerBasic;
025 import org.jetbrains.jet.lang.ModuleConfiguration;
026 import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
027 import org.jetbrains.jet.lang.descriptors.*;
028 import org.jetbrains.jet.lang.descriptors.impl.*;
029 import org.jetbrains.jet.lang.psi.JetClassOrObject;
030 import org.jetbrains.jet.lang.psi.JetDeclaration;
031 import org.jetbrains.jet.lang.psi.JetFile;
032 import org.jetbrains.jet.lang.resolve.name.FqName;
033 import org.jetbrains.jet.lang.resolve.name.Name;
034 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
035 import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
036 import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
037 import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext;
038 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
039
040 import javax.inject.Inject;
041 import java.util.*;
042
043 public class TopDownAnalyzer {
044
045 @NotNull
046 private DeclarationResolver declarationResolver;
047 @NotNull
048 private TypeHierarchyResolver typeHierarchyResolver;
049 @NotNull
050 private OverrideResolver overrideResolver;
051 @NotNull
052 private OverloadResolver overloadResolver;
053 @NotNull
054 private TopDownAnalysisParameters topDownAnalysisParameters;
055 @NotNull
056 private TopDownAnalysisContext context;
057 @NotNull
058 private BindingTrace trace;
059 @NotNull
060 private ModuleDescriptor moduleDescriptor;
061 @NotNull
062 private NamespaceFactoryImpl namespaceFactory;
063 @NotNull
064 private BodyResolver bodyResolver;
065
066 @Inject
067 public void setDeclarationResolver(@NotNull DeclarationResolver declarationResolver) {
068 this.declarationResolver = declarationResolver;
069 }
070
071 @Inject
072 public void setTypeHierarchyResolver(@NotNull TypeHierarchyResolver typeHierarchyResolver) {
073 this.typeHierarchyResolver = typeHierarchyResolver;
074 }
075
076 @Inject
077 public void setOverrideResolver(@NotNull OverrideResolver overrideResolver) {
078 this.overrideResolver = overrideResolver;
079 }
080
081 @Inject
082 public void setOverloadResolver(@NotNull OverloadResolver overloadResolver) {
083 this.overloadResolver = overloadResolver;
084 }
085
086 @Inject
087 public void setTopDownAnalysisParameters(@NotNull TopDownAnalysisParameters topDownAnalysisParameters) {
088 this.topDownAnalysisParameters = topDownAnalysisParameters;
089 }
090
091 @Inject
092 public void setTrace(@NotNull BindingTrace trace) {
093 this.trace = trace;
094 }
095
096 @Inject
097 public void setContext(@NotNull TopDownAnalysisContext context) {
098 this.context = context;
099 }
100
101 @Inject
102 public void setModuleDescriptor(@NotNull ModuleDescriptor moduleDescriptor) {
103 this.moduleDescriptor = moduleDescriptor;
104 }
105
106 @Inject
107 public void setNamespaceFactory(@NotNull NamespaceFactoryImpl namespaceFactory) {
108 this.namespaceFactory = namespaceFactory;
109 }
110
111 @Inject
112 public void setBodyResolver(@NotNull BodyResolver bodyResolver) {
113 this.bodyResolver = bodyResolver;
114 }
115
116
117
118 public void doProcess(
119 JetScope outerScope,
120 NamespaceLikeBuilder owner,
121 Collection<? extends PsiElement> declarations) {
122 // context.enableDebugOutput();
123 context.debug("Enter");
124
125 typeHierarchyResolver.process(outerScope, owner, declarations);
126 declarationResolver.process(outerScope);
127 overrideResolver.process();
128
129 lockScopes();
130
131 overloadResolver.process();
132
133 if (!topDownAnalysisParameters.isAnalyzingBootstrapLibrary()) {
134 bodyResolver.resolveBodies();
135 }
136
137 context.debug("Exit");
138 context.printDebugOutput(System.out);
139 }
140
141 private void lockScopes() {
142 for (MutableClassDescriptor mutableClassDescriptor : context.getClasses().values()) {
143 mutableClassDescriptor.lockScopes();
144 }
145 for (Map.Entry<JetFile, WritableScope> namespaceScope : context.getNamespaceScopes().entrySet()) {
146 // todo: this is hack in favor of REPL
147 if(!namespaceScope.getKey().isScript())
148 namespaceScope.getValue().changeLockLevel(WritableScope.LockLevel.READING);
149 }
150 }
151
152 public static void processStandardLibraryNamespace(
153 @NotNull Project project,
154 @NotNull BindingTrace trace,
155 @NotNull WritableScope outerScope,
156 @NotNull NamespaceDescriptorImpl standardLibraryNamespace,
157 @NotNull List<JetFile> files) {
158
159 TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(
160 Predicates.<PsiFile>alwaysFalse(), true, false, Collections.<AnalyzerScriptParameter>emptyList());
161 InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic(
162 project, topDownAnalysisParameters, new ObservableBindingTrace(trace),
163 KotlinBuiltIns.getInstance().getBuiltInsModule(), PlatformToKotlinClassMap.EMPTY);
164
165 injector.getTopDownAnalyzer().doProcessStandardLibraryNamespace(outerScope, standardLibraryNamespace, files);
166 }
167
168 private void doProcessStandardLibraryNamespace(
169 WritableScope outerScope, NamespaceDescriptorImpl standardLibraryNamespace, List<JetFile> files) {
170 ArrayList<JetDeclaration> toAnalyze = new ArrayList<JetDeclaration>();
171 for(JetFile file : files) {
172 context.getNamespaceDescriptors().put(file, standardLibraryNamespace);
173 context.getNamespaceScopes().put(file, standardLibraryNamespace.getMemberScope());
174 toAnalyze.addAll(file.getDeclarations());
175 }
176 // context.getDeclaringScopes().put(file, outerScope);
177
178 doProcess(outerScope, standardLibraryNamespace.getBuilder(), toAnalyze);
179 }
180
181 public static void processClassOrObject(
182 @NotNull ExpressionTypingContext context,
183 @NotNull final DeclarationDescriptor containingDeclaration,
184 @NotNull JetClassOrObject object
185 ) {
186 ModuleDescriptorImpl moduleDescriptor = new ModuleDescriptorImpl(Name.special("<dummy for object>"),
187 Collections.<ImportPath>emptyList(),
188 PlatformToKotlinClassMap.EMPTY);
189 moduleDescriptor.setModuleConfiguration(ModuleConfiguration.EMPTY);
190
191 TopDownAnalysisParameters topDownAnalysisParameters =
192 new TopDownAnalysisParameters(Predicates.equalTo(object.getContainingFile()),
193 false, true, Collections.<AnalyzerScriptParameter>emptyList());
194
195 InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic(
196 object.getProject(), topDownAnalysisParameters, new ObservableBindingTrace(context.trace),
197 moduleDescriptor, context.expressionTypingServices.getPlatformToKotlinClassMap());
198
199 injector.getTopDownAnalysisContext().setOuterDataFlowInfo(context.dataFlowInfo);
200
201 injector.getTopDownAnalyzer().doProcess(context.scope, new NamespaceLikeBuilder() {
202
203 @NotNull
204 @Override
205 public DeclarationDescriptor getOwnerForChildren() {
206 return containingDeclaration;
207 }
208
209 @Override
210 public void addClassifierDescriptor(@NotNull MutableClassDescriptorLite classDescriptor) {
211
212 }
213
214 @Override
215 public void addFunctionDescriptor(@NotNull SimpleFunctionDescriptor functionDescriptor) {
216 throw new UnsupportedOperationException();
217 }
218
219 @Override
220 public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
221
222 }
223
224 @Override
225 public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptorLite classObjectDescriptor) {
226 return ClassObjectStatus.NOT_ALLOWED;
227 }
228 }, Collections.<PsiElement>singletonList(object));
229 }
230
231 public void analyzeFiles(
232 @NotNull Collection<JetFile> files,
233 @NotNull List<AnalyzerScriptParameter> scriptParameters) {
234 WritableScope scope = new WritableScopeImpl(
235 JetScope.EMPTY, moduleDescriptor,
236 new TraceBasedRedeclarationHandler(trace), "Root scope in analyzeNamespace");
237
238 scope.changeLockLevel(WritableScope.LockLevel.BOTH);
239
240 NamespaceDescriptorImpl rootNs = namespaceFactory.createNamespaceDescriptorPathIfNeeded(FqName.ROOT);
241
242 // map "jet" namespace into KotlinBuiltIns
243 // @see DefaultModuleConfiguraiton#extendNamespaceScope
244 namespaceFactory.createNamespaceDescriptorPathIfNeeded(KotlinBuiltIns.getInstance().getBuiltInsPackageFqName());
245
246 // Import a scope that contains all top-level namespaces that come from dependencies
247 // This makes the namespaces visible at all, does not import themselves
248 scope.importScope(rootNs.getMemberScope());
249
250 scope.changeLockLevel(WritableScope.LockLevel.READING);
251
252 // dummy builder is used because "root" is module descriptor,
253 // namespaces added to module explicitly in
254 doProcess(scope, new NamespaceLikeBuilderDummy(), files);
255 }
256
257
258 public void prepareForTheNextReplLine() {
259 context.getScriptScopes().clear();
260 context.getScripts().clear();
261 }
262
263
264 }
265
266