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