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