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.jvm;
018    
019    import com.intellij.openapi.project.Project;
020    import com.intellij.psi.search.GlobalSearchScope;
021    import org.jetbrains.annotations.NotNull;
022    import org.jetbrains.annotations.Nullable;
023    import org.jetbrains.kotlin.analyzer.AnalysisResult;
024    import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
025    import org.jetbrains.kotlin.context.ModuleContext;
026    import org.jetbrains.kotlin.context.MutableModuleContext;
027    import org.jetbrains.kotlin.descriptors.*;
028    import org.jetbrains.kotlin.frontend.java.di.ContainerForTopDownAnalyzerForJvm;
029    import org.jetbrains.kotlin.frontend.java.di.DiPackage;
030    import org.jetbrains.kotlin.incremental.components.LookupTracker;
031    import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider;
032    import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackagePartProvider;
033    import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache;
034    import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents;
035    import org.jetbrains.kotlin.modules.Module;
036    import org.jetbrains.kotlin.modules.ModulesPackage;
037    import org.jetbrains.kotlin.modules.TargetId;
038    import org.jetbrains.kotlin.name.Name;
039    import org.jetbrains.kotlin.platform.JavaToKotlinClassMap;
040    import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap;
041    import org.jetbrains.kotlin.psi.JetFile;
042    import org.jetbrains.kotlin.resolve.*;
043    import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension;
044    import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory;
045    import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter;
046    import org.jetbrains.kotlin.resolve.scopes.JetScope;
047    
048    import java.util.ArrayList;
049    import java.util.Collection;
050    import java.util.List;
051    
052    import static org.jetbrains.kotlin.context.ContextPackage.ContextForNewModule;
053    
054    public enum TopDownAnalyzerFacadeForJVM {
055    
056        INSTANCE;
057    
058        public static final List<ImportPath> DEFAULT_IMPORTS = buildDefaultImports();
059    
060        private static void addAllClassifiersToImportPathList(List<ImportPath> list, JetScope scope) {
061            for (DeclarationDescriptor descriptor : scope.getDescriptors(DescriptorKindFilter.CLASSIFIERS, JetScope.ALL_NAME_FILTER)) {
062                list.add(new ImportPath(DescriptorUtils.getFqNameSafe(descriptor), false));
063            }
064        }
065    
066        private static List<ImportPath> buildDefaultImports() {
067            List<ImportPath> list = new ArrayList<ImportPath>();
068            list.add(new ImportPath("java.lang.*"));
069            list.add(new ImportPath("kotlin.*"));
070            list.add(new ImportPath("kotlin.annotation.*"));
071            list.add(new ImportPath("kotlin.jvm.*"));
072            list.add(new ImportPath("kotlin.io.*"));
073    
074            addAllClassifiersToImportPathList(list, KotlinBuiltIns.getInstance().getBuiltInsPackageScope());
075            addAllClassifiersToImportPathList(list, KotlinBuiltIns.getInstance().getAnnotationPackageScope());
076    
077            return list;
078        }
079    
080        public static ModuleParameters JVM_MODULE_PARAMETERS = new ModuleParameters() {
081            @NotNull
082            @Override
083            public List<ImportPath> getDefaultImports() {
084                return DEFAULT_IMPORTS;
085            }
086    
087            @NotNull
088            @Override
089            public PlatformToKotlinClassMap getPlatformToKotlinClassMap() {
090                return JavaToKotlinClassMap.INSTANCE;
091            }
092        };
093    
094        @NotNull
095        public static AnalysisResult analyzeFilesWithJavaIntegrationNoIncremental(
096                @NotNull ModuleContext moduleContext,
097                @NotNull Collection<JetFile> files,
098                @NotNull BindingTrace trace,
099                @NotNull TopDownAnalysisMode topDownAnalysisMode,
100                PackagePartProvider packagePartProvider
101        ) {
102            return analyzeFilesWithJavaIntegration(moduleContext, files, trace, topDownAnalysisMode, null, null, packagePartProvider);
103        }
104    
105        @NotNull
106        public static AnalysisResult analyzeFilesWithJavaIntegrationWithCustomContext(
107                @NotNull ModuleContext moduleContext,
108                @NotNull Collection<JetFile> files,
109                @NotNull BindingTrace trace,
110                @Nullable List<Module> modules,
111                @Nullable IncrementalCompilationComponents incrementalCompilationComponents,
112                @NotNull PackagePartProvider packagePartProvider
113        ) {
114            return analyzeFilesWithJavaIntegration(
115                    moduleContext, files, trace, TopDownAnalysisMode.TopLevelDeclarations, modules, incrementalCompilationComponents,
116                    packagePartProvider);
117        }
118    
119        @NotNull
120        private static AnalysisResult analyzeFilesWithJavaIntegration(
121                @NotNull ModuleContext moduleContext,
122                @NotNull Collection<JetFile> files,
123                @NotNull BindingTrace trace,
124                @NotNull TopDownAnalysisMode topDownAnalysisMode,
125                @Nullable List<Module> modules,
126                @Nullable IncrementalCompilationComponents incrementalCompilationComponents,
127                @NotNull PackagePartProvider packagePartProvider
128        ) {
129            Project project = moduleContext.getProject();
130            List<JetFile> allFiles = JvmAnalyzerFacade.getAllFilesToAnalyze(project, null, files);
131    
132            FileBasedDeclarationProviderFactory providerFactory =
133                    new FileBasedDeclarationProviderFactory(moduleContext.getStorageManager(), allFiles);
134    
135            LookupTracker lookupTracker =
136                    incrementalCompilationComponents != null ? incrementalCompilationComponents.getLookupTracker() : LookupTracker.DO_NOTHING;
137    
138            List<TargetId> targetIds = null;
139            if (modules != null) {
140                targetIds = new ArrayList<TargetId>(modules.size());
141    
142                for (Module module : modules) {
143                    targetIds.add(ModulesPackage.TargetId(module));
144                }
145            }
146    
147            packagePartProvider = IncrementalPackagePartProvider.create(packagePartProvider, files, targetIds, incrementalCompilationComponents, moduleContext.getStorageManager());
148    
149            ContainerForTopDownAnalyzerForJvm container = DiPackage.createContainerForTopDownAnalyzerForJvm(
150                    moduleContext,
151                    trace,
152                    providerFactory,
153                    GlobalSearchScope.allScope(project),
154                    lookupTracker,
155                    packagePartProvider
156            );
157    
158            List<PackageFragmentProvider> additionalProviders = new ArrayList<PackageFragmentProvider>();
159    
160            if (targetIds != null && incrementalCompilationComponents != null) {
161                for (TargetId targetId : targetIds) {
162                    IncrementalCache incrementalCache = incrementalCompilationComponents.getIncrementalCache(targetId);
163    
164                    additionalProviders.add(
165                            new IncrementalPackageFragmentProvider(
166                                    files, moduleContext.getModule(), moduleContext.getStorageManager(),
167                                    container.getDeserializationComponentsForJava().getComponents(),
168                                    incrementalCache, targetId
169                            )
170                    );
171                }
172            }
173            additionalProviders.add(container.getJavaDescriptorResolver().getPackageFragmentProvider());
174    
175            container.getLazyTopDownAnalyzerForTopLevel().analyzeFiles(topDownAnalysisMode, allFiles, additionalProviders);
176    
177            BindingContext bindingContext = trace.getBindingContext();
178            ModuleDescriptor module = moduleContext.getModule();
179    
180            Collection<AnalysisCompletedHandlerExtension> analysisCompletedHandlerExtensions =
181                    AnalysisCompletedHandlerExtension.Companion.getInstances(moduleContext.getProject());
182    
183            for (AnalysisCompletedHandlerExtension extension : analysisCompletedHandlerExtensions) {
184                AnalysisResult result = extension.analysisCompleted(project, module, bindingContext, files);
185                if (result != null) return result;
186            }
187    
188            return AnalysisResult.success(bindingContext, module);
189        }
190    
191        @NotNull
192        public static MutableModuleContext createContextWithSealedModule(@NotNull Project project, @NotNull String moduleName) {
193            MutableModuleContext context = ContextForNewModule(
194                    project, Name.special("<" + moduleName + ">"), JVM_MODULE_PARAMETERS
195            );
196            context.setDependencies(context.getModule(), KotlinBuiltIns.getInstance().getBuiltInsModule());
197            return context;
198        }
199    }