001    /*
002     * Copyright 2010-2015 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.kotlin.codegen;
018    
019    import com.intellij.util.ArrayUtil;
020    import kotlin.jvm.functions.Function0;
021    import org.jetbrains.annotations.NotNull;
022    import org.jetbrains.kotlin.codegen.annotation.AnnotatedSimple;
023    import org.jetbrains.kotlin.codegen.context.FieldOwnerContext;
024    import org.jetbrains.kotlin.codegen.state.GenerationState;
025    import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
026    import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor;
027    import org.jetbrains.kotlin.descriptors.VariableDescriptor;
028    import org.jetbrains.kotlin.descriptors.annotations.Annotated;
029    import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
030    import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl;
031    import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
032    import org.jetbrains.kotlin.psi.*;
033    import org.jetbrains.kotlin.resolve.BindingContext;
034    import org.jetbrains.kotlin.serialization.DescriptorSerializer;
035    import org.jetbrains.kotlin.serialization.ProtoBuf;
036    import org.jetbrains.kotlin.serialization.jvm.BitEncoding;
037    import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
038    import org.jetbrains.org.objectweb.asm.Type;
039    
040    import java.util.ArrayList;
041    import java.util.List;
042    
043    import static org.jetbrains.kotlin.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses;
044    import static org.jetbrains.org.objectweb.asm.Opcodes.*;
045    
046    public class PackagePartCodegen extends MemberCodegen<JetFile> {
047        private final Type packagePartType;
048    
049        public PackagePartCodegen(
050                @NotNull ClassBuilder v,
051                @NotNull JetFile file,
052                @NotNull Type packagePartType,
053                @NotNull FieldOwnerContext context,
054                @NotNull GenerationState state
055        ) {
056            super(state, null, context, file, v);
057            this.packagePartType = packagePartType;
058        }
059    
060        @Override
061        protected void generateDeclaration() {
062            v.defineClass(element, V1_6,
063                          ACC_PUBLIC | ACC_FINAL,
064                          packagePartType.getInternalName(),
065                          null,
066                          "java/lang/Object",
067                          ArrayUtil.EMPTY_STRING_ARRAY
068            );
069            v.visitSource(element.getName(), null);
070    
071            generatePropertyMetadataArrayFieldIfNeeded(packagePartType);
072    
073            generateAnnotationsForPartClass();
074        }
075    
076        private void generateAnnotationsForPartClass() {
077            List<AnnotationDescriptor> fileAnnotationDescriptors = new ArrayList<AnnotationDescriptor>();
078            for (JetAnnotationEntry annotationEntry : element.getAnnotationEntries()) {
079                AnnotationDescriptor annotationDescriptor = state.getBindingContext().get(BindingContext.ANNOTATION, annotationEntry);
080                if (annotationDescriptor != null) {
081                    fileAnnotationDescriptors.add(annotationDescriptor);
082                }
083            }
084            Annotated annotatedFile = new AnnotatedSimple(new AnnotationsImpl(fileAnnotationDescriptors));
085            AnnotationCodegen.forClass(v.getVisitor(), state.getTypeMapper()).genAnnotations(annotatedFile, null);
086        }
087    
088        @Override
089        protected void generateBody() {
090            for (JetDeclaration declaration : element.getDeclarations()) {
091                if (declaration instanceof JetNamedFunction || declaration instanceof JetProperty) {
092                    genFunctionOrProperty(declaration);
093                }
094            }
095    
096            if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
097                generateInitializers(new Function0<ExpressionCodegen>() {
098                    @Override
099                    public ExpressionCodegen invoke() {
100                        return createOrGetClInitCodegen();
101                    }
102                });
103            }
104        }
105    
106        @Override
107        protected void generateKotlinAnnotation() {
108            if (state.getClassBuilderMode() != ClassBuilderMode.FULL) {
109                return;
110            }
111    
112            List<DeclarationDescriptor> members = new ArrayList<DeclarationDescriptor>();
113            for (JetDeclaration declaration : element.getDeclarations()) {
114                if (declaration instanceof JetNamedFunction) {
115                    SimpleFunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, declaration);
116                    members.add(functionDescriptor);
117                } else if (declaration instanceof JetProperty) {
118                    VariableDescriptor property = bindingContext.get(BindingContext.VARIABLE, declaration);
119                    members.add(property);
120                }
121            }
122    
123            JvmSerializationBindings bindings = v.getSerializationBindings();
124    
125            DescriptorSerializer serializer = DescriptorSerializer.createTopLevel(new JvmSerializerExtension(bindings, state.getTypeMapper()));
126            ProtoBuf.Package packageProto = serializer.packagePartProto(members).build();
127    
128            if (packageProto.getMemberCount() == 0) return;
129    
130            AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_FILE_FACADE), true);
131            JvmCodegenUtil.writeAbiVersion(av);
132            AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME);
133            for (String string : BitEncoding.encodeBytes(serializer.serialize(packageProto))) {
134                array.visit(null, string);
135            }
136            array.visitEnd();
137            av.visitEnd();
138        }
139    }