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.BridgesPackage;
022 import org.jetbrains.kotlin.codegen.context.ClassContext;
023 import org.jetbrains.kotlin.codegen.state.GenerationState;
024 import org.jetbrains.kotlin.descriptors.ClassDescriptor;
025 import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
026 import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
027 import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
028 import org.jetbrains.kotlin.psi.*;
029 import org.jetbrains.kotlin.resolve.BindingContext;
030 import org.jetbrains.kotlin.resolve.DescriptorUtils;
031
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<JetClassOrObject> {
038 protected final JetClassOrObject myClass;
039 protected final OwnerKind kind;
040 protected final ClassDescriptor descriptor;
041
042 protected ClassBodyCodegen(
043 @NotNull JetClassOrObject 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 = bindingContext.get(BindingContext.CLASS, myClass);
053 }
054
055 @Override
056 protected void generateBody() {
057 if (kind != OwnerKind.TRAIT_IMPL) {
058 //generate nested classes first and only then generate class body. It necessary to access to nested CodegenContexts
059 for (JetDeclaration declaration : myClass.getDeclarations()) {
060 if (shouldProcessFirst(declaration)) {
061 generateDeclaration(declaration);
062 }
063 }
064 }
065
066 for (JetDeclaration declaration : myClass.getDeclarations()) {
067 if (!shouldProcessFirst(declaration)) {
068 generateDeclaration(declaration);
069 }
070 }
071
072 if (!DescriptorUtils.isTrait(descriptor)) {
073 for (DeclarationDescriptor memberDescriptor : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
074 if (memberDescriptor instanceof FunctionDescriptor) {
075 FunctionDescriptor member = (FunctionDescriptor) memberDescriptor;
076 if (!member.getKind().isReal() && BridgesPackage.findTraitImplementation(member) == null) {
077 functionCodegen.generateBridges(member);
078 }
079 }
080 }
081 }
082
083 generatePrimaryConstructorProperties(propertyCodegen, myClass);
084 }
085
086 private static boolean shouldProcessFirst(JetDeclaration declaration) {
087 return !(declaration instanceof JetProperty || declaration instanceof JetNamedFunction);
088 }
089
090
091 protected void generateDeclaration(JetDeclaration declaration) {
092 if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) {
093 genFunctionOrProperty(declaration);
094 }
095 else if (declaration instanceof JetClassOrObject) {
096 if (declaration instanceof JetEnumEntry && !enumEntryNeedSubclass(bindingContext, (JetEnumEntry) declaration)) {
097 return;
098 }
099
100 genClassOrObject((JetClassOrObject) declaration);
101 }
102 }
103
104 private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen, JetClassOrObject origin) {
105 boolean isAnnotation = origin instanceof JetClass && ((JetClass) origin).isAnnotation();
106 for (JetParameter p : getPrimaryConstructorParameters()) {
107 if (p.hasValOrVarNode()) {
108 PropertyDescriptor propertyDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
109 if (propertyDescriptor != null) {
110 if (!isAnnotation) {
111 propertyCodegen.generatePrimaryConstructorProperty(p, propertyDescriptor);
112 }
113 else {
114 propertyCodegen.generateConstructorPropertyAsMethodForAnnotationClass(p, propertyDescriptor);
115 }
116 }
117 }
118 }
119 }
120
121 @NotNull
122 protected List<JetParameter> getPrimaryConstructorParameters() {
123 if (myClass instanceof JetClass) {
124 return ((JetClass) myClass).getPrimaryConstructorParameters();
125 }
126 return Collections.emptyList();
127 }
128
129 @Nullable
130 @Override
131 protected ClassDescriptor classForInnerClassRecord() {
132 return DescriptorUtils.isTopLevelDeclaration(descriptor) ? null : descriptor;
133 }
134 }