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.lang.KotlinBuiltIns;
038
039 import javax.inject.Inject;
040 import java.util.*;
041
042 public class TopDownAnalyzer {
043
044 @NotNull
045 private DeclarationResolver declarationResolver;
046 @NotNull
047 private TypeHierarchyResolver typeHierarchyResolver;
048 @NotNull
049 private OverrideResolver overrideResolver;
050 @NotNull
051 private OverloadResolver overloadResolver;
052 @NotNull
053 private TopDownAnalysisParameters topDownAnalysisParameters;
054 @NotNull
055 private TopDownAnalysisContext context;
056 @NotNull
057 private BindingTrace trace;
058 @NotNull
059 private ModuleDescriptor moduleDescriptor;
060 @NotNull
061 private NamespaceFactoryImpl namespaceFactory;
062 @NotNull
063 private BodyResolver bodyResolver;
064
065 @Inject
066 public void setDeclarationResolver(@NotNull DeclarationResolver declarationResolver) {
067 this.declarationResolver = declarationResolver;
068 }
069
070 @Inject
071 public void setTypeHierarchyResolver(@NotNull TypeHierarchyResolver typeHierarchyResolver) {
072 this.typeHierarchyResolver = typeHierarchyResolver;
073 }
074
075 @Inject
076 public void setOverrideResolver(@NotNull OverrideResolver overrideResolver) {
077 this.overrideResolver = overrideResolver;
078 }
079
080 @Inject
081 public void setOverloadResolver(@NotNull OverloadResolver overloadResolver) {
082 this.overloadResolver = overloadResolver;
083 }
084
085 @Inject
086 public void setTopDownAnalysisParameters(@NotNull TopDownAnalysisParameters topDownAnalysisParameters) {
087 this.topDownAnalysisParameters = topDownAnalysisParameters;
088 }
089
090 @Inject
091 public void setTrace(@NotNull BindingTrace trace) {
092 this.trace = trace;
093 }
094
095 @Inject
096 public void setContext(@NotNull TopDownAnalysisContext context) {
097 this.context = context;
098 }
099
100 @Inject
101 public void setModuleDescriptor(@NotNull ModuleDescriptor moduleDescriptor) {
102 this.moduleDescriptor = moduleDescriptor;
103 }
104
105 @Inject
106 public void setNamespaceFactory(@NotNull NamespaceFactoryImpl namespaceFactory) {
107 this.namespaceFactory = namespaceFactory;
108 }
109
110 @Inject
111 public void setBodyResolver(@NotNull BodyResolver bodyResolver) {
112 this.bodyResolver = bodyResolver;
113 }
114
115
116
117 public void doProcess(
118 JetScope outerScope,
119 NamespaceLikeBuilder owner,
120 Collection<? extends PsiElement> declarations) {
121 // context.enableDebugOutput();
122 context.debug("Enter");
123
124 typeHierarchyResolver.process(outerScope, owner, declarations);
125 declarationResolver.process(outerScope);
126 overrideResolver.process();
127
128 lockScopes();
129
130 overloadResolver.process();
131
132 if (!topDownAnalysisParameters.isAnalyzingBootstrapLibrary()) {
133 bodyResolver.resolveBodies();
134 }
135
136 context.debug("Exit");
137 context.printDebugOutput(System.out);
138 }
139
140 private void lockScopes() {
141 for (MutableClassDescriptor mutableClassDescriptor : context.getClasses().values()) {
142 mutableClassDescriptor.lockScopes();
143 }
144 for (MutableClassDescriptor mutableClassDescriptor : context.getObjects().values()) {
145 mutableClassDescriptor.lockScopes();
146 }
147 for (Map.Entry<JetFile, WritableScope> namespaceScope : context.getNamespaceScopes().entrySet()) {
148 // todo: this is hack in favor of REPL
149 if(!namespaceScope.getKey().isScript())
150 namespaceScope.getValue().changeLockLevel(WritableScope.LockLevel.READING);
151 }
152 }
153
154 public static void processStandardLibraryNamespace(
155 @NotNull Project project,
156 @NotNull BindingTrace trace,
157 @NotNull WritableScope outerScope,
158 @NotNull NamespaceDescriptorImpl standardLibraryNamespace,
159 @NotNull List<JetFile> files) {
160
161 TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(
162 Predicates.<PsiFile>alwaysFalse(), true, false, Collections.<AnalyzerScriptParameter>emptyList());
163 InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic(
164 project, topDownAnalysisParameters, new ObservableBindingTrace(trace),
165 KotlinBuiltIns.getInstance().getBuiltInsModule());
166
167 injector.getTopDownAnalyzer().doProcessStandardLibraryNamespace(outerScope, standardLibraryNamespace, files);
168 }
169
170 private void doProcessStandardLibraryNamespace(
171 WritableScope outerScope, NamespaceDescriptorImpl standardLibraryNamespace, List<JetFile> files) {
172 ArrayList<JetDeclaration> toAnalyze = new ArrayList<JetDeclaration>();
173 for(JetFile file : files) {
174 context.getNamespaceDescriptors().put(file, standardLibraryNamespace);
175 context.getNamespaceScopes().put(file, standardLibraryNamespace.getMemberScope());
176 toAnalyze.addAll(file.getDeclarations());
177 }
178 // context.getDeclaringScopes().put(file, outerScope);
179
180 doProcess(outerScope, standardLibraryNamespace.getBuilder(), toAnalyze);
181 }
182
183 public static void processClassOrObject(
184 @NotNull Project project,
185 @NotNull BindingTrace trace,
186 @NotNull JetScope outerScope,
187 @NotNull final DeclarationDescriptor containingDeclaration,
188 @NotNull JetClassOrObject object
189 ) {
190 ModuleDescriptorImpl moduleDescriptor = new ModuleDescriptorImpl(Name.special("<dummy for object>"),
191 Collections.<ImportPath>emptyList(),
192 PlatformToKotlinClassMap.EMPTY);
193 moduleDescriptor.setModuleConfiguration(ModuleConfiguration.EMPTY);
194
195 TopDownAnalysisParameters topDownAnalysisParameters =
196 new TopDownAnalysisParameters(Predicates.equalTo(object.getContainingFile()),
197 false, true, Collections.<AnalyzerScriptParameter>emptyList());
198
199 InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic(
200 project, topDownAnalysisParameters, new ObservableBindingTrace(trace), moduleDescriptor);
201
202 injector.getTopDownAnalyzer().doProcess(outerScope, new NamespaceLikeBuilder() {
203
204 @NotNull
205 @Override
206 public DeclarationDescriptor getOwnerForChildren() {
207 return containingDeclaration;
208 }
209
210 @Override
211 public void addClassifierDescriptor(@NotNull MutableClassDescriptorLite classDescriptor) {
212
213 }
214
215 @Override
216 public void addObjectDescriptor(@NotNull MutableClassDescriptorLite objectDescriptor) {
217
218 }
219
220 @Override
221 public void addFunctionDescriptor(@NotNull SimpleFunctionDescriptor functionDescriptor) {
222 throw new UnsupportedOperationException();
223 }
224
225 @Override
226 public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
227
228 }
229
230 @Override
231 public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptorLite classObjectDescriptor) {
232 return ClassObjectStatus.NOT_ALLOWED;
233 }
234 }, Collections.<PsiElement>singletonList(object));
235 }
236
237 public void analyzeFiles(
238 @NotNull Collection<JetFile> files,
239 @NotNull List<AnalyzerScriptParameter> scriptParameters) {
240 WritableScope scope = new WritableScopeImpl(
241 JetScope.EMPTY, moduleDescriptor,
242 new TraceBasedRedeclarationHandler(trace), "Root scope in analyzeNamespace");
243
244 scope.changeLockLevel(WritableScope.LockLevel.BOTH);
245
246 NamespaceDescriptorImpl rootNs = namespaceFactory.createNamespaceDescriptorPathIfNeeded(FqName.ROOT);
247
248 // map "jet" namespace into KotlinBuiltIns
249 // @see DefaultModuleConfiguraiton#extendNamespaceScope
250 namespaceFactory.createNamespaceDescriptorPathIfNeeded(KotlinBuiltIns.getInstance().getBuiltInsPackageFqName());
251
252 // Import a scope that contains all top-level namespaces that come from dependencies
253 // This makes the namespaces visible at all, does not import themselves
254 scope.importScope(rootNs.getMemberScope());
255
256 scope.changeLockLevel(WritableScope.LockLevel.READING);
257
258 // dummy builder is used because "root" is module descriptor,
259 // namespaces added to module explicitly in
260 doProcess(scope, new NamespaceLikeBuilderDummy(), files);
261 }
262
263
264 public void prepareForTheNextReplLine() {
265 context.getScriptScopes().clear();
266 context.getScripts().clear();
267 }
268
269
270 }
271
272