001: /*
002: * Copyright 2004-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.apt.comp;
027:
028: import com.sun.mirror.declaration.*;
029: import static com.sun.mirror.declaration.Modifier.*;
030: import com.sun.mirror.type.*;
031: import com.sun.mirror.apt.*;
032:
033: import java.util.*;
034: import com.sun.mirror.util.*;
035:
036: /**
037: * Class used to implement "-print" option.
038: */
039: public class PrintAP implements AnnotationProcessor {
040:
041: static class PrintingVisitors {
042: int indentation = 0; // Indentation level;
043: AnnotationProcessorEnvironment env;
044: Messager out;
045: Declaration java_lang_Object;
046: Declaration java_lang_annotation_Annotation;
047:
048: static Set<Modifier> EMPTY_ELIDES = Collections.emptySet();
049: static Set<Modifier> INTERFACE_ELIDES = EnumSet.of(ABSTRACT);
050: static Set<Modifier> ENUM_ELIDES = EnumSet.of(FINAL, ABSTRACT);
051: static Set<Modifier> INTERFACE_MEMBER_ELIDES = EnumSet.of(
052: ABSTRACT, PUBLIC, STATIC, FINAL);
053:
054: PrintingVisitors(AnnotationProcessorEnvironment env) {
055: this .env = env;
056: this .out = env.getMessager();
057: this .java_lang_Object = env
058: .getTypeDeclaration("java.lang.Object");
059: this .java_lang_annotation_Annotation = env
060: .getTypeDeclaration("java.lang.annotation.Annotation");
061: }
062:
063: static String[] spaces = { "", " ", " ", " ",
064: " ", " ", " ",
065: " ", " ",
066: " ", " " };
067:
068: String indent() {
069: int indentation = this .indentation;
070: if (indentation < 0)
071: return "";
072: else if (indentation <= 10)
073: return spaces[indentation];
074: else {
075: StringBuilder sb = new StringBuilder();
076: while (indentation > 10) {
077: sb.append(spaces[indentation]);
078: indentation -= 10;
079: }
080: sb.append(spaces[indentation]);
081: return sb.toString();
082: }
083: }
084:
085: class PrePrinting extends SimpleDeclarationVisitor {
086: Map<EnumDeclaration, Integer> enumCardinality = new HashMap<EnumDeclaration, Integer>();
087: Map<EnumDeclaration, Integer> enumConstVisited = new HashMap<EnumDeclaration, Integer>();
088:
089: PrePrinting() {
090: }
091:
092: public void visitClassDeclaration(ClassDeclaration d) {
093: System.out.println();
094: printDocComment(d);
095: printModifiers(d, EMPTY_ELIDES);
096: System.out.print("class " + d.getSimpleName());
097: printFormalTypeParameters(d);
098:
099: // Elide "extends Object"
100: ClassType Super = d.getSuperclass();
101: if (Super != null
102: && !java_lang_Object.equals(Super
103: .getDeclaration()))
104: System.out.print(" extends " + Super.toString());
105:
106: printInterfaces(d);
107:
108: System.out.println(" {");
109:
110: PrintingVisitors.this .indentation++;
111: }
112:
113: public void visitEnumDeclaration(EnumDeclaration d) {
114: enumCardinality.put(d, d.getEnumConstants().size());
115: enumConstVisited.put(d, 1);
116:
117: System.out.println();
118: printDocComment(d);
119: printModifiers(d, ENUM_ELIDES);
120:
121: System.out.print("enum " + d.getSimpleName());
122: printFormalTypeParameters(d);
123: printInterfaces(d);
124:
125: System.out.println(" {");
126:
127: PrintingVisitors.this .indentation++;
128: }
129:
130: public void visitInterfaceDeclaration(InterfaceDeclaration d) {
131: System.out.println();
132: printDocComment(d);
133: printModifiers(d, INTERFACE_ELIDES);
134: System.out.print("interface " + d.getSimpleName());
135:
136: printFormalTypeParameters(d);
137: printInterfaces(d);
138:
139: System.out.println(" {");
140:
141: PrintingVisitors.this .indentation++;
142: }
143:
144: public void visitAnnotationTypeDeclaration(
145: AnnotationTypeDeclaration d) {
146: System.out.println();
147: printDocComment(d);
148: printModifiers(d, INTERFACE_ELIDES);
149: System.out.print("@interface " + d.getSimpleName());
150: printFormalTypeParameters(d);
151:
152: printInterfaces(d);
153:
154: System.out.println(" {");
155:
156: PrintingVisitors.this .indentation++;
157: }
158:
159: public void visitFieldDeclaration(FieldDeclaration d) {
160: System.out.println();
161: printDocComment(d);
162: printModifiers(
163: d,
164: (d.getDeclaringType() instanceof InterfaceDeclaration) ? INTERFACE_MEMBER_ELIDES
165: : EMPTY_ELIDES);
166: System.out.print(d.getType().toString() + " "
167: + d.getSimpleName());
168: String constantExpr = d.getConstantExpression();
169: if (constantExpr != null) {
170: System.out.print(" = " + constantExpr);
171: }
172: System.out.println(";");
173: }
174:
175: public void visitEnumConstantDeclaration(
176: EnumConstantDeclaration d) {
177: EnumDeclaration ed = d.getDeclaringType();
178: int enumCard = enumCardinality.get(ed);
179: int enumVisit = enumConstVisited.get(ed);
180:
181: System.out.println();
182: printDocComment(d);
183: System.out.print(PrintingVisitors.this .indent());
184: System.out.print(d.getSimpleName());
185: System.out.println((enumVisit < enumCard) ? "," : ";");
186:
187: enumConstVisited.put(ed, enumVisit + 1);
188: }
189:
190: public void visitMethodDeclaration(MethodDeclaration d) {
191: System.out.println();
192: printDocComment(d);
193: printModifiers(
194: d,
195: (d.getDeclaringType() instanceof InterfaceDeclaration) ? INTERFACE_MEMBER_ELIDES
196: : EMPTY_ELIDES);
197: printFormalTypeParameters(d);
198: System.out.print(d.getReturnType().toString() + " ");
199: System.out.print(d.getSimpleName() + "(");
200: printParameters(d);
201: System.out.print(")");
202: printThrows(d);
203: System.out.println(";");
204: }
205:
206: public void visitConstructorDeclaration(
207: ConstructorDeclaration d) {
208: System.out.println();
209: printDocComment(d);
210: printModifiers(d, EMPTY_ELIDES);
211: printFormalTypeParameters(d);
212: System.out.print(d.getSimpleName() + "(");
213: printParameters(d);
214: System.out.print(")");
215: printThrows(d);
216: System.out.println(";");
217: }
218:
219: }
220:
221: class PostPrinting extends SimpleDeclarationVisitor {
222: PostPrinting() {
223: }
224:
225: public void visitTypeDeclaration(TypeDeclaration d) {
226: PrintingVisitors.this .indentation--;
227:
228: System.out.print(PrintingVisitors.this .indent());
229: System.out.println("}");
230: }
231: }
232:
233: private void printAnnotations(
234: Collection<AnnotationMirror> annots) {
235:
236: for (AnnotationMirror annot : annots) {
237: System.out.print(this .indent());
238: System.out.print(annot.toString());
239: System.out.println();
240: }
241: }
242:
243: private void printAnnotationsInline(
244: Collection<AnnotationMirror> annots) {
245:
246: for (AnnotationMirror annot : annots) {
247: System.out.print(annot);
248: System.out.print(" ");
249: }
250: }
251:
252: private void printParameters(ExecutableDeclaration ex) {
253:
254: Collection<ParameterDeclaration> parameters = ex
255: .getParameters();
256: int size = parameters.size();
257:
258: switch (size) {
259: case 0:
260: break;
261:
262: case 1:
263: for (ParameterDeclaration parameter : parameters) {
264: printModifiers(parameter, EMPTY_ELIDES);
265:
266: if (ex.isVarArgs()) {
267: System.out.print(((ArrayType) parameter
268: .getType()).getComponentType());
269: System.out.print("...");
270: } else
271: System.out.print(parameter.getType());
272: System.out.print(" " + parameter.getSimpleName());
273: }
274: break;
275:
276: default: {
277: int i = 1;
278: for (ParameterDeclaration parameter : parameters) {
279: if (i == 2)
280: PrintingVisitors.this .indentation++;
281:
282: if (i > 1)
283: System.out
284: .print(PrintingVisitors.this .indent());
285:
286: printModifiers(parameter, EMPTY_ELIDES);
287:
288: if (i == size && ex.isVarArgs()) {
289: System.out.print(((ArrayType) parameter
290: .getType()).getComponentType());
291: System.out.print("...");
292: } else
293: System.out.print(parameter.getType());
294: System.out.print(" " + parameter.getSimpleName());
295:
296: if (i < size)
297: System.out.println(",");
298:
299: i++;
300: }
301:
302: if (parameters.size() >= 2)
303: PrintingVisitors.this .indentation--;
304: }
305: break;
306: }
307: }
308:
309: private void printDocComment(Declaration d) {
310: String docComment = d.getDocComment();
311:
312: if (docComment != null) {
313: // Break comment into lines
314: java.util.StringTokenizer st = new StringTokenizer(
315: docComment, "\n\r");
316: System.out.print(PrintingVisitors.this .indent());
317: System.out.println("/**");
318:
319: while (st.hasMoreTokens()) {
320: System.out.print(PrintingVisitors.this .indent());
321: System.out.print(" *");
322: System.out.println(st.nextToken());
323: }
324:
325: System.out.print(PrintingVisitors.this .indent());
326: System.out.println(" */");
327: }
328: }
329:
330: private void printModifiers(Declaration d,
331: Collection<Modifier> elides) {
332: printAnnotations(d.getAnnotationMirrors());
333:
334: System.out.print(PrintingVisitors.this .indent());
335:
336: for (Modifier m : adjustModifiers(d.getModifiers(), elides)) {
337: System.out.print(m.toString() + " ");
338: }
339: }
340:
341: private void printModifiers(ParameterDeclaration d,
342: Collection<Modifier> elides) {
343: printAnnotationsInline(d.getAnnotationMirrors());
344:
345: for (Modifier m : adjustModifiers(d.getModifiers(), elides)) {
346: System.out.print(m.toString() + " ");
347: }
348: }
349:
350: private Collection<Modifier> adjustModifiers(
351: Collection<Modifier> mods, Collection<Modifier> elides) {
352: if (elides.isEmpty())
353: return mods;
354: else {
355: Collection<Modifier> newMods = new LinkedHashSet<Modifier>();
356: newMods.addAll(mods);
357: newMods.removeAll(elides);
358: return newMods;
359: }
360: }
361:
362: private void printFormalTypeParameters(ExecutableDeclaration e) {
363: printFormalTypeParameterSet(e.getFormalTypeParameters(),
364: true);
365: }
366:
367: private void printFormalTypeParameters(TypeDeclaration d) {
368: printFormalTypeParameterSet(d.getFormalTypeParameters(),
369: false);
370: }
371:
372: private void printFormalTypeParameterSet(
373: Collection<TypeParameterDeclaration> typeParams,
374: boolean pad) {
375: if (typeParams.size() != 0) {
376: System.out.print("<");
377:
378: boolean first = true;
379: for (TypeParameterDeclaration tpd : typeParams) {
380: if (!first)
381: System.out.print(", ");
382: System.out.print(tpd.toString());
383: }
384:
385: System.out.print(">");
386: if (pad)
387: System.out.print(" ");
388:
389: }
390: }
391:
392: private void printInterfaceSet(
393: Collection<InterfaceType> interfaces,
394: boolean classNotInterface) {
395: if (interfaces.size() != 0) {
396: System.out.print((classNotInterface ? " implements"
397: : " extends"));
398:
399: boolean first = true;
400: for (InterfaceType interType : interfaces) {
401: if (!first)
402: System.out.print(",");
403: System.out.print(" ");
404: System.out.print(interType.toString());
405: first = false;
406: }
407: }
408: }
409:
410: private void printInterfaces(TypeDeclaration d) {
411: printInterfaceSet(d.getSuperinterfaces(),
412: d instanceof ClassDeclaration);
413: }
414:
415: private void printInterfaces(AnnotationTypeDeclaration d) {
416: Collection<InterfaceType> interfaces = new HashSet<InterfaceType>(
417: d.getSuperinterfaces());
418:
419: for (InterfaceType interType : interfaces) {
420: if (java_lang_annotation_Annotation.equals(interType
421: .getDeclaration()))
422: interfaces.remove(interType);
423: }
424:
425: printInterfaceSet(interfaces, d instanceof ClassDeclaration);
426: }
427:
428: private void printThrows(ExecutableDeclaration d) {
429: Collection<ReferenceType> thrownTypes = d.getThrownTypes();
430: final int size = thrownTypes.size();
431: if (size != 0) {
432: System.out.print(" throws");
433:
434: int i = 1;
435: for (ReferenceType thrownType : thrownTypes) {
436: if (i == 1) {
437: System.out.print(" ");
438: }
439:
440: if (i == 2)
441: PrintingVisitors.this .indentation++;
442:
443: if (i >= 2)
444: System.out
445: .print(PrintingVisitors.this .indent());
446:
447: System.out.print(thrownType.toString());
448:
449: if (i != size) {
450: System.out.println(", ");
451: }
452: i++;
453: }
454:
455: if (size >= 2)
456: PrintingVisitors.this .indentation--;
457: }
458: }
459:
460: DeclarationVisitor getPrintingVisitor() {
461: return DeclarationVisitors
462: .getSourceOrderDeclarationScanner(
463: new PrePrinting(), new PostPrinting());
464: }
465: }
466:
467: AnnotationProcessorEnvironment env;
468:
469: PrintAP(AnnotationProcessorEnvironment env) {
470: this .env = env;
471: }
472:
473: public void process() {
474: Collection<TypeDeclaration> typedecls = env
475: .getSpecifiedTypeDeclarations();
476:
477: for (TypeDeclaration td : typedecls)
478: td.accept((new PrintingVisitors(env)).getPrintingVisitor());
479: }
480: }
|