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