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    }