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.intellij.psi.PsiElement;
020    import kotlin.Function0;
021    import kotlin.Function1;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.kotlin.descriptors.PackageViewDescriptor;
024    import org.jetbrains.kotlin.name.FqName;
025    import org.jetbrains.kotlin.psi.JetFile;
026    import org.jetbrains.kotlin.psi.JetImportDirective;
027    import org.jetbrains.kotlin.psi.JetImportsFactory;
028    import org.jetbrains.kotlin.resolve.ImportPath;
029    import org.jetbrains.kotlin.resolve.TemporaryBindingTrace;
030    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
031    import org.jetbrains.kotlin.resolve.scopes.JetScope;
032    import org.jetbrains.kotlin.storage.MemoizedFunctionToNotNull;
033    import org.jetbrains.kotlin.storage.NotNullLazyValue;
034    
035    import javax.inject.Inject;
036    import java.util.Collection;
037    import java.util.Collections;
038    import java.util.List;
039    
040    public class ScopeProvider implements DeclarationScopeProvider, FileScopeProvider {
041    
042        public static class AdditionalFileScopeProvider {
043            @NotNull
044            public List<JetScope> scopes(@NotNull JetFile file) {
045                return Collections.emptyList();
046            }
047        }
048    
049        private final ResolveSession resolveSession;
050    
051        private final NotNullLazyValue<Collection<JetImportDirective>> defaultImports;
052    
053        private final MemoizedFunctionToNotNull<JetFile, LazyFileScope> fileScopes;
054    
055        private AdditionalFileScopeProvider additionalFileScopeProvider;
056        private DeclarationScopeProvider declarationScopeProvider;
057    
058        @Inject
059        public void setAdditionalFileScopesProvider(@NotNull AdditionalFileScopeProvider additionalFileScopeProvider) {
060            this.additionalFileScopeProvider = additionalFileScopeProvider;
061        }
062    
063        @Inject
064        public void setDeclarationScopeProvider(@NotNull DeclarationScopeProviderImpl declarationScopeProvider) {
065            this.declarationScopeProvider = declarationScopeProvider;
066        }
067    
068        public ScopeProvider(@NotNull final ResolveSession resolveSession) {
069            this.resolveSession = resolveSession;
070    
071            this.defaultImports = resolveSession.getStorageManager().createLazyValue(new Function0<Collection<JetImportDirective>>() {
072                @Override
073                public Collection<JetImportDirective> invoke() {
074                    PackageViewDescriptor rootPackage = resolveSession.getModuleDescriptor().getPackage(FqName.ROOT);
075                    if (rootPackage == null) {
076                        throw new IllegalStateException("Root package not found");
077                    }
078    
079                    JetImportsFactory importsFactory = resolveSession.getJetImportsFactory();
080                    List<ImportPath> defaultImports = resolveSession.getModuleDescriptor().getDefaultImports();
081    
082                    return importsFactory.createImportDirectives(defaultImports);
083                }
084            });
085    
086    
087            this.fileScopes = resolveSession.getStorageManager().createMemoizedFunction(new Function1<JetFile, LazyFileScope>() {
088                @Override
089                public LazyFileScope invoke(JetFile file) {
090                    return createFileScope(file);
091                }
092            });
093        }
094    
095        @Override
096        @NotNull
097        public LazyFileScope getFileScope(@NotNull JetFile file) {
098            return fileScopes.invoke(file);
099        }
100    
101        private LazyFileScope createFileScope(@NotNull JetFile file) {
102            TemporaryBindingTrace tempTrace = TemporaryBindingTrace.create(resolveSession.getTrace(), "Transient trace for default imports lazy resolve");
103            return LazyFileScope.Factory.create(
104                    resolveSession,
105                    file,
106                    defaultImports.invoke(),
107                    additionalFileScopeProvider.scopes(file),
108                    resolveSession.getTrace(),
109                    tempTrace,
110                    "LazyFileScope for file " + file.getName());
111        }
112    
113        @NotNull
114        @Override
115        public JetScope getResolutionScopeForDeclaration(@NotNull PsiElement elementOfDeclaration) {
116            return declarationScopeProvider.getResolutionScopeForDeclaration(elementOfDeclaration);
117        }
118    
119        @NotNull
120        @Override
121        public DataFlowInfo getOuterDataFlowInfoForDeclaration(@NotNull PsiElement elementOfDeclaration) {
122            return declarationScopeProvider.getOuterDataFlowInfoForDeclaration(elementOfDeclaration);
123        }
124    }