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 }