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;
018    
019    import com.intellij.psi.PsiElement;
020    import kotlin.KotlinPackage;
021    import org.jetbrains.annotations.NotNull;
022    import org.jetbrains.kotlin.descriptors.PackageFragmentProvider;
023    import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider;
024    import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
025    import org.jetbrains.kotlin.psi.JetFile;
026    import org.jetbrains.kotlin.psi.JetScript;
027    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
028    import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer;
029    import org.jetbrains.kotlin.resolve.lazy.LazyFileScope;
030    
031    import javax.inject.Inject;
032    import java.util.Arrays;
033    import java.util.Collection;
034    import java.util.List;
035    
036    public class LazyTopDownAnalyzerForTopLevel {
037    
038        private KotlinCodeAnalyzer resolveSession;
039        private LazyTopDownAnalyzer lazyTopDownAnalyzer;
040    
041        @Inject
042        public void setKotlinCodeAnalyzer(@NotNull KotlinCodeAnalyzer kotlinCodeAnalyzer) {
043            this.resolveSession = kotlinCodeAnalyzer;
044        }
045    
046        @Inject
047        public void setLazyTopDownAnalyzer(@NotNull LazyTopDownAnalyzer lazyTopDownAnalyzer) {
048            this.lazyTopDownAnalyzer = lazyTopDownAnalyzer;
049        }
050    
051        @NotNull
052        public TopDownAnalysisContext analyzeFiles(
053                @NotNull TopDownAnalysisParameters topDownAnalysisParameters,
054                @NotNull Collection<JetFile> files,
055                @NotNull List<? extends PackageFragmentProvider> additionalProviders
056        ) {
057            assert topDownAnalysisParameters.isLazy() : "Lazy analyzer is run in non-lazy mode";
058    
059            PackageFragmentProvider provider;
060            if (additionalProviders.isEmpty()) {
061                provider = resolveSession.getPackageFragmentProvider();
062            }
063            else {
064                provider = new CompositePackageFragmentProvider(KotlinPackage.plus(
065                        Arrays.asList(resolveSession.getPackageFragmentProvider()),
066                        additionalProviders));
067            }
068    
069            ((ModuleDescriptorImpl) resolveSession.getModuleDescriptor()).initialize(provider);
070    
071            return analyzeDeclarations(topDownAnalysisParameters, files);
072        }
073    
074        @NotNull
075        public TopDownAnalysisContext analyzeDeclarations(
076                @NotNull TopDownAnalysisParameters topDownAnalysisParameters,
077                @NotNull Collection<? extends PsiElement> elements
078        ) {
079            TopDownAnalysisContext c = lazyTopDownAnalyzer.analyzeDeclarations(topDownAnalysisParameters, elements, DataFlowInfo.EMPTY);
080    
081            resolveImportsInAllFiles(c, resolveSession);
082    
083            return c;
084        }
085    
086        private static void resolveImportsInAllFiles(TopDownAnalysisContext c, KotlinCodeAnalyzer resolveSession) {
087            for (JetFile file : c.getFiles()) {
088                resolveAndCheckImports(file, resolveSession);
089            }
090    
091            for (JetScript script : c.getScripts().keySet()) {
092                resolveAndCheckImports(script.getContainingJetFile(), resolveSession);
093            }
094        }
095    
096        private static void resolveAndCheckImports(@NotNull JetFile file, @NotNull KotlinCodeAnalyzer resolveSession) {
097            LazyFileScope fileScope = resolveSession.getScopeProvider().getFileScope(file);
098            fileScope.forceResolveAllImports();
099        }
100    }
101    
102