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 : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) { 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 }