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