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