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.inline.InlineCodegenUtil;
025 import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
026 import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
027 import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor;
028 import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
029 import org.jetbrains.jet.lang.psi.JetClassOrObject;
030 import org.jetbrains.jet.lang.psi.JetFile;
031 import org.jetbrains.jet.lang.reflect.ReflectionTypes;
032 import org.jetbrains.jet.lang.resolve.BindingContext;
033 import org.jetbrains.jet.lang.resolve.BindingTrace;
034 import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
035 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
036
037 import java.util.List;
038
039 public class GenerationState {
040 public interface GenerateClassFilter {
041 boolean shouldProcess(JetClassOrObject classOrObject);
042
043 GenerateClassFilter ONLY_PACKAGE_CLASS = new GenerateClassFilter() {
044 @Override
045 public boolean shouldProcess(JetClassOrObject classOrObject) {
046 return false;
047 }
048 };
049
050 GenerateClassFilter GENERATE_ALL = new GenerateClassFilter() {
051 @Override
052 public boolean shouldProcess(JetClassOrObject classOrObject) {
053 return true;
054 }
055 };
056 }
057
058 private boolean used = false;
059
060 @NotNull
061 private final Progress progress;
062
063 @NotNull
064 private final List<JetFile> files;
065
066 @NotNull
067 private final ClassBuilderMode classBuilderMode;
068
069 @NotNull
070 private final BindingContext bindingContext;
071
072 @NotNull
073 private final ClassFileFactory classFileFactory;
074
075 @NotNull
076 private final Project project;
077
078 @NotNull
079 private final IntrinsicMethods intrinsics;
080
081 @NotNull
082 private final SamWrapperClasses samWrapperClasses = new SamWrapperClasses(this);
083
084 @NotNull
085 private final BindingTrace bindingTrace;
086
087 @NotNull
088 private final JetTypeMapper typeMapper;
089
090 private final boolean generateNotNullAssertions;
091
092 private final boolean generateNotNullParamAssertions;
093
094 private final GenerateClassFilter generateClassFilter;
095
096 private final boolean inlineEnabled;
097
098 @Nullable
099 private List<ScriptDescriptor> earlierScriptsForReplInterpreter;
100
101 private final JvmFunctionImplTypes functionImplTypes;
102
103 public GenerationState(
104 @NotNull Project project,
105 @NotNull ClassBuilderFactory builderFactory,
106 @NotNull BindingContext bindingContext,
107 @NotNull List<JetFile> files
108 ) {
109 this(project, builderFactory, Progress.DEAF, bindingContext, files, true, false, GenerateClassFilter.GENERATE_ALL,
110 InlineCodegenUtil.DEFAULT_INLINE_FLAG);
111 }
112
113 public GenerationState(
114 @NotNull Project project,
115 @NotNull ClassBuilderFactory builderFactory,
116 @NotNull Progress progress,
117 @NotNull BindingContext bindingContext,
118 @NotNull List<JetFile> files,
119 boolean generateNotNullAssertions,
120 boolean generateNotNullParamAssertions,
121 GenerateClassFilter generateClassFilter,
122 boolean inlineEnabled
123 ) {
124 this.project = project;
125 this.progress = progress;
126 this.files = files;
127 this.classBuilderMode = builderFactory.getClassBuilderMode();
128 this.inlineEnabled = inlineEnabled;
129
130 this.bindingTrace = new DelegatingBindingTrace(bindingContext, "trace in GenerationState");
131 this.bindingContext = bindingTrace.getBindingContext();
132
133 this.typeMapper = new JetTypeMapper(this.bindingContext, classBuilderMode);
134
135 this.intrinsics = new IntrinsicMethods();
136 this.classFileFactory = new ClassFileFactory(this, builderFactory);
137
138 this.generateNotNullAssertions = generateNotNullAssertions;
139 this.generateNotNullParamAssertions = generateNotNullParamAssertions;
140 this.generateClassFilter = generateClassFilter;
141
142 ReflectionTypes reflectionTypes = new ReflectionTypes(getAnyModule());
143 this.functionImplTypes = new JvmFunctionImplTypes(reflectionTypes);
144 }
145
146 @NotNull
147 private ModuleDescriptor getAnyModule() {
148 // TODO: this shouldn't be happening once we have modules in the compiler (there simply will be a ModuleDescriptor instance here)
149
150 if (files.isEmpty()) {
151 // This is a hackish workaround for this code not to fail when invoked for an empty file list. Technically it doesn't matter
152 // which module we return here: if we're not compiling anything, we should never reach a point where we need this module
153 return KotlinBuiltIns.getInstance().getBuiltInsModule();
154 }
155
156 PackageFragmentDescriptor descriptor = bindingContext.get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, files.get(0));
157 assert descriptor != null : "File is not under any module: " + files.get(0);
158 return descriptor.getContainingDeclaration();
159 }
160
161 @NotNull
162 public ClassFileFactory getFactory() {
163 return classFileFactory;
164 }
165
166 @NotNull
167 public Progress getProgress() {
168 return progress;
169 }
170
171 @NotNull
172 public BindingContext getBindingContext() {
173 return bindingContext;
174 }
175
176 @NotNull
177 public ClassBuilderMode getClassBuilderMode() {
178 return classBuilderMode;
179 }
180
181 @NotNull
182 public List<JetFile> getFiles() {
183 return files;
184 }
185
186 @NotNull
187 public BindingTrace getBindingTrace() {
188 return bindingTrace;
189 }
190
191 @NotNull
192 public JetTypeMapper getTypeMapper() {
193 return typeMapper;
194 }
195
196 @NotNull
197 public Project getProject() {
198 return project;
199 }
200
201 @NotNull
202 public IntrinsicMethods getIntrinsics() {
203 return intrinsics;
204 }
205
206 @NotNull
207 public SamWrapperClasses getSamWrapperClasses() {
208 return samWrapperClasses;
209 }
210
211 public boolean isGenerateNotNullAssertions() {
212 return generateNotNullAssertions;
213 }
214
215 public boolean isGenerateNotNullParamAssertions() {
216 return generateNotNullParamAssertions;
217 }
218
219 @NotNull
220 public GenerateClassFilter getGenerateDeclaredClassFilter() {
221 return generateClassFilter;
222 }
223
224 @NotNull
225 public JvmFunctionImplTypes getJvmFunctionImplTypes() {
226 return functionImplTypes;
227 }
228
229 public boolean isInlineEnabled() {
230 return inlineEnabled;
231 }
232
233 public void beforeCompile() {
234 markUsed();
235
236 CodegenBinding.initTrace(this);
237 }
238
239 private void markUsed() {
240 if (used) {
241 throw new IllegalStateException(GenerationState.class + " cannot be used more than once");
242 }
243 used = true;
244 }
245
246 public void destroy() {
247 }
248
249 @Nullable
250 public List<ScriptDescriptor> getEarlierScriptsForReplInterpreter() {
251 return earlierScriptsForReplInterpreter;
252 }
253
254 public void setEarlierScriptsForReplInterpreter(@Nullable List<ScriptDescriptor> earlierScriptsForReplInterpreter) {
255 this.earlierScriptsForReplInterpreter = earlierScriptsForReplInterpreter;
256 }
257 }