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.config.LanguageVersion;
025    import org.jetbrains.kotlin.context.ContextKt;
026    import org.jetbrains.kotlin.context.ModuleContext;
027    import org.jetbrains.kotlin.context.MutableModuleContext;
028    import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
029    import org.jetbrains.kotlin.descriptors.PackageFragmentProvider;
030    import org.jetbrains.kotlin.descriptors.PackagePartProvider;
031    import org.jetbrains.kotlin.frontend.java.di.ContainerForTopDownAnalyzerForJvm;
032    import org.jetbrains.kotlin.frontend.java.di.InjectionKt;
033    import org.jetbrains.kotlin.incremental.components.LookupTracker;
034    import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider;
035    import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackagePartProvider;
036    import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache;
037    import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents;
038    import org.jetbrains.kotlin.modules.Module;
039    import org.jetbrains.kotlin.modules.TargetId;
040    import org.jetbrains.kotlin.modules.TargetIdKt;
041    import org.jetbrains.kotlin.name.Name;
042    import org.jetbrains.kotlin.psi.KtFile;
043    import org.jetbrains.kotlin.resolve.BindingContext;
044    import org.jetbrains.kotlin.resolve.BindingTrace;
045    import org.jetbrains.kotlin.resolve.TopDownAnalysisMode;
046    import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension;
047    import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension;
048    import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform;
049    import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory;
050    
051    import java.util.ArrayList;
052    import java.util.Collection;
053    import java.util.List;
054    
055    public enum TopDownAnalyzerFacadeForJVM {
056    
057        INSTANCE;
058    
059        @NotNull
060        public static AnalysisResult analyzeFilesWithJavaIntegrationNoIncremental(
061                @NotNull ModuleContext moduleContext,
062                @NotNull Collection<KtFile> files,
063                @NotNull BindingTrace trace,
064                @NotNull TopDownAnalysisMode topDownAnalysisMode,
065                PackagePartProvider packagePartProvider
066        ) {
067            return analyzeFilesWithJavaIntegration(moduleContext, files, trace, topDownAnalysisMode, null, null, packagePartProvider);
068        }
069    
070        @NotNull
071        public static AnalysisResult analyzeFilesWithJavaIntegrationWithCustomContext(
072                @NotNull ModuleContext moduleContext,
073                @NotNull Collection<KtFile> files,
074                @NotNull BindingTrace trace,
075                @Nullable List<Module> modules,
076                @Nullable IncrementalCompilationComponents incrementalCompilationComponents,
077                @NotNull PackagePartProvider packagePartProvider
078        ) {
079            return analyzeFilesWithJavaIntegration(
080                    moduleContext, files, trace, TopDownAnalysisMode.TopLevelDeclarations, modules, incrementalCompilationComponents,
081                    packagePartProvider);
082        }
083    
084        @NotNull
085        private static AnalysisResult analyzeFilesWithJavaIntegration(
086                @NotNull ModuleContext moduleContext,
087                @NotNull Collection<KtFile> files,
088                @NotNull BindingTrace trace,
089                @NotNull TopDownAnalysisMode topDownAnalysisMode,
090                @Nullable List<Module> modules,
091                @Nullable IncrementalCompilationComponents incrementalCompilationComponents,
092                @NotNull PackagePartProvider packagePartProvider
093        ) {
094            Project project = moduleContext.getProject();
095            List<KtFile> allFiles = JvmAnalyzerFacade.getAllFilesToAnalyze(project, null, files);
096    
097            FileBasedDeclarationProviderFactory providerFactory =
098                    new FileBasedDeclarationProviderFactory(moduleContext.getStorageManager(), allFiles);
099    
100            LookupTracker lookupTracker =
101                    incrementalCompilationComponents != null
102                    ? incrementalCompilationComponents.getLookupTracker()
103                    : LookupTracker.Companion.getDO_NOTHING();
104    
105            List<TargetId> targetIds = null;
106            if (modules != null) {
107                targetIds = new ArrayList<TargetId>(modules.size());
108    
109                for (Module module : modules) {
110                    targetIds.add(TargetIdKt.TargetId(module));
111                }
112            }
113    
114            packagePartProvider = IncrementalPackagePartProvider.create(
115                    packagePartProvider, files, targetIds, incrementalCompilationComponents, moduleContext.getStorageManager()
116            );
117    
118            ContainerForTopDownAnalyzerForJvm container = InjectionKt.createContainerForTopDownAnalyzerForJvm(
119                    moduleContext,
120                    trace,
121                    providerFactory,
122                    GlobalSearchScope.allScope(project),
123                    lookupTracker,
124                    packagePartProvider,
125                    LanguageVersion.LATEST
126            );
127    
128            List<PackageFragmentProvider> additionalProviders = new ArrayList<PackageFragmentProvider>();
129    
130            if (targetIds != null && incrementalCompilationComponents != null) {
131                for (TargetId targetId : targetIds) {
132                    IncrementalCache incrementalCache = incrementalCompilationComponents.getIncrementalCache(targetId);
133    
134                    additionalProviders.add(
135                            new IncrementalPackageFragmentProvider(
136                                    files, moduleContext.getModule(), moduleContext.getStorageManager(),
137                                    container.getDeserializationComponentsForJava().getComponents(),
138                                    incrementalCache, targetId
139                            )
140                    );
141                }
142            }
143            additionalProviders.add(container.getJavaDescriptorResolver().getPackageFragmentProvider());
144    
145            for (PackageFragmentProviderExtension extension : PackageFragmentProviderExtension.Companion.getInstances(project)) {
146                PackageFragmentProvider provider = extension.getPackageFragmentProvider(
147                        project, moduleContext.getModule(), moduleContext.getStorageManager(), trace, null);
148                if (provider != null) additionalProviders.add(provider);
149            }
150    
151            container.getLazyTopDownAnalyzerForTopLevel().analyzeFiles(topDownAnalysisMode, allFiles, additionalProviders);
152    
153            BindingContext bindingContext = trace.getBindingContext();
154            ModuleDescriptor module = moduleContext.getModule();
155    
156            Collection<AnalysisCompletedHandlerExtension> analysisCompletedHandlerExtensions =
157                    AnalysisCompletedHandlerExtension.Companion.getInstances(moduleContext.getProject());
158    
159            for (AnalysisCompletedHandlerExtension extension : analysisCompletedHandlerExtensions) {
160                AnalysisResult result = extension.analysisCompleted(project, module, trace, files);
161                if (result != null) return result;
162            }
163    
164            return AnalysisResult.success(bindingContext, module);
165        }
166    
167        @NotNull
168        public static MutableModuleContext createContextWithSealedModule(@NotNull Project project, @NotNull String moduleName) {
169            MutableModuleContext context = ContextKt.ContextForNewModule(
170                    project, Name.special("<" + moduleName + ">"), JvmPlatform.INSTANCE
171            );
172            context.setDependencies(context.getModule(), JvmPlatform.INSTANCE.getBuiltIns().getBuiltInsModule());
173            return context;
174        }
175    }