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 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(propertyCodegen, declaration);
062 }
063 }
064 }
065
066 for (JetDeclaration declaration : myClass.getDeclarations()) {
067 if (!shouldProcessFirst(declaration)) {
068 generateDeclaration(propertyCodegen, 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(PropertyCodegen propertyCodegen, 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(state.getBindingContext(), (JetEnumEntry) declaration)) {
097 return;
098 }
099
100 genClassOrObject((JetClassOrObject) declaration);
101 }
102 else if (declaration instanceof JetClassObject) {
103 genClassOrObject(((JetClassObject) declaration).getObjectDeclaration());
104 }
105 }
106
107 private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen, JetClassOrObject origin) {
108 boolean isAnnotation = origin instanceof JetClass && ((JetClass) origin).isAnnotation();
109 for (JetParameter p : getPrimaryConstructorParameters()) {
110 if (p.hasValOrVarNode()) {
111 PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
112 if (propertyDescriptor != null) {
113 if (!isAnnotation) {
114 propertyCodegen.generatePrimaryConstructorProperty(p, propertyDescriptor);
115 }
116 else {
117 propertyCodegen.generateConstructorPropertyAsMethodForAnnotationClass(p, propertyDescriptor);
118 }
119 }
120 }
121 }
122 }
123
124 @NotNull
125 protected List<JetParameter> getPrimaryConstructorParameters() {
126 if (myClass instanceof JetClass) {
127 return ((JetClass) myClass).getPrimaryConstructorParameters();
128 }
129 return Collections.emptyList();
130 }
131 }