001    /*
002     * Copyright 2010-2013 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.jet.codegen;
018    
019    import com.google.common.collect.Lists;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.asm4.AnnotationVisitor;
022    import org.jetbrains.asm4.MethodVisitor;
023    import org.jetbrains.asm4.Type;
024    import org.jetbrains.jet.codegen.context.FieldOwnerContext;
025    import org.jetbrains.jet.codegen.state.GenerationState;
026    import org.jetbrains.jet.lang.descriptors.*;
027    import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
028    import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
029    import org.jetbrains.jet.lang.psi.*;
030    import org.jetbrains.jet.lang.resolve.BindingContext;
031    import org.jetbrains.jet.lang.resolve.java.JvmAbi;
032    import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
033    import org.jetbrains.jet.lang.resolve.name.Name;
034    
035    import java.util.Collections;
036    import java.util.List;
037    
038    import static org.jetbrains.asm4.Opcodes.*;
039    import static org.jetbrains.jet.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses;
040    
041    public class NamespacePartCodegen extends MemberCodegen {
042    
043        private final ClassBuilder v;
044    
045        private final NamespaceDescriptor descriptor;
046    
047        private final JetFile jetFile;
048    
049        private final Type namespacePartName;
050    
051        private final FieldOwnerContext context;
052    
053        public NamespacePartCodegen(
054                @NotNull ClassBuilder v,
055                @NotNull JetFile jetFile,
056                @NotNull Type namespacePartName,
057                @NotNull FieldOwnerContext context,
058                @NotNull GenerationState state
059        ) {
060            super(state, null);
061            this.v = v;
062            this.jetFile = jetFile;
063            this.namespacePartName = namespacePartName;
064            this.context = context;
065            descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, jetFile);
066            assert descriptor != null : "No namespace found for jetFile " + jetFile + " declared package: " + jetFile.getPackageName();
067        }
068    
069        public void generate() {
070            v.defineClass(jetFile, V1_6,
071                          ACC_PUBLIC | ACC_FINAL,
072                          namespacePartName.getInternalName(),
073                          null,
074                          //"jet/lang/Namespace",
075                          "java/lang/Object",
076                          new String[0]
077            );
078            v.visitSource(jetFile.getName(), null);
079    
080            writeKotlinPackageFragmentAnnotation();
081    
082            for (JetDeclaration declaration : jetFile.getDeclarations()) {
083                if (declaration instanceof JetNamedFunction || declaration instanceof JetProperty) {
084                    genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v);
085                }
086            }
087    
088            generateStaticInitializers();
089    
090            v.done();
091        }
092    
093        private void writeKotlinPackageFragmentAnnotation() {
094            AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_PACKAGE_FRAGMENT), true);
095            av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION);
096            av.visitEnd();
097        }
098    
099    
100        private void generateStaticInitializers() {
101            List<JetProperty> properties = collectPropertiesToInitialize();
102            if (properties.isEmpty()) return;
103    
104            MethodVisitor mv = v.newMethod(jetFile, ACC_STATIC, "<clinit>", "()V", null, null);
105            if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
106                mv.visitCode();
107    
108                FrameMap frameMap = new FrameMap();
109    
110                SimpleFunctionDescriptorImpl clInit =
111                        new SimpleFunctionDescriptorImpl(this.descriptor, Collections.<AnnotationDescriptor>emptyList(),
112                                                         Name.special("<clinit>"),
113                                                         CallableMemberDescriptor.Kind.SYNTHESIZED);
114                clInit.initialize(null, null, Collections.<TypeParameterDescriptor>emptyList(),
115                                  Collections.<ValueParameterDescriptor>emptyList(), null, null, Visibilities.PRIVATE, false);
116    
117                ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, this.context.intoFunction(clInit), state, this);
118    
119                for (JetDeclaration declaration : properties) {
120                    ImplementationBodyCodegen.
121                            initializeProperty(codegen, state.getBindingContext(), (JetProperty) declaration);
122                }
123    
124                mv.visitInsn(RETURN);
125                FunctionCodegen.endVisit(mv, "static initializer for namespace", jetFile);
126                mv.visitEnd();
127            }
128        }
129    
130        @NotNull
131        private List<JetProperty> collectPropertiesToInitialize() {
132            List<JetProperty> result = Lists.newArrayList();
133            for (JetDeclaration declaration : jetFile.getDeclarations()) {
134                if (declaration instanceof JetProperty &&
135                    ImplementationBodyCodegen.shouldInitializeProperty((JetProperty) declaration, typeMapper)) {
136                    result.add((JetProperty) declaration);
137                }
138            }
139            return result;
140        }
141    }