001/*
002 * Copyright 2010-2013 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
017package org.jetbrains.jet.codegen;
018
019import org.jetbrains.annotations.NotNull;
020import org.jetbrains.annotations.Nullable;
021import org.jetbrains.jet.codegen.context.ClassContext;
022import org.jetbrains.jet.codegen.context.CodegenContext;
023import org.jetbrains.jet.codegen.context.FieldOwnerContext;
024import org.jetbrains.jet.codegen.state.GenerationState;
025import org.jetbrains.jet.codegen.state.GenerationStateAware;
026import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
027import org.jetbrains.jet.lang.psi.*;
028import org.jetbrains.jet.lang.resolve.BindingContext;
029import org.jetbrains.jet.lang.types.ErrorUtils;
030
031
032public class MemberCodegen extends GenerationStateAware {
033
034    @Nullable
035    private MemberCodegen parentCodegen;
036
037    public MemberCodegen(@NotNull GenerationState state, @Nullable MemberCodegen parentCodegen) {
038        super(state);
039        this.parentCodegen = parentCodegen;
040    }
041
042    @Nullable
043    public MemberCodegen getParentCodegen() {
044        return parentCodegen;
045    }
046
047    public void genFunctionOrProperty(
048            @NotNull FieldOwnerContext context,
049            @NotNull JetTypeParameterListOwner functionOrProperty,
050            @NotNull ClassBuilder classBuilder
051    ) {
052        FunctionCodegen functionCodegen = new FunctionCodegen(context, classBuilder, state);
053        if (functionOrProperty instanceof JetNamedFunction) {
054            try {
055                functionCodegen.gen((JetNamedFunction) functionOrProperty);
056            }
057            catch (CompilationException e) {
058                throw e;
059            }
060            catch (Exception e) {
061                throw new CompilationException("Failed to generate function " + functionOrProperty.getName(), e, functionOrProperty);
062            }
063        }
064        else if (functionOrProperty instanceof JetProperty) {
065            try {
066                new PropertyCodegen(context, classBuilder, functionCodegen, this).gen((JetProperty) functionOrProperty);
067            }
068            catch (CompilationException e) {
069                throw e;
070            }
071            catch (Exception e) {
072                throw new CompilationException("Failed to generate property " + functionOrProperty.getName(), e, functionOrProperty);
073            }
074        }
075        else {
076            throw new IllegalArgumentException("Unknown parameter: " + functionOrProperty);
077        }
078    }
079
080    public void genClassOrObject(CodegenContext parentContext, JetClassOrObject aClass) {
081        ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
082
083        if (descriptor == null || ErrorUtils.isError(descriptor) || descriptor.getName().equals(JetPsiUtil.NO_NAME_PROVIDED)) {
084            if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) {
085                throw new IllegalStateException(
086                        "Generating bad descriptor in ClassBuilderMode = " + state.getClassBuilderMode() + ": " + descriptor);
087            }
088            return;
089        }
090
091        ClassBuilder classBuilder = state.getFactory().forClassImplementation(descriptor, aClass.getContainingFile());
092        ClassContext classContext = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
093        new ImplementationBodyCodegen(aClass, classContext, classBuilder, state, this).generate();
094        classBuilder.done();
095
096        if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) {
097            ClassBuilder traitBuilder = state.getFactory().forTraitImplementation(descriptor, state, aClass.getContainingFile());
098            new TraitImplBodyCodegen(aClass, parentContext.intoClass(descriptor, OwnerKind.TRAIT_IMPL, state), traitBuilder, state)
099                    .generate();
100            traitBuilder.done();
101        }
102    }
103}