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