001package Torello.JavaDoc; 002 003 004// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 005// Standard-Java Imports 006// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 007 008import java.util.*; 009 010import java.io.IOException; 011import java.util.function.Consumer; 012 013 014// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 015// Java-HTML Imports 016// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 017 018import Torello.Java.*; 019 020import static Torello.Java.C.*; 021import static Torello.JavaDoc.PF.*; 022 023import Torello.Java.ReadOnly.ReadOnlyList; 024import Torello.Java.ReadOnly.ReadOnlyArrayList; 025import Torello.Java.ReadOnly.ROArrayListBuilder; 026import Torello.Java.Additional.Ret2; 027 028 029// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 030// JDUInternal 031// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 032 033import Torello.JDUInternal.Annotations.EntityAnnotations.Mirror.EntityAnnotationMirrors; 034import Torello.JDUInternal.Annotations.EntityAnnotations.EntityAnnotationData; 035 036import Torello.JDUInternal.Parse.Java.Location.LocationBuilder1; 037import Torello.JDUInternal.Parse.Java.Location.LocationBuilder2; 038 039// NOTE: Here is the Code that uses LocationBuilder1 and 2... It tells you which of the two 040// is applied, and when, and why... 041// 042// this.location = (entity == Entity.INNER_CLASS) 043// ? LocationBuilder2.build(util, tree, util.getJavaDocCommentTree(tree)) 044// : LocationBuilder1.build(...) 045 046 047// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 048// The new Source-Code Parser: com.sun.source.* 049// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 050 051import com.sun.source.util.*; 052import com.sun.source.tree.*; 053import com.sun.source.doctree.*; 054 055 056/** 057 * <B CLASS=JDDescLabel>Reflection Class:</B> 058 * 059 * <BR />Common-Root Ancestor Class of all Bridge Data-Classes. 060 * 061 * <BR /><BR /> 062 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_DECLARATION> 063 */ 064@JDHeaderBackgroundImg 065public abstract class Declaration implements java.io.Serializable 066{ 067 /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */ 068 public static final long serialVersionUID = 1; 069 070 /** 071 * For the purposes of passing these around to different parts of the code, every one of these 072 * are given a unique ID. This id is unique for a method, whether it was parsed from a detail 073 * or a summary section. This id is (probably) not useful outside of the HTML Processor 074 * Classes. 075 * 076 * <BR /><BR /><B CLASS=JDDescLabel>ID Clone:</B> 077 * 078 * <BR />If a subclass of {@code Declaration} is cloned, then this {@code id} field is also 079 * cloned / copied. 080 */ 081 public final int id; 082 083 // The id is just created using this counter. 084 private static int idCounter = 1; 085 086 // Used for Modifiers and other Empty ReadOnlyLists's of String 087 static final ReadOnlyList<String> EMPTY_READONLY_LIST = ReadOnlyList.of(); 088 089 /** 090 * This returns the {@code String} that is to be sent to the Syntax {@link HiLiter}. This is 091 * the code inserted into the "HiLited Code" Part (at the end) of a Details Entry on a Java-Doc 092 * Web Page. 093 * 094 * <BR /><BR />On the part of a Java-Doc Web-Page having a "Method Detail", the Method's 095 * HiLited Source-Code body is obtained by the Upgrader-Logic using this here method. 096 * 097 * <BR /><BR /><B CLASS=JDDescLabel>Sub-Class Return Values:</B> 098 * 099 * <BR />This method is overloaded by all sub-classes, and returns values as follows: 100 * 101 * <BR /><BR /><UL CLASS=JDUL> 102 * <LI>{@link Method} will return its {@link Callable#body} field.</LI> 103 * <LI>{@link Constructor} will return its {@link Callable#body} field.</LI> 104 * <LI>{@link Field} will return the {@link #signature} field</LI> 105 * <LI>{@link EnumConstant} will return the {@link #signature} field</LI> 106 * <LI>{@link AnnotationElem} will return the {@link #signature} field</LI> 107 * <LI>{@link NestedType} will always return null</LI> 108 * </UL> 109 * 110 * @return The {@code String} that is ultimately sent to the Syntax HiLiter, and inserted 111 * into a Java Doc page. 112 * 113 * This is package-private, and isn't useful enough to put into the API - this is used 114 * internally, only. 115 */ 116 abstract String codeHiLiteString(); 117 118 // Package-Private. This only processes Java-Doc Upgrader Annotations. Any other Annotations 119 // which are placed on a Detail-Element can be found in: 120 // 121 // public ReadOnlyList<String> annotations 122 // 123 // However, they will just be the "Raw Sting" version of the Annotation. No More, No Less 124 125 public final EntityAnnotationMirrors jduAnnotationMirrors; 126 127 128 // ******************************************************************************************** 129 // ******************************************************************************************** 130 // Basic String-Fields 131 // ******************************************************************************************** 132 // ******************************************************************************************** 133 134 135 /** 136 * The <B>Name</B> of the java {@link Field}, {@link Method}, {@code Constructor}, 137 * {@link EnumConstant} or {@link AnnotationElem}. This will be a <B>simple, standard</B> 138 * 'Java Identifier'. 139 * 140 * <BR /><BR />Note that the name of a {@code Constructor} (for-example) is always just the 141 * name of the class. 142 * 143 * <BR /><BR />This field will never be null. 144 */ 145 public final String name; 146 147 /** 148 * The complete, declared <B>Signature</B> (as a {@code String}) of the {@link Method}, 149 * {@link Field}, {@link Constructor}, {@link EnumConstant} or {@link AnnotationElem}. 150 * 151 * <BR /><BR />This field would never be null. 152 */ 153 public final String signature; 154 155 /** 156 * The <B>Java Doc Comment</B> of this <B>'{@link Entity}'</B> ({@link Field}, {@link Method}, 157 * {@code Constructor}, {@link EnumConstant}, {@link AnnotationElem} or {@link NestedType}) as 158 * a {@code String} - if one exists. The Java Doc Comment is the one defined directly above 159 * the {@code Declaration}. 160 * 161 * <BR /><BR />If this <CODE>Entity</CODE> / Member ({@code Field, Method, Constructor} etc...) 162 * did not have a Java Doc Comment placed on it, <I>then this field {@code 'jdComment'} will be 163 * {@code null}.</I> 164 */ 165 public final String jdComment; 166 167 /** 168 * The <B>Body</B> of this <B>'{@link Entity}'</B> ({@link Field}, {@link Method}, 169 * {@code Constructor}, {@link EnumConstant}, {@link AnnotationElem} or {@link NestedType}) as 170 * a {@code String} - if one exists. 171 * 172 * <BR /><BR />If this <CODE>Entity</CODE> / Member ({@code Field, Method, Constructor} etc...) 173 * did not have a body, <I>then this field {@code 'body'} will be {@code null}.</I> 174 * 175 * <BR /><BR />The {@code 'body'} of a {@code Method} or {@code Constructor} is exactly the 176 * code that comprises it. If the method is {@code abstract}, then the method will not have a 177 * body, and in such cases this field will be null. If this member / entity is a {@link Field} 178 * then the body is the initializer of the {@code Field}. Again, if there were no initializer 179 * for the field, then {@code 'body'} would also be null. 180 */ 181 public final String body; 182 183 184 // ******************************************************************************************** 185 // ******************************************************************************************** 186 // Non-Basic Fields 187 // ******************************************************************************************** 188 // ******************************************************************************************** 189 190 191 /** 192 * This just stores the type of {@link Entity} this is. For sub-classes instances of 193 * {@link Declaration} which are {@link Method}, this field will be equal to 194 * {@link Entity#METHOD}. For instances of the {@link Field} sub-class, this will equal 195 * {@link Entity#FIELD}, and so on and so forth. 196 * 197 * <BR /><BR />Mostly, this makes code easier to read when used along-side <B>if-statements</B> 198 * or <B>switch-statements</B>. This field somewhat akin to {@code Declaration.getClass()} 199 * (when retrieving the specific {@code Declaration} sub-class type). 200 * 201 * <BR /><BR /><B CLASS=JDDescLabel>Reminder:</B> 202 * 203 * <BR />Both this class, and sub-class {@code Callable} are declared {@code abstract}, and 204 * only instances of Method, Field, Constructor, etc... can be instantiated. Only 205 * non-{@code abstract} implementations of this class need to worry about assigning this field 206 * to any real-value. 207 */ 208 public final Entity entity; 209 210 /** Location instance that contains character-locations within the original Java Source-File */ 211 public final Location location; 212 213 214 // ******************************************************************************************** 215 // ******************************************************************************************** 216 // ReadOnlyList<String> Fields 217 // ******************************************************************************************** 218 // ******************************************************************************************** 219 220 221 /** 222 * The {@code 'modifiers'} placed on this {@code Declaration}, including {@code String's} 223 * such as: {@code public, static, final} etc... 224 */ 225 public ReadOnlyList<String> modifiers; 226 227 /** <EMBED CLASS='external-html' DATA-FILE-ID=JPB_DECL_ANNOT> */ 228 public ReadOnlyList<String> annotations; 229 230 231 // ******************************************************************************************** 232 // ******************************************************************************************** 233 // Constructor - com.sun.source.tree 234 // ******************************************************************************************** 235 // ******************************************************************************************** 236 237 238 // package-private: Only used by subclasses. 239 Declaration( 240 final EntityAnnotationData ead, 241 final TreeUtils util, 242 final Tree tree, 243 final ModifiersTree mt, 244 final String name, 245 final Entity entity, 246 final Tree body 247 ) 248 { 249 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 250 // Pre-Liminary 251 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 252 253 this.id = idCounter++; 254 this.name = name; 255 this.entity = entity; 256 257 258 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 259 // The Annotations Placed on this Declaration 260 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 261 // 262 // NOTE: For EnumConstant's, the passed Modifiers-Tree is just null! 263 264 // List<? extends AnnotationTree> annotList = ... 265 @SuppressWarnings("unchecked") 266 final List<AnnotationTree> annotList = (mt == null) 267 ? null 268 : (List<AnnotationTree>) mt.getAnnotations(); 269 270 if ((annotList == null) || (annotList.size() == 0)) 271 this.annotations = EMPTY_READONLY_LIST; 272 273 else this.annotations = new ReadOnlyArrayList<String> 274 (annotList, (AnnotationTree at) -> at.toString().trim(), annotList.size()); 275 276 277 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 278 // The Modifiers that Flag this Declaration (private, public, static, final, etc...) 279 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 280 // 281 // NOTE: For EnumConstant's, the passed Modifiers-Tree is just null! 282 283 final Set<javax.lang.model.element.Modifier> modSet = (mt == null) 284 ? null 285 : mt.getFlags(); 286 287 if ((modSet == null) || (modSet.size() == 0)) 288 this.modifiers = EMPTY_READONLY_LIST; 289 290 else this.modifiers = new ReadOnlyArrayList<String> 291 (modSet, (javax.lang.model.element.Modifier m) -> m.toString().trim(), modSet.size()); 292 293 294 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 295 // Location 296 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 297 298 this.location = (entity == Entity.INNER_CLASS) 299 300 ? LocationBuilder2.build(util, tree, util.getJavaDocCommentTree(tree)) 301 302 : LocationBuilder1.build( 303 util, tree, util.getJavaDocCommentTree(tree), body, 304 (entity == Entity.FIELD) ? body : null 305 ); 306 307 308 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 309 // Now the String's 310 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 311 312 this.signature = util.srcFileAsStr.substring 313 (this.location.signatureStartPos, this.location.signatureEndPos); 314 315 this.jdComment = (this.location.jdcStartPos == -1) 316 ? null 317 : util.srcFileAsStr.substring(this.location.jdcStartPos, this.location.jdcEndPos); 318 319 this.body = (this.location.bodyStartPos == -1) 320 ? null 321 : util.srcFileAsStr.substring(this.location.bodyStartPos, this.location.bodyEndPos); 322 323 324 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 325 // The JavaDoc-Upgrader SPECIFIC Annotations. These are handled & Processed by JDU 326 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 327 328 if ((annotList == null) || (annotList.size() == 0)) 329 this.jduAnnotationMirrors = EntityAnnotationMirrors.EMPTY_MIRROR; 330 331 332 // Because `this.signature` is passed to this constructor, this whole invocation has to be 333 // at the end of the method, instead of above - where the annotations were processed! 334 // 335 // NOTE: The `annotList` variable was created way above, at the top of this constructor! 336 337 else this.jduAnnotationMirrors = (entity != Entity.INNER_CLASS) 338 ? new EntityAnnotationMirrors(annotList, this.signature, ead) 339 : EntityAnnotationMirrors.EMPTY_MIRROR; 340 } 341 342 343 // ******************************************************************************************** 344 // ******************************************************************************************** 345 // Constructor - synthetic methods 346 // ******************************************************************************************** 347 // ******************************************************************************************** 348 349 350 // Used only by the Callable Subclass, for building instances of derived/synthetic methods 351 // and constructors. (For instance, an enum has 'valueOf()' and 'values()') 352 // These methods do not have a location or a jdComment or even a body to hilite 353 354 Declaration(String name, Entity entity, String signature) 355 { 356 this.id = idCounter++; 357 this.name = name; 358 this.entity = entity; 359 this.modifiers = EMPTY_READONLY_LIST; 360 this.annotations = EMPTY_READONLY_LIST; 361 this.signature = signature; 362 this.jduAnnotationMirrors = EntityAnnotationMirrors.EMPTY_MIRROR; 363 364 // Since this constructor is only used for "Synthetic Methods" (barely ever used), it is no 365 // big deal to just assign these null; 366 367 this.location = null; 368 this.jdComment = null; 369 this.body = null; 370 } 371 372 // Not private - used by sub-classes 373 Declaration(Declaration d) 374 { 375 this.id = d.id; 376 this.annotations = d.annotations; 377 this.modifiers = d.modifiers; 378 this.name = d.name; 379 this.signature = d.signature; 380 this.jdComment = d.jdComment; 381 this.body = d.body; 382 this.entity = d.entity; 383 this.location = d.location; 384 this.jduAnnotationMirrors = d.jduAnnotationMirrors; 385 } 386 387 388 // ******************************************************************************************** 389 // ******************************************************************************************** 390 // Package-Private toString-HELPERS: Used by all subclasses 'toString(int flags)' methods 391 // ******************************************************************************************** 392 // ******************************************************************************************** 393 394 395 Ret2<Boolean, Boolean> jowFlags(int flags) 396 { 397 boolean onlyJOW = (flags & JOW_INSTEAD) > 0; 398 boolean addJOW = (flags & JOW_ALSO) > 0; 399 400 // "onlyJOW" has a higher FLAG-PRECEDENCY 401 if (onlyJOW && addJOW) addJOW = false; 402 403 return new Ret2<>(addJOW, onlyJOW); 404 } 405 406 String printedName(String entity, int numSpaces, boolean color) 407 { 408 return 409 StringParse.rightSpacePad(entity + " Name:", numSpaces) + 410 "[" + (color ? BCYAN : "") + name + (color ? RESET : "") + "]\n"; 411 } 412 413 String printedSignature(int numSpaces, boolean color) 414 { 415 return 416 StringParse.rightSpacePad("Signature:", numSpaces) + 417 "[" + (color ? BYELLOW : "") + 418 StrPrint.abbrevEndRDSF(signature, MAX_STR_LEN, true) + 419 (color ? RESET : "") + "]\n"; 420 } 421 422 String printedDeclaration(int numSpaces, boolean color) 423 { 424 return 425 StringParse.rightSpacePad("Declaration:", numSpaces) + 426 "[" + (color ? BYELLOW : "") + 427 StrPrint.abbrevEndRDSF(signature, MAX_STR_LEN, true) + 428 (color ? RESET : "") + "]\n"; 429 } 430 431 String printedModifiers(int numSpaces) 432 { 433 return 434 StringParse.rightSpacePad("Modifiers:", numSpaces) + 435 "[" + StrCSV.toCSV(modifiers, true, true, null) + "]\n"; 436 } 437 438 String printedComments(int numSpaces, boolean color, boolean comments) 439 { 440 if (! comments) 441 return ""; 442 443 else if (jdComment == null) return 444 "\n" + 445 StringParse.rightSpacePad("JD Comments:", numSpaces) + 446 (color ? BRED : "") + "None Available / Not Included" + (color ? RESET : ""); 447 448 else return 449 "\n" + 450 StringParse.rightSpacePad("JD Comments:", numSpaces) + 451 "[" + 452 (color ? BGREEN : "") + 453 StrPrint.abbrevEndRDSF(jdComment, MAX_STR_LEN, true) + 454 (color ? RESET : "") + 455 "]"; 456 } 457 458 // NOTE: This is always the last item printed to the output-string. This line *DOES NOT* end 459 // with a new-line '\n' character. 460 461 String printedLocation(int numSpaces, boolean color, boolean briefLocation) 462 { 463 if (location == null) return StringParse.rightSpacePad("Location:", numSpaces) + "null"; 464 465 if (briefLocation) return color 466 ? 467 (StringParse.rightSpacePad("Location:", numSpaces) + 468 "[" + 469 "signature-line=" + BRED + this.location.signatureStartLine + RESET + ", " + 470 "javadoc-line=" + BRED + this.location.jdcStartLine + RESET + ", " + 471 "body-line=" + BRED + this.location.bodyStartLine + RESET + 472 "]") 473 : 474 (StringParse.rightSpacePad("Location:", numSpaces) + 475 "[" + 476 "signature-line=" + this.location.signatureStartLine + ", " + 477 "javadoc-line=" + this.location.jdcStartLine + ", " + 478 "body-line=" + this.location.bodyStartLine + 479 ']'); 480 481 String spaces = StringParse.nChars(' ', numSpaces); 482 483 if (color) return 484 StringParse.rightSpacePad("Location:", numSpaces) + 485 "JavaDocComment: [" + 486 "startPos=" + BRED + location.jdcStartPos + RESET + ", " + 487 "endPos=" + BRED + location.jdcEndPos + RESET + ", " + 488 "startLine=" + BRED + location.jdcStartLine + RESET + ", " + 489 "endLine=" + BRED + location.jdcEndLine + RESET + ", " + 490 "startCol=" + BRED + location.jdcStartCol + RESET + ", " + 491 "endCol=" + BRED + location.jdcEndCol + RESET + "]\n" + 492 493 spaces + "Signature: [" + 494 "startPos=" + BRED + location.signatureStartPos + RESET + ", " + 495 "endPos=" + BRED + location.signatureEndPos + RESET + ", " + 496 "startLine=" + BRED + location.signatureStartLine + RESET + ", " + 497 "endLine=" + BRED + location.signatureEndLine + RESET + ", " + 498 "startCol=" + BRED + location.signatureStartCol + RESET + ", " + 499 "endCol=" + BRED + location.signatureEndCol + RESET + "]\n" + 500 501 spaces + "Body: [" + 502 "startPos=" + BRED + location.bodyStartPos + RESET + ", " + 503 "endPos=" + BRED + location.bodyEndPos + RESET + ", " + 504 "startLine=" + BRED + location.bodyStartLine + RESET + ", " + 505 "endLine=" + BRED + location.bodyEndLine + RESET + ", " + 506 "startCol=" + BRED + location.bodyStartCol + RESET + ", " + 507 "endCol=" + BRED + location.bodyEndCol + RESET + "]"; 508 509 else return 510 StringParse.rightSpacePad("Location:", numSpaces) + 511 "JavaDocComment: [" + 512 "startPos=" + location.jdcStartPos + ", " + 513 "endPos=" + location.jdcEndPos + ", " + 514 "startLine=" + location.jdcStartLine + ", " + 515 "endLine=" + location.jdcEndLine + ", " + 516 "startCol=" + location.jdcStartCol + ", " + 517 "endCol=" + location.jdcEndCol + "]\n" + 518 519 spaces + "Signature: [" + 520 "startPos=" + location.signatureStartPos + ", " + 521 "endPos=" + location.signatureEndPos + ", " + 522 "startLine=" + location.signatureStartLine + ", " + 523 "endLine=" + location.signatureEndLine + ", " + 524 "startCol=" + location.signatureStartCol + ", " + 525 "endCol=" + location.signatureEndCol + "]\n" + 526 527 spaces + "Body: [" + 528 "startPos=" + location.bodyStartPos + ", " + 529 "endPos=" + location.bodyEndPos + ", " + 530 "startLine=" + location.bodyStartLine + ", " + 531 "endLine=" + location.bodyEndLine + ", " + 532 "startCol=" + location.bodyStartCol + ", " + 533 "endCol=" + location.bodyEndCol + "]"; 534 } 535 536 537 // ******************************************************************************************** 538 // ******************************************************************************************** 539 // Abstract-Class ToString 540 // ******************************************************************************************** 541 // ******************************************************************************************** 542 543 544 /** 545 * Dummy Method. Overriden by Concrete Sub-Classes. 546 * @see Method#toString() 547 * @see Field#toString() 548 * @see Constructor#toString() 549 */ 550 public String toString() 551 { return "Declaration is Abstract, all Concrete Sub-Classes Override this method."; } 552 553 /** 554 * Dummy Method. Overriden by Concrete Sub-Classes. 555 * @see Method#toString(int) 556 * @see Field#toString(int) 557 * @see Constructor#toString(int) 558 */ 559 public String toString(int flags) 560 { return "Declaration is Abstract, all Concrete Sub-Classes Override this method."; } 561}