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.config.LanguageVersionSettings;
028    import org.jetbrains.kotlin.context.GlobalContext;
029    import org.jetbrains.kotlin.descriptors.*;
030    import org.jetbrains.kotlin.descriptors.annotations.Annotations;
031    import org.jetbrains.kotlin.incremental.components.LookupLocation;
032    import org.jetbrains.kotlin.incremental.components.LookupTracker;
033    import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
034    import org.jetbrains.kotlin.name.FqName;
035    import org.jetbrains.kotlin.name.Name;
036    import org.jetbrains.kotlin.psi.*;
037    import org.jetbrains.kotlin.resolve.*;
038    import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension;
039    import org.jetbrains.kotlin.resolve.lazy.data.KtClassLikeInfo;
040    import org.jetbrains.kotlin.resolve.lazy.data.KtClassOrObjectInfo;
041    import org.jetbrains.kotlin.resolve.lazy.data.KtScriptInfo;
042    import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory;
043    import org.jetbrains.kotlin.resolve.lazy.declarations.PackageMemberDeclarationProvider;
044    import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotations;
045    import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationsContextImpl;
046    import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor;
047    import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
048    import org.jetbrains.kotlin.resolve.scopes.MemberScope;
049    import org.jetbrains.kotlin.storage.*;
050    import org.jetbrains.kotlin.utils.SmartList;
051    
052    import javax.inject.Inject;
053    import java.util.Collection;
054    import java.util.Collections;
055    import java.util.List;
056    
057    public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
058        private final LazyResolveStorageManager storageManager;
059        private final ExceptionTracker exceptionTracker;
060    
061        private final ModuleDescriptor module;
062    
063        private final BindingTrace trace;
064        private final DeclarationProviderFactory declarationProviderFactory;
065    
066        private final MemoizedFunctionToNullable<FqName, LazyPackageDescriptor> packages;
067        private final PackageFragmentProvider packageFragmentProvider;
068    
069        private final MemoizedFunctionToNotNull<KtFile, LazyAnnotations> fileAnnotations;
070        private final MemoizedFunctionToNotNull<KtFile, LazyAnnotations> danglingAnnotations;
071    
072        private KtImportsFactory jetImportFactory;
073        private AnnotationResolver annotationResolve;
074        private DescriptorResolver descriptorResolver;
075        private FunctionDescriptorResolver functionDescriptorResolver;
076        private TypeResolver typeResolver;
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        private LanguageVersionSettings languageVersionSettings;
084        private DelegationFilter delegationFilter;
085    
086        private final SyntheticResolveExtension syntheticResolveExtension;
087    
088        @Inject
089        public void setJetImportFactory(KtImportsFactory jetImportFactory) {
090            this.jetImportFactory = jetImportFactory;
091        }
092    
093        @Inject
094        public void setAnnotationResolve(AnnotationResolver annotationResolve) {
095            this.annotationResolve = annotationResolve;
096        }
097    
098        @Inject
099        public void setDescriptorResolver(DescriptorResolver descriptorResolver) {
100            this.descriptorResolver = descriptorResolver;
101        }
102    
103        @Inject
104        public void setFunctionDescriptorResolver(FunctionDescriptorResolver functionDescriptorResolver) {
105            this.functionDescriptorResolver = functionDescriptorResolver;
106        }
107    
108        @Inject
109        public void setTypeResolver(TypeResolver typeResolver) {
110            this.typeResolver = typeResolver;
111        }
112    
113        @Inject
114        public void setLazyDeclarationResolver(LazyDeclarationResolver lazyDeclarationResolver) {
115            this.lazyDeclarationResolver = lazyDeclarationResolver;
116        }
117    
118        @Inject
119        public void setFileScopeProvider(@NotNull FileScopeProvider fileScopeProvider) {
120            this.fileScopeProvider = fileScopeProvider;
121        }
122    
123        @Inject
124        public void setDeclarationScopeProvider(@NotNull DeclarationScopeProviderImpl declarationScopeProvider) {
125            this.declarationScopeProvider = declarationScopeProvider;
126        }
127    
128        @Inject
129        public void setLookupTracker(@NotNull LookupTracker lookupTracker) {
130            this.lookupTracker = lookupTracker;
131        }
132    
133        @Inject
134        public void setLanguageVersionSettings(@NotNull LanguageVersionSettings languageVersionSettings) {
135            this.languageVersionSettings = languageVersionSettings;
136        }
137    
138    
139        @Inject
140        public void setDelegationFilter(@NotNull  DelegationFilter delegationFilter) {
141            this.delegationFilter = delegationFilter;
142        }
143    
144        // Only calls from injectors expected
145        @Deprecated
146        public ResolveSession(
147                @NotNull Project project,
148                @NotNull GlobalContext globalContext,
149                @NotNull ModuleDescriptor rootDescriptor,
150                @NotNull DeclarationProviderFactory declarationProviderFactory,
151                @NotNull BindingTrace delegationTrace
152        ) {
153            LockBasedLazyResolveStorageManager lockBasedLazyResolveStorageManager =
154                    new LockBasedLazyResolveStorageManager(globalContext.getStorageManager());
155    
156            this.storageManager = lockBasedLazyResolveStorageManager;
157            this.exceptionTracker = globalContext.getExceptionTracker();
158            this.trace = lockBasedLazyResolveStorageManager.createSafeTrace(delegationTrace);
159            this.module = rootDescriptor;
160    
161            this.packages =
162                    storageManager.createMemoizedFunctionWithNullableValues(new Function1<FqName, LazyPackageDescriptor>() {
163                        @Override
164                        @Nullable
165                        public LazyPackageDescriptor invoke(FqName fqName) {
166                            return createPackage(fqName);
167                        }
168                    });
169    
170            this.declarationProviderFactory = declarationProviderFactory;
171    
172            this.packageFragmentProvider = new PackageFragmentProvider() {
173                @NotNull
174                @Override
175                public List<PackageFragmentDescriptor> getPackageFragments(@NotNull FqName fqName) {
176                    return ContainerUtil.<PackageFragmentDescriptor>createMaybeSingletonList(getPackageFragment(fqName));
177                }
178    
179                @NotNull
180                @Override
181                public Collection<FqName> getSubPackagesOf(
182                        @NotNull FqName fqName, @NotNull Function1<? super Name, Boolean> nameFilter
183                ) {
184                    LazyPackageDescriptor packageDescriptor = getPackageFragment(fqName);
185                    if (packageDescriptor == null) {
186                        return Collections.emptyList();
187                    }
188                    return packageDescriptor.getDeclarationProvider().getAllDeclaredSubPackages(nameFilter);
189                }
190            };
191    
192            fileAnnotations = storageManager.createMemoizedFunction(new Function1<KtFile, LazyAnnotations>() {
193                @Override
194                public LazyAnnotations invoke(KtFile file) {
195                    return createAnnotations(file, file.getAnnotationEntries());
196                }
197            });
198    
199            danglingAnnotations = storageManager.createMemoizedFunction(new Function1<KtFile, LazyAnnotations>() {
200                @Override
201                public LazyAnnotations invoke(KtFile file) {
202                    return createAnnotations(file, file.getDanglingAnnotations());
203                }
204            });
205    
206            syntheticResolveExtension = SyntheticResolveExtension.Companion.getInstance(project);
207        }
208    
209        private LazyAnnotations createAnnotations(KtFile file, List<KtAnnotationEntry> annotationEntries) {
210            LexicalScope scope = fileScopeProvider.getFileResolutionScope(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<ClassifierDescriptor> getTopLevelClassifierDescriptors(@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            Collection<ClassifierDescriptor> result = new SmartList<ClassifierDescriptor>();
264    
265            result.addAll(ContainerUtil.mapNotNull(
266                    provider.getClassOrObjectDeclarations(fqName.shortName()),
267                    new Function<KtClassLikeInfo, ClassifierDescriptor>() {
268                        @Override
269                        public ClassDescriptor fun(KtClassLikeInfo classLikeInfo) {
270                            if (classLikeInfo instanceof KtClassOrObjectInfo) {
271                                //noinspection RedundantCast
272                                return getClassDescriptor(((KtClassOrObjectInfo) classLikeInfo).getCorrespondingClassOrObject(), location);
273                            }
274                            else if (classLikeInfo instanceof KtScriptInfo) {
275                                return getScriptDescriptor(((KtScriptInfo) classLikeInfo).getScript());
276                            }
277                            else {
278                                throw new IllegalStateException(
279                                        "Unexpected " + classLikeInfo + " of type " + classLikeInfo.getClass().getName()
280                                );
281                            }
282                        }
283                    }
284            ));
285    
286            result.addAll(ContainerUtil.map(
287                    provider.getTypeAliasDeclarations(fqName.shortName()),
288                    new Function<KtTypeAlias, ClassifierDescriptor>() {
289                        @Override
290                        public ClassifierDescriptor fun(KtTypeAlias alias) {
291                            return (ClassifierDescriptor) lazyDeclarationResolver.resolveToDescriptor(alias);
292                        }
293                    }
294            ));
295    
296            return result;
297        }
298    
299        @Override
300        @NotNull
301        public ClassDescriptor getClassDescriptor(@NotNull KtClassOrObject classOrObject, @NotNull LookupLocation location) {
302            return lazyDeclarationResolver.getClassDescriptor(classOrObject, location);
303        }
304    
305        @NotNull
306        public ScriptDescriptor getScriptDescriptor(@NotNull KtScript script) {
307            return lazyDeclarationResolver.getScriptDescriptor(script, NoLookupLocation.FOR_SCRIPT);
308        }
309    
310        @Override
311        @NotNull
312        public BindingContext getBindingContext() {
313            return trace.getBindingContext();
314        }
315    
316        @Override
317        @NotNull
318        public BindingTrace getTrace() {
319            return trace;
320        }
321    
322        @Override
323        @NotNull
324        public DeclarationProviderFactory getDeclarationProviderFactory() {
325            return declarationProviderFactory;
326        }
327    
328        @Override
329        @NotNull
330        public DeclarationDescriptor resolveToDescriptor(@NotNull KtDeclaration declaration) {
331            if (!areDescriptorsCreatedForDeclaration(declaration)) {
332                throw new IllegalStateException(
333                        "No descriptors are created for declarations of type " + declaration.getClass().getSimpleName()
334                        + "\n. Change the caller accordingly"
335                );
336            }
337            if (!KtPsiUtil.isLocal(declaration)) {
338                return lazyDeclarationResolver.resolveToDescriptor(declaration);
339            }
340            return localDescriptorResolver.resolveLocalDeclaration(declaration);
341        }
342    
343        public static boolean areDescriptorsCreatedForDeclaration(@NotNull KtDeclaration declaration) {
344            return !(declaration instanceof KtAnonymousInitializer || declaration instanceof KtDestructuringDeclaration);
345        }
346    
347        @NotNull
348        public Annotations getFileAnnotations(@NotNull KtFile file) {
349            return fileAnnotations.invoke(file);
350        }
351    
352        @NotNull
353        public Annotations getDanglingAnnotations(@NotNull KtFile file) {
354            return danglingAnnotations.invoke(file);
355        }
356    
357        @NotNull
358        private List<LazyPackageDescriptor> getAllPackages() {
359            LazyPackageDescriptor rootPackage = getPackageFragment(FqName.ROOT);
360            assert rootPackage != null : "Root package must be initialized";
361    
362            return collectAllPackages(Lists.<LazyPackageDescriptor>newArrayList(), rootPackage);
363        }
364    
365        @NotNull
366        private List<LazyPackageDescriptor> collectAllPackages(
367                @NotNull List<LazyPackageDescriptor> result,
368                @NotNull LazyPackageDescriptor current
369        ) {
370            result.add(current);
371            for (FqName subPackage : packageFragmentProvider.getSubPackagesOf(current.getFqName(), MemberScope.Companion.getALL_NAME_FILTER())) {
372                LazyPackageDescriptor fragment = getPackageFragment(subPackage);
373                assert fragment != null : "Couldn't find fragment for " + subPackage;
374                collectAllPackages(result, fragment);
375            }
376            return result;
377        }
378    
379        @Override
380        public void forceResolveAll() {
381            for (LazyPackageDescriptor lazyPackage : getAllPackages()) {
382                ForceResolveUtil.forceResolveAllContents(lazyPackage);
383            }
384        }
385    
386        @NotNull
387        public KtImportsFactory getJetImportsFactory() {
388            return jetImportFactory;
389        }
390    
391        @Override
392        @NotNull
393        public AnnotationResolver getAnnotationResolver() {
394            return annotationResolve;
395        }
396    
397        @Override
398        @NotNull
399        public DescriptorResolver getDescriptorResolver() {
400            return descriptorResolver;
401        }
402    
403        @Override
404        @NotNull
405        public TypeResolver getTypeResolver() {
406            return typeResolver;
407        }
408    
409        @NotNull
410        @Override
411        public FunctionDescriptorResolver getFunctionDescriptorResolver() {
412            return functionDescriptorResolver;
413        }
414    
415        @NotNull
416        @Override
417        public DeclarationScopeProvider getDeclarationScopeProvider() {
418            return declarationScopeProvider;
419        }
420    
421        @Override
422        @NotNull
423        public FileScopeProvider getFileScopeProvider() {
424            return fileScopeProvider;
425        }
426    
427        @NotNull
428        @Override
429        public LookupTracker getLookupTracker() {
430            return lookupTracker;
431        }
432    
433        @NotNull
434        @Override
435        public SupertypeLoopChecker getSupertypeLoopChecker() {
436            return supertypeLoopsResolver;
437        }
438    
439        @Inject
440        public void setSupertypeLoopsResolver(@NotNull SupertypeLoopChecker supertypeLoopsResolver) {
441            this.supertypeLoopsResolver = supertypeLoopsResolver;
442        }
443    
444        @Inject
445        public void setLocalDescriptorResolver(@NotNull LocalDescriptorResolver localDescriptorResolver) {
446            this.localDescriptorResolver = localDescriptorResolver;
447        }
448    
449        @NotNull
450        @Override
451        public LanguageVersionSettings getLanguageVersionSettings() {
452            return languageVersionSettings;
453        }
454    
455        @NotNull
456        @Override
457        public DelegationFilter getDelegationFilter() {
458            return delegationFilter;
459        }
460    
461        @NotNull
462        @Override
463        public SyntheticResolveExtension getSyntheticResolveExtension() {
464            return syntheticResolveExtension;
465        }
466    }