Tue, 11 Aug 2009 01:13:14 +0100
6521805: Regression: JDK5/JDK6 javac allows write access to outer class reference
Summary: javac should warn/complain about identifiers with the same name as synthetic symbol
Reviewed-by: jjg
1 /*
2 * Copyright 1997-2009 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
26 package com.sun.tools.javadoc;
28 import com.sun.javadoc.*;
30 import static com.sun.javadoc.LanguageVersion.*;
32 import com.sun.tools.javac.code.Symbol;
33 import com.sun.tools.javac.code.Symbol.ClassSymbol;
34 import com.sun.tools.javac.code.Type;
35 import com.sun.tools.javac.code.Type.ClassType;
36 import com.sun.tools.javac.code.Type.TypeVar;
37 import com.sun.tools.javac.code.Type.ArrayType;
38 import com.sun.tools.javac.code.Types;
39 import com.sun.tools.javac.util.List;
41 import static com.sun.tools.javac.code.TypeTags.*;
44 public class TypeMaker {
46 public static com.sun.javadoc.Type getType(DocEnv env, Type t) {
47 return getType(env, t, true);
48 }
50 /**
51 * @param errToClassDoc if true, ERROR type results in a ClassDoc;
52 * false preserves legacy behavior
53 */
54 @SuppressWarnings("fallthrough")
55 public static com.sun.javadoc.Type getType(DocEnv env, Type t,
56 boolean errToClassDoc) {
57 if (env.legacyDoclet) {
58 t = env.types.erasure(t);
59 }
60 switch (t.tag) {
61 case CLASS:
62 if (ClassDocImpl.isGeneric((ClassSymbol)t.tsym)) {
63 return env.getParameterizedType((ClassType)t);
64 } else {
65 return env.getClassDoc((ClassSymbol)t.tsym);
66 }
67 case WILDCARD:
68 Type.WildcardType a = (Type.WildcardType)t;
69 return new WildcardTypeImpl(env, a);
70 case TYPEVAR: return new TypeVariableImpl(env, (TypeVar)t);
71 case ARRAY: return new ArrayTypeImpl(env, t);
72 case BYTE: return PrimitiveType.byteType;
73 case CHAR: return PrimitiveType.charType;
74 case SHORT: return PrimitiveType.shortType;
75 case INT: return PrimitiveType.intType;
76 case LONG: return PrimitiveType.longType;
77 case FLOAT: return PrimitiveType.floatType;
78 case DOUBLE: return PrimitiveType.doubleType;
79 case BOOLEAN: return PrimitiveType.booleanType;
80 case VOID: return PrimitiveType.voidType;
81 case ERROR:
82 if (errToClassDoc)
83 return env.getClassDoc((ClassSymbol)t.tsym);
84 // FALLTHRU
85 default:
86 return new PrimitiveType(t.tsym.getQualifiedName().toString());
87 }
88 }
90 /**
91 * Convert a list of javac types into an array of javadoc types.
92 */
93 public static com.sun.javadoc.Type[] getTypes(DocEnv env, List<Type> ts) {
94 return getTypes(env, ts, new com.sun.javadoc.Type[ts.length()]);
95 }
97 /**
98 * Like the above version, but use and return the array given.
99 */
100 public static com.sun.javadoc.Type[] getTypes(DocEnv env, List<Type> ts,
101 com.sun.javadoc.Type res[]) {
102 int i = 0;
103 for (Type t : ts) {
104 res[i++] = getType(env, t);
105 }
106 return res;
107 }
109 public static String getTypeName(Type t, boolean full) {
110 switch (t.tag) {
111 case ARRAY:
112 StringBuffer dimension = new StringBuffer();
113 while (t.tag == ARRAY) {
114 dimension = dimension.append("[]");
115 t = ((ArrayType)t).elemtype;
116 }
117 return getTypeName(t, full) + dimension;
118 case CLASS:
119 return ClassDocImpl.getClassName((ClassSymbol)t.tsym, full);
120 default:
121 return t.tsym.getQualifiedName().toString();
122 }
123 }
125 /**
126 * Return the string representation of a type use. Bounds of type
127 * variables are not included; bounds of wildcard types are.
128 * Class names are qualified if "full" is true.
129 */
130 static String getTypeString(DocEnv env, Type t, boolean full) {
131 switch (t.tag) {
132 case ARRAY:
133 StringBuffer dimension = new StringBuffer();
134 while (t.tag == ARRAY) {
135 dimension = dimension.append("[]");
136 t = env.types.elemtype(t);
137 }
138 return getTypeString(env, t, full) + dimension;
139 case CLASS:
140 return ParameterizedTypeImpl.
141 parameterizedTypeToString(env, (ClassType)t, full);
142 case WILDCARD:
143 Type.WildcardType a = (Type.WildcardType)t;
144 return WildcardTypeImpl.wildcardTypeToString(env, a, full);
145 default:
146 return t.tsym.getQualifiedName().toString();
147 }
148 }
150 /**
151 * Return the formal type parameters of a class or method as an
152 * angle-bracketed string. Each parameter is a type variable with
153 * optional bounds. Class names are qualified if "full" is true.
154 * Return "" if there are no type parameters or we're hiding generics.
155 */
156 static String typeParametersString(DocEnv env, Symbol sym, boolean full) {
157 if (env.legacyDoclet || sym.type.getTypeArguments().isEmpty()) {
158 return "";
159 }
160 StringBuffer s = new StringBuffer();
161 for (Type t : sym.type.getTypeArguments()) {
162 s.append(s.length() == 0 ? "<" : ", ");
163 s.append(TypeVariableImpl.typeVarToString(env, (TypeVar)t, full));
164 }
165 s.append(">");
166 return s.toString();
167 }
169 /**
170 * Return the actual type arguments of a parameterized type as an
171 * angle-bracketed string. Class name are qualified if "full" is true.
172 * Return "" if there are no type arguments or we're hiding generics.
173 */
174 static String typeArgumentsString(DocEnv env, ClassType cl, boolean full) {
175 if (env.legacyDoclet || cl.getTypeArguments().isEmpty()) {
176 return "";
177 }
178 StringBuffer s = new StringBuffer();
179 for (Type t : cl.getTypeArguments()) {
180 s.append(s.length() == 0 ? "<" : ", ");
181 s.append(getTypeString(env, t, full));
182 }
183 s.append(">");
184 return s.toString();
185 }
188 private static class ArrayTypeImpl implements com.sun.javadoc.Type {
190 Type arrayType;
192 DocEnv env;
194 ArrayTypeImpl(DocEnv env, Type arrayType) {
195 this.env = env;
196 this.arrayType = arrayType;
197 }
199 private com.sun.javadoc.Type skipArraysCache = null;
201 private com.sun.javadoc.Type skipArrays() {
202 if (skipArraysCache == null) {
203 Type t;
204 for (t = arrayType; t.tag == ARRAY; t = env.types.elemtype(t)) { }
205 skipArraysCache = TypeMaker.getType(env, t);
206 }
207 return skipArraysCache;
208 }
210 /**
211 * Return the type's dimension information, as a string.
212 * <p>
213 * For example, a two dimensional array of String returns '[][]'.
214 */
215 public String dimension() {
216 StringBuffer dimension = new StringBuffer();
217 for (Type t = arrayType; t.tag == ARRAY; t = env.types.elemtype(t)) {
218 dimension = dimension.append("[]");
219 }
220 return dimension.toString();
221 }
223 /**
224 * Return unqualified name of type excluding any dimension information.
225 * <p>
226 * For example, a two dimensional array of String returns 'String'.
227 */
228 public String typeName() {
229 return skipArrays().typeName();
230 }
232 /**
233 * Return qualified name of type excluding any dimension information.
234 *<p>
235 * For example, a two dimensional array of String
236 * returns 'java.lang.String'.
237 */
238 public String qualifiedTypeName() {
239 return skipArrays().qualifiedTypeName();
240 }
242 /**
243 * Return the simple name of this type excluding any dimension information.
244 */
245 public String simpleTypeName() {
246 return skipArrays().simpleTypeName();
247 }
249 /**
250 * Return this type as a class. Array dimensions are ignored.
251 *
252 * @return a ClassDocImpl if the type is a Class.
253 * Return null if it is a primitive type..
254 */
255 public ClassDoc asClassDoc() {
256 return skipArrays().asClassDoc();
257 }
259 /**
260 * Return this type as a <code>ParameterizedType</code> if it
261 * represents a parameterized type. Array dimensions are ignored.
262 */
263 public ParameterizedType asParameterizedType() {
264 return skipArrays().asParameterizedType();
265 }
267 /**
268 * Return this type as a <code>TypeVariable</code> if it represents
269 * a type variable. Array dimensions are ignored.
270 */
271 public TypeVariable asTypeVariable() {
272 return skipArrays().asTypeVariable();
273 }
275 /**
276 * Return null, as there are no arrays of wildcard types.
277 */
278 public WildcardType asWildcardType() {
279 return null;
280 }
282 /**
283 * Return this type as an <code>AnnotationTypeDoc</code> if it
284 * represents an annotation type. Array dimensions are ignored.
285 */
286 public AnnotationTypeDoc asAnnotationTypeDoc() {
287 return skipArrays().asAnnotationTypeDoc();
288 }
290 /**
291 * Return true if this is an array of a primitive type.
292 */
293 public boolean isPrimitive() {
294 return skipArrays().isPrimitive();
295 }
297 /**
298 * Return a string representation of the type.
299 *
300 * Return name of type including any dimension information.
301 * <p>
302 * For example, a two dimensional array of String returns
303 * <code>String[][]</code>.
304 *
305 * @return name of type including any dimension information.
306 */
307 public String toString() {
308 return qualifiedTypeName() + dimension();
309 }
310 }
311 }