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 TopDownAnalysisMode topDownAnalysisMode,
054                @NotNull Collection<JetFile> files,
055                @NotNull List<? extends PackageFragmentProvider> additionalProviders
056        ) {
057            PackageFragmentProvider provider;
058            if (additionalProviders.isEmpty()) {
059                provider = resolveSession.getPackageFragmentProvider();
060            }
061            else {
062                provider = new CompositePackageFragmentProvider(KotlinPackage.plus(
063                        Arrays.asList(resolveSession.getPackageFragmentProvider()),
064                        additionalProviders));
065            }
066    
067            ((ModuleDescriptorImpl) resolveSession.getModuleDescriptor()).initialize(provider);
068    
069            return analyzeDeclarations(topDownAnalysisMode, files);
070        }
071    
072        @NotNull
073        public TopDownAnalysisContext analyzeDeclarations(
074                @NotNull TopDownAnalysisMode topDownAnalysisMode,
075                @NotNull Collection<? extends PsiElement> elements
076        ) {
077            TopDownAnalysisContext c = lazyTopDownAnalyzer.analyzeDeclarations(topDownAnalysisMode, elements, DataFlowInfo.EMPTY);
078    
079            resolveImportsInAllFiles(c, resolveSession);
080    
081            return c;
082        }
083    
084        private static void resolveImportsInAllFiles(TopDownAnalysisContext c, KotlinCodeAnalyzer resolveSession) {
085            for (JetFile file : c.getFiles()) {
086                resolveAndCheckImports(file, resolveSession);
087            }
088    
089            for (JetScript script : c.getScripts().keySet()) {
090                resolveAndCheckImports(script.getContainingJetFile(), resolveSession);
091            }
092        }
093    
094        private static void resolveAndCheckImports(@NotNull JetFile file, @NotNull KotlinCodeAnalyzer resolveSession) {
095            LazyFileScope fileScope = resolveSession.getScopeProvider().getFileScope(file);
096            fileScope.forceResolveAllImports();
097        }
098    }
099    
100