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