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