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 }