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 }