001    /*
002     * Copyright 2010-2013 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.intellij.openapi.project.Project;
022    import com.intellij.psi.PsiFile;
023    import org.jetbrains.annotations.NotNull;
024    import org.jetbrains.jet.analyzer.AnalyzeExhaust;
025    import org.jetbrains.jet.analyzer.AnalyzerFacade;
026    import org.jetbrains.jet.analyzer.AnalyzerFacadeForEverything;
027    import org.jetbrains.jet.di.InjectorForJavaDescriptorResolver;
028    import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJvm;
029    import org.jetbrains.jet.lang.ModuleConfiguration;
030    import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
031    import org.jetbrains.jet.lang.descriptors.ModuleDescriptorImpl;
032    import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
033    import org.jetbrains.jet.lang.psi.JetFile;
034    import org.jetbrains.jet.lang.resolve.*;
035    import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap;
036    import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
037    import org.jetbrains.jet.lang.resolve.lazy.declarations.FileBasedDeclarationProviderFactory;
038    import org.jetbrains.jet.lang.resolve.lazy.storage.LockBasedLazyResolveStorageManager;
039    import org.jetbrains.jet.lang.resolve.name.FqName;
040    import org.jetbrains.jet.lang.resolve.name.Name;
041    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
042    import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
043    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
044    
045    import java.util.Collection;
046    import java.util.Collections;
047    import java.util.List;
048    
049    public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
050    
051        INSTANCE;
052    
053        private AnalyzerFacadeForJVM() {
054        }
055    
056        @Override
057        @NotNull
058        public AnalyzeExhaust analyzeFiles(@NotNull Project project,
059                @NotNull Collection<JetFile> files,
060                @NotNull List<AnalyzerScriptParameter> scriptParameters,
061                @NotNull Predicate<PsiFile> filesToAnalyzeCompletely) {
062            return analyzeFilesWithJavaIntegration(project, files, scriptParameters, filesToAnalyzeCompletely, true);
063        }
064    
065        @NotNull
066        @Override
067        public AnalyzeExhaust analyzeBodiesInFiles(@NotNull Project project,
068                                                   @NotNull List<AnalyzerScriptParameter> scriptParameters,
069                                                   @NotNull Predicate<PsiFile> filesForBodiesResolve,
070                                                   @NotNull BindingTrace headersTraceContext,
071                                                   @NotNull BodiesResolveContext bodiesResolveContext,
072                                                   @NotNull ModuleDescriptor module
073        ) {
074            return AnalyzerFacadeForEverything.analyzeBodiesInFilesWithJavaIntegration(
075                    project, scriptParameters, filesForBodiesResolve,
076                    headersTraceContext, bodiesResolveContext, module);
077        }
078    
079        @NotNull
080        @Override
081        public ResolveSession getLazyResolveSession(@NotNull Project fileProject, @NotNull Collection<JetFile> files) {
082            BindingTraceContext javaResolverTrace = new BindingTraceContext();
083            InjectorForJavaDescriptorResolver injector = new InjectorForJavaDescriptorResolver(fileProject, javaResolverTrace);
084            return createLazyResolveSession(fileProject, files, javaResolverTrace, injector, true);
085        }
086    
087        @NotNull
088        public static ResolveSession createLazyResolveSession(
089                @NotNull Project project,
090                @NotNull Collection<JetFile> files,
091                @NotNull BindingTrace trace,
092                @NotNull InjectorForJavaDescriptorResolver injector,
093                final boolean addBuiltIns
094        ) {
095            final JavaClassFinderImpl classFinder = injector.getJavaClassFinder();
096    
097            // TODO: Replace with stub declaration provider
098            LockBasedLazyResolveStorageManager storageManager = new LockBasedLazyResolveStorageManager();
099            FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory(storageManager, files, new Predicate<FqName>() {
100                @Override
101                public boolean apply(FqName fqName) {
102                    return classFinder.findPackage(fqName) != null || KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME.equals(fqName);
103                }
104            });
105    
106            final JavaDescriptorResolver javaDescriptorResolver = injector.getJavaDescriptorResolver();
107    
108            ModuleConfiguration moduleConfiguration = new ModuleConfiguration() {
109                @Override
110                public void extendNamespaceScope(
111                        @NotNull NamespaceDescriptor namespaceDescriptor,
112                        @NotNull WritableScope namespaceMemberScope
113                ) {
114                    FqName fqName = DescriptorUtils.getFQName(namespaceDescriptor).toSafe();
115                    if (KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME.equals(fqName) && addBuiltIns) {
116                        namespaceMemberScope.importScope(KotlinBuiltIns.getInstance().getBuiltInsScope());
117                    }
118                    if (classFinder.findPackage(fqName) != null) {
119                        JetScope javaPackageScope = javaDescriptorResolver.getJavaPackageScope(namespaceDescriptor);
120                        assert javaPackageScope != null;
121                        namespaceMemberScope.importScope(javaPackageScope);
122                    }
123                }
124            };
125    
126            ModuleDescriptorImpl lazyModule = createJavaModule("<lazy module>");
127            lazyModule.setModuleConfiguration(moduleConfiguration);
128    
129            return new ResolveSession(project, storageManager, lazyModule, declarationProviderFactory, trace);
130        }
131    
132        public static AnalyzeExhaust analyzeOneFileWithJavaIntegrationAndCheckForErrors(
133                JetFile file, List<AnalyzerScriptParameter> scriptParameters) {
134            AnalyzingUtils.checkForSyntacticErrors(file);
135    
136            AnalyzeExhaust analyzeExhaust = analyzeOneFileWithJavaIntegration(file, scriptParameters);
137    
138            AnalyzingUtils.throwExceptionOnErrors(analyzeExhaust.getBindingContext());
139    
140            return analyzeExhaust;
141        }
142    
143        public static AnalyzeExhaust analyzeOneFileWithJavaIntegration(
144                JetFile file, List<AnalyzerScriptParameter> scriptParameters) {
145            return analyzeFilesWithJavaIntegration(file.getProject(), Collections.singleton(file), scriptParameters,
146                                                   Predicates.<PsiFile>alwaysTrue());
147        }
148    
149        public static AnalyzeExhaust analyzeFilesWithJavaIntegrationAndCheckForErrors(
150                Project project,
151                Collection<JetFile> files,
152                List<AnalyzerScriptParameter> scriptParameters,
153                Predicate<PsiFile> filesToAnalyzeCompletely
154        ) {
155            for (JetFile file : files) {
156                AnalyzingUtils.checkForSyntacticErrors(file);
157            }
158    
159            AnalyzeExhaust analyzeExhaust = analyzeFilesWithJavaIntegration(
160                    project, files, scriptParameters, filesToAnalyzeCompletely, false);
161    
162            AnalyzingUtils.throwExceptionOnErrors(analyzeExhaust.getBindingContext());
163    
164            return analyzeExhaust;
165        }
166    
167        public static AnalyzeExhaust analyzeFilesWithJavaIntegration(
168                Project project,
169                Collection<JetFile> files,
170                List<AnalyzerScriptParameter> scriptParameters,
171                Predicate<PsiFile> filesToAnalyzeCompletely
172        ) {
173            return analyzeFilesWithJavaIntegration(
174                    project, files, scriptParameters, filesToAnalyzeCompletely, false);
175        }
176    
177        public static AnalyzeExhaust analyzeFilesWithJavaIntegration(
178                Project project, Collection<JetFile> files, List<AnalyzerScriptParameter> scriptParameters, Predicate<PsiFile> filesToAnalyzeCompletely,
179                boolean storeContextForBodiesResolve) {
180            BindingTraceContext bindingTraceContext = new BindingTraceContext();
181    
182            return analyzeFilesWithJavaIntegration(project, files, bindingTraceContext, scriptParameters, filesToAnalyzeCompletely,
183                                                   storeContextForBodiesResolve);
184        }
185    
186        public static AnalyzeExhaust analyzeFilesWithJavaIntegration(
187                Project project,
188                Collection<JetFile> files,
189                BindingTrace trace,
190                List<AnalyzerScriptParameter> scriptParameters,
191                Predicate<PsiFile> filesToAnalyzeCompletely,
192                boolean storeContextForBodiesResolve
193        ) {
194            ModuleDescriptorImpl owner = createJavaModule("<module>");
195    
196            TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(
197                    filesToAnalyzeCompletely, false, false, scriptParameters);
198    
199            InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm(
200                    project, topDownAnalysisParameters,
201                    new ObservableBindingTrace(trace), owner);
202            owner.setModuleConfiguration(injector.getJavaBridgeConfiguration());
203            try {
204                injector.getTopDownAnalyzer().analyzeFiles(files, scriptParameters);
205                BodiesResolveContext bodiesResolveContext = storeContextForBodiesResolve ?
206                                                            new CachedBodiesResolveContext(injector.getTopDownAnalysisContext()) :
207                                                            null;
208                return AnalyzeExhaust.success(trace.getBindingContext(), bodiesResolveContext, owner);
209            } finally {
210                injector.destroy();
211            }
212        }
213    
214        @NotNull
215        public static ModuleDescriptorImpl createJavaModule(@NotNull String name) {
216            return new ModuleDescriptorImpl(Name.special(name), JavaBridgeConfiguration.ALL_JAVA_IMPORTS, JavaToKotlinClassMap.getInstance());
217        }
218    }