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