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 }