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