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    }