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