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.collections.CollectionsKt;
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.KtFile;
026    import org.jetbrains.kotlin.psi.KtScript;
027    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory;
028    import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer;
029    import org.jetbrains.kotlin.resolve.lazy.ImportResolver;
030    
031    import java.util.Arrays;
032    import java.util.Collection;
033    import java.util.List;
034    
035    public class LazyTopDownAnalyzerForTopLevel {
036    
037        @NotNull private final KotlinCodeAnalyzer codeAnalyzer;
038        @NotNull private final LazyTopDownAnalyzer lazyTopDownAnalyzer;
039    
040        public LazyTopDownAnalyzerForTopLevel(
041                @NotNull LazyTopDownAnalyzer lazyTopDownAnalyzer,
042                @NotNull KotlinCodeAnalyzer codeAnalyzer
043        ) {
044            this.lazyTopDownAnalyzer = lazyTopDownAnalyzer;
045            this.codeAnalyzer = codeAnalyzer;
046        }
047    
048        @NotNull
049        public TopDownAnalysisContext analyzeFiles(
050                @NotNull TopDownAnalysisMode topDownAnalysisMode,
051                @NotNull Collection<KtFile> files,
052                @NotNull List<? extends PackageFragmentProvider> additionalProviders
053        ) {
054            PackageFragmentProvider provider;
055            if (additionalProviders.isEmpty()) {
056                provider = codeAnalyzer.getPackageFragmentProvider();
057            }
058            else {
059                provider = new CompositePackageFragmentProvider(CollectionsKt.plus(
060                        Arrays.asList(codeAnalyzer.getPackageFragmentProvider()),
061                        additionalProviders));
062            }
063    
064            ((ModuleDescriptorImpl) codeAnalyzer.getModuleDescriptor()).initialize(provider);
065    
066            return analyzeDeclarations(topDownAnalysisMode, files);
067        }
068    
069        @NotNull
070        public TopDownAnalysisContext analyzeDeclarations(
071                @NotNull TopDownAnalysisMode topDownAnalysisMode,
072                @NotNull Collection<? extends PsiElement> elements
073        ) {
074            TopDownAnalysisContext c = lazyTopDownAnalyzer.analyzeDeclarations(topDownAnalysisMode, elements, DataFlowInfoFactory.EMPTY);
075    
076            resolveImportsInAllFiles(c, codeAnalyzer);
077    
078            return c;
079        }
080    
081        private static void resolveImportsInAllFiles(TopDownAnalysisContext c, KotlinCodeAnalyzer resolveSession) {
082            for (KtFile file : c.getFiles()) {
083                resolveAndCheckImports(file, resolveSession);
084            }
085    
086            for (KtScript script : c.getScripts().keySet()) {
087                resolveAndCheckImports(script.getContainingKtFile(), resolveSession);
088            }
089        }
090    
091        private static void resolveAndCheckImports(@NotNull KtFile file, @NotNull KotlinCodeAnalyzer resolveSession) {
092            ImportResolver importResolver = resolveSession.getFileScopeProvider().getImportResolver(file);
093            importResolver.forceResolveAllImports();
094        }
095    }
096    
097