001 002package gudusoft.gsqlparser.pp.utils; 003 004import gudusoft.gsqlparser.ETokenStatus; 005import gudusoft.gsqlparser.ETokenType; 006import gudusoft.gsqlparser.TSourceToken; 007import gudusoft.gsqlparser.TSourceTokenList; 008import gudusoft.gsqlparser.pp.logger.PPLogger; 009import gudusoft.gsqlparser.pp.para.GFmtOpt; 010 011/** 012 * the helper class used for operating the source token 013 * 014 * @author zhoujun 015 * 016 */ 017public class SourceTokenOperator 018{ 019 020 public static int removeWhitespaceBackward( GFmtOpt opt, 021 TSourceTokenList list, int end ) 022 { 023 if ( end == 0 ) 024 { 025 return 0; 026 } 027 028 StringBuilder buf = PPLogger.isInfoEnabled( ) ? new StringBuilder( ) : null; 029 if ( buf != null ) 030 { 031 buf.append( "removeWhitespaceAndReturnFromEnd:\ntargetToken:" ) 032 .append(list.get(end).getAstext()) 033 .append( " newToken:" ) 034 .append( escapeNewlines( list.get(end).getAstext() ) ) 035 .append( "(type:" ) 036 .append( list.get( end ).tokentype ) 037 .append( ")" ); 038 } 039 int deleteWhitespaceCount = 0; 040 // int deleteReturn = 0; 041 042 int pos = end - 1; 043 044 // remove all white space before end item 045 TSourceToken token = list.get( pos ); 046 while ( token.tokentype == ETokenType.ttwhitespace ) 047 { 048 049 if ( token.tokentype == ETokenType.ttwhitespace ) 050 { 051 deleteWhitespaceCount++; 052 } 053 054 if ( opt.opearateSourceToken ) 055 { 056 token.setReplaceToken( SourceTokenConstant.EMPTY ); 057 } 058 059 pos--; 060 if ( pos >= 0 ) 061 { 062 token = token.container.get( pos ); 063 } 064 else 065 { 066 break; 067 } 068 } 069 070 if ( token.tokentype == ETokenType.ttreturn ) 071 { 072 StringBuilder b = new StringBuilder( ); 073 for (int i = 0; i < token.getAstext().length( ); i++ ) 074 { 075 char c = token.getAstext().charAt( i ); 076 if ( c != ' ' ) 077 { 078 b.append( c ); 079 } 080 } 081 token.setAstext(b.toString( )); 082 } 083 084 if ( buf != null ) 085 { 086 buf.append( "\nDeleteWhiteSpace:" ).append( deleteWhitespaceCount ); 087 PPLogger.info( 2, buf.toString( ), null ); 088 } 089 090 return pos; 091 } 092 093 /** 094 * remove the white space and the return token from the end 095 * 096 * @param list 097 * @param end 098 * @return the pos which is not white space and return token in the source 099 * token list 100 */ 101 public static int removeWhitespaceAndReturnFromEnd( GFmtOpt opt, 102 TSourceTokenList list, int end ) 103 { 104 if ( end == 0 ) 105 { 106 return 0; 107 } 108 109 StringBuilder buf = PPLogger.isInfoEnabled( ) ? new StringBuilder( ) : null; 110 if ( buf != null ) 111 { 112 buf.append( "removeWhitespaceAndReturnFromEnd:\ntargetToken:" ) 113 .append(list.get(end).getAstext()) 114 .append( " newToken:" ) 115 .append( escapeNewlines( list.get(end).getAstext() ) ) 116 .append( "(type:" ) 117 .append( list.get( end ).tokentype ) 118 .append( ")" ); 119 } 120 int deleteWhitespaceCount = 0; 121 int deleteReturn = 0; 122 123 int pos = end - 1; 124 125 // remove all white space before end item 126 TSourceToken token = list.get( pos ); 127 while ( token.tokentype == ETokenType.ttwhitespace 128 || token.tokentype == ETokenType.ttreturn ) 129 { 130 if ( token.tokentype == ETokenType.ttwhitespace ) 131 { 132 deleteWhitespaceCount++; 133 } 134 135 if ( token.tokentype == ETokenType.ttreturn ) 136 { 137 deleteReturn++; 138 } 139 140 if ( opt.opearateSourceToken ) 141 { 142 token.setReplaceToken( SourceTokenConstant.EMPTY ); 143 } 144 145 pos--; 146 if ( pos >= 0 ) 147 { 148 token = token.container.get( pos ); 149 } 150 else 151 { 152 break; 153 } 154 } 155 156 if ( buf != null ) 157 { 158 buf.append( "\nDeleteWhiteSpace:" ) 159 .append( deleteWhitespaceCount ) 160 .append( ", DeleteReturn:" ) 161 .append( deleteReturn ); 162 PPLogger.info( 2, buf.toString( ), null ); 163 } 164 165 return pos; 166 } 167 168 /** 169 * remove the white space and the return token from the end 170 * 171 * @param token 172 * @return the pos which is not whitespace and return token in the source 173 * token list 174 */ 175 public static int removeWhitespaceAndReturnFromEnd( GFmtOpt opt, 176 TSourceToken token ) 177 { 178 if ( token == null ) 179 { 180 return -1; 181 } 182 return removeWhitespaceAndReturnFromEnd( opt, 183 token.container, 184 token.posinlist ); 185 } 186 187 /** 188 * remove the white space and the return token before this token and after 189 * this token 190 * 191 * @param opt 192 * @param token 193 */ 194 public static void removeWhitespaceAndReturnFormBeforeAndAfter( 195 GFmtOpt opt, TSourceToken token ) 196 { 197 if ( token == null ) 198 { 199 return; 200 } 201 removeWhitespaceAndReturnFromEnd( opt, token ); 202 removeWhitespaceAndReturnFromStart( opt, 203 token.container, 204 token.posinlist + 1 ); 205 206 } 207 208 /** 209 * remove the white space and the return token 210 * 211 * @param list 212 * @param start 213 * @param end 214 */ 215 public static void removeWhitespaceAndReturn( GFmtOpt opt, 216 TSourceTokenList list, int start, int end ) 217 { 218 StringBuilder buf = PPLogger.isInfoEnabled( ) ? new StringBuilder( ) : null; 219 if ( buf != null ) 220 { 221 buf.append( "removeWhitespaceAndReturn:\ntargetToken:" ) 222 .append(list.get(end).getAstext()) 223 .append( " newToken:" ) 224 .append( escapeNewlines( list.get(end).getAstext() ) ) 225 .append( "(type:" ) 226 .append( list.get( end ).tokentype ) 227 .append( ")" ); 228 } 229 int deleteWhitespaceCount = 0; 230 int deleteReturn = 0; 231 232 for ( int i = start; i < end; i++ ) 233 { 234 if ( i < 0 || i > list.size( ) ) 235 { 236 return; 237 } 238 TSourceToken token = list.get( i ); 239 if ( token.tokentype == ETokenType.ttwhitespace 240 || token.tokentype == ETokenType.ttreturn ) 241 { 242 243 if ( token.tokentype == ETokenType.ttwhitespace ) 244 { 245 deleteWhitespaceCount++; 246 } 247 248 if ( token.tokentype == ETokenType.ttreturn ) 249 { 250 deleteReturn++; 251 } 252 if ( opt.opearateSourceToken ) 253 { 254 token.setReplaceToken( SourceTokenConstant.EMPTY ); 255 } 256 } 257 } 258 259 if ( buf != null ) 260 { 261 buf.append( "\nDeleteWhiteSpace:" ) 262 .append( deleteWhitespaceCount ) 263 .append( ", DeleteReturn:" ) 264 .append( deleteReturn ); 265 PPLogger.info( 2, buf.toString( ), null ); 266 } 267 268 } 269 270 /** 271 * remove the white space and the return token from the end 272 * 273 * @param list 274 */ 275 public static int removeWhitespaceAndReturnFromStart( GFmtOpt opt, 276 TSourceTokenList list, int startPos ) 277 { 278 StringBuilder buf = PPLogger.isInfoEnabled( ) ? new StringBuilder( ) : null; 279 if ( list.size( ) <= startPos ) 280 { 281 return list.size( ) - 1; 282 } 283 if ( buf != null ) 284 { 285 buf.append( "removeWhitespaceAndReturnFromStart:\ntargetToken:" ) 286 .append(list.get(startPos).getAstext()) 287 .append( " newToken:" ) 288 .append( escapeNewlines( list.get(startPos).getAstext() ) ) 289 .append( "(type:" ) 290 .append( list.get( startPos ).tokentype ) 291 .append( ")" ); 292 } 293 int deleteWhitespaceCount = 0; 294 int deleteReturn = 0; 295 296 int pos = startPos; 297 // remove all white space before end item 298 TSourceToken token = list.get( pos ); 299 while ( token.tokentype == ETokenType.ttwhitespace 300 || token.tokentype == ETokenType.ttreturn ) 301 { 302 if ( token.tokentype == ETokenType.ttwhitespace ) 303 { 304 deleteWhitespaceCount++; 305 } 306 307 if ( token.tokentype == ETokenType.ttreturn ) 308 { 309 deleteReturn++; 310 } 311 312 if ( opt.opearateSourceToken ) 313 { 314 token.setReplaceToken( SourceTokenConstant.EMPTY ); 315 } 316 317 pos++; 318 if ( pos < list.size( ) ) 319 { 320 token = token.container.get( pos ); 321 } 322 else 323 { 324 break; 325 } 326 } 327 328 if ( buf != null ) 329 { 330 buf.append( "\nDeleteWhiteSpace:" ) 331 .append( deleteWhitespaceCount ) 332 .append( ", DeleteReturn:" ) 333 .append( deleteReturn ); 334 PPLogger.info( 2, buf.toString( ), null ); 335 } 336 337 return pos; 338 } 339 340 /** 341 * calculate the text length for all virtual token (which are call before 342 * tokens, after tokens and replace token) 343 * 344 * @param list 345 * @param start 346 * @param end 347 * @return 348 */ 349 public static int textLengthVT( TSourceTokenList list, int start, int end ) 350 { 351 int total = 0; 352 for ( int i = start; i < end; i++ ) 353 { 354 TSourceToken token = list.get( i ); 355 356 if ( token.getTokensBefore( ).size( ) > 0 ) 357 { 358 total += textLengthVT( token.getTokensBefore( ), 359 0, 360 token.getTokensBefore( ).size( ) ); 361 } 362 if ( token.getReplaceToken( ) != null ) 363 { 364 total += ( token.getReplaceToken().getAstext() != null ? token.getReplaceToken().getAstext().length( ) 365 : 0 ); 366 } 367 else 368 { 369 total += ( token.getAstext() != null ? token.getAstext().length( ) : 0 ); 370 } 371 if ( token.getTokensAfter( ).size( ) > 0 ) 372 { 373 total += textLengthVT( token.getTokensAfter( ), 374 0, 375 token.getTokensAfter( ).size( ) ); 376 } 377 } 378 379 return total; 380 } 381 382 /** 383 * calcaulate the text length from a given position to the line start. VT is 384 * the abbr for "virtual token" (which contains before tokens, after tokens 385 * and replace token) 386 * 387 * @param list 388 * @param pos 389 * @return 390 */ 391 public static int curColumnNumberVT( TSourceTokenList list, int pos ) 392 { 393 394 int total = 0; 395 396 for ( int i = pos; i >= 0; i-- ) 397 { 398 TSourceToken token = list.get( i ); 399 400 if(token.tokenstatus == ETokenStatus.tsdeleted) { 401 continue; 402 } 403 404 // the after tokens in the last sourceToken should not calculated. 405 if ( i != pos && token.getTokensAfter( ).size( ) > 0 ) 406 { 407 for ( int j = token.getTokensAfter( ).size( ) - 1; j >= 0; j-- ) 408 { 409 TSourceToken after = token.getTokensAfter( ).get( j ); 410 if ( after.tokentype != ETokenType.ttreturn ) 411 { 412 total += ( after.getAstext() != null ? after.getAstext().length( ) 413 : 0 ); 414 } 415 else 416 { 417 return total; 418 } 419 } 420 } 421 if ( i != pos ) 422 { 423 if ( token.getReplaceToken( ) != null ) 424 { 425 if ( token.getReplaceToken( ).tokentype != ETokenType.ttreturn ) 426 { 427 total += ( token.getReplaceToken().getAstext() != null ? token.getReplaceToken().getAstext().length( ) 428 : 0 ); 429 } 430 else 431 { 432 return total; 433 } 434 } 435 else 436 { 437 if ( token.tokentype != ETokenType.ttreturn ) 438 { 439 if(token.tokentype == ETokenType.ttsimplecomment) { 440 if(token.nextToken()!=null && 441 token.nextToken().getAstext() !=null && 442 token.nextToken().getAstext().trim().length() == 0) { 443 total -= token.nextToken().getAstext().length( ); 444 } 445 continue; 446 } 447 if(isOracleHint(token)) { 448 if(token.nextToken()!=null && 449 token.nextToken().getAstext() !=null && 450 token.nextToken().getAstext().trim().length() == 0) { 451 total -= token.nextToken().getAstext().length( ); 452 } 453 continue; 454 } 455 total += ( token.getAstext() != null ? token.getAstext().length( ) 456 : 0 ); 457 } 458 else 459 { 460 return total; 461 } 462 } 463 } 464 465 if ( token.getTokensBefore( ).size( ) > 0 ) 466 { 467 for ( int j = token.getTokensBefore( ).size( ) - 1; j >= 0; j-- ) 468 { 469 TSourceToken before = token.getTokensBefore( ).get( j ); 470 if ( before.tokentype != ETokenType.ttreturn ) 471 { 472 total += ( before.getAstext() != null ? before.getAstext().length( ) 473 : 0 ); 474 } 475 else 476 { 477 return total; 478 } 479 } 480 } 481 } 482 483 return total; 484 } 485 486 private static boolean isOracleHint(TSourceToken token) { 487 return token!=null && token.getAstext() !=null && token.getAstext().startsWith("/*+"); 488 } 489 490 /** 491 * calcaulate the text length from a given position to the line start. VT is 492 * the abbr for "virtual token" (which contains before tokens, after tokens 493 * and replace token) 494 * 495 * @param token 496 * @return 497 */ 498 public static int curColumnNumberVT( TSourceToken token ) 499 { 500 return curColumnNumberVT( token.container, token.posinlist ); 501 } 502 503 /** 504 * calculate the current indent length VT is the abbr for "virtual token" 505 * (which contains before tokens, after tokens and replace token) 506 * 507 * @param list 508 * @param pos 509 * @return 510 */ 511 public static int curIndentLenVT( TSourceTokenList list, int pos ) 512 { 513 int indentLen = 0; 514 for ( int i = pos; i >= 0; i-- ) 515 { 516 TSourceToken token = list.get( i ); 517 518 if(token.tokenstatus == ETokenStatus.tsdeleted) { 519 continue; 520 } 521 522 // the after tokens in the last sourceToken should not calculated. 523 if ( i != pos && token.getTokensAfter( ).size( ) > 0 ) 524 { 525 for ( int j = token.getTokensAfter( ).size( ) - 1; j >= 0; j-- ) 526 { 527 TSourceToken after = token.getTokensAfter( ).get( j ); 528 if ( after.tokentype == ETokenType.ttreturn ) 529 { 530 return indentLen; 531 } 532 else if ( after.tokentype == ETokenType.ttwhitespace ) 533 { 534 indentLen += ( after.getAstext() != null ? after.getAstext().length( ) 535 : 0 ); 536 } 537 else 538 { 539 indentLen = 0; 540 } 541 } 542 } 543 544 if ( i != pos ) 545 { 546 if ( token.getReplaceToken( ) != null ) 547 { 548 if ( token.getReplaceToken( ).tokentype == ETokenType.ttreturn ) 549 { 550 return indentLen; 551 } 552 else if ( token.getReplaceToken( ).tokentype == ETokenType.ttwhitespace ) 553 { 554 indentLen += ( token.getReplaceToken().getAstext() != null ? token.getReplaceToken().getAstext().length( ) 555 : 0 ); 556 } 557 else 558 { 559 indentLen = 0; 560 } 561 562 } 563 else 564 { 565 if ( token.tokentype == ETokenType.ttreturn ) 566 { 567 return indentLen; 568 } 569 else if ( token.tokentype == ETokenType.ttwhitespace ) 570 { 571 indentLen += ( token.getAstext() != null ? token.getAstext().length( ) 572 : 0 ); 573 } 574 else 575 { 576 indentLen = 0; 577 } 578 } 579 } 580 581 if ( token.getTokensBefore( ).size( ) > 0 ) 582 { 583 for ( int j = token.getTokensBefore( ).size( ) - 1; j >= 0; j-- ) 584 { 585 TSourceToken before = token.getTokensBefore( ).get( j ); 586 if ( before.tokentype == ETokenType.ttreturn ) 587 { 588 return indentLen; 589 } 590 else if ( before.tokentype == ETokenType.ttwhitespace ) 591 { 592 indentLen += ( before.getAstext() != null ? before.getAstext().length( ) 593 : 0 ); 594 } 595 else 596 { 597 indentLen = 0; 598 } 599 } 600 } 601 602 } 603 return indentLen; 604 } 605 606 /** 607 * calculate the current indent length VT is the abbr for "virtual token" 608 * (which contains before tokens, after tokens and replace token) 609 * 610 * @param token 611 * @return 612 */ 613 public static int curIndentLenVT( TSourceToken token ) 614 { 615 return curIndentLenVT( token.container, token.posinlist ); 616 } 617 618 /** 619 * create the white space source token 620 * 621 * @param length 622 * @return 623 */ 624 public static TSourceToken createWhitespaceSourceToken( int length ) 625 { 626 return WhitespaceSourceTokenHelper.createWhitespaceSourceToken( length ); 627 } 628 629 private static TSourceToken noFormatFlag = null; 630 static 631 { 632 noFormatFlag = new TSourceToken( "" ); 633 noFormatFlag.tokentype = ETokenType.ttwhitespace; 634 } 635 636 public static TSourceToken createNoFormatFlagToken( ) 637 { 638 return noFormatFlag; 639 } 640 641 public static TSourceToken createReturnSourceToken( ) 642 { 643 TSourceToken t = new TSourceToken( "\n" ); 644 t.tokentype = ETokenType.ttreturn; 645 return t; 646 } 647 648 private static final TSourceToken statementBreak = createReturnSourceToken( ); 649 650 /** 651 * The one line break placed before a statement that started on the line 652 * of the previous statement's terminator, so that the columns computed 653 * while the statement is formatted start from that break. The empty-line 654 * pass between statements removes it again and lays out the real breaks. 655 */ 656 public static TSourceToken createStatementBreakToken( ) 657 { 658 return statementBreak; 659 } 660 661 /** 662 * combine all the white spaces into a single white space 663 * 664 * @param list 665 * @param startPos 666 * @param endPos 667 */ 668 public static void combineWhitespace( TSourceTokenList list, int startPos, 669 int endPos ) 670 { 671 boolean findWhitespace = false; 672 for ( int i = startPos; i < endPos; i++ ) 673 { 674 if ( i >= 0 && i < list.size( ) ) 675 { 676 TSourceToken token = list.get( i ); 677 678 if(token.tokenstatus == ETokenStatus.tsdeleted) { 679 continue; 680 } 681 682 if ( token.tokentype == ETokenType.ttwhitespace ) 683 { 684 token.setReplaceToken( SourceTokenConstant.EMPTY ); 685 findWhitespace = true; 686 } 687 } 688 } 689 if ( findWhitespace ) 690 { 691 list.get( endPos ) 692 .getTokensBefore( ) 693 .add( createWhitespaceSourceToken( 1 ) ); 694 } 695 } 696 697 /** 698 * insert the source token before the target source token 699 * 700 * @param targetToken 701 * @param needAddToken 702 */ 703 public static void addBefore( GFmtOpt opt, TSourceToken targetToken, 704 TSourceToken needAddToken ) 705 { 706 if ( needAddToken == null ) 707 { 708 return; 709 } 710 711 StringBuilder buf = PPLogger.isInfoEnabled( ) ? new StringBuilder( ) : null; 712 if ( buf != null ) 713 { 714 buf.append( "AddBefore:\ntargetToken:" ) 715 .append(targetToken.getAstext()) 716 .append( "(pos:" ) 717 .append( targetToken.posinlist ) 718 .append( ")" ) 719 .append( " newToken:" ) 720 .append( escapeNewlines( needAddToken.getAstext() ) ) 721 .append( "(type:" ) 722 .append( needAddToken.tokentype ) 723 .append( ")" ); 724 } 725 726 if ( buf != null && targetToken.getTokensBefore( ).size( ) > 0 ) 727 { 728 buf.append( "\noldTokenBefore:" ); 729 for ( int i = 0; i < targetToken.getTokensBefore( ).size( ); i++ ) 730 { 731 TSourceToken token = targetToken.getTokensBefore( ).get( i ); 732 733 if(token.tokenstatus == ETokenStatus.tsdeleted) { 734 continue; 735 } 736 737 buf.append( "[" ) 738 .append( token.getAstext() != null ? escapeNewlines( token.getAstext() ) 739 : "" ) 740 .append( "] " ) 741 .append( "(type:" ) 742 .append( token.tokentype ) 743 .append( ")" ); 744 } 745 } 746 747 if ( buf != null ) 748 { 749 PPLogger.info( 2, buf.toString( ), null ); 750 } 751 752 if ( opt.opearateSourceToken ) 753 { 754 targetToken.getTokensBefore( ).add( needAddToken ); 755 } 756 } 757 758 public static void addAfter( GFmtOpt opt, TSourceToken targetToken, 759 TSourceToken needAddToken ) 760 { 761 if ( needAddToken == null ) 762 { 763 return; 764 } 765 766 StringBuilder buf = PPLogger.isInfoEnabled( ) ? new StringBuilder( ) : null; 767 if ( buf != null ) 768 { 769 buf.append( "AddAfter:\ntargetToken:" ) 770 .append(targetToken.getAstext()) 771 .append( "(pos:" ) 772 .append( targetToken.posinlist ) 773 .append( ")" ) 774 .append( " newToken:" ) 775 .append( needAddToken.getAstext() != null ? escapeNewlines( needAddToken.getAstext() ) 776 : "" ) 777 .append( "(type:" ) 778 .append( needAddToken.tokentype ) 779 .append( ")" ); 780 } 781 782 if ( buf != null && targetToken.getTokensAfter( ).size( ) > 0 ) 783 { 784 buf.append( "\noldTokenAfter:" ); 785 for ( int i = 0; i < targetToken.getTokensAfter( ).size( ); i++ ) 786 { 787 TSourceToken token = targetToken.getTokensAfter( ).get( i ); 788 789 if(token.tokenstatus == ETokenStatus.tsdeleted) { 790 continue; 791 } 792 793 buf.append( "[" ) 794 .append( token.getAstext() != null ? escapeNewlines( token.getAstext() ) 795 : "" ) 796 .append( "] " ) 797 .append( "(type:" ) 798 .append( token.tokentype ) 799 .append( ")" ); 800 } 801 } 802 803 if ( buf != null ) 804 { 805 PPLogger.info( 2, buf.toString( ), null ); 806 } 807 808 if ( opt.opearateSourceToken ) 809 { 810 targetToken.getTokensAfter( ).add( needAddToken ); 811 } 812 } 813 814 /** 815 * remove all source token in the before source token list VT is the abbr 816 * for "virtual token" (that this method will operates before tokens, after 817 * tokens and replace token) 818 * 819 * @param targetToken 820 */ 821 public static void removeAllBeforeTokenVT( GFmtOpt opt, 822 TSourceToken targetToken ) 823 { 824 StringBuilder buf = PPLogger.isInfoEnabled( ) ? new StringBuilder( ) : null; 825 TSourceTokenList before = targetToken.getTokensBefore( ); 826 if ( buf != null ) 827 { 828 buf.append( "RemoveAllBeforeTokenVT:" ); 829 for ( int i = 0; i < before.size( ); i++ ) 830 { 831 TSourceToken token = before.get( i ); 832 // a deleted token prints nothing, so the log does not list it 833 if ( token.tokenstatus == ETokenStatus.tsdeleted ) 834 { 835 continue; 836 } 837 buf.append( "\nremoveToken:" ) 838 .append( "[" ) 839 .append( token.getAstext() != null ? escapeNewlines( token.getAstext() ) 840 : "" ) 841 .append( "] " ) 842 .append( "(type:" ) 843 .append( token.tokentype ) 844 .append( ")" ); 845 } 846 } 847 // Every token goes, deleted ones included. The loop this replaces removed the head token only while 848 // operating and skipped a deleted head without removing it, so a deleted token, or a run with 849 // opearateSourceToken off, left the list non-empty and the loop never ended. 850 if ( opt.opearateSourceToken ) 851 { 852 before.clear( ); 853 } 854 if ( buf != null ) 855 { 856 PPLogger.info( 2, buf.toString( ), null ); 857 } 858 } 859 860 public static void removeThisToken( TSourceToken token ) 861 { 862 token.setReplaceToken( SourceTokenOperator.createWhitespaceSourceToken( 1 ) ); 863 } 864 865 /** The text with each line feed written as the two characters backslash, n: the form a log line shows. */ 866 private static String escapeNewlines( String text ) 867 { 868 if ( text.indexOf( '\n' ) < 0 ) 869 { 870 return text; 871 } 872 StringBuilder b = new StringBuilder( text.length( ) + 8 ); 873 for ( int i = 0; i < text.length( ); i++ ) 874 { 875 char c = text.charAt( i ); 876 if ( c == '\n' ) 877 { 878 b.append( "\\n" ); 879 } 880 else 881 { 882 b.append( c ); 883 } 884 } 885 return b.toString( ); 886 } 887}