28using IKVM.ByteCode.Decoding;
34 sealed partial class ClassFile
37 internal sealed class Field : FieldOrMethod
41 string[] propertyGetterSetter;
50 internal Field(ClassFile classFile,
string[] utf8_cp,
IKVM.ByteCode.Decoding.Field field) :
51 base(classFile, utf8_cp, field.AccessFlags, field.
Name, field.Descriptor)
53 if ((IsPrivate && IsPublic) || (IsPrivate && IsProtected) || (IsPublic && IsProtected) || (IsFinal && IsVolatile) || (classFile.IsInterface && (!IsPublic || !IsStatic || !IsFinal || IsTransient)))
54 throw new ClassFormatError(
"{0} (Illegal field modifiers: 0x{1:X})", classFile.Name, accessFlags);
56 for (
int i = 0; i < field.Attributes.Count; i++)
58 var attribute = field.Attributes[i];
60 switch (classFile.GetConstantPoolUtf8String(utf8_cp, attribute.Name))
62 case AttributeName.Deprecated:
63 attribute.AsDeprecated();
64 flags |= FLAG_MASK_DEPRECATED;
66 case AttributeName.ConstantValue:
69 var _constantValue = (ConstantValueAttribute)attribute;
70 constantValue = Signature
switch
72 "I" => classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)_constantValue.Value),
73 "S" => (short)classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)_constantValue.Value),
74 "B" => (byte)classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)_constantValue.Value),
75 "C" => (char)classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)_constantValue.Value),
76 "Z" => classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)_constantValue.Value) != 0,
77 "J" => classFile.GetConstantPoolConstantLong((LongConstantHandle)_constantValue.Value),
78 "F" => classFile.GetConstantPoolConstantFloat((FloatConstantHandle)_constantValue.Value),
79 "D" => classFile.GetConstantPoolConstantDouble((DoubleConstantHandle)_constantValue.Value),
80 "Ljava.lang.String;" => classFile.GetConstantPoolConstantString((StringConstantHandle)_constantValue.Value),
81 _ =>
throw new ClassFormatError(
"{0} (Invalid signature for constant)", classFile.Name),
84 catch (InvalidCastException)
86 throw new ClassFormatError(
"{0} (Bad index into constant pool)", classFile.Name);
88 catch (IndexOutOfRangeException)
90 throw new ClassFormatError(
"{0} (Bad index into constant pool)", classFile.Name);
92 catch (InvalidOperationException)
94 throw new ClassFormatError(
"{0} (Bad index into constant pool)", classFile.Name);
96 catch (NullReferenceException)
98 throw new ClassFormatError(
"{0} (Bad index into constant pool)", classFile.Name);
100 catch (ByteCodeException)
102 throw new ClassFormatError(
"{0} (Bad index into constant pool)", classFile.Name);
105 case AttributeName.Signature:
106 if (classFile.MajorVersion < 49)
109 var _signature = (
IKVM.ByteCode.Decoding.SignatureAttribute)attribute;
110 signature = classFile.GetConstantPoolUtf8String(utf8_cp, _signature.Signature);
112 case AttributeName.RuntimeVisibleAnnotations:
113 if (classFile.MajorVersion < 49)
116 var _runtimeVisibleAnnotation = (RuntimeVisibleAnnotationsAttribute)attribute;
117 annotations = ReadAnnotations(_runtimeVisibleAnnotation.Annotations, classFile, utf8_cp);
119 case AttributeName.RuntimeInvisibleAnnotations:
120 if (classFile.MajorVersion < 49)
123 var _runtimeInvisibleAnnotations = (RuntimeInvisibleAnnotationsAttribute)attribute;
125 foreach (
object[] annot
in ReadAnnotations(_runtimeInvisibleAnnotations.Annotations, classFile, utf8_cp))
127 if (annot[1].Equals(
"Likvm/lang/Property;"))
128 DecodePropertyAnnotation(classFile, annot);
130 else if(annot[1].Equals(
"Likvm/lang/Internal;"))
133 flags |= FLAG_MASK_INTERNAL;
139 case AttributeName.RuntimeVisibleTypeAnnotations:
140 if (classFile.MajorVersion < 52)
143 var _runtimeVisibleTypeAnnotations = (
IKVM.ByteCode.Decoding.RuntimeVisibleTypeAnnotationsAttribute)attribute;
144 classFile.CreateUtf8ConstantPoolItems(utf8_cp);
145 runtimeVisibleTypeAnnotations = _runtimeVisibleTypeAnnotations.TypeAnnotations;
154 private void DecodePropertyAnnotation(ClassFile classFile,
object[] annot)
156 if (propertyGetterSetter !=
null)
158 classFile.diagnostics.GenericClassLoadingError($
"Ignoring duplicate ikvm.lang.Property annotation on {classFile.Name}.{this.Name}");
162 propertyGetterSetter =
new string[2];
163 for (
int i = 2; i < annot.Length - 1; i += 2)
165 string value = annot[i + 1] as string;
168 propertyGetterSetter =
null;
171 if (annot[i].Equals(
"get") && propertyGetterSetter[0] ==
null)
173 propertyGetterSetter[0] = value;
175 else if (annot[i].Equals(
"set") && propertyGetterSetter[1] ==
null)
177 propertyGetterSetter[1] = value;
181 propertyGetterSetter =
null;
186 if (propertyGetterSetter ==
null || propertyGetterSetter[0] ==
null)
188 propertyGetterSetter =
null;
189 classFile.diagnostics.GenericClassLoadingError($
"Ignoring malformed ikvm.lang.Property annotation on {classFile.Name}.{Name}");
194 protected override void ValidateSig(ClassFile classFile,
string descriptor)
197 throw new ClassFormatError(
"{0} (Field \"{1}\" has invalid signature \"{2}\")", classFile.Name,
this.Name, descriptor);
200 internal object ConstantValue => constantValue;
202 internal void PatchConstantValue(
object value) => constantValue = value;
204 internal bool IsStaticFinalConstant => (accessFlags & (Modifiers.Final |
Modifiers.Static)) == (
Modifiers.Final |
Modifiers.Static) && constantValue !=
null;
206 internal bool IsProperty => propertyGetterSetter !=
null;
208 internal string PropertyGetter => propertyGetterSetter[0];
210 internal string PropertySetter => propertyGetterSetter[1];
global::java.lang.invoke.LambdaForm.Name Name
static bool IsValidFieldDescriptor(string descriptor)
Returns true if the specified descriptor is a valid field descriptor.