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