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