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.ArrayList; 030 import java.util.Collections; 031 import java.util.List; 032 033 import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.enumEntryNeedSubclass; 034 035 public abstract class ClassBodyCodegen extends MemberCodegen<KtClassOrObject> { 036 protected final KtClassOrObject myClass; 037 protected final OwnerKind kind; 038 protected final ClassDescriptor descriptor; 039 040 protected ClassBodyCodegen( 041 @NotNull KtClassOrObject myClass, 042 @NotNull ClassContext context, 043 @NotNull ClassBuilder v, 044 @NotNull GenerationState state, 045 @Nullable MemberCodegen<?> parentCodegen 046 ) { 047 super(state, parentCodegen, context, myClass, v); 048 this.myClass = myClass; 049 this.kind = context.getContextKind(); 050 this.descriptor = bindingContext.get(BindingContext.CLASS, myClass); 051 } 052 053 @Override 054 protected void generateBody() { 055 List<KtObjectDeclaration> companions = new ArrayList<KtObjectDeclaration>(); 056 if (kind != OwnerKind.DEFAULT_IMPLS) { 057 //generate nested classes first and only then generate class body. It necessary to access to nested CodegenContexts 058 for (KtDeclaration declaration : myClass.getDeclarations()) { 059 if (shouldProcessFirst(declaration)) { 060 //Generate companions after class body generation (need to record all synthetic accessors) 061 if (declaration instanceof KtObjectDeclaration && ((KtObjectDeclaration) declaration).isCompanion()) { 062 companions.add((KtObjectDeclaration) declaration); 063 CodegenUtilKt.populateCompanionBackingFieldNamesToOuterContextIfNeeded((KtObjectDeclaration) declaration, context, state); 064 } 065 else { 066 generateDeclaration(declaration); 067 } 068 } 069 } 070 } 071 072 for (KtDeclaration declaration : myClass.getDeclarations()) { 073 if (!shouldProcessFirst(declaration)) { 074 generateDeclaration(declaration); 075 } 076 } 077 078 generatePrimaryConstructorProperties(); 079 generateConstructors(); 080 generateDefaultImplsIfNeeded(); 081 082 for (KtObjectDeclaration companion : companions) { 083 generateDeclaration(companion); 084 } 085 086 if (!DescriptorUtils.isInterface(descriptor)) { 087 for (DeclarationDescriptor memberDescriptor : DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope())) { 088 if (memberDescriptor instanceof CallableMemberDescriptor) { 089 CallableMemberDescriptor member = (CallableMemberDescriptor) memberDescriptor; 090 if (!member.getKind().isReal() && ImplKt.findTraitImplementation(member) == null) { 091 if (member instanceof FunctionDescriptor) { 092 functionCodegen.generateBridges((FunctionDescriptor) member); 093 } 094 else if (member instanceof PropertyDescriptor) { 095 PropertyGetterDescriptor getter = ((PropertyDescriptor) member).getGetter(); 096 if (getter != null) { 097 functionCodegen.generateBridges(getter); 098 } 099 PropertySetterDescriptor setter = ((PropertyDescriptor) member).getSetter(); 100 if (setter != null) { 101 functionCodegen.generateBridges(setter); 102 } 103 } 104 } 105 } 106 } 107 } 108 } 109 110 protected void generateConstructors() { 111 112 } 113 114 protected void generateDefaultImplsIfNeeded() { 115 116 } 117 118 private static boolean shouldProcessFirst(KtDeclaration declaration) { 119 return !(declaration instanceof KtProperty || declaration instanceof KtNamedFunction); 120 } 121 122 protected void generateDeclaration(KtDeclaration declaration) { 123 if (declaration instanceof KtProperty || declaration instanceof KtNamedFunction) { 124 genFunctionOrProperty(declaration); 125 } 126 else if (declaration instanceof KtClassOrObject) { 127 if (declaration instanceof KtEnumEntry && !enumEntryNeedSubclass(bindingContext, (KtEnumEntry) declaration)) { 128 return; 129 } 130 131 genClassOrObject((KtClassOrObject) declaration); 132 } 133 } 134 135 private void generatePrimaryConstructorProperties() { 136 boolean isAnnotation = descriptor.getKind() == ClassKind.ANNOTATION_CLASS; 137 for (KtParameter p : getPrimaryConstructorParameters()) { 138 if (p.hasValOrVar()) { 139 PropertyDescriptor propertyDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p); 140 if (propertyDescriptor != null) { 141 if (!isAnnotation) { 142 propertyCodegen.generatePrimaryConstructorProperty(p, propertyDescriptor); 143 } 144 else { 145 propertyCodegen.generateConstructorPropertyAsMethodForAnnotationClass(p, propertyDescriptor); 146 } 147 } 148 } 149 } 150 } 151 152 @NotNull 153 protected List<KtParameter> getPrimaryConstructorParameters() { 154 if (myClass instanceof KtClass) { 155 return ((KtClass) myClass).getPrimaryConstructorParameters(); 156 } 157 return Collections.emptyList(); 158 } 159 160 @Nullable 161 @Override 162 protected ClassDescriptor classForInnerClassRecord() { 163 return DescriptorUtils.isTopLevelDeclaration(descriptor) ? null : descriptor; 164 } 165 }