Fri, 31 Aug 2012 10:37:46 +0100
7151010: Add compiler support for repeating annotations
Reviewed-by: jjg, mcimadamore
1 /*
2 * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.javadoc;
28 import com.sun.javadoc.*;
30 /**
31 * Documents a Serializable field defined by an ObjectStreamField.
32 * <pre>
33 * The class parses and stores the three serialField tag parameters:
34 *
35 * - field name
36 * - field type name
37 * (fully-qualified or visible from the current import context)
38 * - description of the valid values for the field
40 * </pre>
41 * This tag is only allowed in the javadoc for the special member
42 * serialPersistentFields.
43 *
44 * @author Joe Fialli
45 * @author Neal Gafter
46 *
47 * @see java.io.ObjectStreamField
48 */
49 class SerialFieldTagImpl
50 extends TagImpl
51 implements SerialFieldTag, Comparable<Object>
52 {
53 //### These could be final, except that the constructor
54 //### does not set them directly.
56 private String fieldName; // Required Argument 1 of serialField
57 private String fieldType; // Required Argument 2 of serialField
58 private String description; // Optional Remaining Arguments of serialField
60 private ClassDoc containingClass; // Class containing serialPersistentField member
61 private ClassDoc fieldTypeDoc; // ClassDocImpl of fieldType
62 private FieldDocImpl matchingField; // FieldDocImpl with same name as fieldName
64 /* Constructor. */
65 SerialFieldTagImpl(DocImpl holder, String name, String text) {
66 super(holder, name, text);
67 parseSerialFieldString();
68 if (holder instanceof MemberDoc) {
69 containingClass = ((MemberDocImpl)holder).containingClass();
70 }
71 }
73 /*
74 * The serialField tag is composed of three entities.
75 *
76 * serialField serializableFieldName serisliableFieldType
77 * description of field.
78 *
79 * The fieldName and fieldType must be legal Java Identifiers.
80 */
81 private void parseSerialFieldString() {
82 int len = text.length();
83 if (len == 0) {
84 return;
85 }
87 // if no white space found
88 /* Skip white space. */
89 int inx = 0;
90 int cp;
91 for (; inx < len; inx += Character.charCount(cp)) {
92 cp = text.codePointAt(inx);
93 if (!Character.isWhitespace(cp)) {
94 break;
95 }
96 }
98 /* find first word. */
99 int first = inx;
100 int last = inx;
101 cp = text.codePointAt(inx);
102 if (! Character.isJavaIdentifierStart(cp)) {
103 docenv().warning(holder,
104 "tag.serialField.illegal_character",
105 new String(Character.toChars(cp)), text);
106 return;
107 }
109 for (inx += Character.charCount(cp); inx < len; inx += Character.charCount(cp)) {
110 cp = text.codePointAt(inx);
111 if (!Character.isJavaIdentifierPart(cp)) {
112 break;
113 }
114 }
116 if (inx < len && ! Character.isWhitespace(cp = text.codePointAt(inx))) {
117 docenv().warning(holder,
118 "tag.serialField.illegal_character",
119 new String(Character.toChars(cp)), text);
120 return;
121 }
123 last = inx;
124 fieldName = text.substring(first, last);
126 /* Skip white space. */
127 for (; inx < len; inx += Character.charCount(cp)) {
128 cp = text.codePointAt(inx);
129 if (!Character.isWhitespace(cp)) {
130 break;
131 }
132 }
134 /* find second word. */
135 first = inx;
136 last = inx;
138 for (; inx < len; inx += Character.charCount(cp)) {
139 cp = text.codePointAt(inx);
140 if (Character.isWhitespace(cp)) {
141 break;
142 }
143 }
144 if (inx < len && ! Character.isWhitespace(cp = text.codePointAt(inx))) {
145 docenv().warning(holder,
146 "tag.serialField.illegal_character",
147 new String(Character.toChars(cp)), text);
148 return;
149 }
150 last = inx;
151 fieldType = text.substring(first, last);
153 /* Skip leading white space. Rest of string is description for serialField.*/
154 for (; inx < len; inx += Character.charCount(cp)) {
155 cp = text.codePointAt(inx);
156 if (!Character.isWhitespace(cp)) {
157 break;
158 }
159 }
160 description = text.substring(inx);
161 }
163 /**
164 * return a key for sorting.
165 */
166 String key() {
167 return fieldName;
168 }
170 /*
171 * Optional. Link this serialField tag to its corrsponding
172 * field in the class. Note: there is no requirement that
173 * there be a field in the class that matches serialField tag.
174 */
175 void mapToFieldDocImpl(FieldDocImpl fd) {
176 matchingField = fd;
177 }
179 /**
180 * Return the serialziable field name.
181 */
182 public String fieldName() {
183 return fieldName;
184 }
186 /**
187 * Return the field type string.
188 */
189 public String fieldType() {
190 return fieldType;
191 }
193 /**
194 * Return the ClassDocImpl for field type.
195 *
196 * @returns null if no ClassDocImpl for field type is visible from
197 * containingClass context.
198 */
199 public ClassDoc fieldTypeDoc() {
200 if (fieldTypeDoc == null && containingClass != null) {
201 fieldTypeDoc = containingClass.findClass(fieldType);
202 }
203 return fieldTypeDoc;
204 }
206 /**
207 * Return the corresponding FieldDocImpl for this SerialFieldTagImpl.
208 *
209 * @returns null if no matching FieldDocImpl.
210 */
211 FieldDocImpl getMatchingField() {
212 return matchingField;
213 }
215 /**
216 * Return the field comment. If there is no serialField comment, return
217 * javadoc comment of corresponding FieldDocImpl.
218 */
219 public String description() {
220 if (description.length() == 0 && matchingField != null) {
222 //check for javadoc comment of corresponding field.
223 Comment comment = matchingField.comment();
224 if (comment != null) {
225 return comment.commentText();
226 }
227 }
228 return description;
229 }
231 /**
232 * Return the kind of this tag.
233 */
234 public String kind() {
235 return "@serialField";
236 }
238 /**
239 * Convert this object to a string.
240 */
241 public String toString() {
242 return name + ":" + text;
243 }
245 /**
246 * Compares this Object with the specified Object for order. Returns a
247 * negative integer, zero, or a positive integer as this Object is less
248 * than, equal to, or greater than the given Object.
249 * <p>
250 * Included to make SerialFieldTagImpl items java.lang.Comparable.
251 *
252 * @param obj the <code>Object</code> to be compared.
253 * @return a negative integer, zero, or a positive integer as this Object
254 * is less than, equal to, or greater than the given Object.
255 * @exception ClassCastException the specified Object's type prevents it
256 * from being compared to this Object.
257 * @since 1.2
258 */
259 public int compareTo(Object obj) {
260 return key().compareTo(((SerialFieldTagImpl)obj).key());
261 }
262 }