001 /*
002 * Copyright 2010-2015 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.kotlin.resolve.lazy;
018
019 import com.google.common.collect.Lists;
020 import com.intellij.openapi.project.Project;
021 import com.intellij.util.Function;
022 import com.intellij.util.containers.ContainerUtil;
023 import kotlin.jvm.functions.Function1;
024 import org.jetbrains.annotations.NotNull;
025 import org.jetbrains.annotations.Nullable;
026 import org.jetbrains.annotations.ReadOnly;
027 import org.jetbrains.kotlin.context.GlobalContext;
028 import org.jetbrains.kotlin.descriptors.*;
029 import org.jetbrains.kotlin.descriptors.annotations.Annotations;
030 import org.jetbrains.kotlin.name.FqName;
031 import org.jetbrains.kotlin.name.Name;
032 import org.jetbrains.kotlin.psi.*;
033 import org.jetbrains.kotlin.resolve.*;
034 import org.jetbrains.kotlin.resolve.lazy.data.JetClassLikeInfo;
035 import org.jetbrains.kotlin.resolve.lazy.data.JetScriptInfo;
036 import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory;
037 import org.jetbrains.kotlin.resolve.lazy.declarations.PackageMemberDeclarationProvider;
038 import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotations;
039 import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationsContextImpl;
040 import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor;
041 import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor;
042 import org.jetbrains.kotlin.resolve.scopes.JetScope;
043 import org.jetbrains.kotlin.storage.*;
044
045 import javax.inject.Inject;
046 import java.util.Collection;
047 import java.util.Collections;
048 import java.util.List;
049
050 public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
051 private final LazyResolveStorageManager storageManager;
052 private final ExceptionTracker exceptionTracker;
053
054 private final ModuleDescriptor module;
055
056 private final BindingTrace trace;
057 private final DeclarationProviderFactory declarationProviderFactory;
058
059 private final MemoizedFunctionToNullable<FqName, LazyPackageDescriptor> packages;
060 private final PackageFragmentProvider packageFragmentProvider;
061
062 private final MemoizedFunctionToNotNull<JetScript, LazyScriptDescriptor> scriptDescriptors;
063
064 private final MemoizedFunctionToNotNull<JetFile, LazyAnnotations> fileAnnotations;
065 private final MemoizedFunctionToNotNull<JetFile, LazyAnnotations> danglingAnnotations;
066
067 private ScopeProvider scopeProvider;
068
069 private JetImportsFactory jetImportFactory;
070 private AnnotationResolver annotationResolve;
071 private DescriptorResolver descriptorResolver;
072 private FunctionDescriptorResolver functionDescriptorResolver;
073 private TypeResolver typeResolver;
074 private QualifiedExpressionResolver qualifiedExpressionResolver;
075 private ScriptBodyResolver scriptBodyResolver;
076 private LazyDeclarationResolver lazyDeclarationResolver;
077
078 @Inject
079 public void setJetImportFactory(JetImportsFactory jetImportFactory) {
080 this.jetImportFactory = jetImportFactory;
081 }
082
083 @Inject
084 public void setAnnotationResolve(AnnotationResolver annotationResolve) {
085 this.annotationResolve = annotationResolve;
086 }
087
088 @Inject
089 public void setDescriptorResolver(DescriptorResolver descriptorResolver) {
090 this.descriptorResolver = descriptorResolver;
091 }
092
093 @Inject
094 public void setFunctionDescriptorResolver(FunctionDescriptorResolver functionDescriptorResolver) {
095 this.functionDescriptorResolver = functionDescriptorResolver;
096 }
097
098 @Inject
099 public void setTypeResolver(TypeResolver typeResolver) {
100 this.typeResolver = typeResolver;
101 }
102
103 @Inject
104 public void setQualifiedExpressionResolver(QualifiedExpressionResolver qualifiedExpressionResolver) {
105 this.qualifiedExpressionResolver = qualifiedExpressionResolver;
106 }
107
108 @Inject
109 public void setScopeProvider(ScopeProvider scopeProvider) {
110 this.scopeProvider = scopeProvider;
111 }
112
113 @Inject
114 public void setScriptBodyResolver(ScriptBodyResolver scriptBodyResolver) {
115 this.scriptBodyResolver = scriptBodyResolver;
116 }
117
118 @Inject
119 public void setLazyDeclarationResolver(LazyDeclarationResolver lazyDeclarationResolver) {
120 this.lazyDeclarationResolver = lazyDeclarationResolver;
121 }
122
123 // Only calls from injectors expected
124 @Deprecated
125 public ResolveSession(
126 @NotNull Project project,
127 @NotNull GlobalContext globalContext,
128 @NotNull ModuleDescriptor rootDescriptor,
129 @NotNull DeclarationProviderFactory declarationProviderFactory,
130 @NotNull BindingTrace delegationTrace
131 ) {
132 LockBasedLazyResolveStorageManager lockBasedLazyResolveStorageManager =
133 new LockBasedLazyResolveStorageManager(globalContext.getStorageManager());
134
135 this.storageManager = lockBasedLazyResolveStorageManager;
136 this.exceptionTracker = globalContext.getExceptionTracker();
137 this.trace = lockBasedLazyResolveStorageManager.createSafeTrace(delegationTrace);
138 this.module = rootDescriptor;
139
140 this.packages =
141 storageManager.createMemoizedFunctionWithNullableValues(new Function1<FqName, LazyPackageDescriptor>() {
142 @Nullable
143 public LazyPackageDescriptor invoke(FqName fqName) {
144 return createPackage(fqName);
145 }
146 });
147
148 this.declarationProviderFactory = declarationProviderFactory;
149
150 this.packageFragmentProvider = new PackageFragmentProvider() {
151 @NotNull
152 @Override
153 public List<PackageFragmentDescriptor> getPackageFragments(@NotNull FqName fqName) {
154 return ContainerUtil.<PackageFragmentDescriptor>createMaybeSingletonList(getPackageFragment(fqName));
155 }
156
157 @NotNull
158 @Override
159 public Collection<FqName> getSubPackagesOf(
160 @NotNull FqName fqName, @NotNull Function1<? super Name, ? extends Boolean> nameFilter
161 ) {
162 LazyPackageDescriptor packageDescriptor = getPackageFragment(fqName);
163 if (packageDescriptor == null) {
164 return Collections.emptyList();
165 }
166 return packageDescriptor.getDeclarationProvider().getAllDeclaredSubPackages();
167 }
168 };
169
170 this.scriptDescriptors = storageManager.createMemoizedFunction(
171 new Function1<JetScript, LazyScriptDescriptor>() {
172 @Override
173 public LazyScriptDescriptor invoke(JetScript script) {
174 return new LazyScriptDescriptor(
175 ResolveSession.this,
176 scriptBodyResolver,
177 script,
178 ScriptPriorities.getScriptPriority(script)
179 );
180 }
181 }
182 );
183
184 fileAnnotations = storageManager.createMemoizedFunction(new Function1<JetFile, LazyAnnotations>() {
185 @Override
186 public LazyAnnotations invoke(JetFile file) {
187 return createAnnotations(file, file.getAnnotationEntries());
188 }
189 });
190
191 danglingAnnotations = storageManager.createMemoizedFunction(new Function1<JetFile, LazyAnnotations>() {
192 @Override
193 public LazyAnnotations invoke(JetFile file) {
194 return createAnnotations(file, file.getDanglingAnnotations());
195 }
196 });
197 }
198
199 private LazyAnnotations createAnnotations(JetFile file, List<JetAnnotationEntry> annotationEntries) {
200 JetScope scope = getScopeProvider().getFileScope(file);
201 LazyAnnotationsContextImpl lazyAnnotationContext = new LazyAnnotationsContextImpl(annotationResolve, storageManager, trace, scope);
202 return new LazyAnnotations(lazyAnnotationContext, annotationEntries);
203 }
204
205 @Override
206 @NotNull
207 public PackageFragmentProvider getPackageFragmentProvider() {
208 return packageFragmentProvider;
209 }
210
211 @Override
212 @Nullable
213 public LazyPackageDescriptor getPackageFragment(@NotNull FqName fqName) {
214 return packages.invoke(fqName);
215 }
216
217 @Nullable
218 private LazyPackageDescriptor createPackage(FqName fqName) {
219 if (!fqName.isRoot() && getPackageFragment(fqName.parent()) == null) {
220 return null;
221 }
222 PackageMemberDeclarationProvider provider = declarationProviderFactory.getPackageMemberDeclarationProvider(fqName);
223 if (provider == null) {
224 return null;
225 }
226 return new LazyPackageDescriptor(module, fqName, this, provider);
227 }
228
229 @NotNull
230 @Override
231 public ModuleDescriptor getModuleDescriptor() {
232 return module;
233 }
234
235 @NotNull
236 @Override
237 public LazyResolveStorageManager getStorageManager() {
238 return storageManager;
239 }
240
241 @NotNull
242 public ExceptionTracker getExceptionTracker() {
243 return exceptionTracker;
244 }
245
246 @Override
247 @NotNull
248 @ReadOnly
249 public Collection<ClassDescriptor> getTopLevelClassDescriptors(@NotNull FqName fqName) {
250 if (fqName.isRoot()) return Collections.emptyList();
251
252 PackageMemberDeclarationProvider provider = declarationProviderFactory.getPackageMemberDeclarationProvider(fqName.parent());
253 if (provider == null) return Collections.emptyList();
254
255 return ContainerUtil.mapNotNull(
256 provider.getClassOrObjectDeclarations(fqName.shortName()),
257 new Function<JetClassLikeInfo, ClassDescriptor>() {
258 @Override
259 public ClassDescriptor fun(JetClassLikeInfo classLikeInfo) {
260 if (classLikeInfo instanceof JetScriptInfo) {
261 return getClassDescriptorForScript(((JetScriptInfo) classLikeInfo).getScript());
262 }
263 JetClassOrObject classOrObject = classLikeInfo.getCorrespondingClassOrObject();
264 if (classOrObject == null) return null;
265 return getClassDescriptor(classOrObject);
266 }
267 }
268 );
269 }
270
271 @Override
272 @NotNull
273 public ClassDescriptor getClassDescriptor(@NotNull JetClassOrObject classOrObject) {
274 return lazyDeclarationResolver.getClassDescriptor(classOrObject);
275 }
276
277 @NotNull
278 public ClassDescriptor getClassDescriptorForScript(@NotNull JetScript script) {
279 JetScope resolutionScope = lazyDeclarationResolver.resolutionScopeToResolveDeclaration(script);
280 FqName fqName = ScriptNameUtil.classNameForScript(script);
281 ClassifierDescriptor classifier = resolutionScope.getClassifier(fqName.shortName());
282 assert classifier != null : "No descriptor for " + fqName + " in file " + script.getContainingFile();
283 return (ClassDescriptor) classifier;
284 }
285
286 @Override
287 @NotNull
288 public ScriptDescriptor getScriptDescriptor(@NotNull JetScript script) {
289 return scriptDescriptors.invoke(script);
290 }
291
292 @Override
293 @NotNull
294 public BindingContext getBindingContext() {
295 return trace.getBindingContext();
296 }
297
298 @Override
299 @NotNull
300 public BindingTrace getTrace() {
301 return trace;
302 }
303
304 @Override
305 @NotNull
306 public DeclarationProviderFactory getDeclarationProviderFactory() {
307 return declarationProviderFactory;
308 }
309
310 @Override
311 @NotNull
312 public DeclarationDescriptor resolveToDescriptor(@NotNull JetDeclaration declaration) {
313 return lazyDeclarationResolver.resolveToDescriptor(declaration);
314 }
315
316 @NotNull
317 public Annotations getFileAnnotations(@NotNull JetFile file) {
318 return fileAnnotations.invoke(file);
319 }
320
321 @NotNull
322 public Annotations getDanglingAnnotations(@NotNull JetFile file) {
323 return danglingAnnotations.invoke(file);
324 }
325
326 @NotNull
327 private List<LazyPackageDescriptor> getAllPackages() {
328 LazyPackageDescriptor rootPackage = getPackageFragment(FqName.ROOT);
329 assert rootPackage != null : "Root package must be initialized";
330
331 return collectAllPackages(Lists.<LazyPackageDescriptor>newArrayList(), rootPackage);
332 }
333
334 @NotNull
335 private List<LazyPackageDescriptor> collectAllPackages(
336 @NotNull List<LazyPackageDescriptor> result,
337 @NotNull LazyPackageDescriptor current
338 ) {
339 result.add(current);
340 for (FqName subPackage : packageFragmentProvider.getSubPackagesOf(current.getFqName(), JetScope.ALL_NAME_FILTER)) {
341 LazyPackageDescriptor fragment = getPackageFragment(subPackage);
342 assert fragment != null : "Couldn't find fragment for " + subPackage;
343 collectAllPackages(result, fragment);
344 }
345 return result;
346 }
347
348 @Override
349 public void forceResolveAll() {
350 for (LazyPackageDescriptor lazyPackage : getAllPackages()) {
351 ForceResolveUtil.forceResolveAllContents(lazyPackage);
352 }
353 }
354
355 @Override
356 @NotNull
357 public ScopeProvider getScopeProvider() {
358 return scopeProvider;
359 }
360
361 @NotNull
362 public JetImportsFactory getJetImportsFactory() {
363 return jetImportFactory;
364 }
365
366 @Override
367 @NotNull
368 public AnnotationResolver getAnnotationResolver() {
369 return annotationResolve;
370 }
371
372 @Override
373 @NotNull
374 public DescriptorResolver getDescriptorResolver() {
375 return descriptorResolver;
376 }
377
378 @Override
379 @NotNull
380 public TypeResolver getTypeResolver() {
381 return typeResolver;
382 }
383
384 @NotNull
385 public QualifiedExpressionResolver getQualifiedExpressionResolver() {
386 return qualifiedExpressionResolver;
387 }
388
389 @NotNull
390 @Override
391 public FunctionDescriptorResolver getFunctionDescriptorResolver() {
392 return functionDescriptorResolver;
393 }
394 }