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