001package Torello.JavaDoc; 002 003 004// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 005// Java-HTML Imports 006// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 007 008import Torello.Java.*; 009 010import static Torello.Java.C.*; 011import static Torello.JavaDoc.PF.*; 012 013 014// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 015// Standard-Java Imports 016// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 017 018import java.util.Optional; 019import java.io.IOException; 020 021 022// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 023// The new Source-Code Parser: com.sun.source.* 024// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 025 026import com.sun.source.tree.Tree; 027import com.sun.source.doctree.DocCommentTree; 028 029/** 030 * Location Information storing line-number, column-number and character-number for items inside 031 * of a Java Source-Code File (a {@code '.java'} file). 032 */ 033public class Location implements java.io.Serializable, Cloneable 034{ 035 /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */ 036 protected static final long serialVersionUID = 1; 037 038 039 // ******************************************************************************************** 040 // ******************************************************************************************** 041 // This class' public fields 042 // ******************************************************************************************** 043 // ******************************************************************************************** 044 045 046 /** <EMBED CLASS='external-html' DATA-FILE-ID=LOC_SIG_START_POS> */ 047 public final int signatureStartPos; 048 049 /** <EMBED CLASS='external-html' DATA-FILE-ID=LOC_SIG_START_LINE> */ 050 public final int signatureStartLine; 051 052 /** <EMBED CLASS='external-html' DATA-FILE-ID=LOC_SIG_START_COL> */ 053 public final int signatureStartCol; 054 055 056 /** <EMBED CLASS='external-html' DATA-FILE-ID=LOC_SIG_END_POS> */ 057 public final int signatureEndPos; 058 059 /** <EMBED CLASS='external-html' DATA-FILE-ID=LOC_SIG_END_LINE> */ 060 public final int signatureEndLine; 061 062 /** <EMBED CLASS='external-html' DATA-FILE-ID=LOC_SIG_END_COL> */ 063 public final int signatureEndCol; 064 065 066 /** <EMBED CLASS='external-html' DATA-FILE-ID=LOC_JDC_START_POS> */ 067 public final int jdcStartPos; 068 069 /** <EMBED CLASS='external-html' DATA-FILE-ID=LOC_JDC_START_LINE> */ 070 public final int jdcStartLine; 071 072 /** <EMBED CLASS='external-html' DATA-FILE-ID=LOC_JDC_START_COL> */ 073 public final int jdcStartCol; 074 075 076 /** <EMBED CLASS='external-html' DATA-FILE-ID=LOC_JDC_END_POS> */ 077 public final int jdcEndPos; 078 079 /** <EMBED CLASS='external-html' DATA-FILE-ID=LOC_JDC_END_LINE> */ 080 public final int jdcEndLine; 081 082 /** <EMBED CLASS='external-html' DATA-FILE-ID=LOC_JDC_END_COL> */ 083 public final int jdcEndCol; 084 085 086 /** <EMBED CLASS='external-html' DATA-FILE-ID=LOC_BODY_START_POS> */ 087 public final int bodyStartPos; 088 089 /** <EMBED CLASS='external-html' DATA-FILE-ID=LOC_BODY_START_LINE> */ 090 public final int bodyStartLine; 091 092 /** <EMBED CLASS='external-html' DATA-FILE-ID=LOC_BODY_START_COL> */ 093 public final int bodyStartCol; 094 095 096 /** <EMBED CLASS='external-html' DATA-FILE-ID=LOC_BODY_END_POS> */ 097 public final int bodyEndPos; 098 099 /** <EMBED CLASS='external-html' DATA-FILE-ID=LOC_BODY_END_LINE> */ 100 public final int bodyEndLine; 101 102 /** <EMBED CLASS='external-html' DATA-FILE-ID=LOC_BODY_END_COL> */ 103 public final int bodyEndCol; 104 105 106 // ******************************************************************************************** 107 // ******************************************************************************************** 108 // Constructor - com.sun.source.tree 109 // ******************************************************************************************** 110 // ******************************************************************************************** 111 112 113 Location(TreeUtils util, Tree tree, DocCommentTree dct, Tree body, Tree fieldInitializerTree) 114 { 115 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 116 // Java-Doc Comments Location-Information 117 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 118 119 if (dct == null) 120 { 121 // If this 'entity' doesn't have a JavaDoc Comment, then set these to '-1' 122 this.jdcStartPos = this.jdcEndPos = -1; 123 this.jdcStartLine = this.jdcEndLine = -1; 124 this.jdcStartCol = this.jdcEndCol = -1; 125 } 126 127 else 128 { 129 int sPos = (int) util.docSourcePositions.getStartPosition 130 (util.compilationUnitTree, dct, dct); 131 132 int ePos = (int) util.docSourcePositions.getEndPosition 133 (util.compilationUnitTree, dct, dct); 134 135 // This can happen if the code has a /** */ above a field or method that turns out to 136 // just be totally and completely empty! I am a little busy at the moment documenting 137 // something else. March 5th, 2024. This is trivial, but I am not doing right now. 138 139 if (ePos == -1) throw new Torello.Java.ToDoException( 140 "This really needs to be analyzed, and it is likely very easy, but I am in the " + 141 "middle of another documentation-thing right now...\n\n" + 142 "To Quickly Fix your problem, make sure there are no JavaDoc Comments that look " + 143 "like /** */ - where there is nothing but white-space inside your comment.\n\n" + 144 "I will get to this hopefully soon. Today is March 4th, 2024." 145 ); 146 147 while (sPos >= 2) 148 if (util.srcFileAsStr.charAt(sPos--) == '*') 149 if (util.srcFileAsStr.regionMatches(sPos - 1, "/**", 0, 3)) 150 { sPos--; break; } 151 152 int MAX = util.srcFileAsStr.length() - 2; 153 154 while (ePos < MAX) 155 if (util.srcFileAsStr.charAt(ePos++) == '*') 156 if (util.srcFileAsStr.regionMatches(ePos - 1, "*/", 0, 2)) 157 { ePos++; break; } 158 159 this.jdcStartPos = sPos; 160 this.jdcEndPos = ePos; 161 162 this.jdcStartLine = (int) util.lineMap.getLineNumber(sPos); 163 this.jdcEndLine = (int) util.lineMap.getLineNumber(ePos); 164 165 this.jdcStartCol = positionToColumn(this.jdcStartPos, util.srcFileAsStr); 166 this.jdcEndCol = positionToColumn(this.jdcEndPos, util.srcFileAsStr); 167 168 /* 169 System.out.println( 170 "TU: " + StrPrint.abbrev( 171 util.srcFileAsStr.substring(this.jdcStartPos, this.jdcEndPos), 172 60, true, null, 120 173 )); 174 */ 175 } 176 177 178 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 179 // Body Location-Information 180 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 181 // 182 // NOTE: Fields that do not have any initialization expressions, and absolutely enum 183 // constants - will not have a body, and the 'body' parameter will be null in such 184 // cases. Annotation-Elements without a default-value may pass null to the body too, 185 // as could a method defined inside of an interface that doesn't have a definition. 186 187 if (body == null) 188 { 189 // If this 'entity' doesn't have a Body, then set these to '-1' 190 this.bodyStartPos = this.bodyEndPos = -1; 191 this.bodyStartLine = this.bodyEndLine = -1; 192 this.bodyStartCol = this.bodyEndCol = -1; 193 } 194 else 195 { 196 this.bodyStartPos = (int) util.sourcePositions.getStartPosition 197 (util.compilationUnitTree, body); 198 199 this.bodyEndPos = (int) util.sourcePositions.getEndPosition 200 (util.compilationUnitTree, body); 201 202 this.bodyStartLine = (int) util.lineMap.getLineNumber(this.bodyStartPos); 203 this.bodyEndLine = (int) util.lineMap.getLineNumber(this.bodyEndPos); 204 205 this.bodyStartCol = positionToColumn(this.bodyStartPos, util.srcFileAsStr); 206 this.bodyEndCol = positionToColumn(this.bodyEndPos, util.srcFileAsStr); 207 208 /* 209 System.out.println( 210 "TU: " + StrPrint.abbrev( 211 util.srcFileAsStr.substring(this.bodyStartPos, this.bodyEndPos), 212 60, true, null, 120 213 )); 214 */ 215 } 216 217 218 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 219 // Signature Location-Information 220 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 221 222 this.signatureStartPos = (int) util.sourcePositions.getStartPosition 223 (util.compilationUnitTree, tree); 224 225 this.signatureStartLine = (int) util.lineMap.getLineNumber(this.signatureStartPos); 226 this.signatureStartCol = positionToColumn(this.signatureStartPos, util.srcFileAsStr); 227 228 if (fieldInitializerTree != null) 229 { 230 // NOTE: Here, a '+1' is added at the very end of the statement to account for the 231 // ending semi-colon, which Java-Parser is adding. 232 233 this.signatureEndPos = (int) util.sourcePositions.getEndPosition 234 (util.compilationUnitTree, fieldInitializerTree) + 1; 235 236 this.signatureEndLine = (int) util.lineMap.getLineNumber(this.signatureEndPos); 237 this.signatureEndCol = positionToColumn(this.signatureEndPos, util.srcFileAsStr); 238 } 239 else if (body == null) 240 { 241 this.signatureEndPos = (int) util.sourcePositions.getEndPosition 242 (util.compilationUnitTree, tree); 243 244 this.signatureEndLine = (int) util.lineMap.getLineNumber(this.signatureEndPos); 245 this.signatureEndCol = positionToColumn(this.signatureEndPos, util.srcFileAsStr); 246 } 247 else 248 { 249 int line = this.bodyStartLine; 250 int pos = this.bodyStartPos; 251 int col = 2; 252 char c = 0; 253 254 while (Character.isWhitespace(c = util.srcFileAsStr.charAt(--pos))) if (c == '\n') line--; 255 while (util.srcFileAsStr.charAt(--pos) != '\n') col++; 256 257 this.signatureEndLine = line; 258 this.signatureEndCol = col; 259 this.signatureEndPos = pos + col; 260 } 261 } 262 263 264 // ******************************************************************************************** 265 // ******************************************************************************************** 266 // Constructor for NestedType - com.sun.source.tree 267 // ******************************************************************************************** 268 // ******************************************************************************************** 269 270 271 Location(TreeUtils util, Tree tree, DocCommentTree dct) 272 { 273 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 274 // Java-Doc Comments Location (COPIED DIRECTLY/VERBATIM FROM PREVIOUS CONSTRUCTOR) 275 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 276 277 if (dct == null) 278 { 279 // If this 'entity' doesn't have a JavaDoc Comment, then set these to '-1' 280 this.jdcStartPos = this.jdcEndPos = -1; 281 this.jdcStartLine = this.jdcEndLine = -1; 282 this.jdcStartCol = this.jdcEndCol = -1; 283 } 284 else 285 { 286 int sPos = (int) util.docSourcePositions.getStartPosition 287 (util.compilationUnitTree, dct, dct); 288 289 int ePos = (int) util.docSourcePositions.getEndPosition 290 (util.compilationUnitTree, dct, dct); 291 292 while (sPos >= 2) 293 if (util.srcFileAsStr.charAt(sPos--) == '*') 294 if (util.srcFileAsStr.regionMatches(sPos - 1, "/**", 0, 3)) 295 { sPos--; break; } 296 297 int MAX = util.srcFileAsStr.length() - 2; 298 while (ePos < MAX) 299 if (util.srcFileAsStr.charAt(ePos++) == '*') 300 if (util.srcFileAsStr.regionMatches(ePos - 1, "*/", 0, 2)) 301 { ePos++; break; } 302 303 this.jdcStartPos = sPos; 304 this.jdcEndPos = ePos; 305 306 this.jdcStartLine = (int) util.lineMap.getLineNumber(sPos); 307 this.jdcEndLine = (int) util.lineMap.getLineNumber(ePos); 308 309 this.jdcStartCol = positionToColumn(this.jdcStartPos, util.srcFileAsStr); 310 this.jdcEndCol = positionToColumn(this.jdcEndPos, util.srcFileAsStr); 311 } 312 313 314 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 315 // Signature Location-Information - ONLY DO THE STARTING PART 316 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 317 318 this.signatureStartPos = (int) util.sourcePositions.getStartPosition 319 (util.compilationUnitTree, tree); 320 321 this.signatureStartLine = (int) util.lineMap.getLineNumber(this.signatureStartPos); 322 this.signatureStartCol = positionToColumn(this.signatureStartPos, util.srcFileAsStr); 323 324 325 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 326 // Now do the body ***AND*** The rest of signature 327 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 328 329 int line = this.signatureStartLine; 330 int col = this.signatureStartCol; 331 int pos = StrIndexOf.nth(util.srcFileAsStr, line - 1, '\n') + col; 332 int MAX = util.srcFileAsStr.length() - 1; 333 char c = 0; 334 335 while ((pos < MAX) && ((c = util.srcFileAsStr.charAt(++pos)) != '{') && (c != ';')) 336 if (c == '\n') line++; 337 338 if (c == '{') 339 { 340 this.bodyStartPos = pos; 341 this.bodyStartLine = line; 342 this.bodyStartCol = positionToColumn(pos, util.srcFileAsStr); 343 344 this.bodyEndPos = (int) util.sourcePositions.getEndPosition 345 (util.compilationUnitTree, tree); 346 347 this.bodyEndLine = (int) util.lineMap.getLineNumber(this.bodyEndPos); 348 this.bodyEndCol = positionToColumn(this.bodyEndPos, util.srcFileAsStr); 349 350 351 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 352 // Signature-End 353 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 354 355 while ((--pos > 0) && Character.isWhitespace(c = util.srcFileAsStr.charAt(pos))) 356 if (c == '\n') line--; 357 358 this.signatureEndLine = line; 359 this.signatureEndPos = pos + 1; 360 this.signatureEndCol = positionToColumn(this.signatureEndPos , util.srcFileAsStr); 361 } 362 else 363 { 364 this.bodyStartPos = this.bodyStartCol = this.bodyStartLine = 365 this.bodyEndPos = this.bodyEndCol = this.bodyEndLine = -1; 366 367 368 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 369 // Signature-End 370 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 371 372 this.signatureEndPos = (int) util.sourcePositions.getEndPosition 373 (util.compilationUnitTree, tree); 374 375 this.signatureEndLine = (int) util.lineMap.getLineNumber(this.signatureEndPos); 376 this.signatureEndCol = positionToColumn(this.signatureEndPos, util.srcFileAsStr); 377 } 378 } 379 380 381 // ******************************************************************************************** 382 // ******************************************************************************************** 383 // Two Simple Constructor Helpers 384 // ******************************************************************************************** 385 // ******************************************************************************************** 386 387 388 private static int positionToColumn(int pos, String srcFileAsStr) 389 { 390 int col = 1; 391 char c; 392 393 while ( (--pos >= 0) 394 && ((c = srcFileAsStr.charAt(pos)) != '\n') 395 && (c != '\r') 396 ) 397 col++; 398 399 return col; 400 } 401 402 // It is expected the line1, col1, pos1 define a specific location / are "consisten" 403 // (I Hope you know what I mean by "consistent") 404 // 405 // ALSO: line2 & col2 are also consistent, and come AFTER the first position 406 private static int colAndLineToPosition 407 (String srcFileAsStr, int line1, int col1, int pos1, int line2, int col2) 408 { 409 if (line2 > line1) 410 { 411 // The presumption, here, is that 'pos1' is a "starting" location - for either the body 412 // or the signature. It **WILL NOT** be a new-line '\n' character, it will be 413 // something like the letter 'p' which is the first letter in 'public' or 'private' 414 // 415 // If this is for a body, then it will hold a '{' The only reason this code uses 'pos' 416 // rather than just re-using 'pos1' from the input-parameter / signature, is for this 417 // comment that you are reading right now! 418 419 int pos = pos1; 420 for (int count = line2-line1; count > 0; ) 421 if (srcFileAsStr.charAt(++pos) == '\n') count--; 422 423 return pos + col2; 424 } 425 else if (line2 == line1) 426 return pos1 - col1 + col2; 427 428 // This should never happen 429 else 430 throw new UnreachableError(); 431 } 432 433 // ******************************************************************************************** 434 // ******************************************************************************************** 435 // Private Clone Constructor 436 // ******************************************************************************************** 437 // ******************************************************************************************** 438 439 440 private Location(Location l) 441 { 442 this.signatureStartPos = l.signatureStartPos; 443 this.signatureStartLine = l.signatureStartLine; 444 this.signatureStartCol = l.signatureStartCol; 445 446 this.signatureEndPos = l.signatureEndPos; 447 this.signatureEndLine = l.signatureEndLine; 448 this.signatureEndCol = l.signatureEndCol; 449 450 this.jdcStartPos = l.jdcStartPos; 451 this.jdcStartLine = l.jdcStartLine; 452 this.jdcStartCol = l.jdcStartCol; 453 454 this.jdcEndPos = l.jdcEndPos; 455 this.jdcEndLine = l.jdcEndLine; 456 this.jdcEndCol = l.jdcEndCol; 457 458 this.bodyStartPos = l.bodyStartPos; 459 this.bodyStartLine = l.bodyStartLine; 460 this.bodyStartCol = l.bodyStartCol; 461 462 this.bodyEndPos = l.bodyEndPos; 463 this.bodyEndLine = l.bodyEndLine; 464 this.bodyEndCol = l.bodyEndCol; 465 } 466 467 468 // ******************************************************************************************** 469 // ******************************************************************************************** 470 // java.lang.Object methods 471 // ******************************************************************************************** 472 // ******************************************************************************************** 473 474 475 /** 476 * Standard Java {@code toString()} method 477 * @return Returns the contents of this class, as a {@code java.lang.String} 478 */ 479 public String toString() 480 { 481 return 482 "signatureStartPos: " + signatureStartPos + '\n' + 483 "signatureStartLine: " + signatureStartLine + '\n' + 484 "signatureStartCol: " + signatureStartCol + '\n' + 485 486 "signatureEndPos: " + signatureEndPos + '\n' + 487 "signatureEndLine: " + signatureEndLine + '\n' + 488 "signatureEndCol: " + signatureEndCol + '\n' + 489 490 "jdcStartPos: " + jdcStartPos + '\n' + 491 "jdcStartLine: " + jdcStartLine + '\n' + 492 "jdcStartCol: " + jdcStartCol + '\n' + 493 494 "jdcEndPos: " + jdcEndPos + '\n' + 495 "jdcEndLine: " + jdcEndLine + '\n' + 496 "jdcEndCol: " + jdcEndCol + '\n' + 497 498 "bodyStartPos: " + bodyStartPos + '\n' + 499 "bodyStartLine: " + bodyStartLine + '\n' + 500 "bodyStartCol: " + bodyStartCol + '\n' + 501 502 "bodyEndPos: " + bodyEndPos + '\n' + 503 "bodyEndLine: " + bodyEndLine + '\n' + 504 "bodyEndCol: " + bodyEndCol + '\n'; 505 } 506 507 /** 508 * Standard Java {@code clone()} method 509 * @return Returns a copy of {@code 'this'} instance 510 */ 511 public Object clone() 512 { return new Location(this); } 513 514 /** 515 * Standard Java {@code equals()} method 516 * 517 * @param other This may be any Java Object, but one that extends class {@code 'Location'} 518 * has the potential to result in a {@code TRUE} evaluation from this method. 519 * 520 * @return {@code TRUE} if and only if the contents of {@code 'this'} instance are identical to 521 * the contents of {@code 'other'} (and only if {@code 'other'} is actually an instance of 522 * {@code Location}, or extends at least extends it). 523 */ 524 public boolean equals(Object other) 525 { 526 if (! Location.class.isAssignableFrom(other.getClass())) return false; 527 528 Location l = (Location) other; 529 530 return 531 (this.signatureStartPos == l.signatureStartPos) 532 && (this.signatureStartLine == l.signatureStartLine) 533 && (this.signatureStartCol == l.signatureStartCol) 534 535 && (this.signatureEndPos == l.signatureEndPos) 536 && (this.signatureEndLine == l.signatureEndLine) 537 && (this.signatureEndCol == l.signatureEndCol) 538 539 && (this.jdcStartPos == l.jdcStartPos) 540 && (this.jdcStartLine == l.jdcStartLine) 541 && (this.jdcStartCol == l.jdcStartCol) 542 543 && (this.jdcEndPos == l.jdcEndPos) 544 && (this.jdcEndLine == l.jdcEndLine) 545 && (this.jdcEndCol == l.jdcEndCol) 546 547 && (this.bodyStartPos == l.bodyStartPos) 548 && (this.bodyStartLine == l.bodyStartLine) 549 && (this.bodyStartCol == l.bodyStartCol) 550 551 && (this.bodyEndPos == l.bodyEndPos) 552 && (this.bodyEndLine == l.bodyEndLine) 553 && (this.bodyEndCol == l.bodyEndCol); 554 } 555 556 /** 557 * Simply invokes the {@code hashCode()} static-method provided by class {@code java.lang.Integer}. 558 * @return a hash code value for this object. 559 */ 560 public int hashCode() 561 { return Integer.hashCode(this.signatureStartPos * this.signatureEndPos); } 562 563 564 // ******************************************************************************************** 565 // ******************************************************************************************** 566 // Specialized toString 567 // ******************************************************************************************** 568 // ******************************************************************************************** 569 570 571 /** 572 * Generates a {@code String} - with all information available, including any content requested 573 * by the {@code 'flags'} parameter. 574 * 575 * @param flags These are the {@code toString(...)} flags from class {@code PF} 576 * ("Print Flags"). View available flags listed in class {@link PF}. 577 * 578 * @param srcFileAsStr This parameter should contain the complete {@code '.java'} source-code 579 * file as a {@code String}. If you have passed the Print-Flags for requesting that the body 580 * or Java-Doc Comment be output to the returned-{@code String}, this parameter must be passed 581 * a valid copy of the {@code '.java'} File. 582 * 583 * <BR /><BR />This parameter may be null, and if it is it will be ignored. When null is 584 * passed to this parameter, the actual Body, Java-Doc Comment & Signature simply cannot 585 * be extracted, and the output of this {@code toString} method shall only print the location 586 * numbers, column's and line-numbers instead. 587 * 588 * <BR /><BR />If a valid copy of the contents of the {@code '.java'} file that produced 589 * {@code 'this'} instance of {@code Location} is passed <B STYLE='color: red;'><I>and</I></B> 590 * if the appropriate Print-Flags are passed tot he {@code 'flags'} parameter requesting that 591 * the specified-elements (signature, comment and body) be output to the 592 * returned-{@code String}, <B STYLE='color: red;'><I>then</I></B> those elements will be 593 * printed to the output-{@code String}. 594 * 595 * <BR /><BR /><B>NOTE:</B> If the contents of parameter {@code 'srcFileAsstr'} are not the 596 * exact and un-modified contents of the {@code'.java} file that produced {@code 'this'} 597 * instance of location, then the {@code String} returned will contain erroneous information. 598 * It is even possible that a {@code StringIndexOutOfBoundsException} may be thrown. 599 * 600 * @return A printable {@code String} of the locations represented by this instance 601 * 602 * @see PF 603 * @see StrCSV#toCSV(String[], boolean, boolean, Integer) 604 * @see #toString() 605 */ 606 public String toString(int flags, String srcFileAsStr) 607 { 608 boolean color = (flags & UNIX_COLORS) > 0; 609 boolean src = srcFileAsStr != null; 610 boolean signature = src; 611 boolean bodyShort = src && ((flags & BODY_SHORT) > 0); 612 boolean bodyLong = (! bodyShort) && src && ((flags & BODY) > 0); 613 boolean jdc = src && ((flags & JAVADOC_COMMENTS) > 0); 614 boolean locShort = (flags & BRIEF_LOCATION) > 0; 615 int M_OVER_2 = MAX_STR_LEN / 2; 616 617 if (locShort) return 618 619 (signature 620 ? ("Signature: " + StrIndent.indentAfter2ndLine 621 (srcFileAsStr.substring(signatureStartPos, signatureEndPos), 4, true, false) + 622 '\n') 623 : "") + 624 625 "Signature-Start: " + 626 "pos=" + (color ? BGREEN : "") + signatureStartPos + (color ? RESET : "") + ", " + 627 "line=" + (color ? BGREEN : "") + signatureStartLine + (color ? RESET : "") + ", " + 628 "col=" + (color ? BGREEN : "") + signatureStartCol + (color ? RESET : "") + "\n" + 629 630 "Signature-End: " + 631 "pos=" + (color ? BCYAN : "") + signatureEndPos + (color ? RESET : "") + ", " + 632 "line=" + (color ? BCYAN : "") + signatureEndLine + (color ? RESET : "") + ", " + 633 "col=" + (color ? BCYAN : "") + signatureEndCol + (color ? RESET : "") + "\n" + 634 635 (jdc 636 ? ("Java-Doc Comment: " + StrPrint.abbrev(srcFileAsStr.substring 637 (jdcStartPos, jdcEndPos), M_OVER_2, true, null, MAX_STR_LEN) + '\n') 638 : "") + 639 640 "Java-Doc-Start: " + 641 "pos=" + (color ? BGREEN : "") + jdcStartPos + (color ? RESET : "") + ", " + 642 "line=" + (color ? BGREEN : "") + jdcStartLine + (color ? RESET : "") + ", " + 643 "col=" + (color ? BGREEN : "") + jdcStartCol + (color ? RESET : "") + "\n" + 644 645 "Java-Doc-End: " + 646 "pos=" + (color ? BCYAN : "") + jdcEndPos + (color ? RESET : "") + ", " + 647 "line=" + (color ? BCYAN : "") + jdcEndLine + (color ? RESET : "") + ", " + 648 "col=" + (color ? BCYAN : "") + jdcEndCol + (color ? RESET : "") + "\n" + 649 650 (bodyShort 651 ? ("Body: " + StrPrint.abbrev(srcFileAsStr.substring 652 (signatureStartPos, signatureEndPos), M_OVER_2, true, null, MAX_STR_LEN)) 653 : "") + 654 655 (bodyLong 656 ? ("Body: " + StrIndent.indentAfter2ndLine 657 (srcFileAsStr.substring(signatureStartPos, signatureEndPos), 4, true, false)) 658 : "") + 659 660 "Body-Start: " + 661 "pos=" + (color ? BGREEN : "") + bodyStartPos + (color ? RESET : "") + ", " + 662 "line=" + (color ? BGREEN : "") + bodyStartLine + (color ? RESET : "") + ", " + 663 "col=" + (color ? BGREEN : "") + bodyStartCol + (color ? RESET : "") + "\n" + 664 665 "Body-End: " + 666 "pos=" + (color ? BCYAN : "") + bodyEndPos + (color ? RESET : "") + ", " + 667 "line=" + (color ? BCYAN : "") + bodyEndLine + (color ? RESET : "") + ", " + 668 "col=" + (color ? BCYAN : "") + bodyEndCol + (color ? RESET : ""); 669 670 else return 671 672 (signature 673 ? ("SIGNATURE: " + StrIndent.indentAfter2ndLine 674 (srcFileAsStr.substring(signatureStartPos, signatureEndPos), 4, true, false)) 675 : "") + 676 677 "signatureStartPos: " + (color ? BGREEN : "") + signatureStartPos + '\n' + 678 (color ? RESET : "") + 679 "signatureStartLine: " + (color ? BGREEN : "") + signatureStartLine + '\n' + 680 (color ? RESET : "") + 681 "signatureStartCol: " + (color ? BGREEN : "") + signatureStartCol + '\n' + 682 (color ? RESET : "") + 683 684 "signatureEndPos: " + (color ? BCYAN : "") + signatureEndPos + '\n' + 685 (color ? RESET : "") + 686 "signatureEndLine: " + (color ? BCYAN : "") + signatureEndLine + '\n' + 687 (color ? RESET : "") + 688 "signatureEndCol: " + (color ? BCYAN : "") + signatureEndCol + '\n' + 689 (color ? RESET : "") + 690 691 (jdc 692 ? ("BODY: " + StrPrint.abbrev(srcFileAsStr.substring 693 (jdcStartPos, jdcEndPos), M_OVER_2, true, null, MAX_STR_LEN)) 694 : "") + 695 696 "jdcStartPos: " + (color ? BGREEN : "") + jdcStartPos + '\n' + 697 (color ? RESET : "") + 698 "jdcStartLine: " + (color ? BGREEN : "") + jdcStartLine + '\n' + 699 (color ? RESET : "") + 700 "jdcStartCol: " + (color ? BGREEN : "") + jdcStartCol + '\n' + 701 (color ? RESET : "") + 702 703 "jdcEndPos: " + (color ? BCYAN : "") + jdcEndPos + '\n' + 704 (color ? RESET : "") + 705 "jdcEndLine: " + (color ? BCYAN : "") + jdcEndLine + '\n' + 706 (color ? RESET : "") + 707 "jdcEndCol: " + (color ? BCYAN : "") + jdcEndCol + '\n' + 708 (color ? RESET : "") + 709 710 (bodyShort 711 ? ("BODY: " + StrPrint.abbrev(srcFileAsStr.substring 712 (signatureStartPos, signatureEndPos), M_OVER_2, true, null, MAX_STR_LEN)) 713 : "") + 714 715 (bodyLong 716 ? ("BODY: " + StrIndent.indentAfter2ndLine 717 (srcFileAsStr.substring(signatureStartPos, signatureEndPos), 4, true, false)) 718 : "") + 719 720 "bodyStartPos: " + (color ? BGREEN : "") + bodyStartPos +'\n' + 721 (color ? RESET : "") + 722 "bodyStartLine: " + (color ? BGREEN : "") + bodyStartLine + '\n' + 723 (color ? RESET : "") + 724 "bodyStartCol: " + (color ? BGREEN : "") + bodyStartCol + '\n' + 725 (color ? RESET : "") + 726 727 "bodyEndPos: " + (color ? BCYAN : "") + bodyEndPos + '\n' + 728 (color ? RESET : "") + 729 "bodyEndLine: " + (color ? BCYAN : "") + bodyEndLine + '\n' + 730 (color ? RESET : "") + 731 "bodyEndCol: " + (color ? BCYAN : "") + bodyEndCol + '\n' + 732 (color ? RESET : ""); 733 } 734 735 /** 736 * Produces a quick-summary, as a {@code String}. 737 * @return a very brief summary of the information contained by this class. Lists only the 738 * starting line numbers for the three sections. 739 */ 740 public String quickSummary() 741 { 742 return "signature-line=" + this.signatureStartLine + ", javadoc-line=" + this.jdcStartLine + 743 ", body-line=" + this.bodyStartLine; 744 } 745 746 747 // ******************************************************************************************** 748 // ******************************************************************************************** 749 // Error-Checking 750 // ******************************************************************************************** 751 // ******************************************************************************************** 752 753 754 private void check() 755 { 756 757 } 758 759 760 // ******************************************************************************************** 761 // ******************************************************************************************** 762 // Package-Private Debugging Tool for finding where two Declaration instances are different 763 // ******************************************************************************************** 764 // ******************************************************************************************** 765 766 767 // NOTE: This class has a local copy of 'diff' -> since the only diff's that are being done 768 // here are for integers. 769 770 void diff(Location other, Appendable a, String indentation) throws IOException 771 { 772 diff(this.signatureStartPos, other.signatureStartPos, "signatureStartPos", a, indentation); 773 774 diff( 775 this.signatureStartLine, other.signatureStartLine, "signatureStartLine", a, 776 indentation 777 ); 778 779 diff(this.signatureStartCol, other.signatureStartCol, "signatureStartCol", a, indentation); 780 781 diff(this.signatureEndPos, other.signatureEndPos, "signatureEndPos", a, indentation); 782 diff(this.signatureEndLine, other.signatureEndLine, "signatureEndLine", a, indentation); 783 diff(this.signatureEndCol, other.signatureEndCol, "signatureEndCol", a, indentation); 784 785 diff(this.jdcStartPos, other.jdcStartPos, "jdcStartPos", a, indentation); 786 diff(this.jdcStartLine, other.jdcStartLine, "jdcStartLine", a, indentation); 787 diff(this.jdcStartCol, other.jdcStartCol, "jdcStartCol", a, indentation); 788 789 diff(this.jdcEndPos, other.jdcEndPos, "jdcEndPos", a, indentation); 790 diff(this.jdcEndLine, other.jdcEndLine, "jdcEndLine", a, indentation); 791 diff(this.jdcEndCol, other.jdcEndCol, "jdcEndCol", a, indentation); 792 793 diff(this.bodyStartPos, other.bodyStartPos, "bodyStartPos", a, indentation); 794 diff(this.bodyStartLine, other.bodyStartLine, "bodyStartLine", a, indentation); 795 diff(this.bodyStartCol, other.bodyStartCol, "bodyStartCol", a, indentation); 796 797 diff(this.bodyEndPos, other.bodyEndPos, "bodyEndPos", a, indentation); 798 diff(this.bodyEndLine, other.bodyEndLine, "bodyEndLine", a, indentation); 799 diff(this.bodyEndCol, other.bodyEndCol, "bodyEndCol", a, indentation); 800 } 801 802 private void diff(int int1, int int2, String intName, Appendable a, String indentation) 803 throws IOException 804 { 805 if (int2 != int1) a.append( 806 indentation + 807 "this.location." + intName + ": [" + BGREEN + ("" + int1) + RESET + "], " + 808 "other.location." + intName + ": [" + BGREEN + ("" + int2) + RESET + "]\n" 809 ); 810 } 811}