001    /*
002     * Copyright 2010-2014 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.jet.lang.resolve.java;
018    
019    import com.google.common.base.Predicate;
020    import com.google.common.base.Predicates;
021    import com.google.common.collect.ImmutableList;
022    import com.intellij.openapi.project.Project;
023    import com.intellij.psi.PsiFile;
024    import org.jetbrains.annotations.NotNull;
025    import org.jetbrains.jet.analyzer.AnalyzeExhaust;
026    import org.jetbrains.jet.analyzer.AnalyzerFacade;
027    import org.jetbrains.jet.analyzer.AnalyzerFacadeForEverything;
028    import org.jetbrains.jet.context.ContextPackage;
029    import org.jetbrains.jet.context.GlobalContext;
030    import org.jetbrains.jet.context.GlobalContextImpl;
031    import org.jetbrains.jet.di.InjectorForLazyResolveWithJava;
032    import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJvm;
033    import org.jetbrains.jet.lang.descriptors.DependencyKind;
034    import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
035    import org.jetbrains.jet.lang.descriptors.ModuleDescriptorImpl;
036    import org.jetbrains.jet.lang.psi.JetFile;
037    import org.jetbrains.jet.lang.resolve.*;
038    import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap;
039    import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
040    import org.jetbrains.jet.lang.resolve.lazy.declarations.FileBasedDeclarationProviderFactory;
041    import org.jetbrains.jet.lang.resolve.name.Name;
042    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
043    
044    import java.util.Collection;
045    import java.util.Collections;
046    import java.util.List;
047    
048    public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
049    
050        INSTANCE;
051    
052        public static final List<ImportPath> DEFAULT_IMPORTS = ImmutableList.of(
053                new ImportPath("java.lang.*"),
054                new ImportPath("kotlin.*"),
055                new ImportPath("kotlin.io.*"));
056    
057        private AnalyzerFacadeForJVM() {
058        }
059    
060        @Override
061        @NotNull
062        public AnalyzeExhaust analyzeFiles(@NotNull Project project,
063                @NotNull Collection<JetFile> files,
064                @NotNull List<AnalyzerScriptParameter> scriptParameters,
065                @NotNull Predicate<PsiFile> filesToAnalyzeCompletely) {
066            return analyzeFilesWithJavaIntegration(project, files, scriptParameters, filesToAnalyzeCompletely, true);
067        }
068    
069        @NotNull
070        @Override
071        public AnalyzeExhaust analyzeBodiesInFiles(@NotNull Project project,
072                                                   @NotNull List<AnalyzerScriptParameter> scriptParameters,
073                                                   @NotNull Predicate<PsiFile> filesForBodiesResolve,
074                                                   @NotNull BindingTrace headersTraceContext,
075                                                   @NotNull BodiesResolveContext bodiesResolveContext,
076                                                   @NotNull ModuleDescriptor module
077        ) {
078            return AnalyzerFacadeForEverything.analyzeBodiesInFilesWithJavaIntegration(
079                    project, scriptParameters, filesForBodiesResolve,
080                    headersTraceContext, bodiesResolveContext, module);
081        }
082    
083        @NotNull
084        @Override
085        public ResolveSession getLazyResolveSession(@NotNull Project fileProject, @NotNull Collection<JetFile> files) {
086            return createLazyResolveSession(fileProject, files, new BindingTraceContext(), true);
087        }
088    
089        @NotNull
090        public static ResolveSession createLazyResolveSession(
091                @NotNull Project project,
092                @NotNull Collection<JetFile> files,
093                @NotNull BindingTrace trace,
094                boolean addBuiltIns
095        ) {
096            GlobalContextImpl globalContext = ContextPackage.GlobalContext();
097    
098            // TODO: Replace with stub declaration provider
099            FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory(
100                    globalContext.getStorageManager(),
101                    files);
102    
103            InjectorForLazyResolveWithJava resolveWithJava = new InjectorForLazyResolveWithJava(
104                    project,
105                    globalContext,
106                    declarationProviderFactory,
107                    trace);
108    
109            resolveWithJava.getModule().addFragmentProvider(
110                    DependencyKind.BINARIES, resolveWithJava.getJavaDescriptorResolver().getPackageFragmentProvider());
111    
112            if (addBuiltIns) {
113                resolveWithJava.getModule().addFragmentProvider(
114                        DependencyKind.BUILT_INS,
115                        KotlinBuiltIns.getInstance().getBuiltInsModule().getPackageFragmentProvider());
116            }
117    
118            return resolveWithJava.getResolveSession();
119        }
120    
121        @NotNull
122        public static AnalyzeExhaust analyzeOneFileWithJavaIntegrationAndCheckForErrors(
123                JetFile file, List<AnalyzerScriptParameter> scriptParameters) {
124            AnalyzingUtils.checkForSyntacticErrors(file);
125    
126            AnalyzeExhaust analyzeExhaust = analyzeOneFileWithJavaIntegration(file, scriptParameters);
127    
128            AnalyzingUtils.throwExceptionOnErrors(analyzeExhaust.getBindingContext());
129    
130            return analyzeExhaust;
131        }
132    
133        @NotNull
134        public static AnalyzeExhaust analyzeOneFileWithJavaIntegration(
135                JetFile file, List<AnalyzerScriptParameter> scriptParameters) {
136            return analyzeFilesWithJavaIntegration(file.getProject(), Collections.singleton(file), scriptParameters,
137                                                   Predicates.<PsiFile>alwaysTrue());
138        }
139    
140        @NotNull
141        public static AnalyzeExhaust analyzeFilesWithJavaIntegrationAndCheckForErrors(
142                Project project,
143                Collection<JetFile> files,
144                List<AnalyzerScriptParameter> scriptParameters,
145                Predicate<PsiFile> filesToAnalyzeCompletely
146        ) {
147            for (JetFile file : files) {
148                AnalyzingUtils.checkForSyntacticErrors(file);
149            }
150    
151            AnalyzeExhaust analyzeExhaust = analyzeFilesWithJavaIntegration(
152                    project, files, scriptParameters, filesToAnalyzeCompletely, false);
153    
154            AnalyzingUtils.throwExceptionOnErrors(analyzeExhaust.getBindingContext());
155    
156            return analyzeExhaust;
157        }
158    
159        @NotNull
160        public static AnalyzeExhaust analyzeFilesWithJavaIntegration(
161                Project project,
162                Collection<JetFile> files,
163                List<AnalyzerScriptParameter> scriptParameters,
164                Predicate<PsiFile> filesToAnalyzeCompletely
165        ) {
166            return analyzeFilesWithJavaIntegration(
167                    project, files, scriptParameters, filesToAnalyzeCompletely, false);
168        }
169    
170        @NotNull
171        public static AnalyzeExhaust analyzeFilesWithJavaIntegration(
172                Project project, Collection<JetFile> files, List<AnalyzerScriptParameter> scriptParameters, Predicate<PsiFile> filesToAnalyzeCompletely,
173                boolean storeContextForBodiesResolve) {
174            BindingTraceContext bindingTraceContext = new BindingTraceContext();
175    
176            return analyzeFilesWithJavaIntegration(project, files, bindingTraceContext, scriptParameters, filesToAnalyzeCompletely,
177                                                   storeContextForBodiesResolve);
178        }
179    
180        @NotNull
181        public static AnalyzeExhaust analyzeFilesWithJavaIntegration(
182                Project project,
183                Collection<JetFile> files,
184                BindingTrace trace,
185                List<AnalyzerScriptParameter> scriptParameters,
186                Predicate<PsiFile> filesToAnalyzeCompletely,
187                boolean storeContextForBodiesResolve
188        ) {
189            return analyzeFilesWithJavaIntegration(project, files, trace, scriptParameters, filesToAnalyzeCompletely,
190                                                   storeContextForBodiesResolve, createJavaModule("<module>"));
191        }
192    
193        @NotNull
194        public static AnalyzeExhaust analyzeFilesWithJavaIntegration(
195                Project project,
196                Collection<JetFile> files,
197                BindingTrace trace,
198                List<AnalyzerScriptParameter> scriptParameters,
199                Predicate<PsiFile> filesToAnalyzeCompletely,
200                boolean storeContextForBodiesResolve,
201                ModuleDescriptorImpl module
202        ) {
203            GlobalContext globalContext = ContextPackage.GlobalContext();
204            return analyzeFilesWithJavaIntegrationInGlobalContext(project, files, trace, scriptParameters, filesToAnalyzeCompletely,
205                                                                  storeContextForBodiesResolve, module, globalContext);
206        }
207    
208        @NotNull
209        public static AnalyzeExhaust analyzeFilesWithJavaIntegrationInGlobalContext(
210                Project project,
211                Collection<JetFile> files,
212                BindingTrace trace,
213                List<AnalyzerScriptParameter> scriptParameters,
214                Predicate<PsiFile> filesToAnalyzeCompletely,
215                boolean storeContextForBodiesResolve,
216                ModuleDescriptorImpl module,
217                GlobalContext globalContext
218        ) {
219            TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(
220                    globalContext.getStorageManager(),
221                    globalContext.getExceptionTracker(),
222                    filesToAnalyzeCompletely,
223                    false,
224                    false,
225                    scriptParameters
226            );
227    
228            InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm(project, topDownAnalysisParameters, trace, module);
229            try {
230                module.addFragmentProvider(DependencyKind.BINARIES, injector.getJavaDescriptorResolver().getPackageFragmentProvider());
231                TopDownAnalysisContext topDownAnalysisContext = injector.getTopDownAnalyzer().analyzeFiles(topDownAnalysisParameters, files);
232                BodiesResolveContext bodiesResolveContext = storeContextForBodiesResolve ?
233                                                            new CachedBodiesResolveContext(topDownAnalysisContext) :
234                                                            null;
235                return AnalyzeExhaust.success(trace.getBindingContext(), bodiesResolveContext, module);
236            }
237            finally {
238                injector.destroy();
239            }
240        }
241    
242        @NotNull
243        public static ModuleDescriptorImpl createJavaModule(@NotNull String name) {
244            return new ModuleDescriptorImpl(Name.special(name), DEFAULT_IMPORTS, JavaToKotlinClassMap.getInstance());
245        }
246    }