001 /*
002 * Copyright 2010-2013 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;
018
019 import com.google.common.collect.Lists;
020 import com.intellij.util.ArrayUtil;
021 import org.jetbrains.annotations.NotNull;
022 import org.jetbrains.asm4.AnnotationVisitor;
023 import org.jetbrains.asm4.MethodVisitor;
024 import org.jetbrains.asm4.Type;
025 import org.jetbrains.jet.codegen.context.FieldOwnerContext;
026 import org.jetbrains.jet.codegen.state.GenerationState;
027 import org.jetbrains.jet.lang.descriptors.*;
028 import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
029 import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
030 import org.jetbrains.jet.lang.psi.*;
031 import org.jetbrains.jet.lang.resolve.BindingContext;
032 import org.jetbrains.jet.lang.resolve.java.JvmAbi;
033 import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
034 import org.jetbrains.jet.lang.resolve.name.Name;
035
036 import java.util.Collections;
037 import java.util.List;
038
039 import static org.jetbrains.asm4.Opcodes.*;
040 import static org.jetbrains.jet.codegen.AsmUtil.asmTypeByFqNameWithoutInnerClasses;
041 import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KOTLIN_SYNTHETIC_CLASS;
042
043 public class PackagePartCodegen extends MemberCodegen {
044
045 private final ClassBuilder v;
046
047 private final PackageFragmentDescriptor descriptor;
048
049 private final JetFile jetFile;
050
051 private final Type packagePartName;
052
053 private final FieldOwnerContext context;
054
055 public PackagePartCodegen(
056 @NotNull ClassBuilder v,
057 @NotNull JetFile jetFile,
058 @NotNull Type packagePartName,
059 @NotNull FieldOwnerContext context,
060 @NotNull GenerationState state
061 ) {
062 super(state, null, context, v);
063 this.v = v;
064 this.jetFile = jetFile;
065 this.packagePartName = packagePartName;
066 this.context = context;
067 descriptor = state.getBindingContext().get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, jetFile);
068 assert descriptor != null : "No package fragment found for jetFile " + jetFile + " declared package: " + jetFile.getPackageName();
069 }
070
071 public void generate() {
072 v.defineClass(jetFile, V1_6,
073 ACC_PUBLIC | ACC_FINAL,
074 packagePartName.getInternalName(),
075 null,
076 "java/lang/Object",
077 ArrayUtil.EMPTY_STRING_ARRAY
078 );
079 v.visitSource(jetFile.getName(), null);
080
081 writeKotlinAnnotation();
082
083 for (JetDeclaration declaration : jetFile.getDeclarations()) {
084 if (declaration instanceof JetNamedFunction || declaration instanceof JetProperty) {
085 genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v);
086 }
087 }
088
089 generateStaticInitializers();
090
091 v.done();
092 }
093
094 private void writeKotlinAnnotation() {
095 Type type = asmTypeByFqNameWithoutInnerClasses(KOTLIN_SYNTHETIC_CLASS);
096 AnnotationVisitor av = v.newAnnotation(type.getDescriptor(), true);
097 av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION);
098 av.visitEnum("kind", "L" + type.getInternalName() + "$Kind;", "PACKAGE_PART");
099 av.visitEnd();
100 }
101
102
103 private void generateStaticInitializers() {
104 List<JetProperty> properties = collectPropertiesToInitialize();
105 if (properties.isEmpty()) return;
106
107 MethodVisitor mv = v.newMethod(jetFile, ACC_STATIC, "<clinit>", "()V", null, null);
108 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
109 mv.visitCode();
110
111 FrameMap frameMap = new FrameMap();
112
113 SimpleFunctionDescriptorImpl clInit =
114 new SimpleFunctionDescriptorImpl(this.descriptor, Annotations.EMPTY,
115 Name.special("<clinit>"),
116 CallableMemberDescriptor.Kind.SYNTHESIZED);
117 clInit.initialize(null, null, Collections.<TypeParameterDescriptor>emptyList(),
118 Collections.<ValueParameterDescriptor>emptyList(), null, null, Visibilities.PRIVATE);
119
120 ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, this.context.intoFunction(clInit), state, this);
121
122 for (JetDeclaration declaration : properties) {
123 ImplementationBodyCodegen.
124 initializeProperty(codegen, state.getBindingContext(), (JetProperty) declaration);
125 }
126
127 mv.visitInsn(RETURN);
128 FunctionCodegen.endVisit(mv, "static initializer for package", jetFile);
129 mv.visitEnd();
130 }
131 }
132
133 @NotNull
134 private List<JetProperty> collectPropertiesToInitialize() {
135 List<JetProperty> result = Lists.newArrayList();
136 for (JetDeclaration declaration : jetFile.getDeclarations()) {
137 if (declaration instanceof JetProperty &&
138 ImplementationBodyCodegen.shouldInitializeProperty((JetProperty) declaration, typeMapper)) {
139 result.add((JetProperty) declaration);
140 }
141 }
142 return result;
143 }
144 }