1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/*
2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2008 The Android Open Source Project
3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License");
5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License.
6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at
7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *      http://www.apache.org/licenses/LICENSE-2.0
9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software
11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS,
12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and
14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License.
15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.dex.file;
18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.annotation.Annotations;
20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.annotation.AnnotationsList;
21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstFieldRef;
22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstMethodRef;
23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.AnnotatedOutput;
24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.Hex;
25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.PrintWriter;
27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.ArrayList;
28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.Collections;
29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/**
31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Per-class directory of annotations.
32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class AnnotationsDirectoryItem extends OffsettedItem {
34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** the required alignment for instances of this class */
35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int ALIGNMENT = 4;
36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** write size of this class's header, in bytes */
38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int HEADER_SIZE = 16;
39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** write size of a list element, in bytes */
41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int ELEMENT_SIZE = 8;
42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code null-ok;} the class-level annotations, if any */
44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private AnnotationSetItem classAnnotations;
45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code null-ok;} the annotated fields, if any */
47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private ArrayList<FieldAnnotationStruct> fieldAnnotations;
48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code null-ok;} the annotated methods, if any */
50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private ArrayList<MethodAnnotationStruct> methodAnnotations;
51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code null-ok;} the annotated parameters, if any */
53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private ArrayList<ParameterAnnotationStruct> parameterAnnotations;
54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Constructs an empty instance.
57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public AnnotationsDirectoryItem() {
59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        super(ALIGNMENT, -1);
60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        classAnnotations = null;
62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        fieldAnnotations = null;
63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        methodAnnotations = null;
64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        parameterAnnotations = null;
65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public ItemType itemType() {
70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM;
71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns whether this item is empty (has no contents).
75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code true} if this item is empty, or {@code false}
77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * if not
78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public boolean isEmpty() {
80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return (classAnnotations == null) &&
81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            (fieldAnnotations == null) &&
82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            (methodAnnotations == null) &&
83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            (parameterAnnotations == null);
84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns whether this item is a candidate for interning. The only
88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * interning candidates are ones that <i>only</i> have a non-null
89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * set of class annotations, with no other lists.
90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code true} if this is an interning candidate, or
92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code false} if not
93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public boolean isInternable() {
95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return (classAnnotations != null) &&
96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            (fieldAnnotations == null) &&
97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            (methodAnnotations == null) &&
98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            (parameterAnnotations == null);
99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public int hashCode() {
104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (classAnnotations == null) {
105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return 0;
106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return classAnnotations.hashCode();
109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@inheritDoc}
113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * <p><b>Note:</b>: This throws an exception if this item is not
115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * internable.</p>
116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @see #isInternable
118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public int compareTo0(OffsettedItem other) {
121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (! isInternable()) {
122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new UnsupportedOperationException("uninternable instance");
123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        AnnotationsDirectoryItem otherDirectory =
126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            (AnnotationsDirectoryItem) other;
127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return classAnnotations.compareTo(otherDirectory.classAnnotations);
128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Sets the direct annotations on this instance. These are annotations
132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * made on the class, per se, as opposed to on one of its members.
133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * It is only valid to call this method at most once per instance.
134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param annotations {@code non-null;} annotations to set for this class
136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void setClassAnnotations(Annotations annotations) {
138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (annotations == null) {
139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("annotations == null");
140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (classAnnotations != null) {
143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new UnsupportedOperationException(
144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    "class annotations already set");
145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        classAnnotations = new AnnotationSetItem(annotations);
148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Adds a field annotations item to this instance.
152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param field {@code non-null;} field in question
154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param annotations {@code non-null;} associated annotations to add
155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void addFieldAnnotations(CstFieldRef field,
157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            Annotations annotations) {
158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (fieldAnnotations == null) {
159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            fieldAnnotations = new ArrayList<FieldAnnotationStruct>();
160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        fieldAnnotations.add(new FieldAnnotationStruct(field,
163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                        new AnnotationSetItem(annotations)));
164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Adds a method annotations item to this instance.
168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param method {@code non-null;} method in question
170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param annotations {@code non-null;} associated annotations to add
171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void addMethodAnnotations(CstMethodRef method,
173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            Annotations annotations) {
174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (methodAnnotations == null) {
175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            methodAnnotations = new ArrayList<MethodAnnotationStruct>();
176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        methodAnnotations.add(new MethodAnnotationStruct(method,
179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                        new AnnotationSetItem(annotations)));
180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Adds a parameter annotations item to this instance.
184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param method {@code non-null;} method in question
186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param list {@code non-null;} associated list of annotation sets to add
187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void addParameterAnnotations(CstMethodRef method,
189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            AnnotationsList list) {
190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (parameterAnnotations == null) {
191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            parameterAnnotations = new ArrayList<ParameterAnnotationStruct>();
192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        parameterAnnotations.add(new ParameterAnnotationStruct(method, list));
195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the method annotations for a given method, if any. This is
199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * meant for use by debugging / dumping code.
200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param method {@code non-null;} the method
202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code null-ok;} the method annotations, if any
203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public Annotations getMethodAnnotations(CstMethodRef method) {
205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (methodAnnotations == null) {
206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return null;
207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (MethodAnnotationStruct item : methodAnnotations) {
210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (item.getMethod().equals(method)) {
211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                return item.getAnnotations();
212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return null;
216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the parameter annotations for a given method, if any. This is
220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * meant for use by debugging / dumping code.
221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param method {@code non-null;} the method
223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code null-ok;} the parameter annotations, if any
224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public AnnotationsList getParameterAnnotations(CstMethodRef method) {
226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (parameterAnnotations == null) {
227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return null;
228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (ParameterAnnotationStruct item : parameterAnnotations) {
231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (item.getMethod().equals(method)) {
232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                return item.getAnnotationsList();
233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return null;
237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void addContents(DexFile file) {
241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        MixedItemSection wordData = file.getWordData();
242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (classAnnotations != null) {
244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            classAnnotations = wordData.intern(classAnnotations);
245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (fieldAnnotations != null) {
248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            for (FieldAnnotationStruct item : fieldAnnotations) {
249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                item.addContents(file);
250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (methodAnnotations != null) {
254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            for (MethodAnnotationStruct item : methodAnnotations) {
255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                item.addContents(file);
256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (parameterAnnotations != null) {
260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            for (ParameterAnnotationStruct item : parameterAnnotations) {
261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                item.addContents(file);
262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public String toHuman() {
269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        throw new RuntimeException("unsupported");
270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    protected void place0(Section addedTo, int offset) {
275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        // We just need to set the write size here.
276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int elementCount = listSize(fieldAnnotations)
278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            + listSize(methodAnnotations) + listSize(parameterAnnotations);
279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        setWriteSize(HEADER_SIZE + (elementCount * ELEMENT_SIZE));
280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    protected void writeTo0(DexFile file, AnnotatedOutput out) {
285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        boolean annotates = out.annotates();
286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int classOff = OffsettedItem.getAbsoluteOffsetOr0(classAnnotations);
287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int fieldsSize = listSize(fieldAnnotations);
288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int methodsSize = listSize(methodAnnotations);
289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int parametersSize = listSize(parameterAnnotations);
290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (annotates) {
292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(0, offsetString() + " annotations directory");
293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(4, "  class_annotations_off: " + Hex.u4(classOff));
294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(4, "  fields_size:           " +
295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    Hex.u4(fieldsSize));
296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(4, "  methods_size:          " +
297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    Hex.u4(methodsSize));
298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(4, "  parameters_size:       " +
299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    Hex.u4(parametersSize));
300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeInt(classOff);
303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeInt(fieldsSize);
304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeInt(methodsSize);
305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeInt(parametersSize);
306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (fieldsSize != 0) {
308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            Collections.sort(fieldAnnotations);
309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (annotates) {
310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.annotate(0, "  fields:");
311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            for (FieldAnnotationStruct item : fieldAnnotations) {
313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                item.writeTo(file, out);
314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
315917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
316917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
317917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (methodsSize != 0) {
318917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            Collections.sort(methodAnnotations);
319917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (annotates) {
320917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.annotate(0, "  methods:");
321917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
322917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            for (MethodAnnotationStruct item : methodAnnotations) {
323917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                item.writeTo(file, out);
324917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
325917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
326917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
327917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (parametersSize != 0) {
328917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            Collections.sort(parameterAnnotations);
329917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (annotates) {
330917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.annotate(0, "  parameters:");
331917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
332917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            for (ParameterAnnotationStruct item : parameterAnnotations) {
333917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                item.writeTo(file, out);
334917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
335917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
336917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
337917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
338917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
339917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the list size of the given list, or {@code 0} if given
340917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code null}.
341917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
342917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param list {@code null-ok;} the list in question
343917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code >= 0;} its size
344917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
345917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static int listSize(ArrayList<?> list) {
346917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (list == null) {
347917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return 0;
348917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
349917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
350917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return list.size();
351917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
352917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
353917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
354917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Prints out the contents of this instance, in a debugging-friendly
355917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * way. This is meant to be called from {@link ClassDefItem#debugPrint}.
356917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
357917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param out {@code non-null;} where to output to
358917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
359917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /*package*/ void debugPrint(PrintWriter out) {
360917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (classAnnotations != null) {
361917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.println("  class annotations: " + classAnnotations);
362917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
363917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
364917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (fieldAnnotations != null) {
365917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.println("  field annotations:");
366917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            for (FieldAnnotationStruct item : fieldAnnotations) {
367917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.println("    " + item.toHuman());
368917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
369917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
370917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
371917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (methodAnnotations != null) {
372917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.println("  method annotations:");
373917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            for (MethodAnnotationStruct item : methodAnnotations) {
374917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.println("    " + item.toHuman());
375917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
376917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
377917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
378917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (parameterAnnotations != null) {
379917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.println("  parameter annotations:");
380917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            for (ParameterAnnotationStruct item : parameterAnnotations) {
381917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.println("    " + item.toHuman());
382917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
383917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
384917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
385917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul}
386