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