001 /*
002 * Copyright 2010-2015 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.kotlin.codegen.state;
018
019 import com.intellij.openapi.project.Project;
020 import org.jetbrains.annotations.NotNull;
021 import org.jetbrains.annotations.Nullable;
022 import org.jetbrains.kotlin.builtins.ReflectionTypes;
023 import org.jetbrains.kotlin.codegen.*;
024 import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
025 import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension;
026 import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
027 import org.jetbrains.kotlin.codegen.optimization.OptimizationClassBuilderFactory;
028 import org.jetbrains.kotlin.codegen.when.MappingsClassesForWhenByEnum;
029 import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
030 import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
031 import org.jetbrains.kotlin.diagnostics.DiagnosticSink;
032 import org.jetbrains.kotlin.name.FqName;
033 import org.jetbrains.kotlin.psi.JetClassOrObject;
034 import org.jetbrains.kotlin.psi.JetFile;
035 import org.jetbrains.kotlin.psi.JetScript;
036 import org.jetbrains.kotlin.resolve.BindingContext;
037 import org.jetbrains.kotlin.resolve.BindingTrace;
038 import org.jetbrains.kotlin.resolve.DelegatingBindingTrace;
039
040 import java.io.File;
041 import java.util.Collection;
042 import java.util.Collections;
043 import java.util.List;
044
045 public class GenerationState {
046 public interface GenerateClassFilter {
047 boolean shouldAnnotateClass(JetClassOrObject classOrObject);
048 boolean shouldGenerateClass(JetClassOrObject classOrObject);
049 boolean shouldGeneratePackagePart(JetFile jetFile);
050 boolean shouldGenerateScript(JetScript script);
051
052 GenerateClassFilter GENERATE_ALL = new GenerateClassFilter() {
053 @Override
054 public boolean shouldAnnotateClass(JetClassOrObject classOrObject) {
055 return true;
056 }
057
058 @Override
059 public boolean shouldGenerateClass(JetClassOrObject classOrObject) {
060 return true;
061 }
062
063 @Override
064 public boolean shouldGenerateScript(JetScript script) {
065 return true;
066 }
067
068 @Override
069 public boolean shouldGeneratePackagePart(JetFile jetFile) {
070 return true;
071 }
072 };
073 }
074
075 private boolean used = false;
076
077 @NotNull
078 private final Progress progress;
079
080 @NotNull
081 private final List<JetFile> files;
082
083 @NotNull
084 private final ClassBuilderMode classBuilderMode;
085
086 @NotNull
087 private final BindingContext bindingContext;
088
089 @NotNull
090 private final ClassFileFactory classFileFactory;
091
092 @NotNull
093 private final Project project;
094
095 @NotNull
096 private final IntrinsicMethods intrinsics;
097
098 @NotNull
099 private final SamWrapperClasses samWrapperClasses = new SamWrapperClasses(this);
100
101 @NotNull
102 private final InlineCycleReporter inlineCycleReporter;
103
104 @NotNull
105 private final MappingsClassesForWhenByEnum mappingsClassesForWhenByEnum = new MappingsClassesForWhenByEnum(this);
106
107 @NotNull
108 private final BindingTrace bindingTrace;
109
110 @NotNull
111 private final JetTypeMapper typeMapper;
112
113 private final boolean disableCallAssertions;
114
115 private final boolean disableParamAssertions;
116
117 private final GenerateClassFilter generateClassFilter;
118
119 private final boolean disableInline;
120
121 @Nullable
122 private List<ScriptDescriptor> earlierScriptsForReplInterpreter;
123
124 private final ReflectionTypes reflectionTypes;
125
126 private final JvmRuntimeTypes runtimeTypes;
127
128 @NotNull
129 private final ModuleDescriptor module;
130
131 private final DiagnosticSink diagnostics;
132
133 @NotNull
134 private final Collection<FqName> packagesWithObsoleteParts;
135
136 @Nullable
137 private final String moduleId; // for PackageCodegen in incremental compilation mode
138
139 @Nullable
140 private final File outDirectory; // TODO: temporary hack, see JetTypeMapperWithOutDirectory state for details
141
142 @NotNull
143 private final ClassBuilderFactory interceptedBuilderFactory;
144
145 public GenerationState(
146 @NotNull Project project,
147 @NotNull ClassBuilderFactory builderFactory,
148 @NotNull ModuleDescriptor module,
149 @NotNull BindingContext bindingContext,
150 @NotNull List<JetFile> files
151 ) {
152 this(project, builderFactory, Progress.DEAF, module, bindingContext, files, true, true, GenerateClassFilter.GENERATE_ALL,
153 false, false, null, null, DiagnosticSink.DO_NOTHING, null);
154 }
155
156 public GenerationState(
157 @NotNull Project project,
158 @NotNull ClassBuilderFactory builderFactory,
159 @NotNull Progress progress,
160 @NotNull ModuleDescriptor module,
161 @NotNull BindingContext bindingContext,
162 @NotNull List<JetFile> files,
163 boolean disableCallAssertions,
164 boolean disableParamAssertions,
165 GenerateClassFilter generateClassFilter,
166 boolean disableInline,
167 boolean disableOptimization,
168 @Nullable Collection<FqName> packagesWithObsoleteParts,
169 @Nullable String moduleId,
170 @NotNull DiagnosticSink diagnostics,
171 @Nullable File outDirectory
172 ) {
173 this.project = project;
174 this.progress = progress;
175 this.module = module;
176 this.files = files;
177 this.moduleId = moduleId;
178 this.packagesWithObsoleteParts = packagesWithObsoleteParts == null ? Collections.<FqName>emptySet() : packagesWithObsoleteParts;
179 this.classBuilderMode = builderFactory.getClassBuilderMode();
180 this.disableInline = disableInline;
181
182 this.bindingTrace = new DelegatingBindingTrace(bindingContext, "trace in GenerationState");
183 this.bindingContext = bindingTrace.getBindingContext();
184
185 this.outDirectory = outDirectory;
186 this.typeMapper = new JetTypeMapperWithOutDirectory(this.bindingContext, classBuilderMode, outDirectory);
187
188 this.intrinsics = new IntrinsicMethods();
189
190 if (!disableOptimization) {
191 builderFactory = new OptimizationClassBuilderFactory(builderFactory);
192 }
193
194 ClassBuilderFactory interceptedBuilderFactory = new BuilderFactoryForDuplicateSignatureDiagnostics(
195 builderFactory, this.bindingContext, diagnostics);
196
197 Collection<ClassBuilderInterceptorExtension> interceptExtensions =
198 ClassBuilderInterceptorExtension.Companion.getInstances(project);
199
200 for (ClassBuilderInterceptorExtension extension : interceptExtensions) {
201 interceptedBuilderFactory = extension.interceptClassBuilderFactory(interceptedBuilderFactory, bindingContext, diagnostics);
202 }
203
204 this.interceptedBuilderFactory = interceptedBuilderFactory;
205
206 this.diagnostics = diagnostics;
207 this.classFileFactory = new ClassFileFactory(this, interceptedBuilderFactory);
208
209 this.disableCallAssertions = disableCallAssertions;
210 this.disableParamAssertions = disableParamAssertions;
211 this.generateClassFilter = generateClassFilter;
212
213 this.reflectionTypes = new ReflectionTypes(module);
214 this.runtimeTypes = new JvmRuntimeTypes();
215
216 this.inlineCycleReporter = new InlineCycleReporter(diagnostics);
217 }
218
219 @NotNull
220 public ClassFileFactory getFactory() {
221 return classFileFactory;
222 }
223
224 @NotNull
225 public Progress getProgress() {
226 return progress;
227 }
228
229 @NotNull
230 public BindingContext getBindingContext() {
231 return bindingContext;
232 }
233
234 @NotNull
235 public ClassBuilderMode getClassBuilderMode() {
236 return classBuilderMode;
237 }
238
239 @NotNull
240 public List<JetFile> getFiles() {
241 return files;
242 }
243
244 @NotNull
245 public BindingTrace getBindingTrace() {
246 return bindingTrace;
247 }
248
249 @NotNull
250 public JetTypeMapper getTypeMapper() {
251 return typeMapper;
252 }
253
254 @NotNull
255 public Project getProject() {
256 return project;
257 }
258
259 @NotNull
260 public IntrinsicMethods getIntrinsics() {
261 return intrinsics;
262 }
263
264 @NotNull
265 public SamWrapperClasses getSamWrapperClasses() {
266 return samWrapperClasses;
267 }
268
269 @NotNull
270 public InlineCycleReporter getInlineCycleReporter() {
271 return inlineCycleReporter;
272 }
273
274 @NotNull
275 public MappingsClassesForWhenByEnum getMappingsClassesForWhenByEnum() {
276 return mappingsClassesForWhenByEnum;
277 }
278
279 public boolean isCallAssertionsEnabled() {
280 return !disableCallAssertions;
281 }
282
283 public boolean isParamAssertionsEnabled() {
284 return !disableParamAssertions;
285 }
286
287 @NotNull
288 public GenerateClassFilter getGenerateDeclaredClassFilter() {
289 return generateClassFilter;
290 }
291
292 @NotNull
293 public ReflectionTypes getReflectionTypes() {
294 return reflectionTypes;
295 }
296
297 @NotNull
298 public JvmRuntimeTypes getJvmRuntimeTypes() {
299 return runtimeTypes;
300 }
301
302 @NotNull
303 public DiagnosticSink getDiagnostics() {
304 return diagnostics;
305 }
306
307 public boolean isInlineEnabled() {
308 return !disableInline;
309 }
310
311 public void beforeCompile() {
312 markUsed();
313
314 CodegenBinding.initTrace(this);
315 }
316
317 private void markUsed() {
318 if (used) {
319 throw new IllegalStateException(GenerationState.class + " cannot be used more than once");
320 }
321 used = true;
322 }
323
324 public void destroy() {
325 interceptedBuilderFactory.close();
326 }
327
328 @Nullable
329 public List<ScriptDescriptor> getEarlierScriptsForReplInterpreter() {
330 return earlierScriptsForReplInterpreter;
331 }
332
333 public void setEarlierScriptsForReplInterpreter(@Nullable List<ScriptDescriptor> earlierScriptsForReplInterpreter) {
334 this.earlierScriptsForReplInterpreter = earlierScriptsForReplInterpreter;
335 }
336
337 @NotNull
338 public ModuleDescriptor getModule() {
339 return module;
340 }
341
342 @NotNull
343 public Collection<FqName> getPackagesWithObsoleteParts() {
344 return packagesWithObsoleteParts;
345 }
346
347 @Nullable
348 public String getModuleId() {
349 return moduleId;
350 }
351
352 @Nullable
353 public File getOutDirectory() {
354 return outDirectory;
355 }
356 }