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;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
021    import org.jetbrains.kotlin.descriptors.ClassDescriptor;
022    import org.jetbrains.kotlin.descriptors.ClassKind;
023    import org.jetbrains.kotlin.load.java.JvmAbi;
024    import org.jetbrains.kotlin.resolve.DescriptorUtils;
025    import org.jetbrains.org.objectweb.asm.Type;
026    
027    public class FieldInfo {
028        @NotNull
029        public static FieldInfo createForSingleton(@NotNull ClassDescriptor classDescriptor, @NotNull JetTypeMapper typeMapper) {
030            ClassKind kind = classDescriptor.getKind();
031            if (!kind.isSingleton()) {
032                throw new UnsupportedOperationException("Can't create singleton field for class: " + classDescriptor);
033            }
034    
035            ClassDescriptor ownerDescriptor = kind == ClassKind.OBJECT
036                                              ? classDescriptor
037                                              : DescriptorUtils.getParentOfType(classDescriptor, ClassDescriptor.class);
038            assert ownerDescriptor != null : "Owner not found for class: " + classDescriptor;
039            Type ownerType = typeMapper.mapType(ownerDescriptor);
040    
041            String fieldName = kind == ClassKind.ENUM_ENTRY
042                               ? classDescriptor.getName().asString()
043                               : classDescriptor.getKind() == ClassKind.CLASS_OBJECT ? JvmAbi.CLASS_OBJECT_FIELD : JvmAbi.INSTANCE_FIELD;
044            return new FieldInfo(ownerType, typeMapper.mapType(classDescriptor), fieldName, true);
045        }
046    
047        @NotNull
048        public static FieldInfo createForHiddenField(@NotNull Type owner, @NotNull Type fieldType, @NotNull String fieldName) {
049            return new FieldInfo(owner, fieldType, fieldName, false);
050        }
051    
052        private final Type fieldType;
053        private final Type ownerType;
054        private final String fieldName;
055        private final boolean isStatic;
056    
057        private FieldInfo(@NotNull Type ownerType, @NotNull Type fieldType, @NotNull String fieldName, boolean isStatic) {
058            this.ownerType = ownerType;
059            this.fieldType = fieldType;
060            this.fieldName = fieldName;
061            this.isStatic = isStatic;
062        }
063    
064        @NotNull
065        public Type getFieldType() {
066            return fieldType;
067        }
068    
069        @NotNull
070        public Type getOwnerType() {
071            return ownerType;
072        }
073    
074        @NotNull
075        public String getOwnerInternalName() {
076            return ownerType.getInternalName();
077        }
078    
079        @NotNull
080        public String getFieldName() {
081            return fieldName;
082        }
083    
084        public boolean isStatic() {
085            return isStatic;
086        }
087    
088        @Override
089        public String toString() {
090            return String.format("%s %s.%s : %s", isStatic ? "GETSTATIC" : "GETFIELD", ownerType.getInternalName(), fieldName, fieldType);
091        }
092    }