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