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.LockBasedStorageManager;
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    
085            final PsiClassFinder psiClassFinder = injector.getPsiClassFinder();
086    
087            // TODO: Replace with stub declaration provider
088            LockBasedStorageManager storageManager = new LockBasedStorageManager();
089            FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory(storageManager, files, new Predicate<FqName>() {
090                @Override
091                public boolean apply(FqName fqName) {
092                    return psiClassFinder.findPsiPackage(fqName) != null || new FqName("jet").equals(fqName);
093                }
094            });
095    
096            final JavaDescriptorResolver javaDescriptorResolver = injector.getJavaDescriptorResolver();
097    
098            ModuleConfiguration moduleConfiguration = new ModuleConfiguration() {
099    
100                @Override
101                public void extendNamespaceScope(
102                        @NotNull BindingTrace trace,
103                        @NotNull NamespaceDescriptor namespaceDescriptor,
104                        @NotNull WritableScope namespaceMemberScope
105                ) {
106                    FqName fqName = DescriptorUtils.getFQName(namespaceDescriptor).toSafe();
107                    if (new FqName("jet").equals(fqName)) {
108                        namespaceMemberScope.importScope(KotlinBuiltIns.getInstance().getBuiltInsScope());
109                    }
110                    if (psiClassFinder.findPsiPackage(fqName) != null) {
111                        JetScope javaPackageScope = javaDescriptorResolver.getJavaPackageScope(namespaceDescriptor);
112                        assert javaPackageScope != null;
113                        namespaceMemberScope.importScope(javaPackageScope);
114                    }
115                }
116            };
117    
118            ModuleDescriptorImpl lazyModule = createJavaModule("<lazy module>");
119            lazyModule.setModuleConfiguration(moduleConfiguration);
120    
121            return new ResolveSession(fileProject, storageManager, lazyModule, declarationProviderFactory, javaResolverTrace);
122        }
123    
124        public static AnalyzeExhaust analyzeOneFileWithJavaIntegrationAndCheckForErrors(
125                JetFile file, List<AnalyzerScriptParameter> scriptParameters) {
126            AnalyzingUtils.checkForSyntacticErrors(file);
127    
128            AnalyzeExhaust analyzeExhaust = analyzeOneFileWithJavaIntegration(file, scriptParameters);
129    
130            AnalyzingUtils.throwExceptionOnErrors(analyzeExhaust.getBindingContext());
131    
132            return analyzeExhaust;
133        }
134    
135        public static AnalyzeExhaust analyzeOneFileWithJavaIntegration(
136                JetFile file, List<AnalyzerScriptParameter> scriptParameters) {
137            return analyzeFilesWithJavaIntegration(file.getProject(), Collections.singleton(file), scriptParameters,
138                                                   Predicates.<PsiFile>alwaysTrue());
139        }
140    
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        public static AnalyzeExhaust analyzeFilesWithJavaIntegration(
160                Project project,
161                Collection<JetFile> files,
162                List<AnalyzerScriptParameter> scriptParameters,
163                Predicate<PsiFile> filesToAnalyzeCompletely
164        ) {
165            return analyzeFilesWithJavaIntegration(
166                    project, files, scriptParameters, filesToAnalyzeCompletely, false);
167        }
168    
169        public static AnalyzeExhaust analyzeFilesWithJavaIntegration(
170                Project project, Collection<JetFile> files, List<AnalyzerScriptParameter> scriptParameters, Predicate<PsiFile> filesToAnalyzeCompletely,
171                boolean storeContextForBodiesResolve) {
172            BindingTraceContext bindingTraceContext = new BindingTraceContext();
173    
174            return analyzeFilesWithJavaIntegration(project, files, bindingTraceContext, scriptParameters, filesToAnalyzeCompletely,
175                                                   storeContextForBodiesResolve);
176        }
177    
178        public static AnalyzeExhaust analyzeFilesWithJavaIntegration(
179                Project project,
180                Collection<JetFile> files,
181                BindingTrace trace,
182                List<AnalyzerScriptParameter> scriptParameters,
183                Predicate<PsiFile> filesToAnalyzeCompletely,
184                boolean storeContextForBodiesResolve
185        ) {
186            ModuleDescriptorImpl owner = createJavaModule("<module>");
187    
188            TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(
189                    filesToAnalyzeCompletely, false, false, scriptParameters);
190    
191            InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm(
192                    project, topDownAnalysisParameters,
193                    new ObservableBindingTrace(trace), owner);
194            owner.setModuleConfiguration(injector.getJavaBridgeConfiguration());
195            try {
196                injector.getTopDownAnalyzer().analyzeFiles(files, scriptParameters);
197                BodiesResolveContext bodiesResolveContext = storeContextForBodiesResolve ?
198                                                            new CachedBodiesResolveContext(injector.getTopDownAnalysisContext()) :
199                                                            null;
200                return AnalyzeExhaust.success(trace.getBindingContext(), bodiesResolveContext, owner);
201            } finally {
202                injector.destroy();
203            }
204        }
205    
206        @NotNull
207        public static ModuleDescriptorImpl createJavaModule(@NotNull String name) {
208            return new ModuleDescriptorImpl(Name.special(name), JavaBridgeConfiguration.ALL_JAVA_IMPORTS, JavaToKotlinClassMap.getInstance());
209        }
210    }