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