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