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 }