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.google.common.collect.Sets;
021 import com.intellij.openapi.project.Project;
022 import com.intellij.psi.PsiElement;
023 import kotlin.Function1;
024 import kotlin.KotlinPackage;
025 import org.jetbrains.annotations.NotNull;
026 import org.jetbrains.annotations.Nullable;
027 import org.jetbrains.jet.context.GlobalContext;
028 import org.jetbrains.jet.context.GlobalContextImpl;
029 import org.jetbrains.jet.di.InjectorForLazyResolve;
030 import org.jetbrains.jet.di.InjectorForTopDownAnalyzerBasic;
031 import org.jetbrains.jet.lang.descriptors.*;
032 import org.jetbrains.jet.lang.descriptors.impl.*;
033 import org.jetbrains.jet.lang.psi.JetClassOrObject;
034 import org.jetbrains.jet.lang.psi.JetFile;
035 import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
036 import org.jetbrains.jet.lang.resolve.lazy.declarations.FileBasedDeclarationProviderFactory;
037 import org.jetbrains.jet.lang.resolve.name.FqName;
038 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
039 import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
040 import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext;
041 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
042 import org.jetbrains.jet.storage.LockBasedStorageManager;
043
044 import javax.inject.Inject;
045 import java.util.Collection;
046 import java.util.Collections;
047 import java.util.LinkedHashSet;
048 import java.util.Set;
049
050 public class TopDownAnalyzer {
051
052 @NotNull
053 private BindingTrace trace;
054 @NotNull
055 private DeclarationResolver declarationResolver;
056 @NotNull
057 private TypeHierarchyResolver typeHierarchyResolver;
058 @NotNull
059 private OverrideResolver overrideResolver;
060 @NotNull
061 private OverloadResolver overloadResolver;
062 @NotNull
063 private ModuleDescriptor moduleDescriptor;
064 @NotNull
065 private MutablePackageFragmentProvider packageFragmentProvider;
066 @NotNull
067 private BodyResolver bodyResolver;
068 @NotNull
069 private Project project;
070
071 @NotNull
072 private LazyTopDownAnalyzer lazyTopDownAnalyzer;
073
074 @Inject
075 public void setTrace(@NotNull BindingTrace trace) {
076 this.trace = trace;
077 }
078
079 @Inject
080 public void setDeclarationResolver(@NotNull DeclarationResolver declarationResolver) {
081 this.declarationResolver = declarationResolver;
082 }
083
084 @Inject
085 public void setTypeHierarchyResolver(@NotNull TypeHierarchyResolver typeHierarchyResolver) {
086 this.typeHierarchyResolver = typeHierarchyResolver;
087 }
088
089 @Inject
090 public void setOverrideResolver(@NotNull OverrideResolver overrideResolver) {
091 this.overrideResolver = overrideResolver;
092 }
093
094 @Inject
095 public void setOverloadResolver(@NotNull OverloadResolver overloadResolver) {
096 this.overloadResolver = overloadResolver;
097 }
098
099 @Inject
100 public void setModuleDescriptor(@NotNull ModuleDescriptor moduleDescriptor) {
101 this.moduleDescriptor = moduleDescriptor;
102 }
103
104 @Inject
105 public void setPackageFragmentProvider(@NotNull MutablePackageFragmentProvider packageFragmentProvider) {
106 this.packageFragmentProvider = packageFragmentProvider;
107 }
108
109 @Inject
110 public void setBodyResolver(@NotNull BodyResolver bodyResolver) {
111 this.bodyResolver = bodyResolver;
112 }
113
114 @Inject
115 public void setProject(@NotNull Project project) {
116 this.project = project;
117 }
118
119 @Inject
120 public void setLazyTopDownAnalyzer(@NotNull LazyTopDownAnalyzer lazyTopDownAnalyzer) {
121 this.lazyTopDownAnalyzer = lazyTopDownAnalyzer;
122 }
123
124 public void doProcess(
125 @NotNull TopDownAnalysisContext c,
126 @NotNull JetScope outerScope,
127 @NotNull PackageLikeBuilder owner,
128 @NotNull Collection<? extends PsiElement> declarations
129 ) {
130 // c.enableDebugOutput();
131 c.debug("Enter");
132
133 if (c.getTopDownAnalysisParameters().isLazyTopDownAnalysis()) {
134 ResolveSession resolveSession = new InjectorForLazyResolve(
135 project,
136 new GlobalContextImpl((LockBasedStorageManager) c.getStorageManager(), c.getExceptionTracker()), // TODO
137 (ModuleDescriptorImpl) moduleDescriptor, // TODO
138 new FileBasedDeclarationProviderFactory(c.getStorageManager(), getFiles(declarations)),
139 trace
140 ).getResolveSession();
141
142 lazyTopDownAnalyzer.analyzeDeclarations(
143 resolveSession,
144 c.getTopDownAnalysisParameters(),
145 declarations
146 );
147 return;
148 }
149
150 typeHierarchyResolver.process(c, outerScope, owner, declarations);
151 declarationResolver.process(c);
152 overrideResolver.process(c);
153 lockScopes(c);
154
155 overloadResolver.process(c);
156
157 if (!c.getTopDownAnalysisParameters().isAnalyzingBootstrapLibrary()) {
158 bodyResolver.resolveBodies(c);
159 }
160
161 c.debug("Exit");
162 c.printDebugOutput(System.out);
163 }
164
165 private static Collection<JetFile> getFiles(Collection<? extends PsiElement> declarations) {
166 return new LinkedHashSet<JetFile>(KotlinPackage.map(declarations, new Function1<PsiElement, JetFile>() {
167 @Nullable
168 @Override
169 public JetFile invoke(PsiElement element) {
170 return (JetFile) element.getContainingFile();
171 }
172 }));
173 }
174
175 private void lockScopes(@NotNull TopDownAnalysisContext c) {
176 for (ClassDescriptorWithResolutionScopes mutableClassDescriptor : c.getDeclaredClasses().values()) {
177 ((MutableClassDescriptor) mutableClassDescriptor).lockScopes();
178 }
179
180 // SCRIPT: extra code for scripts
181 Set<FqName> scriptFqNames = Sets.newHashSet();
182 for (JetFile file : c.getFileScopes().keySet()) {
183 if (file.isScript()) {
184 scriptFqNames.add(file.getPackageFqName());
185 }
186 }
187 for (MutablePackageFragmentDescriptor fragment : packageFragmentProvider.getAllFragments()) {
188 // todo: this is hack in favor of REPL
189 if (!scriptFqNames.contains(fragment.getFqName())) {
190 fragment.getMemberScope().changeLockLevel(WritableScope.LockLevel.READING);
191 }
192 }
193 }
194
195 public static void processClassOrObject(
196 @NotNull GlobalContext globalContext,
197 @Nullable final WritableScope scope,
198 @NotNull ExpressionTypingContext context,
199 @NotNull final DeclarationDescriptor containingDeclaration,
200 @NotNull JetClassOrObject object
201 ) {
202 TopDownAnalysisParameters topDownAnalysisParameters =
203 TopDownAnalysisParameters.createForLocalDeclarations(
204 globalContext.getStorageManager(),
205 globalContext.getExceptionTracker(),
206 Predicates.equalTo(object.getContainingFile())
207 );
208
209 InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic(
210 object.getProject(), topDownAnalysisParameters, context.trace, DescriptorUtils.getContainingModule(containingDeclaration)
211 );
212
213 TopDownAnalysisContext c = new TopDownAnalysisContext(topDownAnalysisParameters);
214 c.setOuterDataFlowInfo(context.dataFlowInfo);
215
216 injector.getTopDownAnalyzer().doProcess(
217 c,
218 context.scope,
219 new PackageLikeBuilder() {
220
221 @NotNull
222 @Override
223 public DeclarationDescriptor getOwnerForChildren() {
224 return containingDeclaration;
225 }
226
227 @Override
228 public void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor) {
229 if (scope != null) {
230 scope.addClassifierDescriptor(classDescriptor);
231 }
232 }
233
234 @Override
235 public void addFunctionDescriptor(@NotNull SimpleFunctionDescriptor functionDescriptor) {
236 throw new UnsupportedOperationException();
237 }
238
239 @Override
240 public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
241
242 }
243
244 @Override
245 public ClassObjectStatus setClassObjectDescriptor(@NotNull ClassDescriptor classObjectDescriptor) {
246 return ClassObjectStatus.NOT_ALLOWED;
247 }
248 },
249 Collections.<PsiElement>singletonList(object)
250 );
251 }
252
253 @NotNull
254 public TopDownAnalysisContext analyzeFiles(
255 @NotNull TopDownAnalysisParameters topDownAnalysisParameters,
256 @NotNull Collection<JetFile> files
257 ) {
258 ((ModuleDescriptorImpl) moduleDescriptor).addFragmentProvider(DependencyKind.SOURCES, packageFragmentProvider);
259
260 // "depend on" builtins module
261 ((ModuleDescriptorImpl) moduleDescriptor).addFragmentProvider(DependencyKind.BUILT_INS, KotlinBuiltIns.getInstance().getBuiltInsModule().getPackageFragmentProvider());
262
263 // dummy builder is used because "root" is module descriptor,
264 // packages added to module explicitly in
265
266 TopDownAnalysisContext c = new TopDownAnalysisContext(topDownAnalysisParameters);
267 doProcess(c, JetModuleUtil.getSubpackagesOfRootScope(moduleDescriptor), new PackageLikeBuilderDummy(), files);
268 return c;
269 }
270
271
272 @NotNull
273 public MutablePackageFragmentProvider getPackageFragmentProvider() {
274 return packageFragmentProvider;
275 }
276
277 }
278
279