001 /* 002 * Copyright 2010-2014 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.jet.codegen; 018 019 import org.jetbrains.annotations.NotNull; 020 import org.jetbrains.annotations.Nullable; 021 import org.jetbrains.jet.codegen.bridges.BridgesPackage; 022 import org.jetbrains.jet.codegen.context.ClassContext; 023 import org.jetbrains.jet.codegen.state.GenerationState; 024 import org.jetbrains.jet.lang.descriptors.ClassDescriptor; 025 import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; 026 import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; 027 import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; 028 import org.jetbrains.jet.lang.psi.*; 029 import org.jetbrains.jet.lang.resolve.BindingContext; 030 import org.jetbrains.jet.lang.resolve.DescriptorUtils; 031 032 import java.util.Collections; 033 import java.util.List; 034 035 import static org.jetbrains.jet.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 aClass, 044 @NotNull ClassContext context, 045 @NotNull ClassBuilder v, 046 @NotNull GenerationState state, 047 @Nullable MemberCodegen<?> parentCodegen 048 ) { 049 super(state, parentCodegen, context, aClass, v); 050 myClass = aClass; 051 kind = context.getContextKind(); 052 descriptor = bindingContext.get(BindingContext.CLASS, aClass); 053 } 054 055 @Override 056 protected void generateBody() { 057 FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state, this); 058 PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, this); 059 060 if (kind != OwnerKind.TRAIT_IMPL) { 061 //generate nested classes first and only then generate class body. It necessary to access to nested CodegenContexts 062 for (JetDeclaration declaration : myClass.getDeclarations()) { 063 if (shouldProcessFirst(declaration)) { 064 generateDeclaration(propertyCodegen, declaration); 065 } 066 } 067 } 068 069 for (JetDeclaration declaration : myClass.getDeclarations()) { 070 if (!shouldProcessFirst(declaration)) { 071 generateDeclaration(propertyCodegen, declaration); 072 } 073 } 074 075 if (state.getClassBuilderMode() == ClassBuilderMode.FULL && !DescriptorUtils.isTrait(descriptor)) { 076 for (DeclarationDescriptor memberDescriptor : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) { 077 if (memberDescriptor instanceof FunctionDescriptor) { 078 FunctionDescriptor member = (FunctionDescriptor) memberDescriptor; 079 if (!member.getKind().isReal() && BridgesPackage.findTraitImplementation(member) == null) { 080 functionCodegen.generateBridges(member); 081 } 082 } 083 } 084 } 085 086 generatePrimaryConstructorProperties(propertyCodegen, myClass); 087 } 088 089 private static boolean shouldProcessFirst(JetDeclaration declaration) { 090 return !(declaration instanceof JetProperty || declaration instanceof JetNamedFunction); 091 } 092 093 094 protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration) { 095 if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) { 096 genFunctionOrProperty((JetTypeParameterListOwner) declaration, v); 097 } 098 else if (declaration instanceof JetClassOrObject) { 099 if (declaration instanceof JetEnumEntry && !enumEntryNeedSubclass(state.getBindingContext(), (JetEnumEntry) declaration)) { 100 return; 101 } 102 103 genClassOrObject((JetClassOrObject) declaration); 104 } 105 else if (declaration instanceof JetClassObject) { 106 genClassOrObject(((JetClassObject) declaration).getObjectDeclaration()); 107 } 108 } 109 110 private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen, JetClassOrObject origin) { 111 boolean isAnnotation = origin instanceof JetClass && ((JetClass) origin).isAnnotation(); 112 for (JetParameter p : getPrimaryConstructorParameters()) { 113 if (p.getValOrVarNode() != null) { 114 PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p); 115 if (propertyDescriptor != null) { 116 if (!isAnnotation) { 117 propertyCodegen.generatePrimaryConstructorProperty(p, propertyDescriptor); 118 } 119 else { 120 propertyCodegen.generateConstructorPropertyAsMethodForAnnotationClass(p, propertyDescriptor); 121 } 122 } 123 } 124 } 125 } 126 127 @NotNull 128 protected List<JetParameter> getPrimaryConstructorParameters() { 129 if (myClass instanceof JetClass) { 130 return ((JetClass) myClass).getPrimaryConstructorParameters(); 131 } 132 return Collections.emptyList(); 133 } 134 }