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;
7   
8   import edu.umd.cs.findbugs.annotations.NonNull;
9   import edu.umd.cs.findbugs.annotations.Nullable;
10  
11  import java.util.List;
12  
13  import mockit.asm.annotations.AnnotationVisitor;
14  import mockit.asm.constantPool.ConstantPoolGeneration;
15  import mockit.asm.jvmConstants.Access;
16  import mockit.asm.util.ByteVector;
17  
18  import org.checkerframework.checker.index.qual.NonNegative;
19  
20  public class BaseWriter {
21      /**
22       * The dynamically generated constant pool of the class being built/modified.
23       */
24      protected ConstantPoolGeneration cp;
25  
26      /**
27       * The access flags of this class, field, or method.
28       */
29      protected int classOrMemberAccess;
30  
31      @NonNegative
32      private int deprecatedAttributeIndex;
33      @NonNegative
34      private int syntheticAttributeIndex;
35  
36      /**
37       * The runtime visible annotations of this class/field/method.
38       */
39      @Nullable
40      protected AnnotationVisitor annotations;
41  
42      protected BaseWriter() {
43      }
44  
45      protected BaseWriter(@NonNull ConstantPoolGeneration cp, int classOrMemberAccess) {
46          this.cp = cp;
47          this.classOrMemberAccess = classOrMemberAccess;
48      }
49  
50      /**
51       * Returns the {@link #cp constant pool generation helper object} used by this writer.
52       *
53       * @return the constant pool generation
54       */
55      @NonNull
56      public final ConstantPoolGeneration getConstantPoolGeneration() {
57          return cp;
58      }
59  
60      /**
61       * Visits an annotation of the class/field/method being visited.
62       *
63       * @param desc
64       *            the descriptor of the annotation type
65       *
66       * @return a visitor to visit the annotation values, or <code>null</code> if this visitor is not interested in
67       *         visiting the annotation
68       */
69      @Nullable
70      public AnnotationVisitor visitAnnotation(@NonNull String desc) {
71          return addAnnotation(desc);
72      }
73  
74      @NonNull
75      private AnnotationVisitor addAnnotation(@NonNull String desc) {
76          AnnotationVisitor aw = new AnnotationVisitor(cp, desc);
77          aw.setNext(annotations);
78          annotations = aw;
79          return aw;
80      }
81  
82      /**
83       * Visits the end of the class/field/method being visited. This method, which is the last one to be called, is used
84       * to inform the visitor that all the annotations and attributes of the class/field/method have been visited.
85       */
86      public void visitEnd() {
87      }
88  
89      protected final void createMarkerAttributes(int classVersion) {
90          if (Access.isDeprecated(classOrMemberAccess)) {
91              deprecatedAttributeIndex = cp.newUTF8("Deprecated");
92          }
93  
94          if (Access.isSynthetic(classOrMemberAccess, classVersion)) {
95              syntheticAttributeIndex = cp.newUTF8("Synthetic");
96          }
97      }
98  
99      @NonNegative
100     protected final int getAnnotationsSize() {
101         if (annotations != null) {
102             getConstantPoolItemForRuntimeVisibleAnnotationsAttribute();
103             return 8 + annotations.getSize();
104         }
105 
106         return 0;
107     }
108 
109     @NonNegative
110     private int getConstantPoolItemForRuntimeVisibleAnnotationsAttribute() {
111         return cp.newUTF8("RuntimeVisibleAnnotations");
112     }
113 
114     @NonNegative
115     protected final int getMarkerAttributeCount() {
116         return (deprecatedAttributeIndex == 0 ? 0 : 1) + (syntheticAttributeIndex == 0 ? 0 : 1);
117     }
118 
119     @NonNegative
120     protected final int getMarkerAttributesSize() {
121         int attributeCount = getMarkerAttributeCount();
122         return 6 * attributeCount;
123     }
124 
125     protected final void putAccess(@NonNull ByteVector out, int baseMask) {
126         int accessFlag = Access.computeFlag(classOrMemberAccess, baseMask);
127         out.putShort(accessFlag);
128     }
129 
130     protected final void putMarkerAttributes(@NonNull ByteVector out) {
131         if (deprecatedAttributeIndex > 0) {
132             out.putShort(deprecatedAttributeIndex).putInt(0);
133         }
134 
135         if (syntheticAttributeIndex > 0) {
136             out.putShort(syntheticAttributeIndex).putInt(0);
137         }
138     }
139 
140     protected final void putAnnotations(@NonNull ByteVector out) {
141         if (annotations != null) {
142             int item = getConstantPoolItemForRuntimeVisibleAnnotationsAttribute();
143             out.putShort(item);
144             annotations.put(out);
145         }
146     }
147 
148     protected void put(@NonNull ByteVector out) {
149     }
150 
151     protected static void put(@NonNull ByteVector out, @NonNull List<? extends BaseWriter> writers) {
152         out.putShort(writers.size());
153 
154         for (BaseWriter writer : writers) {
155             writer.put(out);
156         }
157     }
158 }