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