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 (MutableClassDescriptor mutableClassDescriptor : context.getObjects().values()) {
146 mutableClassDescriptor.lockScopes();
147 }
148 for (Map.Entry<JetFile, WritableScope> namespaceScope : context.getNamespaceScopes().entrySet()) {
149 // todo: this is hack in favor of REPL
150 if(!namespaceScope.getKey().isScript())
151 namespaceScope.getValue().changeLockLevel(WritableScope.LockLevel.READING);
152 }
153 }
154
155 public static void processStandardLibraryNamespace(
156 @NotNull Project project,
157 @NotNull BindingTrace trace,
158 @NotNull WritableScope outerScope,
159 @NotNull NamespaceDescriptorImpl standardLibraryNamespace,
160 @NotNull List<JetFile> files) {
161
162 TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(
163 Predicates.<PsiFile>alwaysFalse(), true, false, Collections.<AnalyzerScriptParameter>emptyList());
164 InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic(
165 project, topDownAnalysisParameters, new ObservableBindingTrace(trace),
166 KotlinBuiltIns.getInstance().getBuiltInsModule());
167
168 injector.getTopDownAnalyzer().doProcessStandardLibraryNamespace(outerScope, standardLibraryNamespace, files);
169 }
170
171 private void doProcessStandardLibraryNamespace(
172 WritableScope outerScope, NamespaceDescriptorImpl standardLibraryNamespace, List<JetFile> files) {
173 ArrayList<JetDeclaration> toAnalyze = new ArrayList<JetDeclaration>();
174 for(JetFile file : files) {
175 context.getNamespaceDescriptors().put(file, standardLibraryNamespace);
176 context.getNamespaceScopes().put(file, standardLibraryNamespace.getMemberScope());
177 toAnalyze.addAll(file.getDeclarations());
178 }
179 // context.getDeclaringScopes().put(file, outerScope);
180
181 doProcess(outerScope, standardLibraryNamespace.getBuilder(), toAnalyze);
182 }
183
184 public static void processClassOrObject(
185 @NotNull ExpressionTypingContext context,
186 @NotNull final DeclarationDescriptor containingDeclaration,
187 @NotNull JetClassOrObject object
188 ) {
189 ModuleDescriptorImpl moduleDescriptor = new ModuleDescriptorImpl(Name.special("<dummy for object>"),
190 Collections.<ImportPath>emptyList(),
191 PlatformToKotlinClassMap.EMPTY);
192 moduleDescriptor.setModuleConfiguration(ModuleConfiguration.EMPTY);
193
194 TopDownAnalysisParameters topDownAnalysisParameters =
195 new TopDownAnalysisParameters(Predicates.equalTo(object.getContainingFile()),
196 false, true, Collections.<AnalyzerScriptParameter>emptyList());
197
198 InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic(
199 object.getProject(), topDownAnalysisParameters, new ObservableBindingTrace(context.trace), moduleDescriptor);
200
201 injector.getTopDownAnalysisContext().setOuterDataFlowInfo(context.dataFlowInfo);
202
203 injector.getTopDownAnalyzer().doProcess(context.scope, new NamespaceLikeBuilder() {
204
205 @NotNull
206 @Override
207 public DeclarationDescriptor getOwnerForChildren() {
208 return containingDeclaration;
209 }
210
211 @Override
212 public void addClassifierDescriptor(@NotNull MutableClassDescriptorLite classDescriptor) {
213
214 }
215
216 @Override
217 public void addObjectDescriptor(@NotNull MutableClassDescriptorLite objectDescriptor) {
218
219 }
220
221 @Override
222 public void addFunctionDescriptor(@NotNull SimpleFunctionDescriptor functionDescriptor) {
223 throw new UnsupportedOperationException();
224 }
225
226 @Override
227 public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
228
229 }
230
231 @Override
232 public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptorLite classObjectDescriptor) {
233 return ClassObjectStatus.NOT_ALLOWED;
234 }
235 }, Collections.<PsiElement>singletonList(object));
236 }
237
238 public void analyzeFiles(
239 @NotNull Collection<JetFile> files,
240 @NotNull List<AnalyzerScriptParameter> scriptParameters) {
241 WritableScope scope = new WritableScopeImpl(
242 JetScope.EMPTY, moduleDescriptor,
243 new TraceBasedRedeclarationHandler(trace), "Root scope in analyzeNamespace");
244
245 scope.changeLockLevel(WritableScope.LockLevel.BOTH);
246
247 NamespaceDescriptorImpl rootNs = namespaceFactory.createNamespaceDescriptorPathIfNeeded(FqName.ROOT);
248
249 // map "jet" namespace into KotlinBuiltIns
250 // @see DefaultModuleConfiguraiton#extendNamespaceScope
251 namespaceFactory.createNamespaceDescriptorPathIfNeeded(KotlinBuiltIns.getInstance().getBuiltInsPackageFqName());
252
253 // Import a scope that contains all top-level namespaces that come from dependencies
254 // This makes the namespaces visible at all, does not import themselves
255 scope.importScope(rootNs.getMemberScope());
256
257 scope.changeLockLevel(WritableScope.LockLevel.READING);
258
259 // dummy builder is used because "root" is module descriptor,
260 // namespaces added to module explicitly in
261 doProcess(scope, new NamespaceLikeBuilderDummy(), files);
262 }
263
264
265 public void prepareForTheNextReplLine() {
266 context.getScriptScopes().clear();
267 context.getScripts().clear();
268 }
269
270
271 }
272
273