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.lazy.ResolveSession;
036    import org.jetbrains.jet.lang.resolve.lazy.declarations.FileBasedDeclarationProviderFactory;
037    import org.jetbrains.jet.lang.resolve.lazy.storage.LockBasedStorageManager;
038    import org.jetbrains.jet.lang.resolve.name.FqName;
039    import org.jetbrains.jet.lang.resolve.name.Name;
040    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
041    import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
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        private AnalyzerFacadeForJVM() {
053        }
054    
055        @Override
056        @NotNull
057        public AnalyzeExhaust analyzeFiles(@NotNull Project project,
058                @NotNull Collection<JetFile> files,
059                @NotNull List<AnalyzerScriptParameter> scriptParameters,
060                @NotNull Predicate<PsiFile> filesToAnalyzeCompletely) {
061            return analyzeFilesWithJavaIntegration(project, files, scriptParameters, filesToAnalyzeCompletely, true);
062        }
063    
064        @NotNull
065        @Override
066        public AnalyzeExhaust analyzeBodiesInFiles(@NotNull Project project,
067                                                   @NotNull List<AnalyzerScriptParameter> scriptParameters,
068                                                   @NotNull Predicate<PsiFile> filesForBodiesResolve,
069                                                   @NotNull BindingTrace headersTraceContext,
070                                                   @NotNull BodiesResolveContext bodiesResolveContext,
071                                                   @NotNull ModuleDescriptor module
072        ) {
073            return AnalyzerFacadeForEverything.analyzeBodiesInFilesWithJavaIntegration(
074                    project, scriptParameters, filesForBodiesResolve,
075                    headersTraceContext, bodiesResolveContext, module);
076        }
077    
078        @NotNull
079        @Override
080        public ResolveSession getLazyResolveSession(@NotNull Project fileProject, @NotNull Collection<JetFile> files) {
081            ModuleDescriptorImpl javaModule = createJavaModule("<java module>");
082    
083            BindingTraceContext javaResolverTrace = new BindingTraceContext();
084            InjectorForJavaDescriptorResolver injector = new InjectorForJavaDescriptorResolver(fileProject, javaResolverTrace, javaModule);
085    
086            final PsiClassFinder psiClassFinder = injector.getPsiClassFinder();
087    
088            // TODO: Replace with stub declaration provider
089            LockBasedStorageManager storageManager = new LockBasedStorageManager();
090            FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory(storageManager, files, new Predicate<FqName>() {
091                @Override
092                public boolean apply(FqName fqName) {
093                    return psiClassFinder.findPsiPackage(fqName) != null || new FqName("jet").equals(fqName);
094                }
095            });
096    
097            final JavaDescriptorResolver javaDescriptorResolver = injector.getJavaDescriptorResolver();
098    
099            ModuleConfiguration moduleConfiguration = new ModuleConfiguration() {
100    
101                @Override
102                public void extendNamespaceScope(
103                        @NotNull BindingTrace trace,
104                        @NotNull NamespaceDescriptor namespaceDescriptor,
105                        @NotNull WritableScope namespaceMemberScope
106                ) {
107                    FqName fqName = DescriptorUtils.getFQName(namespaceDescriptor).toSafe();
108                    if (new FqName("jet").equals(fqName)) {
109                        namespaceMemberScope.importScope(KotlinBuiltIns.getInstance().getBuiltInsScope());
110                    }
111                    if (psiClassFinder.findPsiPackage(fqName) != null) {
112                        JetScope javaPackageScope = javaDescriptorResolver.getJavaPackageScope(namespaceDescriptor);
113                        assert javaPackageScope != null;
114                        namespaceMemberScope.importScope(javaPackageScope);
115                    }
116                }
117            };
118            javaModule.setModuleConfiguration(moduleConfiguration);
119    
120            ModuleDescriptorImpl lazyModule = createJavaModule("<lazy module>");
121            lazyModule.setModuleConfiguration(moduleConfiguration);
122    
123            return new ResolveSession(fileProject, storageManager, lazyModule, declarationProviderFactory, javaResolverTrace);
124        }
125    
126        public static AnalyzeExhaust analyzeOneFileWithJavaIntegrationAndCheckForErrors(
127                JetFile file, List<AnalyzerScriptParameter> scriptParameters) {
128            AnalyzingUtils.checkForSyntacticErrors(file);
129    
130            AnalyzeExhaust analyzeExhaust = analyzeOneFileWithJavaIntegration(file, scriptParameters);
131    
132            AnalyzingUtils.throwExceptionOnErrors(analyzeExhaust.getBindingContext());
133    
134            return analyzeExhaust;
135        }
136    
137        public static AnalyzeExhaust analyzeOneFileWithJavaIntegration(
138                JetFile file, List<AnalyzerScriptParameter> scriptParameters) {
139            return analyzeFilesWithJavaIntegration(file.getProject(), Collections.singleton(file), scriptParameters,
140                                                   Predicates.<PsiFile>alwaysTrue());
141        }
142    
143        public static AnalyzeExhaust analyzeFilesWithJavaIntegrationAndCheckForErrors(
144                Project project,
145                Collection<JetFile> files,
146                List<AnalyzerScriptParameter> scriptParameters,
147                Predicate<PsiFile> filesToAnalyzeCompletely
148        ) {
149            for (JetFile file : files) {
150                AnalyzingUtils.checkForSyntacticErrors(file); 
151            }
152           
153            AnalyzeExhaust analyzeExhaust = analyzeFilesWithJavaIntegration(
154                    project, files, scriptParameters, filesToAnalyzeCompletely, false);
155    
156            AnalyzingUtils.throwExceptionOnErrors(analyzeExhaust.getBindingContext());
157    
158            return analyzeExhaust;
159        }
160    
161        public static AnalyzeExhaust analyzeFilesWithJavaIntegration(
162                Project project,
163                Collection<JetFile> files,
164                List<AnalyzerScriptParameter> scriptParameters,
165                Predicate<PsiFile> filesToAnalyzeCompletely
166        ) {
167            return analyzeFilesWithJavaIntegration(
168                    project, files, scriptParameters, filesToAnalyzeCompletely, false);
169        }
170    
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        public static AnalyzeExhaust analyzeFilesWithJavaIntegration(
181                Project project,
182                Collection<JetFile> files,
183                BindingTrace trace,
184                List<AnalyzerScriptParameter> scriptParameters,
185                Predicate<PsiFile> filesToAnalyzeCompletely,
186                boolean storeContextForBodiesResolve
187        ) {
188            ModuleDescriptorImpl owner = createJavaModule("<module>");
189    
190            TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(
191                    filesToAnalyzeCompletely, false, false, scriptParameters);
192    
193            InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm(
194                    project, topDownAnalysisParameters,
195                    new ObservableBindingTrace(trace), owner);
196            owner.setModuleConfiguration(injector.getJavaBridgeConfiguration());
197            try {
198                injector.getTopDownAnalyzer().analyzeFiles(files, scriptParameters);
199                BodiesResolveContext bodiesResolveContext = storeContextForBodiesResolve ?
200                                                            new CachedBodiesResolveContext(injector.getTopDownAnalysisContext()) :
201                                                            null;
202                return AnalyzeExhaust.success(trace.getBindingContext(), bodiesResolveContext, owner);
203            } finally {
204                injector.destroy();
205            }
206        }
207    
208        @NotNull
209        public static ModuleDescriptorImpl createJavaModule(@NotNull String name) {
210            return new ModuleDescriptorImpl(Name.special(name), JavaBridgeConfiguration.ALL_JAVA_IMPORTS, JavaToKotlinClassMap.getInstance());
211        }
212    }