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