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.google.common.base.Predicate;
020    import com.intellij.openapi.project.Project;
021    import com.intellij.psi.PsiFile;
022    import com.intellij.psi.search.GlobalSearchScope;
023    import org.jetbrains.annotations.NotNull;
024    import org.jetbrains.annotations.Nullable;
025    import org.jetbrains.kotlin.analyzer.AnalysisResult;
026    import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
027    import org.jetbrains.kotlin.context.GlobalContext;
028    import org.jetbrains.kotlin.descriptors.ClassDescriptor;
029    import org.jetbrains.kotlin.descriptors.PackageFragmentProvider;
030    import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
031    import org.jetbrains.kotlin.di.InjectorForTopDownAnalyzerForJvm;
032    import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider;
033    import org.jetbrains.kotlin.load.kotlin.incremental.cache.IncrementalCache;
034    import org.jetbrains.kotlin.load.kotlin.incremental.cache.IncrementalCacheProvider;
035    import org.jetbrains.kotlin.name.FqName;
036    import org.jetbrains.kotlin.name.Name;
037    import org.jetbrains.kotlin.platform.JavaToKotlinClassMap;
038    import org.jetbrains.kotlin.psi.JetFile;
039    import org.jetbrains.kotlin.resolve.BindingTrace;
040    import org.jetbrains.kotlin.resolve.DescriptorUtils;
041    import org.jetbrains.kotlin.resolve.ImportPath;
042    import org.jetbrains.kotlin.resolve.TopDownAnalysisParameters;
043    import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory;
044    
045    import java.util.ArrayList;
046    import java.util.Collection;
047    import java.util.List;
048    
049    public enum TopDownAnalyzerFacadeForJVM {
050    
051        INSTANCE;
052    
053        public static final List<ImportPath> DEFAULT_IMPORTS = buildDefaultImports();
054    
055        private static List<ImportPath> buildDefaultImports() {
056            List<ImportPath> list = new ArrayList<ImportPath>();
057            list.add(new ImportPath("java.lang.*"));
058            list.add(new ImportPath("kotlin.*"));
059            list.add(new ImportPath("kotlin.jvm.*"));
060            list.add(new ImportPath("kotlin.io.*"));
061            // all classes from package "kotlin" mapped to java classes are imported explicitly so that they take priority over classes from java.lang
062            for (ClassDescriptor descriptor : JavaToKotlinClassMap.INSTANCE.allKotlinClasses()) {
063                FqName fqName = DescriptorUtils.getFqNameSafe(descriptor);
064                if (fqName.parent().equals(new FqName("kotlin"))) {
065                    list.add(new ImportPath(fqName, false));
066                }
067            }
068            return list;
069        }
070    
071        private TopDownAnalyzerFacadeForJVM() {
072        }
073    
074        @NotNull
075        public static AnalysisResult analyzeFilesWithJavaIntegrationNoIncremental(
076                @NotNull Project project,
077                @NotNull Collection<JetFile> files,
078                @NotNull BindingTrace trace,
079                @NotNull TopDownAnalysisParameters topDownAnalysisParameters,
080                @NotNull ModuleDescriptorImpl module
081        ) {
082            return analyzeFilesWithJavaIntegration(project, files, trace, topDownAnalysisParameters, module, null, null);
083        }
084    
085        @NotNull
086        public static AnalysisResult analyzeFilesWithJavaIntegrationWithCustomContext(
087                @NotNull Project project,
088                @NotNull GlobalContext globalContext,
089                @NotNull Collection<JetFile> files,
090                @NotNull BindingTrace trace,
091                @NotNull Predicate<PsiFile> filesToAnalyzeCompletely,
092                @NotNull ModuleDescriptorImpl module,
093                @Nullable List<String> moduleIds,
094                @Nullable IncrementalCacheProvider incrementalCacheProvider
095        ) {
096            TopDownAnalysisParameters topDownAnalysisParameters = TopDownAnalysisParameters.create(
097                    globalContext.getStorageManager(),
098                    globalContext.getExceptionTracker(),
099                    filesToAnalyzeCompletely,
100                    false,
101                    false
102            );
103    
104            return analyzeFilesWithJavaIntegration(
105                    project, files, trace, topDownAnalysisParameters, module,
106                    moduleIds, incrementalCacheProvider);
107        }
108    
109        @NotNull
110        private static AnalysisResult analyzeFilesWithJavaIntegration(
111                Project project,
112                Collection<JetFile> files,
113                BindingTrace trace,
114                TopDownAnalysisParameters topDownAnalysisParameters,
115                ModuleDescriptorImpl module,
116                @Nullable List<String> moduleIds,
117                @Nullable IncrementalCacheProvider incrementalCacheProvider
118        ) {
119            List<JetFile> allFiles = JvmAnalyzerFacade.getAllFilesToAnalyze(project, null, files);
120    
121            FileBasedDeclarationProviderFactory providerFactory =
122                    new FileBasedDeclarationProviderFactory(topDownAnalysisParameters.getStorageManager(), allFiles);
123    
124            InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm(
125                    project,
126                    topDownAnalysisParameters,
127                    trace,
128                    module,
129                    providerFactory,
130                    GlobalSearchScope.allScope(project)
131            );
132    
133            try {
134                List<PackageFragmentProvider> additionalProviders = new ArrayList<PackageFragmentProvider>();
135    
136                if (moduleIds != null && incrementalCacheProvider != null) {
137                    for (String moduleId : moduleIds) {
138                        IncrementalCache incrementalCache = incrementalCacheProvider.getIncrementalCache(moduleId);
139    
140                        additionalProviders.add(
141                                new IncrementalPackageFragmentProvider(
142                                        files, module, topDownAnalysisParameters.getStorageManager(),
143                                        injector.getDeserializationComponentsForJava().getComponents(),
144                                        incrementalCache, moduleId
145                                )
146                        );
147                    }
148                }
149                additionalProviders.add(injector.getJavaDescriptorResolver().getPackageFragmentProvider());
150    
151                injector.getLazyTopDownAnalyzerForTopLevel().analyzeFiles(topDownAnalysisParameters, allFiles, additionalProviders);
152                return AnalysisResult.success(trace.getBindingContext(), module);
153            }
154            finally {
155                injector.destroy();
156            }
157        }
158    
159        @NotNull
160        public static ModuleDescriptorImpl createJavaModule(@NotNull String name) {
161            return new ModuleDescriptorImpl(Name.special(name),
162                                            DEFAULT_IMPORTS,
163                                            JavaToKotlinClassMap.INSTANCE);
164        }
165    
166        @NotNull
167        public static ModuleDescriptorImpl createSealedJavaModule() {
168            ModuleDescriptorImpl module = createJavaModule("<shared-module>");
169            module.addDependencyOnModule(module);
170            module.addDependencyOnModule(KotlinBuiltIns.getInstance().getBuiltInsModule());
171            module.seal();
172            return module;
173        }
174    }