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 }