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.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<KtClassOrObject> {
035 protected final KtClassOrObject myClass;
036 protected final OwnerKind kind;
037 protected final ClassDescriptor descriptor;
038
039 protected ClassBodyCodegen(
040 @NotNull KtClassOrObject 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.DEFAULT_IMPLS) {
055 //generate nested classes first and only then generate class body. It necessary to access to nested CodegenContexts
056 for (KtDeclaration declaration : myClass.getDeclarations()) {
057 if (shouldProcessFirst(declaration)) {
058 generateDeclaration(declaration);
059 }
060 }
061 }
062
063 for (KtDeclaration declaration : myClass.getDeclarations()) {
064 if (!shouldProcessFirst(declaration)) {
065 generateDeclaration(declaration);
066 }
067 }
068
069 if (!DescriptorUtils.isInterface(descriptor)) {
070 for (DeclarationDescriptor memberDescriptor : DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope())) {
071 if (memberDescriptor instanceof CallableMemberDescriptor) {
072 CallableMemberDescriptor member = (CallableMemberDescriptor) memberDescriptor;
073 if (!member.getKind().isReal() && ImplKt.findTraitImplementation(member) == null) {
074 if (member instanceof FunctionDescriptor) {
075 functionCodegen.generateBridges((FunctionDescriptor) member);
076 }
077 else if (member instanceof PropertyDescriptor) {
078 PropertyGetterDescriptor getter = ((PropertyDescriptor) member).getGetter();
079 if (getter != null) {
080 functionCodegen.generateBridges(getter);
081 }
082 PropertySetterDescriptor setter = ((PropertyDescriptor) member).getSetter();
083 if (setter != null) {
084 functionCodegen.generateBridges(setter);
085 }
086 }
087 }
088 }
089 }
090 }
091
092 generatePrimaryConstructorProperties();
093 }
094
095 private static boolean shouldProcessFirst(KtDeclaration declaration) {
096 return !(declaration instanceof KtProperty || declaration instanceof KtNamedFunction);
097 }
098
099 protected void generateDeclaration(KtDeclaration declaration) {
100 if (declaration instanceof KtProperty || declaration instanceof KtNamedFunction) {
101 genFunctionOrProperty(declaration);
102 }
103 else if (declaration instanceof KtClassOrObject) {
104 if (declaration instanceof KtEnumEntry && !enumEntryNeedSubclass(bindingContext, (KtEnumEntry) declaration)) {
105 return;
106 }
107
108 genClassOrObject((KtClassOrObject) declaration);
109 }
110 }
111
112 private void generatePrimaryConstructorProperties() {
113 boolean isAnnotation = descriptor.getKind() == ClassKind.ANNOTATION_CLASS;
114 for (KtParameter p : getPrimaryConstructorParameters()) {
115 if (p.hasValOrVar()) {
116 PropertyDescriptor propertyDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
117 if (propertyDescriptor != null) {
118 if (!isAnnotation) {
119 propertyCodegen.generatePrimaryConstructorProperty(p, propertyDescriptor);
120 }
121 else {
122 propertyCodegen.generateConstructorPropertyAsMethodForAnnotationClass(p, propertyDescriptor);
123 }
124 }
125 }
126 }
127 }
128
129 @NotNull
130 protected List<KtParameter> getPrimaryConstructorParameters() {
131 if (myClass instanceof KtClass) {
132 return ((KtClass) myClass).getPrimaryConstructorParameters();
133 }
134 return Collections.emptyList();
135 }
136
137 @Nullable
138 @Override
139 protected ClassDescriptor classForInnerClassRecord() {
140 return DescriptorUtils.isTopLevelDeclaration(descriptor) ? null : descriptor;
141 }
142 }