001: /*
002: * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.tools.javadoc;
027:
028: import com.sun.javadoc.*;
029:
030: import static com.sun.javadoc.LanguageVersion.*;
031:
032: import com.sun.tools.javac.code.Flags;
033: import com.sun.tools.javac.code.Symbol.ClassSymbol;
034: import com.sun.tools.javac.code.Symbol.VarSymbol;
035: import com.sun.tools.javac.code.TypeTags;
036:
037: import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
038:
039: import com.sun.tools.javac.util.Position;
040:
041: import java.lang.reflect.Modifier;
042:
043: /**
044: * Represents a field in a java class.
045: *
046: * @see MemberDocImpl
047: *
048: * @since 1.2
049: * @author Robert Field
050: * @author Neal Gafter (rewrite)
051: * @author Scott Seligman (generics, enums, annotations)
052: */
053: public class FieldDocImpl extends MemberDocImpl implements FieldDoc {
054:
055: protected final VarSymbol sym;
056:
057: /**
058: * Constructor.
059: */
060: public FieldDocImpl(DocEnv env, VarSymbol sym, String rawDocs,
061: JCVariableDecl tree, Position.LineMap lineMap) {
062: super (env, sym, rawDocs, tree, lineMap);
063: this .sym = sym;
064: }
065:
066: /**
067: * Constructor.
068: */
069: public FieldDocImpl(DocEnv env, VarSymbol sym) {
070: this (env, sym, null, null, null);
071: }
072:
073: /**
074: * Returns the flags in terms of javac's flags
075: */
076: protected long getFlags() {
077: return sym.flags();
078: }
079:
080: /**
081: * Identify the containing class
082: */
083: protected ClassSymbol getContainingClass() {
084: return sym.enclClass();
085: }
086:
087: /**
088: * Get type of this field.
089: */
090: public com.sun.javadoc.Type type() {
091: return TypeMaker.getType(env, sym.type, false);
092: }
093:
094: /**
095: * Get the value of a constant field.
096: *
097: * @return the value of a constant field. The value is
098: * automatically wrapped in an object if it has a primitive type.
099: * If the field is not constant, returns null.
100: */
101: public Object constantValue() {
102: Object result = sym.getConstValue();
103: if (result != null && sym.type.tag == TypeTags.BOOLEAN)
104: // javac represents false and true as Integers 0 and 1
105: result = Boolean
106: .valueOf(((Integer) result).intValue() != 0);
107: return result;
108: }
109:
110: /**
111: * Get the value of a constant field.
112: *
113: * @return the text of a Java language expression whose value
114: * is the value of the constant. The expression uses no identifiers
115: * other than primitive literals. If the field is
116: * not constant, returns null.
117: */
118: public String constantValueExpression() {
119: return constantValueExpression(constantValue());
120: }
121:
122: /**
123: * A static version of the above.
124: */
125: static String constantValueExpression(Object cb) {
126: if (cb == null)
127: return null;
128: if (cb instanceof Character)
129: return sourceForm(((Character) cb).charValue());
130: if (cb instanceof Byte)
131: return sourceForm(((Byte) cb).byteValue());
132: if (cb instanceof String)
133: return sourceForm((String) cb);
134: if (cb instanceof Double)
135: return sourceForm(((Double) cb).doubleValue(), 'd');
136: if (cb instanceof Float)
137: return sourceForm(((Float) cb).doubleValue(), 'f');
138: if (cb instanceof Long)
139: return cb + "L";
140: return cb.toString(); // covers int, short
141: }
142:
143: // where
144: private static String sourceForm(double v, char suffix) {
145: if (Double.isNaN(v))
146: return "0" + suffix + "/0" + suffix;
147: if (v == Double.POSITIVE_INFINITY)
148: return "1" + suffix + "/0" + suffix;
149: if (v == Double.NEGATIVE_INFINITY)
150: return "-1" + suffix + "/0" + suffix;
151: return v + (suffix == 'f' || suffix == 'F' ? "" + suffix : "");
152: }
153:
154: private static String sourceForm(char c) {
155: StringBuffer buf = new StringBuffer(8);
156: buf.append('\'');
157: sourceChar(c, buf);
158: buf.append('\'');
159: return buf.toString();
160: }
161:
162: private static String sourceForm(byte c) {
163: return "0x" + Integer.toString(c & 0xff, 16);
164: }
165:
166: private static String sourceForm(String s) {
167: StringBuffer buf = new StringBuffer(s.length() + 5);
168: buf.append('\"');
169: for (int i = 0; i < s.length(); i++) {
170: char c = s.charAt(i);
171: sourceChar(c, buf);
172: }
173: buf.append('\"');
174: return buf.toString();
175: }
176:
177: private static void sourceChar(char c, StringBuffer buf) {
178: switch (c) {
179: case '\b':
180: buf.append("\\b");
181: return;
182: case '\t':
183: buf.append("\\t");
184: return;
185: case '\n':
186: buf.append("\\n");
187: return;
188: case '\f':
189: buf.append("\\f");
190: return;
191: case '\r':
192: buf.append("\\r");
193: return;
194: case '\"':
195: buf.append("\\\"");
196: return;
197: case '\'':
198: buf.append("\\\'");
199: return;
200: case '\\':
201: buf.append("\\\\");
202: return;
203: default:
204: if (isPrintableAscii(c)) {
205: buf.append(c);
206: return;
207: }
208: unicodeEscape(c, buf);
209: return;
210: }
211: }
212:
213: private static void unicodeEscape(char c, StringBuffer buf) {
214: final String chars = "0123456789abcdef";
215: buf.append("\\u");
216: buf.append(chars.charAt(15 & (c >> 12)));
217: buf.append(chars.charAt(15 & (c >> 8)));
218: buf.append(chars.charAt(15 & (c >> 4)));
219: buf.append(chars.charAt(15 & (c >> 0)));
220: }
221:
222: private static boolean isPrintableAscii(char c) {
223: return c >= ' ' && c <= '~';
224: }
225:
226: /**
227: * Return true if this field is included in the active set.
228: */
229: public boolean isIncluded() {
230: return containingClass().isIncluded()
231: && env.shouldDocument(sym);
232: }
233:
234: /**
235: * Is this Doc item a field (but not an enum constant?
236: */
237: public boolean isField() {
238: return !isEnumConstant();
239: }
240:
241: /**
242: * Is this Doc item an enum constant?
243: * (For legacy doclets, return false.)
244: */
245: public boolean isEnumConstant() {
246: return (getFlags() & Flags.ENUM) != 0 && !env.legacyDoclet;
247: }
248:
249: /**
250: * Return true if this field is transient
251: */
252: public boolean isTransient() {
253: return Modifier.isTransient(getModifiers());
254: }
255:
256: /**
257: * Return true if this field is volatile
258: */
259: public boolean isVolatile() {
260: return Modifier.isVolatile(getModifiers());
261: }
262:
263: /**
264: * Returns true if this field was synthesized by the compiler.
265: */
266: public boolean isSynthetic() {
267: return (getFlags() & Flags.SYNTHETIC) != 0;
268: }
269:
270: /**
271: * Return the serialField tags in this FieldDocImpl item.
272: *
273: * @return an array of <tt>SerialFieldTagImpl</tt> containing all
274: * <code>@serialField</code> tags.
275: */
276: public SerialFieldTag[] serialFieldTags() {
277: return comment().serialFieldTags();
278: }
279:
280: public String name() {
281: return sym.name.toString();
282: }
283:
284: public String qualifiedName() {
285: return sym.enclClass().getQualifiedName() + "." + name();
286: }
287:
288: /**
289: * Return the source position of the entity, or null if
290: * no position is available.
291: */
292: public SourcePosition position() {
293: if (sym.enclClass().sourcefile == null)
294: return null;
295: return SourcePositionImpl.make(sym.enclClass().sourcefile
296: .toString(), (tree == null) ? 0 : tree.pos, lineMap);
297: }
298: }
|