ClassBodyCodegen.java 6.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * Copyright 2010-2012 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

17 18
package org.jetbrains.jet.codegen;

19
import com.intellij.openapi.progress.ProcessCanceledException;
20 21 22
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.*;
23
import org.jetbrains.jet.lang.resolve.BindingContext;
24
import org.objectweb.asm.MethodVisitor;
25
import org.objectweb.asm.Opcodes;
26
import org.objectweb.asm.Type;
27
import org.objectweb.asm.commons.InstructionAdapter;
28

29
import java.util.ArrayList;
30 31 32
import java.util.Collections;
import java.util.List;

A
Alex Tkachman 已提交
33 34 35
import static org.objectweb.asm.Opcodes.ACC_ABSTRACT;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;

36 37 38 39 40
/**
 * @author max
 * @author yole
 */
public abstract class ClassBodyCodegen {
41 42
    protected final GenerationState state;

43
    protected final JetClassOrObject myClass;
44 45
    protected final OwnerKind kind;
    protected final ClassDescriptor descriptor;
46
    protected final ClassBuilder v;
47
    protected final CodegenContext context;
48

49 50
    protected final List<CodeChunk> staticInitializerChunks = new ArrayList<CodeChunk>();

51
    public ClassBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState state) {
52
        this.state = state;
53
        descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
54
        myClass = aClass;
M
Maxim Shafirov 已提交
55 56
        this.context = context;
        this.kind = context.getContextKind();
57 58 59
        this.v = v;
    }

60
    public final void generate() {
61 62 63 64
        generateDeclaration();

        generateClassBody();

65
        generateSyntheticParts();
A
Alex Tkachman 已提交
66

67
        generateStaticInitializer();
68 69 70 71
    }

    protected abstract void generateDeclaration();

72
    protected void generateSyntheticParts() {
73 74 75
    }

    private void generateClassBody() {
M
Maxim Shafirov 已提交
76 77
        final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
        final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
78 79

        for (JetDeclaration declaration : myClass.getDeclarations()) {
80
            generateDeclaration(propertyCodegen, declaration, functionCodegen);
81 82
        }

83
        generatePrimaryConstructorProperties(propertyCodegen, myClass);
84 85
    }

86
    protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
S
Stepan Koltsov 已提交
87 88 89
        if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) {
            state.getInjector().getMemberCodegen().generateFunctionOrProperty(
                    (JetTypeParameterListOwner) declaration, context, v);
90
        }
A
Alex Tkachman 已提交
91 92
    }

A
Alex Tkachman 已提交
93 94
    private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen, JetClassOrObject origin) {
        boolean isAnnotation = origin instanceof JetClass && ((JetClass)origin).isAnnotation();
M
Maxim Shafirov 已提交
95
        OwnerKind kind = context.getContextKind();
96
        for (JetParameter p : getPrimaryConstructorParameters()) {
97
            if (p.getValOrVarNode() != null) {
98
                PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
99
                if (propertyDescriptor != null) {
A
Alex Tkachman 已提交
100 101 102 103
                    if(!isAnnotation) {
                        propertyCodegen.generateDefaultGetter(propertyDescriptor, ACC_PUBLIC, p);
                        if (propertyDescriptor.isVar()) {
                            propertyCodegen.generateDefaultSetter(propertyDescriptor, ACC_PUBLIC, origin);
104
                        }
A
Alex Tkachman 已提交
105 106 107 108 109 110 111 112 113 114

                        //noinspection ConstantConditions
                        if (!(kind instanceof OwnerKind.DelegateKind) && state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
                            int modifiers = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0);
                            if (!propertyDescriptor.isVar()) {
                                modifiers |= Opcodes.ACC_FINAL;
                            }
                            if(state.getInjector().getJetStandardLibrary().isVolatile(propertyDescriptor)) {
                                modifiers |= Opcodes.ACC_VOLATILE;
                            }
115 116
                            Type type = state.getInjector().getJetTypeMapper().mapType(propertyDescriptor.getType(), MapTypeMode.VALUE);
                            v.newField(p, modifiers, p.getName(), type.getDescriptor(), null, null);
117
                        }
A
Alex Tkachman 已提交
118 119
                    }
                    else {
120 121
                        Type type = state.getInjector().getJetTypeMapper().mapType(propertyDescriptor.getType(), MapTypeMode.VALUE);
                        v.newMethod(p, ACC_PUBLIC | ACC_ABSTRACT, p.getName(), "()" + type.getDescriptor(), null, null);
122 123 124 125 126 127
                    }
                }
            }
        }
    }

128 129 130 131 132 133
    protected List<JetParameter> getPrimaryConstructorParameters() {
        if (myClass instanceof JetClass) {
            return ((JetClass) myClass).getPrimaryConstructorParameters();
        }
        return Collections.emptyList();
    }
134 135 136

    private void generateStaticInitializer() {
        if (staticInitializerChunks.size() > 0) {
A
Alex Tkachman 已提交
137
            final MethodVisitor mv = v.newMethod(null, ACC_PUBLIC | Opcodes.ACC_STATIC,"<clinit>", "()V", null, null);
138
            if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
139
                mv.visitCode();
140

141
                InstructionAdapter v = new InstructionAdapter(mv);
142

143 144 145
                for (CodeChunk chunk : staticInitializerChunks) {
                    chunk.generate(v);
                }
146

147
                mv.visitInsn(Opcodes.RETURN);
A
Alex Tkachman 已提交
148
                FunctionCodegen.endVisit(v, "static initializer", myClass);
149
            }
150 151
        }
    }
152
}