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    }