1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/*
2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright (C) 2008 The Android Open Source Project
3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * you may not use this file except in compliance with the License.
6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * You may obtain a copy of the License at
7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Unless required by applicable law or agreed to in writing, software
11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * See the License for the specific language governing permissions and
14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * limitations under the License.
15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */
16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpackage com.android.dx.dex.file;
18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.annotation.Annotations;
20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.annotation.AnnotationsList;
21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.CstFieldRef;
22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.CstMethodRef;
23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.AnnotatedOutput;
24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.Hex;
25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.io.PrintWriter;
27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.ArrayList;
28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.Collections;
29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/**
31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Per-class directory of annotations.
32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */
33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic final class AnnotationsDirectoryItem extends OffsettedItem {
34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** the required alignment for instances of this class */
35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private static final int ALIGNMENT = 4;
36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** write size of this class's header, in bytes */
38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private static final int HEADER_SIZE = 16;
39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** write size of a list element, in bytes */
41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private static final int ELEMENT_SIZE = 8;
42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code null-ok;} the class-level annotations, if any */
44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private AnnotationSetItem classAnnotations;
45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code null-ok;} the annotated fields, if any */
47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private ArrayList<FieldAnnotationStruct> fieldAnnotations;
48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code null-ok;} the annotated methods, if any */
50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private ArrayList<MethodAnnotationStruct> methodAnnotations;
51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code null-ok;} the annotated parameters, if any */
53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private ArrayList<ParameterAnnotationStruct> parameterAnnotations;
54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Constructs an empty instance.
57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public AnnotationsDirectoryItem() {
59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        super(ALIGNMENT, -1);
60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        classAnnotations = null;
62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fieldAnnotations = null;
63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        methodAnnotations = null;
64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        parameterAnnotations = null;
65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public ItemType itemType() {
70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM;
71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Returns whether this item is empty (has no contents).
75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code true} if this item is empty, or {@code false}
77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * if not
78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean isEmpty() {
80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return (classAnnotations == null) &&
81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            (fieldAnnotations == null) &&
82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            (methodAnnotations == null) &&
83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            (parameterAnnotations == null);
84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Returns whether this item is a candidate for interning. The only
88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * interning candidates are ones that <i>only</i> have a non-null
89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * set of class annotations, with no other lists.
90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code true} if this is an interning candidate, or
92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code false} if not
93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean isInternable() {
95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return (classAnnotations != null) &&
96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            (fieldAnnotations == null) &&
97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            (methodAnnotations == null) &&
98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            (parameterAnnotations == null);
99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public int hashCode() {
104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (classAnnotations == null) {
105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return 0;
106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return classAnnotations.hashCode();
109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@inheritDoc}
113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * <p><b>Note:</b>: This throws an exception if this item is not
115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * internable.</p>
116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @see #isInternable
118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public int compareTo0(OffsettedItem other) {
121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (! isInternable()) {
122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new UnsupportedOperationException("uninternable instance");
123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        AnnotationsDirectoryItem otherDirectory =
126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            (AnnotationsDirectoryItem) other;
127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return classAnnotations.compareTo(otherDirectory.classAnnotations);
128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Sets the direct annotations on this instance. These are annotations
132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * made on the class, per se, as opposed to on one of its members.
133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * It is only valid to call this method at most once per instance.
134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param annotations {@code non-null;} annotations to set for this class
136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void setClassAnnotations(Annotations annotations) {
138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (annotations == null) {
139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new NullPointerException("annotations == null");
140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (classAnnotations != null) {
143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new UnsupportedOperationException(
144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    "class annotations already set");
145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        classAnnotations = new AnnotationSetItem(annotations);
148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Adds a field annotations item to this instance.
152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param field {@code non-null;} field in question
154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param annotations {@code non-null;} associated annotations to add
155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void addFieldAnnotations(CstFieldRef field,
157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            Annotations annotations) {
158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (fieldAnnotations == null) {
159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            fieldAnnotations = new ArrayList<FieldAnnotationStruct>();
160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fieldAnnotations.add(new FieldAnnotationStruct(field,
163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        new AnnotationSetItem(annotations)));
164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Adds a method annotations item to this instance.
168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param method {@code non-null;} method in question
170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param annotations {@code non-null;} associated annotations to add
171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void addMethodAnnotations(CstMethodRef method,
173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            Annotations annotations) {
174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (methodAnnotations == null) {
175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            methodAnnotations = new ArrayList<MethodAnnotationStruct>();
176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
178579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        methodAnnotations.add(new MethodAnnotationStruct(method,
179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        new AnnotationSetItem(annotations)));
180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
183579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Adds a parameter annotations item to this instance.
184579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
185579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param method {@code non-null;} method in question
186579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param list {@code non-null;} associated list of annotation sets to add
187579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
188579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void addParameterAnnotations(CstMethodRef method,
189579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            AnnotationsList list) {
190579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (parameterAnnotations == null) {
191579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            parameterAnnotations = new ArrayList<ParameterAnnotationStruct>();
192579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
193579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
194579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        parameterAnnotations.add(new ParameterAnnotationStruct(method, list));
195579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
196579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
197579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
198579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the method annotations for a given method, if any. This is
199579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * meant for use by debugging / dumping code.
200579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
201579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param method {@code non-null;} the method
202579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code null-ok;} the method annotations, if any
203579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
204579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public Annotations getMethodAnnotations(CstMethodRef method) {
205579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (methodAnnotations == null) {
206579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return null;
207579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
208579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
209579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        for (MethodAnnotationStruct item : methodAnnotations) {
210579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (item.getMethod().equals(method)) {
211579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return item.getAnnotations();
212579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
213579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
214579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
215579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return null;
216579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
217579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
218579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
219579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the parameter annotations for a given method, if any. This is
220579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * meant for use by debugging / dumping code.
221579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
222579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param method {@code non-null;} the method
223579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code null-ok;} the parameter annotations, if any
224579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
225579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public AnnotationsList getParameterAnnotations(CstMethodRef method) {
226579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (parameterAnnotations == null) {
227579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return null;
228579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
229579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
230579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        for (ParameterAnnotationStruct item : parameterAnnotations) {
231579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (item.getMethod().equals(method)) {
232579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return item.getAnnotationsList();
233579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
234579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
235579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
236579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return null;
237579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
238579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
239579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
240579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void addContents(DexFile file) {
241579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        MixedItemSection wordData = file.getWordData();
242579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
243579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (classAnnotations != null) {
244579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            classAnnotations = wordData.intern(classAnnotations);
245579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
246579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
247579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (fieldAnnotations != null) {
248579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            for (FieldAnnotationStruct item : fieldAnnotations) {
249579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                item.addContents(file);
250579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
251579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
252579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
253579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (methodAnnotations != null) {
254579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            for (MethodAnnotationStruct item : methodAnnotations) {
255579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                item.addContents(file);
256579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
257579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
258579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
259579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (parameterAnnotations != null) {
260579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            for (ParameterAnnotationStruct item : parameterAnnotations) {
261579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                item.addContents(file);
262579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
263579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
264579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
265579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
266579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
267579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
268579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public String toHuman() {
269579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        throw new RuntimeException("unsupported");
270579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
271579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
272579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
273579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
274579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    protected void place0(Section addedTo, int offset) {
275579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        // We just need to set the write size here.
276579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
277579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int elementCount = listSize(fieldAnnotations)
278579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            + listSize(methodAnnotations) + listSize(parameterAnnotations);
279579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        setWriteSize(HEADER_SIZE + (elementCount * ELEMENT_SIZE));
280579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
281579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
282579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
283579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
284579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    protected void writeTo0(DexFile file, AnnotatedOutput out) {
285579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        boolean annotates = out.annotates();
286579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int classOff = OffsettedItem.getAbsoluteOffsetOr0(classAnnotations);
287579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int fieldsSize = listSize(fieldAnnotations);
288579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int methodsSize = listSize(methodAnnotations);
289579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int parametersSize = listSize(parameterAnnotations);
290579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
291579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (annotates) {
292579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            out.annotate(0, offsetString() + " annotations directory");
293579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            out.annotate(4, "  class_annotations_off: " + Hex.u4(classOff));
294579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            out.annotate(4, "  fields_size:           " +
295579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    Hex.u4(fieldsSize));
296579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            out.annotate(4, "  methods_size:          " +
297579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    Hex.u4(methodsSize));
298579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            out.annotate(4, "  parameters_size:       " +
299579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    Hex.u4(parametersSize));
300579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
301579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
302579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        out.writeInt(classOff);
303579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        out.writeInt(fieldsSize);
304579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        out.writeInt(methodsSize);
305579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        out.writeInt(parametersSize);
306579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
307579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (fieldsSize != 0) {
308579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            Collections.sort(fieldAnnotations);
309579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (annotates) {
310579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                out.annotate(0, "  fields:");
311579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
312579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            for (FieldAnnotationStruct item : fieldAnnotations) {
313579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                item.writeTo(file, out);
314579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
315579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
316579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
317579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (methodsSize != 0) {
318579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            Collections.sort(methodAnnotations);
319579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (annotates) {
320579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                out.annotate(0, "  methods:");
321579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
322579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            for (MethodAnnotationStruct item : methodAnnotations) {
323579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                item.writeTo(file, out);
324579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
325579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
326579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
327579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (parametersSize != 0) {
328579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            Collections.sort(parameterAnnotations);
329579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (annotates) {
330579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                out.annotate(0, "  parameters:");
331579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
332579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            for (ParameterAnnotationStruct item : parameterAnnotations) {
333579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                item.writeTo(file, out);
334579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
335579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
336579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
337579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
338579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
339579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the list size of the given list, or {@code 0} if given
340579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code null}.
341579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
342579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param list {@code null-ok;} the list in question
343579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code >= 0;} its size
344579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
345579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private static int listSize(ArrayList<?> list) {
346579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (list == null) {
347579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return 0;
348579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
349579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
350579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return list.size();
351579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
352579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
353579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
354579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Prints out the contents of this instance, in a debugging-friendly
355579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * way. This is meant to be called from {@link ClassDefItem#debugPrint}.
356579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
357579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param out {@code non-null;} where to output to
358579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
359579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /*package*/ void debugPrint(PrintWriter out) {
360579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (classAnnotations != null) {
361579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            out.println("  class annotations: " + classAnnotations);
362579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
363579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
364579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (fieldAnnotations != null) {
365579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            out.println("  field annotations:");
366579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            for (FieldAnnotationStruct item : fieldAnnotations) {
367579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                out.println("    " + item.toHuman());
368579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
369579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
370579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
371579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (methodAnnotations != null) {
372579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            out.println("  method annotations:");
373579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            for (MethodAnnotationStruct item : methodAnnotations) {
374579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                out.println("    " + item.toHuman());
375579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
376579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
377579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
378579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (parameterAnnotations != null) {
379579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            out.println("  parameter annotations:");
380579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            for (ParameterAnnotationStruct item : parameterAnnotations) {
381579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                out.println("    " + item.toHuman());
382579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
383579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
384579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
385579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson}
386