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 org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.kotlin.backend.common.bridges.BridgesPackage;
022    import org.jetbrains.kotlin.codegen.context.ClassContext;
023    import org.jetbrains.kotlin.codegen.state.GenerationState;
024    import org.jetbrains.kotlin.descriptors.ClassDescriptor;
025    import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
026    import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
027    import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
028    import org.jetbrains.kotlin.psi.*;
029    import org.jetbrains.kotlin.resolve.BindingContext;
030    import org.jetbrains.kotlin.resolve.DescriptorUtils;
031    
032    import java.util.Collections;
033    import java.util.List;
034    
035    import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
036    
037    public abstract class ClassBodyCodegen extends MemberCodegen<JetClassOrObject> {
038        protected final JetClassOrObject myClass;
039        protected final OwnerKind kind;
040        protected final ClassDescriptor descriptor;
041    
042        protected ClassBodyCodegen(
043                @NotNull JetClassOrObject myClass,
044                @NotNull ClassContext context,
045                @NotNull ClassBuilder v,
046                @NotNull GenerationState state,
047                @Nullable MemberCodegen<?> parentCodegen
048        ) {
049            super(state, parentCodegen, context, myClass, v);
050            this.myClass = myClass;
051            this.kind = context.getContextKind();
052            this.descriptor = bindingContext.get(BindingContext.CLASS, myClass);
053        }
054    
055        @Override
056        protected void generateBody() {
057            if (kind != OwnerKind.TRAIT_IMPL) {
058                //generate nested classes first and only then generate class body. It necessary to access to nested CodegenContexts
059                for (JetDeclaration declaration : myClass.getDeclarations()) {
060                    if (shouldProcessFirst(declaration)) {
061                        generateDeclaration(declaration);
062                    }
063                }
064            }
065    
066            for (JetDeclaration declaration : myClass.getDeclarations()) {
067                if (!shouldProcessFirst(declaration)) {
068                    generateDeclaration(declaration);
069                }
070            }
071    
072            if (!DescriptorUtils.isTrait(descriptor)) {
073                for (DeclarationDescriptor memberDescriptor : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
074                    if (memberDescriptor instanceof FunctionDescriptor) {
075                        FunctionDescriptor member = (FunctionDescriptor) memberDescriptor;
076                        if (!member.getKind().isReal() && BridgesPackage.findTraitImplementation(member) == null) {
077                            functionCodegen.generateBridges(member);
078                        }
079                    }
080                }
081            }
082    
083            generatePrimaryConstructorProperties(propertyCodegen, myClass);
084        }
085    
086        private static boolean shouldProcessFirst(JetDeclaration declaration) {
087            return !(declaration instanceof JetProperty || declaration instanceof JetNamedFunction);
088        }
089    
090    
091        protected void generateDeclaration(JetDeclaration declaration) {
092            if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) {
093                genFunctionOrProperty(declaration);
094            }
095            else if (declaration instanceof JetClassOrObject) {
096                if (declaration instanceof JetEnumEntry && !enumEntryNeedSubclass(bindingContext, (JetEnumEntry) declaration)) {
097                    return;
098                }
099    
100                genClassOrObject((JetClassOrObject) declaration);
101            }
102            else if (declaration instanceof JetClassObject) {
103                genClassOrObject(((JetClassObject) declaration).getObjectDeclaration());
104            }
105        }
106    
107        private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen, JetClassOrObject origin) {
108            boolean isAnnotation = origin instanceof JetClass && ((JetClass) origin).isAnnotation();
109            for (JetParameter p : getPrimaryConstructorParameters()) {
110                if (p.hasValOrVarNode()) {
111                    PropertyDescriptor propertyDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
112                    if (propertyDescriptor != null) {
113                        if (!isAnnotation) {
114                            propertyCodegen.generatePrimaryConstructorProperty(p, propertyDescriptor);
115                        }
116                        else {
117                            propertyCodegen.generateConstructorPropertyAsMethodForAnnotationClass(p, propertyDescriptor);
118                        }
119                    }
120                }
121            }
122        }
123    
124        @NotNull
125        protected List<JetParameter> getPrimaryConstructorParameters() {
126            if (myClass instanceof JetClass) {
127                return ((JetClass) myClass).getPrimaryConstructorParameters();
128            }
129            return Collections.emptyList();
130        }
131    
132        @Nullable
133        @Override
134        protected ClassDescriptor classForInnerClassRecord() {
135            return DescriptorUtils.isTopLevelDeclaration(descriptor) ? null : descriptor;
136        }
137    }