001: /*
002: * Copyright 2005-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.javac.processing;
027:
028: import com.sun.tools.javac.util.Version;
029: import javax.annotation.processing.*;
030: import javax.lang.model.*;
031: import javax.lang.model.element.*;
032: import static javax.lang.model.element.ElementKind.*;
033: import static javax.lang.model.element.NestingKind.*;
034: import javax.lang.model.type.*;
035: import javax.lang.model.util.*;
036: import static javax.lang.model.util.ElementFilter.*;
037:
038: import java.io.PrintWriter;
039: import java.io.Writer;
040: import java.util.*;
041:
042: /**
043: * A processor which prints out elements. Used to implement the
044: * -Xprint option; the included visitor class is used to implement
045: * Elements.printElements.
046: *
047: * <p><b>This is NOT part of any API supported by Sun Microsystems.
048: * If you write code that depends on this, you do so at your own risk.
049: * This code and its internal interfaces are subject to change or
050: * deletion without notice.</b>
051: */
052: @SupportedAnnotationTypes("*")
053: @SupportedSourceVersion(SourceVersion.RELEASE_6)
054: @Version("@(#)PrintingProcessor.java 1.13 07/05/05")
055: public class PrintingProcessor extends AbstractProcessor {
056: PrintWriter writer;
057:
058: public PrintingProcessor() {
059: super ();
060: writer = new PrintWriter(System.out);
061: }
062:
063: public void setWriter(Writer w) {
064: writer = new PrintWriter(w);
065: }
066:
067: @Override
068: public boolean process(Set<? extends TypeElement> tes,
069: RoundEnvironment renv) {
070:
071: for (Element element : renv.getRootElements()) {
072: print(element);
073: }
074:
075: // Just print the elements, nothing more to do.
076: return true;
077: }
078:
079: void print(Element element) {
080: new PrintingElementVisitor(writer, processingEnv
081: .getElementUtils()).visit(element).flush();
082: }
083:
084: /**
085: * Used for the -Xprint option and called by Elements.printElements
086: */
087: public static class PrintingElementVisitor extends
088: SimpleElementVisitor6<PrintingElementVisitor, Boolean> {
089: int indentation; // Indentation level;
090: final PrintWriter writer;
091: final Elements elementUtils;
092:
093: public PrintingElementVisitor(Writer w, Elements elementUtils) {
094: super ();
095: this .writer = new PrintWriter(w);
096: this .elementUtils = elementUtils;
097: indentation = 0;
098: }
099:
100: @Override
101: protected PrintingElementVisitor defaultAction(Element e,
102: Boolean newLine) {
103: if (newLine != null && newLine)
104: writer.println();
105: printDocComment(e);
106: printModifiers(e);
107: return this ;
108: }
109:
110: @Override
111: public PrintingElementVisitor visitExecutable(
112: ExecutableElement e, Boolean p) {
113: ElementKind kind = e.getKind();
114:
115: if (kind != STATIC_INIT && kind != INSTANCE_INIT) {
116: Element enclosing = e.getEnclosingElement();
117:
118: // Don't print out the constructor of an anonymous class
119: if (kind == CONSTRUCTOR && enclosing != null
120: && NestingKind.ANONYMOUS ==
121: // Use an anonymous class to determine anonymity!
122: (new SimpleElementVisitor6<NestingKind, Void>() {
123: @Override
124: public NestingKind visitType(TypeElement e,
125: Void p) {
126: return e.getNestingKind();
127: }
128: }).visit(enclosing))
129: return this ;
130:
131: defaultAction(e, true);
132: printFormalTypeParameters(e);
133:
134: switch (kind) {
135: case CONSTRUCTOR:
136: // Print out simple name of the class
137: writer.print(e.getEnclosingElement()
138: .getSimpleName());
139: break;
140:
141: case METHOD:
142: writer.print(e.getReturnType().toString());
143: writer.print(" ");
144: writer.print(e.getSimpleName().toString());
145: break;
146: }
147:
148: writer.print("(");
149: printParameters(e);
150: writer.print(")");
151: AnnotationValue defaultValue = e.getDefaultValue();
152: if (defaultValue != null)
153: writer.print(" default " + defaultValue);
154:
155: printThrows(e);
156: writer.println(";");
157: }
158: return this ;
159: }
160:
161: @Override
162: public PrintingElementVisitor visitType(TypeElement e, Boolean p) {
163: ElementKind kind = e.getKind();
164: NestingKind nestingKind = e.getNestingKind();
165:
166: if (NestingKind.ANONYMOUS == nestingKind) {
167: // Print out an anonymous class in the style of a
168: // class instance creation expression rather than a
169: // class declaration.
170: writer.print("new ");
171:
172: // If the anonymous class implements an interface
173: // print that name, otherwise print the superclass.
174: List<? extends TypeMirror> interfaces = e
175: .getInterfaces();
176: if (!interfaces.isEmpty())
177: writer.print(interfaces.get(0));
178: else
179: writer.print(e.getSuperclass());
180:
181: writer.print("(");
182: // Anonymous classes that implement an interface can't
183: // have any constructor arguments.
184: if (interfaces.isEmpty()) {
185: // Print out the parameter list from the sole
186: // constructor. For now, don't try to elide any
187: // synthetic parameters by determining if the
188: // anonymous class is in a static context, etc.
189: List<? extends ExecutableElement> constructors = ElementFilter
190: .constructorsIn(e.getEnclosedElements());
191:
192: if (!constructors.isEmpty())
193: printParameters(constructors.get(0));
194: }
195: writer.print(")");
196: } else {
197: if (nestingKind == TOP_LEVEL) {
198: PackageElement pkg = elementUtils.getPackageOf(e);
199: if (!pkg.isUnnamed())
200: writer.print("package "
201: + pkg.getQualifiedName() + ";\n");
202: }
203:
204: defaultAction(e, true);
205:
206: switch (kind) {
207: case ANNOTATION_TYPE:
208: writer.print("@interface");
209: break;
210: default:
211: writer.print(kind.toString().toLowerCase());
212: }
213: writer.print(" ");
214: writer.print(e.getSimpleName());
215:
216: printFormalTypeParameters(e);
217:
218: // Print superclass information if informative
219: if (kind == CLASS) {
220: TypeMirror super type = e.getSuperclass();
221: if (super type.getKind() != TypeKind.NONE) {
222: TypeElement e2 = (TypeElement) ((DeclaredType) super type)
223: .asElement();
224: if (e2.getSuperclass().getKind() != TypeKind.NONE)
225: writer.print(" extends " + super type);
226: }
227: }
228:
229: printInterfaces(e);
230: }
231: writer.println(" {");
232: indentation++;
233:
234: if (kind == ENUM) {
235: List<Element> enclosedElements = new ArrayList<Element>(
236: e.getEnclosedElements());
237: List<Element> enumConstants = new ArrayList<Element>();
238: for (Element element : enclosedElements) {
239: if (element.getKind() == ENUM_CONSTANT)
240: enumConstants.add(element);
241: }
242:
243: int i;
244: for (i = 0; i < enumConstants.size() - 1; i++) {
245: this .visit(enumConstants.get(i), true);
246: writer.print(",");
247: }
248: if (i >= 0) {
249: this .visit(enumConstants.get(i), true);
250: writer.print(";");
251: }
252:
253: enclosedElements.removeAll(enumConstants);
254: for (Element element : enclosedElements)
255: this .visit(element);
256: } else {
257: for (Element element : e.getEnclosedElements())
258: this .visit(element);
259: }
260:
261: indentation--;
262: indent();
263: writer.println("}");
264: return this ;
265: }
266:
267: @Override
268: public PrintingElementVisitor visitVariable(VariableElement e,
269: Boolean newLine) {
270: ElementKind kind = e.getKind();
271: defaultAction(e, newLine);
272:
273: if (kind == ENUM_CONSTANT)
274: writer.print(e.getSimpleName());
275: else {
276: writer.print(e.asType().toString() + " "
277: + e.getSimpleName());
278: Object constantValue = e.getConstantValue();
279: if (constantValue != null) {
280: writer.print(" = ");
281: writer.print(elementUtils
282: .getConstantExpression(constantValue));
283: }
284: writer.println(";");
285: }
286: return this ;
287: }
288:
289: @Override
290: public PrintingElementVisitor visitTypeParameter(
291: TypeParameterElement e, Boolean p) {
292: writer.print(e.getSimpleName());
293: return this ;
294: }
295:
296: // Should we do more here?
297: @Override
298: public PrintingElementVisitor visitPackage(PackageElement e,
299: Boolean p) {
300: defaultAction(e, false);
301: if (!e.isUnnamed())
302: writer.println("package " + e.getQualifiedName() + ";");
303: else
304: writer.println("// Unnamed package");
305: return this ;
306: }
307:
308: public void flush() {
309: writer.flush();
310: }
311:
312: private void printDocComment(Element e) {
313: String docComment = elementUtils.getDocComment(e);
314:
315: if (docComment != null) {
316: // Break comment into lines
317: java.util.StringTokenizer st = new StringTokenizer(
318: docComment, "\n\r");
319: indent();
320: writer.println("/**");
321:
322: while (st.hasMoreTokens()) {
323: indent();
324: writer.print(" *");
325: writer.println(st.nextToken());
326: }
327:
328: indent();
329: writer.println(" */");
330: }
331: }
332:
333: private void printModifiers(Element e) {
334: ElementKind kind = e.getKind();
335: if (kind == PARAMETER) {
336: printAnnotationsInline(e);
337: } else {
338: printAnnotations(e);
339: indent();
340: }
341:
342: if (kind == ENUM_CONSTANT)
343: return;
344:
345: Set<Modifier> modifiers = new LinkedHashSet<Modifier>();
346: modifiers.addAll(e.getModifiers());
347:
348: switch (kind) {
349: case ANNOTATION_TYPE:
350: case INTERFACE:
351: modifiers.remove(Modifier.ABSTRACT);
352: break;
353:
354: case ENUM:
355: modifiers.remove(Modifier.FINAL);
356: modifiers.remove(Modifier.ABSTRACT);
357: break;
358:
359: case METHOD:
360: case FIELD:
361: Element enclosingElement = e.getEnclosingElement();
362: if (enclosingElement != null
363: && enclosingElement.getKind().isInterface()) {
364: modifiers.remove(Modifier.PUBLIC);
365: modifiers.remove(Modifier.ABSTRACT); // only for methods
366: modifiers.remove(Modifier.STATIC); // only for fields
367: modifiers.remove(Modifier.FINAL); // only for fields
368: }
369: break;
370:
371: }
372:
373: for (Modifier m : modifiers) {
374: writer.print(m.toString() + " ");
375: }
376: }
377:
378: private void printFormalTypeParameters(
379: ExecutableElement executable) {
380: printFormalTypeParameters(executable.getTypeParameters(),
381: true);
382: }
383:
384: private void printFormalTypeParameters(TypeElement type) {
385: printFormalTypeParameters(type.getTypeParameters(), false);
386: }
387:
388: private void printFormalTypeParameters(
389: List<? extends TypeParameterElement> typeParams,
390: boolean pad) {
391: if (typeParams.size() > 0) {
392: writer.print("<");
393:
394: boolean first = true;
395: for (TypeParameterElement tpe : typeParams) {
396: if (!first)
397: writer.print(", ");
398: writer.print(tpe.toString());
399: first = false;
400: }
401:
402: writer.print(">");
403: if (pad)
404: writer.print(" ");
405: }
406: }
407:
408: private void printAnnotationsInline(Element e) {
409: List<? extends AnnotationMirror> annots = e
410: .getAnnotationMirrors();
411: for (AnnotationMirror annotationMirror : annots) {
412: writer.print(annotationMirror);
413: writer.print(" ");
414: }
415: }
416:
417: private void printAnnotations(Element e) {
418: List<? extends AnnotationMirror> annots = e
419: .getAnnotationMirrors();
420: for (AnnotationMirror annotationMirror : annots) {
421: indent();
422: writer.println(annotationMirror);
423: }
424: }
425:
426: // TODO: Refactor
427: private void printParameters(ExecutableElement e) {
428: List<? extends VariableElement> parameters = e
429: .getParameters();
430: int size = parameters.size();
431:
432: switch (size) {
433: case 0:
434: break;
435:
436: case 1:
437: for (VariableElement parameter : parameters) {
438: printModifiers(parameter);
439:
440: if (e.isVarArgs()) {
441: TypeMirror tm = parameter.asType();
442: if (tm.getKind() != TypeKind.ARRAY)
443: throw new AssertionError(
444: "Var-args parameter is not an array type: "
445: + tm);
446: writer.print((ArrayType.class.cast(tm))
447: .getComponentType());
448: writer.print("...");
449: } else
450: writer.print(parameter.asType());
451: writer.print(" " + parameter.getSimpleName());
452: }
453: break;
454:
455: default: {
456: int i = 1;
457: for (VariableElement parameter : parameters) {
458: if (i == 2)
459: indentation++;
460:
461: if (i > 1)
462: indent();
463:
464: printModifiers(parameter);
465:
466: if (i == size && e.isVarArgs()) {
467: TypeMirror tm = parameter.asType();
468: if (tm.getKind() != TypeKind.ARRAY)
469: throw new AssertionError(
470: "Var-args parameter is not an array type: "
471: + tm);
472: writer.print((ArrayType.class.cast(tm))
473: .getComponentType());
474:
475: writer.print("...");
476: } else
477: writer.print(parameter.asType());
478: writer.print(" " + parameter.getSimpleName());
479:
480: if (i < size)
481: writer.println(",");
482:
483: i++;
484: }
485:
486: if (parameters.size() >= 2)
487: indentation--;
488: }
489: break;
490: }
491: }
492:
493: private void printInterfaces(TypeElement e) {
494: ElementKind kind = e.getKind();
495:
496: if (kind != ANNOTATION_TYPE) {
497: List<? extends TypeMirror> interfaces = e
498: .getInterfaces();
499: if (interfaces.size() > 0) {
500: writer.print((kind.isClass() ? " implements"
501: : " extends"));
502:
503: boolean first = true;
504: for (TypeMirror interf : interfaces) {
505: if (!first)
506: writer.print(",");
507: writer.print(" ");
508: writer.print(interf.toString());
509: first = false;
510: }
511: }
512: }
513: }
514:
515: private void printThrows(ExecutableElement e) {
516: List<? extends TypeMirror> thrownTypes = e.getThrownTypes();
517: final int size = thrownTypes.size();
518: if (size != 0) {
519: writer.print(" throws");
520:
521: int i = 1;
522: for (TypeMirror thrownType : thrownTypes) {
523: if (i == 1)
524: writer.print(" ");
525:
526: if (i == 2)
527: indentation++;
528:
529: if (i >= 2)
530: indent();
531:
532: writer.print(thrownType);
533:
534: if (i != size)
535: writer.println(", ");
536:
537: i++;
538: }
539:
540: if (size >= 2)
541: indentation--;
542: }
543: }
544:
545: private static final String[] spaces = { "", " ", " ",
546: " ", " ", " ", " ",
547: " ", " ",
548: " ", " " };
549:
550: private void indent() {
551: int indentation = this .indentation;
552: if (indentation < 0)
553: return;
554: final int maxIndex = spaces.length - 1;
555:
556: while (indentation > maxIndex) {
557: writer.print(spaces[maxIndex]);
558: indentation -= maxIndex;
559: }
560: writer.print(spaces[indentation]);
561: }
562:
563: }
564: }
|