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