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.context;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.kotlin.codegen.OwnerKind;
022    import org.jetbrains.kotlin.codegen.StackValue;
023    import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
024    import org.jetbrains.kotlin.descriptors.ClassDescriptor;
025    
026    import static org.jetbrains.kotlin.codegen.AsmUtil.CAPTURED_THIS_FIELD;
027    import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLOSURE;
028    import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.canHaveOuter;
029    
030    public class ClassContext extends FieldOwnerContext<ClassDescriptor> {
031        private final JetTypeMapper typeMapper;
032    
033        public ClassContext(
034                @NotNull JetTypeMapper typeMapper,
035                @NotNull ClassDescriptor contextDescriptor,
036                @NotNull OwnerKind contextKind,
037                @Nullable CodegenContext parentContext,
038                @Nullable LocalLookup localLookup
039        ) {
040            super(contextDescriptor, contextKind, parentContext, typeMapper.getBindingContext().get(CLOSURE, contextDescriptor),
041                  contextDescriptor, localLookup);
042    
043            this.typeMapper = typeMapper;
044        }
045    
046        @Override
047        @Nullable
048        protected StackValue.Field computeOuterExpression() {
049            ClassDescriptor enclosingClass = getEnclosingClass();
050            if (enclosingClass == null) return null;
051    
052            if (!canHaveOuter(typeMapper.getBindingContext(), getContextDescriptor())) return null;
053    
054            return StackValue.field(
055                    typeMapper.mapType(enclosingClass),
056                    typeMapper.mapType(getContextDescriptor()),
057                    CAPTURED_THIS_FIELD,
058                    /* isStatic = */ false,
059                    StackValue.LOCAL_0
060            );
061        }
062    
063        @Nullable
064        public CodegenContext getCompanionObjectContext() {
065            if (getContextDescriptor().getCompanionObjectDescriptor() != null) {
066                return findChildContext(getContextDescriptor().getCompanionObjectDescriptor());
067            }
068            return null;
069        }
070    
071        @Override
072        public String toString() {
073            return "Class: " + getContextDescriptor();
074        }
075    }