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 JvmRuntimeTypes runtimeTypes;
121    
122        @NotNull
123        private final ModuleDescriptor module;
124    
125        @NotNull
126        private final Collection<FqName> packagesWithObsoleteParts;
127    
128        @Nullable
129        private final String moduleId; // for PackageCodegen in incremental compilation mode
130    
131        @Nullable
132        private final File outDirectory; // TODO: temporary hack, see JetTypeMapperWithOutDirectory state for details
133    
134        public GenerationState(
135                @NotNull Project project,
136                @NotNull ClassBuilderFactory builderFactory,
137                @NotNull ModuleDescriptor module,
138                @NotNull BindingContext bindingContext,
139                @NotNull List<JetFile> files
140        ) {
141            this(project, builderFactory, Progress.DEAF, module, bindingContext, files, true, true, GenerateClassFilter.GENERATE_ALL,
142                 false, false, null, null, DiagnosticSink.DO_NOTHING, null);
143        }
144    
145        public GenerationState(
146                @NotNull Project project,
147                @NotNull ClassBuilderFactory builderFactory,
148                @NotNull Progress progress,
149                @NotNull ModuleDescriptor module,
150                @NotNull BindingContext bindingContext,
151                @NotNull List<JetFile> files,
152                boolean disableCallAssertions,
153                boolean disableParamAssertions,
154                GenerateClassFilter generateClassFilter,
155                boolean disableInline,
156                boolean disableOptimization,
157                @Nullable Collection<FqName> packagesWithObsoleteParts,
158                @Nullable String moduleId,
159                @NotNull DiagnosticSink diagnostics,
160                @Nullable File outDirectory
161        ) {
162            this.project = project;
163            this.progress = progress;
164            this.module = module;
165            this.files = files;
166            this.moduleId = moduleId;
167            this.packagesWithObsoleteParts = packagesWithObsoleteParts == null ? Collections.<FqName>emptySet() : packagesWithObsoleteParts;
168            this.classBuilderMode = builderFactory.getClassBuilderMode();
169            this.disableInline = disableInline;
170    
171            this.bindingTrace = new DelegatingBindingTrace(bindingContext, "trace in GenerationState");
172            this.bindingContext = bindingTrace.getBindingContext();
173    
174            this.outDirectory = outDirectory;
175            this.typeMapper = new JetTypeMapperWithOutDirectory(this.bindingContext, classBuilderMode, outDirectory);
176    
177            this.intrinsics = new IntrinsicMethods();
178    
179            if (!disableOptimization) {
180                builderFactory = new OptimizationClassBuilderFactory(builderFactory);
181            }
182    
183            this.classFileFactory = new ClassFileFactory(this, new BuilderFactoryForDuplicateSignatureDiagnostics(
184                    builderFactory, this.bindingContext, diagnostics));
185    
186            this.disableCallAssertions = disableCallAssertions;
187            this.disableParamAssertions = disableParamAssertions;
188            this.generateClassFilter = generateClassFilter;
189    
190            ReflectionTypes reflectionTypes = new ReflectionTypes(module);
191            this.runtimeTypes = new JvmRuntimeTypes(reflectionTypes);
192        }
193    
194        @NotNull
195        public ClassFileFactory getFactory() {
196            return classFileFactory;
197        }
198    
199        @NotNull
200        public Progress getProgress() {
201            return progress;
202        }
203    
204        @NotNull
205        public BindingContext getBindingContext() {
206            return bindingContext;
207        }
208    
209        @NotNull
210        public ClassBuilderMode getClassBuilderMode() {
211            return classBuilderMode;
212        }
213    
214        @NotNull
215        public List<JetFile> getFiles() {
216            return files;
217        }
218    
219        @NotNull
220        public BindingTrace getBindingTrace() {
221            return bindingTrace;
222        }
223    
224        @NotNull
225        public JetTypeMapper getTypeMapper() {
226            return typeMapper;
227        }
228    
229        @NotNull
230        public Project getProject() {
231            return project;
232        }
233    
234        @NotNull
235        public IntrinsicMethods getIntrinsics() {
236            return intrinsics;
237        }
238    
239        @NotNull
240        public SamWrapperClasses getSamWrapperClasses() {
241            return samWrapperClasses;
242        }
243    
244        @NotNull
245        public MappingsClassesForWhenByEnum getMappingsClassesForWhenByEnum() {
246            return mappingsClassesForWhenByEnum;
247        }
248    
249        public boolean isCallAssertionsEnabled() {
250            return !disableCallAssertions;
251        }
252    
253        public boolean isParamAssertionsEnabled() {
254            return !disableParamAssertions;
255        }
256    
257        @NotNull
258        public GenerateClassFilter getGenerateDeclaredClassFilter() {
259            return generateClassFilter;
260        }
261    
262        @NotNull
263        public JvmRuntimeTypes getJvmRuntimeTypes() {
264            return runtimeTypes;
265        }
266    
267        public boolean isInlineEnabled() {
268            return !disableInline;
269        }
270    
271        public void beforeCompile() {
272            markUsed();
273    
274            CodegenBinding.initTrace(this);
275        }
276    
277        private void markUsed() {
278            if (used) {
279                throw new IllegalStateException(GenerationState.class + " cannot be used more than once");
280            }
281            used = true;
282        }
283    
284        public void destroy() {
285        }
286    
287        @Nullable
288        public List<ScriptDescriptor> getEarlierScriptsForReplInterpreter() {
289            return earlierScriptsForReplInterpreter;
290        }
291    
292        public void setEarlierScriptsForReplInterpreter(@Nullable List<ScriptDescriptor> earlierScriptsForReplInterpreter) {
293            this.earlierScriptsForReplInterpreter = earlierScriptsForReplInterpreter;
294        }
295    
296        @NotNull
297        public ModuleDescriptor getModule() {
298            return module;
299        }
300    
301        @NotNull
302        public Collection<FqName> getPackagesWithObsoleteParts() {
303            return packagesWithObsoleteParts;
304        }
305    
306        @Nullable
307        public String getModuleId() {
308            return moduleId;
309        }
310    
311        @Nullable
312        public File getOutDirectory() {
313            return outDirectory;
314        }
315    }