View Javadoc
1   /*
2    * MIT License
3    * Copyright (c) 2006-2025 JMockit developers
4    * See LICENSE file for full license text.
5    */
6   package mockit.asm.fields;
7   
8   import edu.umd.cs.findbugs.annotations.NonNull;
9   import edu.umd.cs.findbugs.annotations.Nullable;
10  
11  import mockit.asm.BaseWriter;
12  import mockit.asm.SignatureWriter;
13  import mockit.asm.classes.ClassWriter;
14  import mockit.asm.jvmConstants.Opcodes;
15  import mockit.asm.types.JavaType;
16  import mockit.asm.util.ByteVector;
17  
18  import org.checkerframework.checker.index.qual.NonNegative;
19  
20  /**
21   * A visitor to visit a Java field, in the following order: ({@link #visitAnnotation})* {@link #visitEnd}.
22   */
23  public final class FieldVisitor extends BaseWriter {
24      /**
25       * The index of the constant pool item that contains the name of this field.
26       */
27      @NonNegative
28      private final int nameItemIndex;
29  
30      /**
31       * The index of the constant pool item that contains the descriptor of this field.
32       */
33      @NonNegative
34      private final int descItemIndex;
35  
36      @Nullable
37      private final SignatureWriter signatureWriter;
38  
39      /**
40       * The index of the constant pool item that contains the constant value of this field.
41       */
42      @NonNegative
43      private final int valueItemIndex;
44  
45      /**
46       * Initializes a new field visitor.
47       *
48       * @param cw
49       *            the class writer to which this field must be added
50       * @param access
51       *            the field's access flags (see {@link Opcodes})
52       * @param name
53       *            the field's name
54       * @param desc
55       *            the field's descriptor (see {@link JavaType})
56       * @param signature
57       *            the field's signature
58       * @param value
59       *            the field's constant value
60       */
61      public FieldVisitor(@NonNull ClassWriter cw, int access, @NonNull String name, @NonNull String desc,
62              @Nullable String signature, @Nullable Object value) {
63          super(cw.getConstantPoolGeneration(), access);
64  
65          nameItemIndex = cp.newUTF8(name);
66          descItemIndex = cp.newUTF8(desc);
67          signatureWriter = signature == null ? null : new SignatureWriter(cp, signature);
68          valueItemIndex = value == null ? 0 : cp.newConstItem(value).index;
69  
70          createMarkerAttributes(cw.getClassVersion());
71      }
72  
73      /**
74       * Returns the size of this field.
75       */
76      @NonNegative
77      public int getSize() {
78          int size = 8 + getMarkerAttributesSize() + getAnnotationsSize();
79  
80          if (valueItemIndex != 0) {
81              cp.newUTF8("ConstantValue");
82              size += 8;
83          }
84  
85          if (signatureWriter != null) {
86              size += signatureWriter.getSize();
87          }
88  
89          return size;
90      }
91  
92      /**
93       * Puts the content of this field into the given byte vector.
94       */
95      @Override
96      protected void put(@NonNull ByteVector out) {
97          putAccess(out, 0);
98          out.putShort(nameItemIndex);
99          out.putShort(descItemIndex);
100 
101         int attributeCount = getAttributeCount();
102         out.putShort(attributeCount);
103 
104         if (valueItemIndex != 0) {
105             out.putShort(cp.newUTF8("ConstantValue"));
106             out.putInt(2).putShort(valueItemIndex);
107         }
108 
109         putMarkerAttributes(out);
110 
111         if (signatureWriter != null) {
112             signatureWriter.put(out);
113         }
114 
115         putAnnotations(out);
116     }
117 
118     @NonNegative
119     private int getAttributeCount() {
120         int attributeCount = getMarkerAttributeCount();
121 
122         if (valueItemIndex != 0) {
123             attributeCount++;
124         }
125 
126         if (signatureWriter != null) {
127             attributeCount++;
128         }
129 
130         if (annotations != null) {
131             attributeCount++;
132         }
133 
134         return attributeCount;
135     }
136 }