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.ImplKt;
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.ArrayList;
030    import java.util.Collections;
031    import java.util.List;
032    
033    import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
034    
035    public abstract class ClassBodyCodegen extends MemberCodegen<KtClassOrObject> {
036        protected final KtClassOrObject myClass;
037        protected final OwnerKind kind;
038        protected final ClassDescriptor descriptor;
039    
040        protected ClassBodyCodegen(
041                @NotNull KtClassOrObject myClass,
042                @NotNull ClassContext context,
043                @NotNull ClassBuilder v,
044                @NotNull GenerationState state,
045                @Nullable MemberCodegen<?> parentCodegen
046        ) {
047            super(state, parentCodegen, context, myClass, v);
048            this.myClass = myClass;
049            this.kind = context.getContextKind();
050            this.descriptor = bindingContext.get(BindingContext.CLASS, myClass);
051        }
052    
053        @Override
054        protected void generateBody() {
055            List<KtObjectDeclaration> companions = new ArrayList<KtObjectDeclaration>();
056            if (kind != OwnerKind.DEFAULT_IMPLS) {
057                //generate nested classes first and only then generate class body. It necessary to access to nested CodegenContexts
058                for (KtDeclaration declaration : myClass.getDeclarations()) {
059                    if (shouldProcessFirst(declaration)) {
060                        //Generate companions after class body generation (need to record all synthetic accessors)
061                        if (declaration instanceof KtObjectDeclaration && ((KtObjectDeclaration) declaration).isCompanion()) {
062                            companions.add((KtObjectDeclaration) declaration);
063                            CodegenUtilKt.populateCompanionBackingFieldNamesToOuterContextIfNeeded((KtObjectDeclaration) declaration, context, state);
064                        }
065                        else {
066                            generateDeclaration(declaration);
067                        }
068                    }
069                }
070            }
071    
072            for (KtDeclaration declaration : myClass.getDeclarations()) {
073                if (!shouldProcessFirst(declaration)) {
074                    generateDeclaration(declaration);
075                }
076            }
077    
078            generatePrimaryConstructorProperties();
079            generateConstructors();
080            generateDefaultImplsIfNeeded();
081    
082            for (KtObjectDeclaration companion : companions) {
083                generateDeclaration(companion);
084            }
085    
086            if (!DescriptorUtils.isInterface(descriptor)) {
087                for (DeclarationDescriptor memberDescriptor : DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope())) {
088                    if (memberDescriptor instanceof CallableMemberDescriptor) {
089                        CallableMemberDescriptor member = (CallableMemberDescriptor) memberDescriptor;
090                        if (!member.getKind().isReal() && ImplKt.findTraitImplementation(member) == null) {
091                            if (member instanceof FunctionDescriptor) {
092                                functionCodegen.generateBridges((FunctionDescriptor) member);
093                            }
094                            else if (member instanceof PropertyDescriptor) {
095                                PropertyGetterDescriptor getter = ((PropertyDescriptor) member).getGetter();
096                                if (getter != null) {
097                                    functionCodegen.generateBridges(getter);
098                                }
099                                PropertySetterDescriptor setter = ((PropertyDescriptor) member).getSetter();
100                                if (setter != null) {
101                                    functionCodegen.generateBridges(setter);
102                                }
103                            }
104                        }
105                    }
106                }
107            }
108        }
109    
110        protected void generateConstructors() {
111    
112        }
113    
114        protected void generateDefaultImplsIfNeeded() {
115    
116        }
117    
118        private static boolean shouldProcessFirst(KtDeclaration declaration) {
119            return !(declaration instanceof KtProperty || declaration instanceof KtNamedFunction);
120        }
121    
122        protected void generateDeclaration(KtDeclaration declaration) {
123            if (declaration instanceof KtProperty || declaration instanceof KtNamedFunction) {
124                genFunctionOrProperty(declaration);
125            }
126            else if (declaration instanceof KtClassOrObject) {
127                if (declaration instanceof KtEnumEntry && !enumEntryNeedSubclass(bindingContext, (KtEnumEntry) declaration)) {
128                    return;
129                }
130    
131                genClassOrObject((KtClassOrObject) declaration);
132            }
133        }
134    
135        private void generatePrimaryConstructorProperties() {
136            boolean isAnnotation = descriptor.getKind() == ClassKind.ANNOTATION_CLASS;
137            for (KtParameter p : getPrimaryConstructorParameters()) {
138                if (p.hasValOrVar()) {
139                    PropertyDescriptor propertyDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
140                    if (propertyDescriptor != null) {
141                        if (!isAnnotation) {
142                            propertyCodegen.generatePrimaryConstructorProperty(p, propertyDescriptor);
143                        }
144                        else {
145                            propertyCodegen.generateConstructorPropertyAsMethodForAnnotationClass(p, propertyDescriptor);
146                        }
147                    }
148                }
149            }
150        }
151    
152        @NotNull
153        protected List<KtParameter> getPrimaryConstructorParameters() {
154            if (myClass instanceof KtClass) {
155                return ((KtClass) myClass).getPrimaryConstructorParameters();
156            }
157            return Collections.emptyList();
158        }
159    
160        @Nullable
161        @Override
162        protected ClassDescriptor classForInnerClassRecord() {
163            return DescriptorUtils.isTopLevelDeclaration(descriptor) ? null : descriptor;
164        }
165    }