1 /* 2 * Copyright 2004-2006 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 */ 25 26 package com.sun.tools.apt.comp; 27 28 import com.sun.mirror.declaration.*; 29 import static com.sun.mirror.declaration.Modifier.*; 30 import com.sun.mirror.type.*; 31 import com.sun.mirror.apt.*; 32 33 import java.util.*; 34 import com.sun.mirror.util.*; 35 36 /** 37 * Class used to implement "-print" option. 38 */ 39 public class PrintAP implements AnnotationProcessor { 40 41 42 static class PrintingVisitors { 43 int indentation = 0; // Indentation level; 44 AnnotationProcessorEnvironment env; 45 Messager out; 46 Declaration java_lang_Object; 47 Declaration java_lang_annotation_Annotation; 48 49 static Set<Modifier> EMPTY_ELIDES = Collections.emptySet(); 50 static Set<Modifier> INTERFACE_ELIDES = EnumSet.of(ABSTRACT); 51 static Set<Modifier> ENUM_ELIDES = EnumSet.of(FINAL, ABSTRACT); 52 static Set<Modifier> INTERFACE_MEMBER_ELIDES = EnumSet.of(ABSTRACT, PUBLIC, STATIC, FINAL); 53 54 PrintingVisitors(AnnotationProcessorEnvironment env) { 55 this.env = env; 56 this.out = env.getMessager(); 57 this.java_lang_Object = env.getTypeDeclaration("java.lang.Object"); 58 this.java_lang_annotation_Annotation = env.getTypeDeclaration("java.lang.annotation.Annotation"); 59 } 60 61 62 static String [] spaces = { 63 "", 64 " ", 65 " ", 66 " ", 67 " ", 68 " ", 69 " ", 70 " ", 71 " ", 72 " ", 73 " " 74 }; 75 76 77 String indent(){ 78 int indentation = this.indentation; 79 if (indentation < 0) 80 return ""; 81 else if (indentation <= 10) 82 return spaces[indentation]; 83 else { 84 StringBuilder sb = new StringBuilder(); 85 while (indentation > 10) { 86 sb.append(spaces[indentation]); 87 indentation -= 10; 88 } 89 sb.append(spaces[indentation]); 90 return sb.toString(); 91 } 92 } 93 94 95 class PrePrinting extends SimpleDeclarationVisitor { 96 Map<EnumDeclaration, Integer> enumCardinality = new HashMap<EnumDeclaration, Integer>(); 97 Map<EnumDeclaration, Integer> enumConstVisited = new HashMap<EnumDeclaration, Integer>(); 98 99 PrePrinting(){} 100 101 public void visitClassDeclaration(ClassDeclaration d) { 102 System.out.println(); 103 printDocComment(d); 104 printModifiers(d, EMPTY_ELIDES); 105 System.out.print("class " + d.getSimpleName()); 106 printFormalTypeParameters(d); 107 108 // Elide "extends Object" 109 ClassType Super = d.getSuperclass(); 110 if (Super != null && !java_lang_Object.equals(Super.getDeclaration()) ) 111 System.out.print(" extends " + Super.toString()); 112 113 printInterfaces(d); 114 115 System.out.println(" {"); 116 117 PrintingVisitors.this.indentation++; 118 } 119 120 public void visitEnumDeclaration(EnumDeclaration d) { 121 enumCardinality.put(d, d.getEnumConstants().size()); 122 enumConstVisited.put(d, 1); 123 124 System.out.println(); 125 printDocComment(d); 126 printModifiers(d, ENUM_ELIDES); 127 128 System.out.print("enum " + d.getSimpleName()); 129 printFormalTypeParameters(d); 130 printInterfaces(d); 131 132 System.out.println(" {"); 133 134 PrintingVisitors.this.indentation++; 135 } 136 137 138 public void visitInterfaceDeclaration(InterfaceDeclaration d) { 139 System.out.println(); 140 printDocComment(d); 141 printModifiers(d, INTERFACE_ELIDES); 142 System.out.print("interface " + d.getSimpleName()); 143 144 printFormalTypeParameters(d); 145 printInterfaces(d); 146 147 System.out.println(" {"); 148 149 PrintingVisitors.this.indentation++; 150 } 151 152 public void visitAnnotationTypeDeclaration(AnnotationTypeDeclaration d) { 153 System.out.println(); 154 printDocComment(d); 155 printModifiers(d, INTERFACE_ELIDES); 156 System.out.print("@interface " + d.getSimpleName()); 157 printFormalTypeParameters(d); 158 159 printInterfaces(d); 160 161 System.out.println(" {"); 162 163 PrintingVisitors.this.indentation++; 164 } 165 166 public void visitFieldDeclaration(FieldDeclaration d) { 167 System.out.println(); 168 printDocComment(d); 169 printModifiers(d, 170 (d.getDeclaringType() instanceof InterfaceDeclaration)? 171 INTERFACE_MEMBER_ELIDES : EMPTY_ELIDES); 172 System.out.print(d.getType().toString() + " " + 173 d.getSimpleName() ); 174 String constantExpr = d.getConstantExpression(); 175 if (constantExpr != null) { 176 System.out.print(" = " + constantExpr); 177 } 178 System.out.println(";" ); 179 } 180 181 public void visitEnumConstantDeclaration(EnumConstantDeclaration d) { 182 EnumDeclaration ed = d.getDeclaringType(); 183 int enumCard = enumCardinality.get(ed); 184 int enumVisit = enumConstVisited.get(ed); 185 186 System.out.println(); 187 printDocComment(d); 188 System.out.print(PrintingVisitors.this.indent()); 189 System.out.print(d.getSimpleName() ); 190 System.out.println((enumVisit < enumCard )? ",":";" ); 191 192 enumConstVisited.put(ed, enumVisit+1); 193 } 194 195 public void visitMethodDeclaration(MethodDeclaration d) { 196 System.out.println(); 197 printDocComment(d); 198 printModifiers(d, 199 (d.getDeclaringType() instanceof InterfaceDeclaration)? 200 INTERFACE_MEMBER_ELIDES : EMPTY_ELIDES); 201 printFormalTypeParameters(d); 202 System.out.print(d.getReturnType().toString() + " "); 203 System.out.print(d.getSimpleName() + "("); 204 printParameters(d); 205 System.out.print(")"); 206 printThrows(d); 207 System.out.println(";"); 208 } 209 210 public void visitConstructorDeclaration(ConstructorDeclaration d) { 211 System.out.println(); 212 printDocComment(d); 213 printModifiers(d, EMPTY_ELIDES); 214 printFormalTypeParameters(d); 215 System.out.print(d.getSimpleName() + "("); 216 printParameters(d); 217 System.out.print(")"); 218 printThrows(d); 219 System.out.println(";"); 220 } 221 222 223 } 224 225 class PostPrinting extends SimpleDeclarationVisitor { 226 PostPrinting(){} 227 228 public void visitTypeDeclaration(TypeDeclaration d) { 229 PrintingVisitors.this.indentation--; 230 231 System.out.print(PrintingVisitors.this.indent()); 232 System.out.println("}"); 233 } 234 } 235 236 private void printAnnotations(Collection<AnnotationMirror> annots) { 237 238 for(AnnotationMirror annot: annots) { 239 System.out.print(this.indent()); 240 System.out.print(annot.toString()); 241 System.out.println(); 242 } 243 } 244 245 private void printAnnotationsInline(Collection<AnnotationMirror> annots) { 246 247 for(AnnotationMirror annot: annots) { 248 System.out.print(annot); 249 System.out.print(" "); 250 } 251 } 252 253 254 private void printParameters(ExecutableDeclaration ex) { 255 256 Collection<ParameterDeclaration> parameters = ex.getParameters(); 257 int size = parameters.size(); 258 259 switch (size) { 260 case 0: 261 break; 262 263 case 1: 264 for(ParameterDeclaration parameter: parameters) { 265 printModifiers(parameter, EMPTY_ELIDES); 266 267 if (ex.isVarArgs() ) { 268 System.out.print(((ArrayType)parameter.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 { 278 int i = 1; 279 for(ParameterDeclaration parameter: parameters) { 280 if (i == 2) 281 PrintingVisitors.this.indentation++; 282 283 if (i > 1) 284 System.out.print(PrintingVisitors.this.indent()); 285 286 printModifiers(parameter, EMPTY_ELIDES); 287 288 if (i == size && ex.isVarArgs() ) { 289 System.out.print(((ArrayType)parameter.getType()).getComponentType() ); 290 System.out.print("..."); 291 } else 292 System.out.print(parameter.getType()); 293 System.out.print(" " + parameter.getSimpleName()); 294 295 if (i < size) 296 System.out.println(","); 297 298 i++; 299 } 300 301 if (parameters.size() >= 2) 302 PrintingVisitors.this.indentation--; 303 } 304 break; 305 } 306 } 307 308 private void printDocComment(Declaration d) { 309 String docComment = d.getDocComment(); 310 311 if (docComment != null) { 312 // Break comment into lines 313 java.util.StringTokenizer st = new StringTokenizer(docComment, 314 "\n\r"); 315 System.out.print(PrintingVisitors.this.indent()); 316 System.out.println("/**"); 317 318 while(st.hasMoreTokens()) { 319 System.out.print(PrintingVisitors.this.indent()); 320 System.out.print(" *"); 321 System.out.println(st.nextToken()); 322 } 323 324 System.out.print(PrintingVisitors.this.indent()); 325 System.out.println(" */"); 326 } 327 } 328 329 private void printModifiers(Declaration d, Collection<Modifier> elides) { 330 printAnnotations(d.getAnnotationMirrors()); 331 332 System.out.print(PrintingVisitors.this.indent()); 333 334 for(Modifier m: adjustModifiers(d.getModifiers(), elides) ){ 335 System.out.print(m.toString() + " "); 336 } 337 } 338 339 private void printModifiers(ParameterDeclaration d, Collection<Modifier> elides) { 340 printAnnotationsInline(d.getAnnotationMirrors()); 341 342 for(Modifier m: adjustModifiers(d.getModifiers(), elides) ) { 343 System.out.print(m.toString() + " "); 344 } 345 } 346 347 private Collection<Modifier> adjustModifiers(Collection<Modifier> mods, 348 Collection<Modifier> elides) { 349 if (elides.isEmpty()) 350 return mods; 351 else { 352 Collection<Modifier> newMods = new LinkedHashSet<Modifier>(); 353 newMods.addAll(mods); 354 newMods.removeAll(elides); 355 return newMods; 356 } 357 } 358 359 private void printFormalTypeParameters(ExecutableDeclaration e) { 360 printFormalTypeParameterSet(e.getFormalTypeParameters(), true); 361 } 362 363 private void printFormalTypeParameters(TypeDeclaration d) { 364 printFormalTypeParameterSet(d.getFormalTypeParameters(), false); 365 } 366 367 private void printFormalTypeParameterSet(Collection<TypeParameterDeclaration> typeParams, boolean pad) { 368 if (typeParams.size() != 0) { 369 System.out.print("<"); 370 371 boolean first = true; 372 for(TypeParameterDeclaration tpd: typeParams) { 373 if (!first) 374 System.out.print(", "); 375 System.out.print(tpd.toString()); 376 } 377 378 System.out.print(">"); 379 if (pad) 380 System.out.print(" "); 381 382 } 383 } 384 385 private void printInterfaceSet(Collection<InterfaceType> interfaces, 386 boolean classNotInterface) { 387 if (interfaces.size() != 0) { 388 System.out.print((classNotInterface?" implements" : " extends")); 389 390 boolean first = true; 391 for(InterfaceType interType: interfaces) { 392 if (!first) 393 System.out.print(","); 394 System.out.print(" "); 395 System.out.print(interType.toString()); 396 first = false; 397 } 398 } 399 } 400 401 private void printInterfaces(TypeDeclaration d) { 402 printInterfaceSet(d.getSuperinterfaces(), d instanceof ClassDeclaration); 403 } 404 405 private void printInterfaces(AnnotationTypeDeclaration d) { 406 Collection<InterfaceType> interfaces = new HashSet<InterfaceType>(d.getSuperinterfaces()); 407 408 for(InterfaceType interType: interfaces) { 409 if (java_lang_annotation_Annotation.equals(interType.getDeclaration()) ) 410 interfaces.remove(interType); 411 } 412 413 printInterfaceSet(interfaces, d instanceof ClassDeclaration); 414 } 415 416 private void printThrows(ExecutableDeclaration d) { 417 Collection<ReferenceType> thrownTypes = d.getThrownTypes(); 418 final int size = thrownTypes.size(); 419 if (size != 0) { 420 System.out.print(" throws"); 421 422 int i = 1; 423 for(ReferenceType thrownType: thrownTypes) { 424 if (i == 1) { 425 System.out.print(" "); 426 } 427 428 if (i == 2) 429 PrintingVisitors.this.indentation++; 430 431 if (i >= 2) 432 System.out.print(PrintingVisitors.this.indent()); 433 434 System.out.print(thrownType.toString()); 435 436 437 if (i != size) { 438 System.out.println(", "); 439 } 440 i++; 441 } 442 443 if (size >= 2) 444 PrintingVisitors.this.indentation--; 445 } 446 } 447 448 DeclarationVisitor getPrintingVisitor() { 449 return DeclarationVisitors.getSourceOrderDeclarationScanner(new PrePrinting(), 450 new PostPrinting()); 451 } 452 } 453 454 AnnotationProcessorEnvironment env; 455 PrintAP(AnnotationProcessorEnvironment env) { 456 this.env = env; 457 } 458 459 460 public void process() { 461 Collection<TypeDeclaration> typedecls = env.getSpecifiedTypeDeclarations(); 462 463 for (TypeDeclaration td: typedecls) 464 td.accept((new PrintingVisitors(env)).getPrintingVisitor()); 465 } 466 }