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       " * 456789��12 456789��12 456789��12 456789��12 456789��12 456789��12 456789��12 456789��12 "
895           + "456789��12 456789��",
896       " */",
897       "class Test {}",
898     };
899     String[] expected = {
900       "/**",
901       " * 456789��12 456789��12 456789��12 456789��12 456789��12 456789��12 456789��12 456789��12",
902       " * 456789��12 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