1 /* 2 * Copyright 2016 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 15 package com.google.googlejavaformat.java; 16 17 import static com.google.common.truth.Truth.assertThat; 18 import static java.nio.charset.StandardCharsets.UTF_8; 19 20 import com.google.common.base.Joiner; 21 import com.google.common.io.ByteStreams; 22 import java.util.Arrays; 23 import org.junit.Test; 24 import org.junit.runner.RunWith; 25 import org.junit.runners.JUnit4; 26 27 /** Tests formatting javadoc. */ 28 @RunWith(JUnit4.class) 29 public final class JavadocFormattingTest { 30 31 private final Formatter formatter = new Formatter(); 32 33 @Test notJavadoc()34 public void notJavadoc() { 35 String[] input = { 36 "/**/", // 37 "class Test {}", 38 }; 39 String[] expected = { 40 "/**/", // 41 "class Test {}", 42 }; 43 doFormatTest(input, expected); 44 } 45 46 @Test empty()47 public void empty() { 48 String[] input = { 49 "/***/", // 50 "class Test {}", 51 }; 52 String[] expected = { 53 "/***/", "class Test {}", 54 }; 55 doFormatTest(input, expected); 56 } 57 58 @Test emptyMultipleLines()59 public void emptyMultipleLines() { 60 String[] input = { 61 "/**", // 62 " */", 63 "class Test {}", 64 }; 65 String[] expected = { 66 "/** */", "class Test {}", 67 }; 68 doFormatTest(input, expected); 69 } 70 71 @Test simple()72 public void simple() { 73 String[] input = { 74 "/** */", // 75 "class Test {}", 76 }; 77 String[] expected = { 78 "/** */", "class Test {}", 79 }; 80 doFormatTest(input, expected); 81 } 82 83 @Test commentMostlyUntouched()84 public void commentMostlyUntouched() { 85 // This test isn't necessarily what we'd want to do, but it's what we do now, and it's OK-ish. 86 String[] input = { 87 "/**", 88 " * Foo.", 89 " *", 90 " * <!--", 91 "*abc", 92 " * def ", 93 " * </tr>", 94 " *-->bar", 95 " */", 96 "class Test {}", 97 }; 98 String[] expected = { 99 "/**", 100 " * Foo.", 101 " * <!--", 102 " *abc", 103 " * def", 104 " * </tr>", 105 " *-->", 106 " * bar", 107 " */", 108 "class Test {}", 109 }; 110 doFormatTest(input, expected); 111 } 112 113 @Test moeComments()114 public void moeComments() { 115 String[] input = { 116 "/**", 117 " * Deatomizes the given user.", 118 " * <!-- M" + "OE:begin_intracomment_strip -->", 119 " * See deatomizer-v5 for the design doc.", 120 " * <!-- M" + "OE:end_intracomment_strip -->", 121 " * To reatomize, call {@link reatomize}.", 122 " *", 123 " * <!-- M" + "OE:begin_intracomment_strip -->", 124 " * <p>This method is used in the Google teleporter.", 125 " *", 126 " * <p>Yes, we have a teleporter.", 127 " * <!-- M" + "OE:end_intracomment_strip -->", 128 " *", 129 " * @param user the person to teleport.", 130 " * <!-- M" + "OE:begin_intracomment_strip -->", 131 " * Users must sign deatomize-waiver ahead of time.", 132 " * <!-- M" + "OE:end_intracomment_strip -->", 133 " * <!-- M" + "OE:begin_intracomment_strip -->", 134 " * @deprecated Sometimes turns the user into a goat.", 135 " * <!-- M" + "OE:end_intracomment_strip -->", 136 " */", 137 "class Test {}", 138 }; 139 String[] expected = { 140 "/**", 141 " * Deatomizes the given user.", 142 " * <!-- M" + "OE:begin_intracomment_strip -->", 143 " * See deatomizer-v5 for the design doc.", 144 " * <!-- M" + "OE:end_intracomment_strip -->", 145 " * To reatomize, call {@link reatomize}.", 146 " *", 147 " * <!-- M" + "OE:begin_intracomment_strip -->", 148 " * <p>This method is used in the Google teleporter.", 149 " *", 150 " * <p>Yes, we have a teleporter.", 151 " * <!-- M" + "OE:end_intracomment_strip -->", 152 " *", 153 " * @param user the person to teleport.", 154 " * <!-- M" + "OE:begin_intracomment_strip -->", 155 " * Users must sign deatomize-waiver ahead of time.", 156 " * <!-- M" + "OE:end_intracomment_strip -->", 157 " * <!-- M" + "OE:begin_intracomment_strip -->", 158 " * @deprecated Sometimes turns the user into a goat.", 159 " * <!-- M" + "OE:end_intracomment_strip -->", 160 " */", 161 "class Test {}", 162 }; 163 doFormatTest(input, expected); 164 } 165 166 @Test moeCommentBeginOnlyInMiddleOfDoc()167 public void moeCommentBeginOnlyInMiddleOfDoc() { 168 // We don't really care what happens here so long as we don't explode. 169 String[] input = { 170 "/**", // 171 " * Foo.", 172 " * <!-- M" + "OE:begin_intracomment_strip -->", 173 " * Bar.", 174 " */", 175 "class Test {}", 176 }; 177 String[] expected = { 178 "/**", // 179 " * Foo.", 180 " * <!-- M" + "OE:begin_intracomment_strip -->", 181 " * Bar.", 182 " */", 183 "class Test {}", 184 }; 185 doFormatTest(input, expected); 186 } 187 188 @Test moeCommentBeginOnlyAtEndOfDoc()189 public void moeCommentBeginOnlyAtEndOfDoc() { 190 // We don't really care what happens here so long as we don't explode. 191 // TODO(cpovirk): OK, maybe try to leave it in.... 192 String[] input = { 193 "/**", // 194 " * Foo.", 195 " * <!-- M" + "OE:begin_intracomment_strip -->", 196 " */", 197 "class Test {}", 198 }; 199 String[] expected = { 200 "/** Foo. */", // 201 "class Test {}", 202 }; 203 doFormatTest(input, expected); 204 } 205 206 @Test moeCommentEndOnly()207 public void moeCommentEndOnly() { 208 // We don't really care what happens here so long as we don't explode. 209 String[] input = { 210 "/**", // 211 " * Foo.", 212 " * <!-- M" + "OE:end_intracomment_strip -->", 213 " */", 214 "class Test {}", 215 }; 216 String[] expected = { 217 "/**", // 218 " * Foo.", 219 " * <!-- M" + "OE:end_intracomment_strip -->", 220 " */", 221 "class Test {}", 222 }; 223 doFormatTest(input, expected); 224 } 225 226 @Test tableMostlyUntouched()227 public void tableMostlyUntouched() { 228 String[] input = { 229 "/**", 230 " * Foo.", 231 " *", 232 " * <table>", 233 "*<tr><td>a<td>b</tr>", 234 " * <tr>", 235 " * <td>A", 236 " * <td>B", 237 " * </tr>", 238 " *</table>", 239 " */", 240 "class Test {}", 241 }; 242 String[] expected = { 243 "/**", 244 " * Foo.", 245 " *", 246 " * <table>", 247 " * <tr><td>a<td>b</tr>", 248 " * <tr>", 249 " * <td>A", 250 " * <td>B", 251 " * </tr>", 252 " * </table>", 253 " */", 254 "class Test {}", 255 }; 256 doFormatTest(input, expected); 257 } 258 259 @Test preMostlyUntouched()260 public void preMostlyUntouched() { 261 /* 262 * Arguably we shouldn't insert the space between "*" and "4," since doing so changes the 263 * rendered HTML output (by inserting a space there). However, inserting a space between "*" and 264 * "</pre>" (which has no impact on the rendered HTML AFAIK) is a good thing, and inserting 265 * similar spaces in the case of <table> is good, too. And if "* 4" breaks a user's intended 266 * formatting, that user can fix it up, just as that user would have to fix up the "*4" 267 * style violation. The main downside to "* 4" is that the user might not notice that we made 268 * the change at all. (We've also slightly complicated NEWLINE_PATTERN and writeNewline to 269 * accommodate it.) 270 */ 271 String[] input = { 272 "/**", // 273 " * Example:", 274 " *", 275 " * <pre>", 276 "* 1 2<br> 3 ", 277 " *4 5 6", 278 "7 8", 279 " *</pre>", 280 " */", 281 "class Test {}", 282 }; 283 String[] expected = { 284 "/**", // 285 " * Example:", 286 " *", 287 " * <pre>", 288 " * 1 2<br> 3", 289 " * 4 5 6", 290 " * 7 8", 291 " * </pre>", 292 " */", 293 "class Test {}", 294 }; 295 doFormatTest(input, expected); 296 } 297 298 @Test preCodeExample()299 public void preCodeExample() { 300 // We should figure out whether we want a newline or blank line before <pre> or not. 301 String[] input = { 302 "/**", 303 " * Example:", 304 " *", 305 " * <pre> {@code", 306 " *", 307 " * Abc.def(foo, 7, true); // blah}</pre>", 308 " */", 309 "class Test {}", 310 }; 311 String[] expected = { 312 "/**", 313 " * Example:", 314 " *", 315 " * <pre>{@code", 316 " * Abc.def(foo, 7, true); // blah", 317 " * }</pre>", 318 " */", 319 "class Test {}", 320 }; 321 doFormatTest(input, expected); 322 } 323 324 @Test preNotWrapped()325 public void preNotWrapped() { 326 String[] input = { 327 "/**", 328 " * Example:", 329 " *", 330 " * <pre>", 331 " * 456789012 456789012 456789012 456789012 456789012 456789012 456789012 456789012 " 332 + "456789012 45678901", 333 " * </pre>", 334 " */", 335 "class Test {}", 336 }; 337 String[] expected = { 338 "/**", 339 " * Example:", 340 " *", 341 " * <pre>", 342 " * 456789012 456789012 456789012 456789012 456789012 456789012 456789012 456789012 " 343 + "456789012 45678901", 344 " * </pre>", 345 " */", 346 "class Test {}", 347 }; 348 doFormatTest(input, expected); 349 } 350 351 @Test javaCodeInPre()352 public void javaCodeInPre() { 353 String[] input = { 354 "/**", 355 " * Example:", 356 " *", 357 " *<pre>", 358 " * aaaaa | a | +", 359 " * \"bbbb | b | \"", 360 " *</pre>", 361 " */", 362 "class Test {}", 363 }; 364 String[] expected = { 365 "/**", 366 " * Example:", 367 " *", 368 " * <pre>", 369 " * aaaaa | a | +", 370 " * \"bbbb | b | \"", 371 " * </pre>", 372 " */", 373 "class Test {}", 374 }; 375 doFormatTest(input, expected); 376 } 377 378 @Test joinLines()379 public void joinLines() { 380 String[] input = { 381 "/**", // 382 " * foo", 383 " * bar", 384 " * baz", 385 " */", 386 "class Test {}", 387 }; 388 String[] expected = { 389 "/** foo bar baz */", // 390 "class Test {}", 391 }; 392 doFormatTest(input, expected); 393 } 394 395 @Test oneLinerIs100()396 public void oneLinerIs100() { 397 String[] input = { 398 "/**", 399 " * 567890123 567890123 567890123 567890123 567890123 567890123 567890123 567890123 " 400 + "567890123 567", 401 " */", 402 "class Test {}", 403 }; 404 String[] expected = { 405 "/** 567890123 567890123 567890123 567890123 567890123 567890123 567890123 567890123 " 406 + "567890123 567 */", 407 "class Test {}", 408 }; 409 doFormatTest(input, expected); 410 } 411 412 @Test oneLinerWouldBe101()413 public void oneLinerWouldBe101() { 414 String[] input = { 415 "/**", 416 " * 567890123 567890123 567890123 567890123 567890123 567890123 567890123 567890123 " 417 + "567890123 5678", 418 " */", 419 "class Test {}", 420 }; 421 String[] expected = { 422 "/**", 423 " * 567890123 567890123 567890123 567890123 567890123 567890123 567890123 567890123 " 424 + "567890123 5678", 425 " */", 426 "class Test {}", 427 }; 428 doFormatTest(input, expected); 429 } 430 431 @Test multilineWrap()432 public void multilineWrap() { 433 String[] input = { 434 "/**", 435 " * 456789012 456789012 456789012 456789012 456789012 456789012 456789012 456789012 " 436 + "456789012 45678901", 437 " */", 438 "class Test {}", 439 }; 440 String[] expected = { 441 "/**", 442 " * 456789012 456789012 456789012 456789012 456789012 456789012 456789012 456789012 " 443 + "456789012", 444 " * 45678901", 445 " */", 446 "class Test {}", 447 }; 448 doFormatTest(input, expected); 449 } 450 451 @Test tooLong()452 public void tooLong() { 453 String[] input = { 454 "/**", 455 " * abc", 456 " *", 457 " * <p>789012345678901234567890123456789012345678901234567890123456789012345678901234567" 458 + "8901234567890123456", 459 " */", 460 "class Test {}", 461 }; 462 String[] expected = { 463 "/**", 464 " * abc", 465 " *", 466 " * <p>789012345678901234567890123456789012345678901234567890123456789012345678901234567" 467 + "8901234567890123456", 468 " */", 469 "class Test {}", 470 }; 471 doFormatTest(input, expected); 472 } 473 474 @Test joinedTokens()475 public void joinedTokens() { 476 /* 477 * Originally, 4, <b>, and 8901 are separate tokens. Test that we join them (and thus don't 478 * split them across lines). 479 */ 480 String[] input = { 481 "/**", 482 " * 456789012 456789012 456789012 456789012 456789012 456789012 456789012 456789012 " 483 + "456789012 4<b>8901", 484 " */", 485 "class Test {}", 486 }; 487 String[] expected = { 488 "/**", 489 " * 456789012 456789012 456789012 456789012 456789012 456789012 456789012 456789012 " 490 + "456789012", 491 " * 4<b>8901", 492 " */", 493 "class Test {}", 494 }; 495 doFormatTest(input, expected); 496 } 497 498 @Test joinedAtSign()499 public void joinedAtSign() { 500 /* 501 * The last 456789012 would fit on the first line with the others. But putting it there would 502 * mean the next line would start with @5678901, which would then be interpreted as a tag. 503 */ 504 String[] input = { 505 "/**", 506 " * 456789012 456789012 456789012 456789012 456789012 456789012 456789012 456789012 " 507 + "456789012 @5678901", 508 " */", 509 "class Test {}", 510 }; 511 String[] expected = { 512 "/**", 513 " * 456789012 456789012 456789012 456789012 456789012 456789012 456789012 456789012", 514 " * 456789012 @5678901", 515 " */", 516 "class Test {}", 517 }; 518 doFormatTest(input, expected); 519 } 520 521 @Test joinedMultipleAtSign()522 public void joinedMultipleAtSign() { 523 // This is the same as above except that it tests multiple consecutive @... tokens. 524 String[] input = { 525 "/**", 526 " * 456789012 456789012 456789012 456789012 456789012 456789012 456789012 456789012 " 527 + "@56789012 @5678901", 528 " */", 529 "class Test {}", 530 }; 531 String[] expected = { 532 "/**", 533 " * 456789012 456789012 456789012 456789012 456789012 456789012 456789012", 534 " * 456789012 @56789012 @5678901", 535 " */", 536 "class Test {}", 537 }; 538 doFormatTest(input, expected); 539 } 540 541 @Test noAsterisk()542 public void noAsterisk() { 543 String[] input = { 544 "/**", // 545 " abc<p>def", 546 " */", 547 "class Test {}", 548 }; 549 String[] expected = { 550 "/**", // 551 " * abc", 552 " *", 553 " * <p>def", 554 " */", 555 "class Test {}", 556 }; 557 doFormatTest(input, expected); 558 } 559 560 @Test significantAsterisks()561 public void significantAsterisks() { 562 String[] input = { 563 "/** *", // 564 " * *", 565 " */", 566 "class Test {}", 567 }; 568 String[] expected = { 569 "/** * * */", // 570 "class Test {}", 571 }; 572 doFormatTest(input, expected); 573 } 574 575 @Test links()576 public void links() { 577 String[] input = { 578 "/**", 579 " * 456789012 456789012 456789012 456789012 456789012 456789012 456789012 456789012 " 580 + "456789012 4567 <a", 581 " * href=foo>foo</a>.", 582 " *", 583 " * <p>789012 456789012 456789012 456789012 456789012 456789012 456789012 456789 " 584 + "<a href=foo>", 585 " * foo</a>.", 586 " *", 587 " * <p>789012 456789012 456789012 456789012 456789012 456789012 456789012 4567890 " 588 + "<a href=foo>", 589 " * foo</a>.", 590 " *", 591 " * <p><a href=foo>", 592 " * foo</a>.", 593 " *", 594 " * <p>foo <a href=bar>", 595 " * bar</a>.", 596 " *", 597 " * <p>foo-<a href=bar>", 598 " * bar</a>.", 599 " *", 600 " * <p>foo<a href=bar>", 601 " * bar</a>.", 602 " *", 603 " * <p><a href=foo>foo</a> bar.", 604 " */", 605 "class Test {}", 606 }; 607 String[] expected = { 608 "/**", 609 " * 456789012 456789012 456789012 456789012 456789012 456789012 456789012 456789012 " 610 + "456789012 4567 <a", 611 " * href=foo>foo</a>.", 612 " *", 613 " * <p>789012 456789012 456789012 456789012 456789012 456789012 456789012 456789 " 614 + "<a href=foo>foo</a>.", 615 " *", 616 " * <p>789012 456789012 456789012 456789012 456789012 456789012 456789012 4567890 " 617 + "<a href=foo>", 618 " * foo</a>.", 619 " *", 620 " * <p><a href=foo>foo</a>.", 621 " *", 622 " * <p>foo <a href=bar>bar</a>.", 623 " *", 624 " * <p>foo-<a href=bar>bar</a>.", 625 " *", 626 /* 627 * In this next case, we've removed a space from the output. Fortunately, the depot doesn't 628 * appear to contain any occurrences of this pattern. And if it does, the better fix is to 629 * insert a space before <a href> rather than after. 630 */ 631 " * <p>foo<a href=bar>bar</a>.", 632 " *", 633 " * <p><a href=foo>foo</a> bar.", 634 " */", 635 "class Test {}", 636 }; 637 doFormatTest(input, expected); 638 } 639 640 @Test heading()641 public void heading() { 642 String[] input = { 643 "/**", // 644 " * abc<h1>def</h1>ghi", 645 " */", 646 "class Test {}", 647 }; 648 String[] expected = { 649 "/**", // 650 " * abc", 651 " *", 652 " * <h1>def</h1>", 653 " *", 654 " * ghi", 655 " */", 656 "class Test {}", 657 }; 658 doFormatTest(input, expected); 659 } 660 661 @Test blockquote()662 public void blockquote() { 663 String[] input = { 664 "/**", // 665 " * abc<blockquote><p>def</blockquote>ghi", 666 " */", 667 "class Test {}", 668 }; 669 String[] expected = { 670 "/**", // 671 " * abc", 672 " *", 673 " * <blockquote>", 674 " *", 675 " * <p>def", 676 " *", 677 " * </blockquote>", 678 " *", 679 " * ghi", 680 " */", 681 "class Test {}", 682 }; 683 doFormatTest(input, expected); 684 } 685 686 @Test lists()687 public void lists() { 688 String[] input = { 689 "/**", // 690 "* hi", 691 "*", 692 "* <ul>", 693 "* <li>", 694 "* <ul>", 695 "* <li>a</li>", 696 "* </ul>", 697 "* </li>", 698 "* </ul>", 699 "*/", 700 "class Test {}", 701 }; 702 String[] expected = { 703 "/**", // 704 " * hi", 705 " *", 706 " * <ul>", 707 " * <li>", 708 " * <ul>", 709 " * <li>a", 710 " * </ul>", 711 " * </ul>", 712 " */", 713 "class Test {}", 714 }; 715 doFormatTest(input, expected); 716 } 717 718 @Test lists2()719 public void lists2() { 720 String[] input = { 721 "/**", // 722 " * Foo.", 723 " *", 724 " * <ul><li>1<ul><li>1a<li>1b</ul>more 1<p>still more 1<li>2</ul>", 725 " */", 726 "class Test {}", 727 }; 728 String[] expected = { 729 "/**", // 730 " * Foo.", 731 " *", 732 " * <ul>", 733 " * <li>1", 734 " * <ul>", 735 " * <li>1a", 736 " * <li>1b", 737 " * </ul>", 738 " * more 1", 739 " * <p>still more 1", 740 " * <li>2", 741 " * </ul>", 742 " */", 743 "class Test {}", 744 }; 745 doFormatTest(input, expected); 746 } 747 748 @Test closeInnerListStillNewline()749 public void closeInnerListStillNewline() { 750 String[] input = { 751 "/**", // 752 " * Foo.", 753 " *", 754 " * <ul><li><ul><li>a</ul>b</ul>", 755 " */", 756 "class Test {}", 757 }; 758 String[] expected = { 759 "/**", // 760 " * Foo.", 761 " *", 762 " * <ul>", 763 " * <li>", 764 " * <ul>", 765 " * <li>a", 766 " * </ul>", 767 " * b", 768 " * </ul>", 769 " */", 770 "class Test {}", 771 }; 772 doFormatTest(input, expected); 773 } 774 775 @Test listItemWrap()776 public void listItemWrap() { 777 String[] input = { 778 "/**", // 779 " * Foo.", 780 " *", 781 " * <ul><li>234567890 234567890 234567890 234567890 234567890 234567890 234567890 234567890" 782 + " 234567890 234567890</ul>", 783 " */", 784 "class Test {}", 785 }; 786 String[] expected = { 787 "/**", // 788 " * Foo.", 789 " *", 790 " * <ul>", 791 " * <li>234567890 234567890 234567890 234567890 234567890 234567890 234567890 234567890" 792 + " 234567890", 793 " * 234567890", 794 " * </ul>", 795 " */", 796 "class Test {}", 797 }; 798 doFormatTest(input, expected); 799 } 800 801 @Test unclosedList()802 public void unclosedList() { 803 String[] input = { 804 "/**", // 805 " * Foo.", 806 " *", 807 " * <ul><li>1", 808 " * @return blah", 809 " */", 810 "class Test {}", 811 }; 812 String[] expected = { 813 "/**", // 814 " * Foo.", 815 " *", 816 " * <ul>", 817 " * <li>1", 818 " *", 819 " * @return blah", 820 " */", 821 "class Test {}", 822 }; 823 doFormatTest(input, expected); 824 } 825 826 @Test br()827 public void br() { 828 String[] input = { 829 "/**", // 830 " * abc<br>def", 831 " */", 832 "class Test {}", 833 }; 834 String[] expected = { 835 "/**", // 836 " * abc<br>", 837 " * def", 838 " */", 839 "class Test {}", 840 }; 841 doFormatTest(input, expected); 842 } 843 844 @Test brSpaceBug()845 public void brSpaceBug() { 846 // TODO(b/28983091): Remove the space before <br> here. 847 String[] input = { 848 "/**", // 849 " * abc <br>def", 850 " */", 851 "class Test {}", 852 }; 853 String[] expected = { 854 "/**", // 855 " * abc <br>", 856 " * def", 857 " */", 858 "class Test {}", 859 }; 860 doFormatTest(input, expected); 861 } 862 863 @Test brAtSignBug()864 public void brAtSignBug() { 865 /* 866 * This is a bug -- more of a "spec" bug than an implementation bug, and hard to fix. 867 * Fortunately, some very quick searching didn't turn up any instances in the Google codebase. 868 */ 869 String[] input = { 870 "/**", // 871 " * abc<br>@foo ", 872 " */", 873 "class Test {}", 874 }; 875 String[] expected = { 876 "/**", // 877 " * abc<br>", 878 " * @foo", // interpreted as a block tag now! 879 " */", 880 "class Test {}", 881 }; 882 doFormatTest(input, expected); 883 } 884 885 @Test unicodeCharacterCountArguableBug()886 public void unicodeCharacterCountArguableBug() { 887 /* 888 * We might prefer for multi-char characters like to be treated as taking up one column (or 889 * perhaps for all characters to be treated based on their width in monospace fonts). But 890 * currently we just count chars. 891 */ 892 String[] input = { 893 "/**", 894 " * 45678912 45678912 45678912 45678912 45678912 45678912 45678912 45678912 " 895 + "45678912 456789", 896 " */", 897 "class Test {}", 898 }; 899 String[] expected = { 900 "/**", 901 " * 45678912 45678912 45678912 45678912 45678912 45678912 45678912 45678912", 902 " * 45678912 456789", 903 " */", 904 "class Test {}", 905 }; 906 doFormatTest(input, expected); 907 } 908 909 @Test blankLineBeforeParams()910 public void blankLineBeforeParams() { 911 String[] input = { 912 "/**", // 913 " * hello world", 914 " * @param this is a param", 915 " */", 916 "class Test {}", 917 }; 918 String[] expected = { 919 "/**", // 920 " * hello world", 921 " *", 922 " * @param this is a param", 923 " */", 924 "class Test {}", 925 }; 926 doFormatTest(input, expected); 927 } 928 929 @Test onlyParams()930 public void onlyParams() { 931 String[] input = { 932 "/**", // 933 " *", 934 " *", 935 " * @param this is a param", 936 " */", 937 "class Test {}", 938 }; 939 String[] expected = { 940 "/**", // 941 " * @param this is a param", 942 " */", 943 "class Test {}", 944 }; 945 doFormatTest(input, expected); 946 } 947 948 @Test paramsContinuationIndented()949 public void paramsContinuationIndented() { 950 String[] input = { 951 "/**", // 952 " * hello world", 953 " *", 954 " * @param foo 567890123 567890123 567890123 567890123 567890123 567890123 567890123" 955 + " 567890123 567890123", 956 " * @param bar another", 957 " */", 958 "class Test {}", 959 }; 960 String[] expected = { 961 "/**", // 962 " * hello world", 963 " *", 964 " * @param foo 567890123 567890123 567890123 567890123 567890123 567890123 567890123" 965 + " 567890123", 966 " * 567890123", 967 " * @param bar another", 968 " */", 969 "class Test {}", 970 }; 971 doFormatTest(input, expected); 972 } 973 974 @Test paramsOtherIndents()975 public void paramsOtherIndents() { 976 String[] input = { 977 "/**", // 978 " * hello world", 979 " *", 980 " * @param foo a<p>b<ul><li>a<ul><li>x</ul></ul>", 981 " * @param bar another", 982 " */", 983 "class Test {}", 984 }; 985 String[] expected = { 986 "/**", // 987 " * hello world", 988 " *", 989 " * @param foo a", 990 " * <p>b", 991 " * <ul>", 992 " * <li>a", 993 " * <ul>", 994 " * <li>x", 995 " * </ul>", 996 " * </ul>", 997 " *", // TODO(cpovirk): Ideally we would probably eliminate this. 998 " * @param bar another", 999 " */", 1000 "class Test {}", 1001 }; 1002 doFormatTest(input, expected); 1003 } 1004 1005 @Test paragraphTag()1006 public void paragraphTag() { 1007 String[] input = { 1008 "class Test {", 1009 " /**", 1010 " * hello<p>world", 1011 " */", 1012 " void f() {}", 1013 "", 1014 " /**", 1015 " * hello", 1016 " * <p>", 1017 " * world", 1018 " */", 1019 " void f() {}", 1020 "}", 1021 }; 1022 String[] expected = { 1023 "class Test {", 1024 " /**", 1025 " * hello", 1026 " *", 1027 " * <p>world", 1028 " */", 1029 " void f() {}", 1030 "", 1031 " /**", 1032 " * hello", 1033 " *", 1034 " * <p>world", 1035 " */", 1036 " void f() {}", 1037 "}", 1038 }; 1039 doFormatTest(input, expected); 1040 } 1041 1042 @Test xhtmlParagraphTag()1043 public void xhtmlParagraphTag() { 1044 String[] input = { 1045 "class Test {", 1046 " /**", 1047 " * hello<p/>world", 1048 " */", 1049 " void f() {}", 1050 "", 1051 "}", 1052 }; 1053 String[] expected = { 1054 "class Test {", 1055 " /**", 1056 " * hello", 1057 " *", 1058 " * <p>world", 1059 " */", 1060 " void f() {}", 1061 "}", 1062 }; 1063 doFormatTest(input, expected); 1064 } 1065 1066 @Test removeInitialParagraphTag()1067 public void removeInitialParagraphTag() { 1068 String[] input = { 1069 "/**", // 1070 " * <p>hello<p>world", 1071 " */", 1072 "class Test {}", 1073 }; 1074 String[] expected = { 1075 "/**", // 1076 " * hello", 1077 " *", 1078 " * <p>world", 1079 " */", 1080 "class Test {}", 1081 }; 1082 doFormatTest(input, expected); 1083 } 1084 1085 @Test inferParagraphTags()1086 public void inferParagraphTags() { 1087 String[] input = { 1088 "/**", 1089 " *", 1090 " *", 1091 " * foo", 1092 " * foo", 1093 " *", 1094 " *", 1095 " * foo", 1096 " *", 1097 " * bar", 1098 " *", 1099 " * <pre>", 1100 " *", 1101 " * baz", 1102 " *", 1103 " * </pre>", 1104 " *", 1105 " * <ul>", 1106 " * <li>foo", 1107 " *", 1108 " * bar", 1109 " * </ul>", 1110 " *", 1111 " *", 1112 " */", 1113 "class Test {}", 1114 }; 1115 String[] expected = { 1116 "/**", 1117 " * foo foo", 1118 " *", 1119 " * <p>foo", 1120 " *", 1121 " * <p>bar", 1122 " *", 1123 " * <pre>", 1124 " *", 1125 " * baz", 1126 " *", 1127 " * </pre>", 1128 " *", 1129 " * <ul>", 1130 " * <li>foo", 1131 " * <p>bar", 1132 " * </ul>", 1133 " */", 1134 "class Test {}", 1135 }; 1136 doFormatTest(input, expected); 1137 } 1138 1139 @Test paragraphTagNewlines()1140 public void paragraphTagNewlines() throws Exception { 1141 String input = 1142 new String( 1143 ByteStreams.toByteArray(getClass().getResourceAsStream("testjavadoc/B28750242.input")), 1144 UTF_8); 1145 String expected = 1146 new String( 1147 ByteStreams.toByteArray(getClass().getResourceAsStream("testjavadoc/B28750242.output")), 1148 UTF_8); 1149 String output = formatter.formatSource(input); 1150 assertThat(output).isEqualTo(expected); 1151 } 1152 1153 @Test listItemSpaces()1154 public void listItemSpaces() throws Exception { 1155 String input = 1156 new String( 1157 ByteStreams.toByteArray(getClass().getResourceAsStream("testjavadoc/B31404367.input")), 1158 UTF_8); 1159 String expected = 1160 new String( 1161 ByteStreams.toByteArray(getClass().getResourceAsStream("testjavadoc/B31404367.output")), 1162 UTF_8); 1163 String output = formatter.formatSource(input); 1164 assertThat(output).isEqualTo(expected); 1165 } 1166 1167 @Test htmlTagsInCode()1168 public void htmlTagsInCode() { 1169 String[] input = { 1170 "/** abc {@code {} <p> <li> <pre> <table>} def */", // 1171 "class Test {}", 1172 }; 1173 String[] expected = { 1174 "/** abc {@code {} <p> <li> <pre> <table>} def */", // 1175 "class Test {}", 1176 }; 1177 doFormatTest(input, expected); 1178 } 1179 1180 @Test loneBraceDoesNotStartInlineTag()1181 public void loneBraceDoesNotStartInlineTag() { 1182 String[] input = { 1183 "/** { <p> } */", // 1184 "class Test {}", 1185 }; 1186 String[] expected = { 1187 "/**", // 1188 " * {", 1189 " *", 1190 " * <p>}", 1191 " */", 1192 "class Test {}", 1193 }; 1194 doFormatTest(input, expected); 1195 } 1196 1197 @Test unicodeEscapesNotReplaced()1198 public void unicodeEscapesNotReplaced() { 1199 // Test that we don't replace them with their interpretations. 1200 String[] input = { 1201 "/** foo \\u0000 bar \\u6c34 baz */", // 1202 "class Test {}", 1203 }; 1204 String[] expected = { 1205 "/** foo \\u0000 bar \\u6c34 baz */", // 1206 "class Test {}", 1207 }; 1208 doFormatTest(input, expected); 1209 } 1210 1211 @Test unicodeEscapesNotInterpretedBug()1212 public void unicodeEscapesNotInterpretedBug() { 1213 /* 1214 * In theory, \u003C should be treated exactly like <, and so too should the escaped versions of 1215 * @, *, and other special chars. We don't recognize that, though, so we don't put what is 1216 * effectively "<p>" on a new line. 1217 */ 1218 String[] input = { 1219 "/** a\\u003Cp>b */", // 1220 "class Test {}", 1221 }; 1222 String[] expected = { 1223 "/** a\\u003Cp>b */", // 1224 "class Test {}", 1225 }; 1226 doFormatTest(input, expected); 1227 } 1228 1229 @Test trailingLink()1230 public void trailingLink() { 1231 // Eclipse's parser seems to want to discard the line break after {@link}. Test that we see it. 1232 String[] input = { 1233 "/**", // 1234 " * abc {@link Foo}", 1235 " * def", 1236 " */", 1237 "class Test {}", 1238 }; 1239 String[] expected = { 1240 "/** abc {@link Foo} def */", // 1241 "class Test {}", 1242 }; 1243 doFormatTest(input, expected); 1244 } 1245 1246 @Test codeInCode()1247 public void codeInCode() { 1248 // Eclipse's parser seems to get confused at the second {@code}. Test that we handle it. 1249 String[] input = { 1250 "/** abc {@code {@code foo}} def */", // 1251 "class Test {}", 1252 }; 1253 String[] expected = { 1254 "/** abc {@code {@code foo}} def */", // 1255 "class Test {}", 1256 }; 1257 doFormatTest(input, expected); 1258 } 1259 1260 @Test quotedTextSplitAcrossLinks()1261 public void quotedTextSplitAcrossLinks() { 1262 /* 1263 * This demonstrates one of multiple reasons that we can't hand the Javadoc *content* to 1264 * Eclipse's lexer as if it were Java code. 1265 */ 1266 String[] input = { 1267 "/**", // 1268 " * abc \"foo", 1269 " * bar baz\" def", 1270 " */", 1271 "class Test {}", 1272 }; 1273 String[] expected = { 1274 "/** abc \"foo bar baz\" def */", // 1275 "class Test {}", 1276 }; 1277 doFormatTest(input, expected); 1278 } 1279 1280 @Test standardizeTags()1281 public void standardizeTags() { 1282 String[] input = { 1283 "/**", 1284 " * foo", 1285 " *", 1286 " * <P>bar", 1287 " *", 1288 " * <p class=clazz>baz<BR>", 1289 " * baz", 1290 " */", 1291 "class Test {}", 1292 }; 1293 String[] expected = { 1294 "/**", 1295 " * foo", 1296 " *", 1297 " * <p>bar", 1298 " *", 1299 " * <p class=clazz>baz<br>", 1300 " * baz", 1301 " */", 1302 "class Test {}", 1303 }; 1304 doFormatTest(input, expected); 1305 } 1306 1307 @Test removeCloseTags()1308 public void removeCloseTags() { 1309 String[] input = { 1310 "/**", // 1311 " * foo</p>", 1312 " *", 1313 " * <p>bar</p>", 1314 " */", 1315 "class Test {}", 1316 }; 1317 String[] expected = { 1318 "/**", // 1319 " * foo", 1320 " *", 1321 " * <p>bar", 1322 " */", 1323 "class Test {}", 1324 }; 1325 doFormatTest(input, expected); 1326 } 1327 1328 @Test javadocFullSentences()1329 public void javadocFullSentences() { 1330 String[] input = { 1331 "/** In our application, bats are often found hanging from the ceiling, especially on" 1332 + " Wednesdays. Sometimes sick bats have issues where their claws do not close entirely." 1333 + " This class provides a nice, grippable surface for them to cling to. */", 1334 "class Grippable {}", 1335 }; 1336 String[] expected = { 1337 "/**", 1338 " * In our application, bats are often found hanging from the ceiling, especially on" 1339 + " Wednesdays.", 1340 " * Sometimes sick bats have issues where their claws do not close entirely. This class" 1341 + " provides a", 1342 " * nice, grippable surface for them to cling to.", 1343 " */", 1344 "class Grippable {}", 1345 }; 1346 doFormatTest(input, expected); 1347 } 1348 1349 @Test javadocSentenceFragment()1350 public void javadocSentenceFragment() { 1351 String[] input = { 1352 "/** Provides a comfy, grippable surface for sick bats with claw-closing problems, which are" 1353 + " sometimes found hanging from the ceiling on Wednesdays. */", 1354 "class Grippable {}", 1355 }; 1356 String[] expected = { 1357 "/**", 1358 " * Provides a comfy, grippable surface for sick bats with claw-closing problems, which are" 1359 + " sometimes", 1360 " * found hanging from the ceiling on Wednesdays.", 1361 " */", 1362 "class Grippable {}", 1363 }; 1364 doFormatTest(input, expected); 1365 } 1366 1367 @Test javadocCanEndAnywhere()1368 public void javadocCanEndAnywhere() { 1369 String[] input = { 1370 "/** foo <pre*/", // 1371 "class Test {}", 1372 }; 1373 String[] expected = { 1374 "/** foo <pre */", // 1375 "class Test {}", 1376 }; 1377 doFormatTest(input, expected); 1378 } 1379 doFormatTest(String[] input, String[] expected)1380 private void doFormatTest(String[] input, String[] expected) { 1381 try { 1382 String actual = formatter.formatSource(Joiner.on('\n').join(input)); 1383 assertThat(actual).isEqualTo(Joiner.on('\n').join(expected) + "\n"); 1384 } catch (FormatterException e) { 1385 throw new AssertionError(e); 1386 } 1387 } 1388 1389 @Test windowsLineSeparator()1390 public void windowsLineSeparator() throws FormatterException { 1391 String[] input = { 1392 "/**", " * hello", " *", " * <p>world", " */", "class Test {}", 1393 }; 1394 for (String separator : Arrays.asList("\r", "\r\n")) { 1395 String actual = formatter.formatSource(Joiner.on(separator).join(input)); 1396 assertThat(actual).isEqualTo(Joiner.on(separator).join(input) + separator); 1397 } 1398 } 1399 1400 @Test u2028LineSeparator()1401 public void u2028LineSeparator() { 1402 String[] input = { 1403 "public class Foo {", 1404 " /**\u2028", 1405 " * Set and enable something.", 1406 " */", 1407 " public void setSomething() {}", 1408 "}", 1409 }; 1410 String[] expected = { 1411 "public class Foo {", 1412 " /**", 1413 " * \u2028 Set and enable something.", 1414 " */", 1415 " public void setSomething() {}", 1416 "}", 1417 }; 1418 doFormatTest(input, expected); 1419 } 1420 1421 @Test missingSummaryFragment()1422 public void missingSummaryFragment() { 1423 String[] input = { 1424 "public class Foo {", 1425 " /**", 1426 " * @return something.", 1427 " */", 1428 " public void setSomething() {}", 1429 "", 1430 " /**", 1431 " * @hide", 1432 " */", 1433 " public void setSomething() {}", 1434 "}", 1435 }; 1436 String[] expected = { 1437 "public class Foo {", 1438 " /**", 1439 " * @return something.", 1440 " */", 1441 " public void setSomething() {}", 1442 "", 1443 " /** @hide */", 1444 " public void setSomething() {}", 1445 "}", 1446 }; 1447 doFormatTest(input, expected); 1448 } 1449 } 1450