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