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