• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.facebook.ktfmt.format
18 
19 import com.facebook.ktfmt.testutil.assertFormatted
20 import com.facebook.ktfmt.testutil.assertThatFormatting
21 import com.google.common.truth.Truth.assertThat
22 import org.junit.Assert.fail
23 import org.junit.Test
24 import org.junit.runner.RunWith
25 import org.junit.runners.JUnit4
26 
27 @Suppress("FunctionNaming")
28 @RunWith(JUnit4::class)
29 class FormatterTest {
30 
31   @Test
support script (kts) filesnull32   fun `support script (kts) files`() =
33       assertFormatted(
34           """
35         |package foo
36         |
37         |import java.io.File
38         |
39         |val one: String
40         |
41         |val two: String
42         |
43         |fun f() {
44         |  println("asd")
45         |}
46         |
47         |println("Called with args:")
48         |
49         |args.forEach { println(File + "-") }
50         |"""
51               .trimMargin())
52 
53   @Test
54   fun `support script (kts) files with a shebang`() =
55       assertFormatted(
56           """
57         |#!/usr/bin/env kscript
58         |package foo
59         |
60         |println("Called")
61         |"""
62               .trimMargin())
63 
64   @Test
65   fun `call chains`() =
66       assertFormatted(
67           """
68       |//////////////////////////////////////////////////
69       |fun f() {
70       |  // Static method calls are attached to the class name.
71       |  ImmutableList.newBuilder()
72       |      .add(1)
73       |      .add(1)
74       |      .add(1)
75       |      .add(1)
76       |      .add(1)
77       |      .add(1)
78       |      .add(1)
79       |      .add(1)
80       |      .add(1)
81       |      .add(1)
82       |      .build()
83       |
84       |  // Multiple call expressions --> each on its own line.
85       |  ImmutableList()
86       |      .newBuilder()
87       |      .add(1)
88       |      .add(1)
89       |      .add(1)
90       |      .add(1)
91       |      .add(1)
92       |      .add(1)
93       |      .add(1)
94       |      .add(1)
95       |      .add(1)
96       |      .add(1)
97       |      .build()
98       |}
99       |"""
100               .trimMargin(),
101           deduceMaxWidth = true)
102 
103   @Test
104   fun `line breaks in function arguments`() =
105       assertFormatted(
106           """
107       |//////////////////////////////////////////////////
108       |fun f() {
109       |  computeBreaks(
110       |      javaOutput.commentsHelper,
111       |      maxWidth,
112       |      Doc.State(+0, 0))
113       |  computeBreaks(
114       |      output.commentsHelper, maxWidth, State(0))
115       |  doc.computeBreaks(
116       |      javaOutput.commentsHelper,
117       |      maxWidth,
118       |      Doc.State(+0, 0))
119       |  doc.computeBreaks(
120       |      output.commentsHelper, maxWidth, State(0))
121       |}
122       |"""
123               .trimMargin(),
124           deduceMaxWidth = true)
125 
126   @Test
127   fun `parameters and return type in function definitions`() =
128       assertFormatted(
129           """
130       |////////////////////////////////////////
131       |fun format(
132       |    code: String,
133       |    maxWidth: Int =
134       |        DEFAULT_MAX_WIDTH_VERY_LONG
135       |): String {
136       |  val a = 0
137       |}
138       |
139       |fun print(
140       |    code: String,
141       |    maxWidth: Int =
142       |        DEFAULT_MAX_WIDTH_VERY_LONG
143       |) {
144       |  val a = 0
145       |}
146       |"""
147               .trimMargin(),
148           deduceMaxWidth = true)
149 
150   @Test
151   fun `kitchen sink of tests`() {
152     // Don't add more tests here
153     val code =
154         """
155         |fun
156         |f  (
157         |a : Int
158         | , b: Double , c:String) {           var result = 0
159         | val aVeryLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongVar = 43
160         |          foo.bar.zed.accept(
161         |
162         |          )
163         |
164         |          foo(
165         |
166         |          )
167         |
168         |          foo.bar.zed.accept(
169         |                DoSomething.bar()
170         |          )
171         |
172         |          bar(
173         |          ImmutableList.newBuilder().add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).build())
174         |
175         |
176         |          ImmutableList.newBuilder().add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).add(1).build()
177         |     }
178         |"""
179             .trimMargin()
180 
181     val expected =
182         """
183         |fun f(a: Int, b: Double, c: String) {
184         |  var result = 0
185         |  val aVeryLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongVar =
186         |      43
187         |  foo.bar.zed.accept()
188         |
189         |  foo()
190         |
191         |  foo.bar.zed.accept(DoSomething.bar())
192         |
193         |  bar(
194         |      ImmutableList.newBuilder()
195         |          .add(1)
196         |          .add(1)
197         |          .add(1)
198         |          .add(1)
199         |          .add(1)
200         |          .add(1)
201         |          .add(1)
202         |          .add(1)
203         |          .add(1)
204         |          .add(1)
205         |          .build())
206         |
207         |  ImmutableList.newBuilder()
208         |      .add(1)
209         |      .add(1)
210         |      .add(1)
211         |      .add(1)
212         |      .add(1)
213         |      .add(1)
214         |      .add(1)
215         |      .add(1)
216         |      .add(1)
217         |      .add(1)
218         |      .build()
219         |}
220         |"""
221             .trimMargin()
222 
223     assertThatFormatting(code).isEqualTo(expected)
224     // Don't add more tests here
225   }
226 
227   @Test
spacing around variable declarationsnull228   fun `spacing around variable declarations`() =
229       assertFormatted(
230           """
231       |fun f() {
232       |  var x: Int = 4
233       |  val y = 0
234       |}
235       |"""
236               .trimMargin())
237 
238   @Test fun `class without a body nor properties`() = assertFormatted("class Foo\n")
239 
240   @Test fun `interface without a body nor properties`() = assertFormatted("interface Foo\n")
241 
242   @Test fun `preserve empty primary constructor`() = assertFormatted("class Foo()\n")
243 
244   @Test
245   fun `simple fun interface`() =
246       assertFormatted(
247           """fun interface MyRunnable {
248         |  fun runIt()
249         |}
250         |"""
251               .trimMargin())
252 
253   @Test
254   fun `handle complex fun interface without body`() =
255       assertFormatted("public fun interface Function<T : List<*>> : (Int, T?) -> T?\n")
256 
257   @Test
258   fun `class without a body, with explicit ctor params`() =
259       assertFormatted("class Foo(a: Int, var b: Double, val c: String)\n")
260 
261   @Test
262   fun `class with a body and explicit ctor params`() =
263       assertFormatted(
264           """
265       |class Foo(a: Int, var b: Double, val c: String) {
266       |  val x = 2
267       |
268       |  fun method() {}
269       |
270       |  class Bar
271       |}
272       |"""
273               .trimMargin())
274 
275   @Test
276   fun `properties and fields with modifiers`() =
277       assertFormatted(
278           """
279       |class Foo(public val p1: Int, private val p2: Int, open val p3: Int, final val p4: Int) {
280       |  private var f1 = 0
281       |
282       |  public var f2 = 0
283       |
284       |  open var f3 = 0
285       |
286       |  final var f4 = 0
287       |}
288       |"""
289               .trimMargin())
290 
291   @Test
292   fun `properties with multiple modifiers`() =
293       assertFormatted(
294           """
295       |class Foo(public open inner val p1: Int) {
296       |  public open inner var f2 = 0
297       |}
298       |"""
299               .trimMargin())
300 
301   @Test
302   fun `spaces around binary operations`() =
303       assertFormatted(
304           """
305       |fun foo() {
306       |  a = 5
307       |  x + 1
308       |}
309       |"""
310               .trimMargin())
311 
312   @Test
313   fun `breaking long binary operations`() =
314       assertFormatted(
315           """
316       |////////////////////
317       |fun foo() {
318       |  val finalWidth =
319       |      value1 +
320       |          value2 +
321       |          (value3 +
322       |              value4 +
323       |              value5) +
324       |          foo(v) +
325       |          (1 + 2) +
326       |          function(
327       |              value7,
328       |              value8) +
329       |          value9
330       |}
331       |"""
332               .trimMargin(),
333           deduceMaxWidth = true)
334 
335   @Test
336   fun `prioritize according to associativity`() =
337       assertFormatted(
338           """
339       |//////////////////////////////////////
340       |fun foo() {
341       |  return expression1 != expression2 ||
342       |      expression2 != expression1
343       |}
344       |"""
345               .trimMargin(),
346           deduceMaxWidth = true)
347 
348   @Test
349   fun `once a binary expression is broken, split on every line`() =
350       assertFormatted(
351           """
352         |//////////////////////////////////////
353         |fun foo() {
354         |  val sentence =
355         |      "The" +
356         |          "quick" +
357         |          ("brown" + "fox") +
358         |          "jumps" +
359         |          "over" +
360         |          "the" +
361         |          "lazy" +
362         |          "dog"
363         |}
364         |"""
365               .trimMargin(),
366           deduceMaxWidth = true)
367 
368   @Test
369   fun `long binary expressions with ranges in the middle`() =
370       assertFormatted(
371           """
372         |//////////////////////////////////////
373         |fun foo() {
374         |  val sentence =
375         |      "The" +
376         |          "quick" +
377         |          ("brown".."fox") +
378         |          ("brown"..<"fox") +
379         |          "jumps" +
380         |          "over" +
381         |          "the".."lazy" + "dog"
382         |}
383         |"""
384               .trimMargin(),
385           deduceMaxWidth = true)
386 
387   @Test
388   fun `assignment expressions with scoping functions are block-like`() =
389       assertFormatted(
390           """
391         |///////////////////////////
392         |fun f() {
393         |  name.sub = scope { x ->
394         |    //
395         |  }
396         |  name.sub += scope { x ->
397         |    //
398         |  }
399         |  name.sub -= scope { x ->
400         |    //
401         |  }
402         |  name.sub *= scope { x ->
403         |    //
404         |  }
405         |  name.sub /= scope { x ->
406         |    //
407         |  }
408         |  name.sub %= scope { x ->
409         |    //
410         |  }
411         |}
412         |
413         |fun h() {
414         |  long.name.sub =
415         |      scope { x ->
416         |        //
417         |      }
418         |  long.name.sub +=
419         |      scope { x ->
420         |        //
421         |      }
422         |  long.name.sub -=
423         |      scope { x ->
424         |        //
425         |      }
426         |  long.name.sub *=
427         |      scope { x ->
428         |        //
429         |      }
430         |  long.name.sub /=
431         |      scope { x ->
432         |        //
433         |      }
434         |  long.name.sub %=
435         |      scope { x ->
436         |        //
437         |      }
438         |}
439         |"""
440               .trimMargin(),
441           deduceMaxWidth = true)
442 
443   @Test
444   fun `don't keep adding newlines between these two comments when they're at end of file`() {
445     assertFormatted(
446         """
447      |package foo
448      |// a
449      |
450      |/* Another comment */
451      |"""
452             .trimMargin())
453 
454     assertFormatted(
455         """
456      |// Comment as first element
457      |package foo
458      |// a
459      |
460      |/* Another comment */
461      |"""
462             .trimMargin())
463 
464     assertFormatted(
465         """
466      |// Comment as first element then blank line
467      |
468      |package foo
469      |// a
470      |
471      |/* Another comment */
472      |"""
473             .trimMargin())
474 
475     assertFormatted(
476         """
477      |// Comment as first element
478      |package foo
479      |// Adjacent line comments
480      |// Don't separate
481      |"""
482             .trimMargin())
483   }
484 
485   @Test
properties with line comment above initializernull486   fun `properties with line comment above initializer`() =
487       assertFormatted(
488           """
489       |class Foo {
490       |  var x: Int =
491       |      // Comment
492       |      0
493       |
494       |  var y: Int =
495       |      // Comment
496       |      scope {
497       |        0 //
498       |      }
499       |
500       |  var z: Int =
501       |      // Comment
502       |      if (cond) {
503       |        0
504       |      } else {
505       |        1
506       |      }
507       |}
508       |"""
509               .trimMargin())
510 
511   @Test
512   fun `properties with line comment above delegate`() =
513       assertFormatted(
514           """
515       |class Foo {
516       |  var x: Int by
517       |      // Comment
518       |      0
519       |
520       |  var y: Int by
521       |      // Comment
522       |      scope {
523       |        0 //
524       |      }
525       |
526       |  var z: Int by
527       |      // Comment
528       |      if (cond) {
529       |        0
530       |      } else {
531       |        1
532       |      }
533       |}
534       |"""
535               .trimMargin())
536 
537   @Test
538   fun `properties with accessors`() =
539       assertFormatted(
540           """
541       |class Foo {
542       |  var x: Int
543       |    get() = field
544       |
545       |  var y: Boolean
546       |    get() = x.equals(123)
547       |    set(value) {
548       |      field = value
549       |    }
550       |
551       |  var z: Boolean
552       |    get() {
553       |      x.equals(123)
554       |    }
555       |
556       |  var zz = false
557       |    private set
558       |}
559       |"""
560               .trimMargin())
561 
562   @Test
563   fun `properties with accessors and semicolons on same line`() {
564     val code =
565         """
566       |class Foo {
567       |  var x = false; private set
568       |
569       |  internal val a by lazy { 5 }; internal get
570       |
571       |  var foo: Int; get() = 6; set(x) {};
572       |}
573       |"""
574             .trimMargin()
575 
576     val expected =
577         """
578       |class Foo {
579       |  var x = false
580       |    private set
581       |
582       |  internal val a by lazy { 5 }
583       |    internal get
584       |
585       |  var foo: Int
586       |    get() = 6
587       |    set(x) {}
588       |}
589       |"""
590             .trimMargin()
591 
592     assertThatFormatting(code).isEqualTo(expected)
593   }
594 
595   @Test
a property with a too long name being broken on multiple linesnull596   fun `a property with a too long name being broken on multiple lines`() =
597       assertFormatted(
598           """
599       |////////////////////
600       |class Foo {
601       |  val thisIsALongName:
602       |      String =
603       |      "Hello there this is long"
604       |    get() = field
605       |}
606       |"""
607               .trimMargin(),
608           deduceMaxWidth = true)
609 
610   @Test
611   fun `multi-character unary and binary operators such as ==`() =
612       assertFormatted(
613           """
614       |fun f() {
615       |  3 == 4
616       |  true && false
617       |  a++
618       |  a === b
619       |}
620       |"""
621               .trimMargin())
622 
623   @Test
624   fun `package names stay in one line`() {
625     val code =
626         """
627       | package  com  .example. subexample
628       |
629       |fun f() = 1
630       |"""
631             .trimMargin()
632     val expected =
633         """
634       |package com.example.subexample
635       |
636       |fun f() = 1
637       |"""
638             .trimMargin()
639 
640     assertThatFormatting(code).isEqualTo(expected)
641   }
642 
643   @Test
handle package name and imports with escapes and spacesnull644   fun `handle package name and imports with escapes and spaces`() =
645       assertFormatted(
646           """
647       |package com.`fun times`.`with package names`
648       |
649       |import `nothing stops`.`us`.`from doing this`
650       |
651       |fun f() = `from doing this`()
652       |"""
653               .trimMargin())
654 
655   @Test
656   fun `safe dot operator expression`() =
657       assertFormatted(
658           """
659       |fun f() {
660       |  node?.name
661       |}
662       |"""
663               .trimMargin())
664 
665   @Test
666   fun `safe dot operator expression with normal`() =
667       assertFormatted(
668           """
669       |fun f() {
670       |  node?.name.hello
671       |}
672       |"""
673               .trimMargin())
674 
675   @Test
676   fun `safe dot operator expression chain in expression function`() =
677       assertFormatted(
678           """
679       |//////////////////////////////////////////////////
680       |fun f(number: Int) =
681       |    Something.doStuff(number)?.size
682       |"""
683               .trimMargin(),
684           deduceMaxWidth = true)
685 
686   @Test
687   fun `avoid breaking suspected package names`() =
688       assertFormatted(
689           """
690       |///////////////////////
691       |fun f() {
692       |  com.facebook.Foo
693       |      .format()
694       |  org.facebook.Foo
695       |      .format()
696       |  java.lang.stuff.Foo
697       |      .format()
698       |  javax.lang.stuff.Foo
699       |      .format()
700       |  kotlin.lang.Foo
701       |      .format()
702       |  foo.facebook.Foo
703       |      .format()
704       |}
705       |"""
706               .trimMargin(),
707           deduceMaxWidth = true)
708 
709   @Test
710   fun `an assortment of tests for emitQualifiedExpression`() =
711       assertFormatted(
712           """
713       |/////////////////////////////////////
714       |fun f() {
715       |  // Regression test: https://github.com/facebook/ktfmt/issues/56
716       |  kjsdfglkjdfgkjdfkgjhkerjghkdfj
717       |      ?.methodName1()
718       |
719       |  // a series of field accesses followed by a single call expression
720       |  // is kept together.
721       |  abcdefghijkl.abcdefghijkl
722       |      ?.methodName2()
723       |
724       |  // Similar to above.
725       |  abcdefghijkl.abcdefghijkl
726       |      ?.methodName3
727       |      ?.abcdefghijkl()
728       |
729       |  // Multiple call expressions cause each part of the expression
730       |  // to be placed on its own line.
731       |  abcdefghijkl
732       |      ?.abcdefghijkl
733       |      ?.methodName4()
734       |      ?.abcdefghijkl()
735       |
736       |  // Don't break first call expression if it fits.
737       |  foIt(something.something.happens())
738       |      .thenReturn(result)
739       |
740       |  // Break after `longerThanFour(` because it's longer than 4 chars
741       |  longerThanFour(
742       |          something.something
743       |              .happens())
744       |      .thenReturn(result)
745       |
746       |  // Similarly to above, when part of qualified expression.
747       |  foo.longerThanFour(
748       |          something.something
749       |              .happens())
750       |      .thenReturn(result)
751       |
752       |  // Keep 'super' attached to the method name
753       |  super.abcdefghijkl
754       |      .methodName4()
755       |      .abcdefghijkl()
756       |}
757       |"""
758               .trimMargin(),
759           deduceMaxWidth = true)
760 
761   @Test
762   fun `an assortment of tests for emitQualifiedExpression with lambdas`() =
763       assertFormatted(
764           """
765       |////////////////////////////////////////////////////////////////////////////
766       |fun f() {
767       |  val items =
768       |      items.toMutableList.apply {
769       |        //
770       |        foo
771       |      }
772       |
773       |  val items =
774       |      items.toMutableList().apply {
775       |        //
776       |        foo
777       |      }
778       |
779       |  // All dereferences are on one line (because they fit), even though
780       |  // the apply() at the end requires a line break.
781       |  val items =
782       |      items.toMutableList.sdfkjsdf.sdfjksdflk.sdlfkjsldfj.apply {
783       |        //
784       |        foo
785       |      }
786       |
787       |  // All method calls are on one line (because they fit), even though
788       |  // the apply() at the end requires a line break.
789       |  val items =
790       |      items.toMutableList().sdfkjsdf().sdfjksdflk().sdlfkjsldfj().apply {
791       |        //
792       |        foo
793       |      }
794       |
795       |  // All method calls with lambdas could fit, but we avoid a block like syntax
796       |  // and break to one call per line
797       |  val items =
798       |      items
799       |          .map { it + 1 }
800       |          .filter { it > 0 }
801       |          .apply {
802       |            //
803       |            foo
804       |          }
805       |
806       |  // the lambda is indented properly with the break before it
807       |  val items =
808       |      items.fieldName.sdfkjsdf.sdfjksdflk.sdlfkjsldfj.sdfjksdflk.sdlfkjsldfj
809       |          .sdlfkjsldfj
810       |          .apply {
811       |            //
812       |            foo
813       |          }
814       |  items.fieldName.sdfkjsdf.sdfjksdflk.sdlfkjsldfj.sdfjksdflk.sdlfkjsldfj
815       |      .apply {
816       |        //
817       |        foo
818       |      }
819       |
820       |  // When there are multiple method calls, and they don't fit on one
821       |  // line, put each on a new line.
822       |  val items =
823       |      items
824       |          .toMutableList()
825       |          .sdfkjsdf()
826       |          .sdfjksdflk()
827       |          .sdlfkjsldfj()
828       |          .sdfjksdflk()
829       |          .sdlfkjsldfj()
830       |          .apply {
831       |            //
832       |            foo
833       |          }
834       |}
835       |"""
836               .trimMargin(),
837           deduceMaxWidth = true)
838 
839   @Test
840   fun `when two lambdas are in a chain, avoid block syntax`() =
841       assertFormatted(
842           """
843       |class Foo : Bar() {
844       |  fun doIt() {
845       |    fruit.onlyBananas().forEach { banana ->
846       |      val seeds = banana.find { it.type == SEED }
847       |      println(seeds)
848       |    }
849       |
850       |    fruit
851       |        .filter { isBanana(it, Bananas.types) }
852       |        .forEach { banana ->
853       |          val seeds = banana.find { it.type == SEED }
854       |          println(seeds)
855       |        }
856       |  }
857       |}
858       |"""
859               .trimMargin())
860 
861   @Test
862   fun `don't one-line lambdas following argument breaks`() =
863       assertFormatted(
864           """
865       |////////////////////////////////////////////////////////////////////////
866       |class Foo : Bar() {
867       |  fun doIt() {
868       |    // don't break in lambda, no argument breaks found
869       |    fruit.forEach { eat(it) }
870       |
871       |    // break in the lambda, without comma
872       |    fruit.forEach(
873       |        someVeryLongParameterNameThatWillCauseABreak,
874       |        evenWithoutATrailingCommaOnTheParameterListSoLetsSeeIt) {
875       |          eat(it)
876       |        }
877       |
878       |    // break in the lambda, with comma
879       |    fruit.forEach(
880       |        fromTheVine = true,
881       |    ) {
882       |      eat(it)
883       |    }
884       |
885       |    // don't break in the inner lambda, as nesting doesn't respect outer levels
886       |    fruit.forEach(
887       |        fromTheVine = true,
888       |    ) {
889       |      fruit.forEach { eat(it) }
890       |    }
891       |
892       |    // don't break in the lambda, as breaks don't propagate
893       |    fruit
894       |        .onlyBananas(
895       |            fromTheVine = true,
896       |        )
897       |        .forEach { eat(it) }
898       |
899       |    // don't break in the inner lambda, as breaks don't propagate to parameters
900       |    fruit.onlyBananas(
901       |        fromTheVine = true,
902       |        processThem = { eat(it) },
903       |    ) {
904       |      eat(it)
905       |    }
906       |
907       |    // don't break in the inner lambda, as breaks don't propagate to the body
908       |    fruit.onlyBananas(
909       |        fromTheVine = true,
910       |    ) {
911       |      val anon = { eat(it) }
912       |    }
913       |  }
914       |}
915       |"""
916               .trimMargin(),
917           deduceMaxWidth = true)
918 
919   @Test
indent parameters after a break when there's a lambda afterwardsnull920   fun `indent parameters after a break when there's a lambda afterwards`() =
921       assertFormatted(
922           """
923       |///////////////////////////
924       |class C {
925       |  fun method() {
926       |    Foo.FooBar(
927       |            param1, param2)
928       |        .apply {
929       |          //
930       |          foo
931       |        }
932       |  }
933       |}
934       |"""
935               .trimMargin(),
936           deduceMaxWidth = true)
937 
938   @Test
no forward propagation of breaks in call expressions (at trailing lambda)null939   fun `no forward propagation of breaks in call expressions (at trailing lambda)`() =
940       assertFormatted(
941           """
942       |//////////////////////////
943       |fun test() {
944       |  foo_bar_baz__zip<A>(b) {
945       |    c
946       |  }
947       |  foo.bar(baz).zip<A>(b) {
948       |    c
949       |  }
950       |}
951       |"""
952               .trimMargin(),
953           deduceMaxWidth = true)
954 
955   @Test
forward propagation of breaks in call expressions (at value args)null956   fun `forward propagation of breaks in call expressions (at value args)`() =
957       assertFormatted(
958           """
959       |//////////////////////
960       |fun test() {
961       |  foo_bar_baz__zip<A>(
962       |      b) {
963       |        c
964       |      }
965       |}
966       |
967       |fun test() {
968       |  foo.bar(baz).zip<A>(
969       |      b) {
970       |        c
971       |      }
972       |}
973       |"""
974               .trimMargin(),
975           deduceMaxWidth = true)
976 
977   @Test
forward propagation of breaks in call expressions (at type args)null978   fun `forward propagation of breaks in call expressions (at type args)`() =
979       assertFormatted(
980           """
981       |///////////////////
982       |fun test() {
983       |  foo_bar_baz__zip<
984       |      A>(
985       |      b) {
986       |        c
987       |      }
988       |  foo.bar(baz).zip<
989       |      A>(
990       |      b) {
991       |        c
992       |      }
993       |}
994       |"""
995               .trimMargin(),
996           deduceMaxWidth = true)
997 
998   @Test
expected indent in methods following single-line stringsnull999   fun `expected indent in methods following single-line strings`() =
1000       assertFormatted(
1001           """
1002       |/////////////////////////
1003       |"Hello %s"
1004       |    .format(expression)
1005       |"""
1006               .trimMargin(),
1007           deduceMaxWidth = true)
1008 
1009   @Test
1010   fun `forced break between multi-line strings and their selectors`() =
1011       assertFormatted(
1012           """
1013       |/////////////////////////
1014       |val STRING =
1015       |    $TQ
1016       |    |foo
1017       |    |$TQ
1018       |        .wouldFit()
1019       |
1020       |val STRING =
1021       |    $TQ
1022       |    |foo
1023       |    |//////////////////////////////////$TQ
1024       |        .wouldntFit()
1025       |
1026       |val STRING =
1027       |    $TQ
1028       |    |foo
1029       |    |$TQ
1030       |        .firstLink()
1031       |        .secondLink()
1032       |"""
1033               .trimMargin(),
1034           deduceMaxWidth = true)
1035 
1036   @Test
1037   fun `import list`() {
1038     val code =
1039         """
1040       | import  com .example.common.reality. FooBar
1041       |  import  com .example.common.reality. FooBar2  as  foosBars
1042       |   import com .example.common.reality. *
1043       | import  foo.bar // Test
1044       |  import  abc.def /*
1045       |                  test */
1046       |
1047       |val x = FooBar.def { foosBars(bar) }
1048       |"""
1049             .trimMargin()
1050     val expected =
1051         """
1052       |import abc.def /*
1053       |               test */
1054       |import com.example.common.reality.*
1055       |import com.example.common.reality.FooBar
1056       |import com.example.common.reality.FooBar2 as foosBars
1057       |import foo.bar // Test
1058       |
1059       |val x = FooBar.def { foosBars(bar) }
1060       |"""
1061             .trimMargin()
1062     assertThatFormatting(code).isEqualTo(expected)
1063   }
1064 
1065   @Test
imports with trailing comments and expressionsnull1066   fun `imports with trailing comments and expressions`() {
1067     val code =
1068         """
1069         |import com.example.zab // test
1070         |import com.example.foo ; val x = Sample(foo, zab)
1071         |"""
1072             .trimMargin()
1073 
1074     val expected =
1075         """
1076         |import com.example.foo
1077         |import com.example.zab // test
1078         |
1079         |val x = Sample(foo, zab)
1080         |"""
1081             .trimMargin()
1082 
1083     assertThatFormatting(code).isEqualTo(expected)
1084   }
1085 
1086   @Test
backticks are ignored in import sort ordernull1087   fun `backticks are ignored in import sort order`() =
1088       assertFormatted(
1089           """
1090       |import com.example.`if`
1091       |import com.example.we
1092       |import com.example.`when`
1093       |import com.example.wow
1094       |
1095       |val x = `if` { we.`when`(wow) }
1096       |"""
1097               .trimMargin())
1098 
1099   @Test
backticks are ignored in import sort order ('as' directory)null1100   fun `backticks are ignored in import sort order ('as' directory)`() =
1101       assertFormatted(
1102           """
1103       |import com.example.a as `if`
1104       |import com.example.a as we
1105       |import com.example.a as `when`
1106       |import com.example.a as wow
1107       |
1108       |val x = `if` { we.`when`(wow) }
1109       |"""
1110               .trimMargin())
1111 
1112   @Test
imports are deduplicatednull1113   fun `imports are deduplicated`() {
1114     val code =
1115         """
1116       |import com.example.b.*
1117       |import com.example.b
1118       |import com.example.a as `if`
1119       |import com.example.a as we
1120       |import com.example.a as `when`
1121       |import com.example.a as wow
1122       |import com.example.a as `when`
1123       |
1124       |val x = `if` { we.`when`(wow) } ?: b
1125       |"""
1126             .trimMargin()
1127     val expected =
1128         """
1129       |import com.example.a as `if`
1130       |import com.example.a as we
1131       |import com.example.a as `when`
1132       |import com.example.a as wow
1133       |import com.example.b
1134       |import com.example.b.*
1135       |
1136       |val x = `if` { we.`when`(wow) } ?: b
1137       |"""
1138             .trimMargin()
1139     assertThatFormatting(code).isEqualTo(expected)
1140   }
1141 
1142   @Test
unused imports are removednull1143   fun `unused imports are removed`() {
1144     val code =
1145         """
1146       |import com.unused.Sample
1147       |import com.used.FooBarBaz as Baz
1148       |import com.used.bar // test
1149       |import com.used.`class`
1150       |import com.used.a.*
1151       |import com.used.b as `if`
1152       |import com.used.b as we
1153       |import com.unused.a as `when`
1154       |import com.unused.a as wow
1155       |
1156       |fun test(input: we) {
1157       |  Baz(`class`)
1158       |  `if` { bar }
1159       |  val x = unused()
1160       |}
1161       |"""
1162             .trimMargin()
1163     val expected =
1164         """
1165       |import com.used.FooBarBaz as Baz
1166       |import com.used.a.*
1167       |import com.used.b as `if`
1168       |import com.used.b as we
1169       |import com.used.bar // test
1170       |import com.used.`class`
1171       |
1172       |fun test(input: we) {
1173       |  Baz(`class`)
1174       |  `if` { bar }
1175       |  val x = unused()
1176       |}
1177       |"""
1178             .trimMargin()
1179     assertThatFormatting(code).isEqualTo(expected)
1180   }
1181 
1182   @Test
used imports from this package are removednull1183   fun `used imports from this package are removed`() {
1184     val code =
1185         """
1186             |package com.example
1187             |
1188             |import com.example.Sample
1189             |import com.example.Sample.CONSTANT
1190             |import com.example.a.foo
1191             |
1192             |fun test() {
1193             |  foo(CONSTANT, Sample())
1194             |}
1195             |"""
1196             .trimMargin()
1197     val expected =
1198         """
1199             |package com.example
1200             |
1201             |import com.example.Sample.CONSTANT
1202             |import com.example.a.foo
1203             |
1204             |fun test() {
1205             |  foo(CONSTANT, Sample())
1206             |}
1207             |"""
1208             .trimMargin()
1209     assertThatFormatting(code).isEqualTo(expected)
1210   }
1211 
1212   @Test
potentially unused imports from this package are kept if they are overloadednull1213   fun `potentially unused imports from this package are kept if they are overloaded`() {
1214     val code =
1215         """
1216             |package com.example
1217             |
1218             |import com.example.a
1219             |import com.example.b
1220             |import com.example.c
1221             |import com.notexample.a
1222             |import com.notexample.b
1223             |import com.notexample.notC as c
1224             |
1225             |fun test() {
1226             |  a("hello")
1227             |  c("hello")
1228             |}
1229             |"""
1230             .trimMargin()
1231     val expected =
1232         """
1233             |package com.example
1234             |
1235             |import com.example.a
1236             |import com.example.c
1237             |import com.notexample.a
1238             |import com.notexample.notC as c
1239             |
1240             |fun test() {
1241             |  a("hello")
1242             |  c("hello")
1243             |}
1244             |"""
1245             .trimMargin()
1246     assertThatFormatting(code).isEqualTo(expected)
1247   }
1248 
1249   @Test
used imports from this package are kept if they are aliasednull1250   fun `used imports from this package are kept if they are aliased`() {
1251     val code =
1252         """
1253             |package com.example
1254             |
1255             |import com.example.b as a
1256             |import com.example.c
1257             |
1258             |fun test() {
1259             |  a("hello")
1260             |}
1261             |"""
1262             .trimMargin()
1263     val expected =
1264         """
1265             |package com.example
1266             |
1267             |import com.example.b as a
1268             |
1269             |fun test() {
1270             |  a("hello")
1271             |}
1272             |"""
1273             .trimMargin()
1274     assertThatFormatting(code).isEqualTo(expected)
1275   }
1276 
1277   @Test
unused imports are computed using only the alias name if presentnull1278   fun `unused imports are computed using only the alias name if present`() {
1279     val code =
1280         """
1281             |package com.example
1282             |
1283             |import com.notexample.a as b
1284             |
1285             |fun test() {
1286             |  a("hello")
1287             |}
1288             |"""
1289             .trimMargin()
1290     val expected =
1291         """
1292             |package com.example
1293             |
1294             |fun test() {
1295             |  a("hello")
1296             |}
1297             |"""
1298             .trimMargin()
1299     assertThatFormatting(code).isEqualTo(expected)
1300   }
1301 
1302   @Test
keep import elements only mentioned in kdocnull1303   fun `keep import elements only mentioned in kdoc`() {
1304     val code =
1305         """
1306             |package com.example.kdoc
1307             |
1308             |import com.example.Bar
1309             |import com.example.Example
1310             |import com.example.Foo
1311             |import com.example.JavaDocLink
1312             |import com.example.Param
1313             |import com.example.R
1314             |import com.example.ReturnedValue
1315             |import com.example.Sample
1316             |import com.example.unused
1317             |import com.example.exception.AnException
1318             |import com.example.kdoc.Doc
1319             |
1320             |/**
1321             | * [Foo] is something only mentioned here, just like [R.layout.test] and [Doc].
1322             | *
1323             | * Old {@link JavaDocLink} that gets removed.
1324             | *
1325             | * @throws AnException
1326             | * @exception Sample.SampleException
1327             | * @param unused [Param]
1328             | * @property JavaDocLink [Param]
1329             | * @return [Unit] as [ReturnedValue]
1330             | * @sample Example
1331             | * @see Bar for more info
1332             | * @throws AnException
1333             | */
1334             |class Dummy
1335             |"""
1336             .trimMargin()
1337     val expected =
1338         """
1339             |package com.example.kdoc
1340             |
1341             |import com.example.Bar
1342             |import com.example.Example
1343             |import com.example.Foo
1344             |import com.example.Param
1345             |import com.example.R
1346             |import com.example.ReturnedValue
1347             |import com.example.Sample
1348             |import com.example.exception.AnException
1349             |
1350             |/**
1351             | * [Foo] is something only mentioned here, just like [R.layout.test] and [Doc].
1352             | *
1353             | * Old {@link JavaDocLink} that gets removed.
1354             | *
1355             | * @param unused [Param]
1356             | * @return [Unit] as [ReturnedValue]
1357             | * @property JavaDocLink [Param]
1358             | * @throws AnException
1359             | * @throws AnException
1360             | * @exception Sample.SampleException
1361             | * @sample Example
1362             | * @see Bar for more info
1363             | */
1364             |class Dummy
1365             |"""
1366             .trimMargin()
1367     assertThatFormatting(code).isEqualTo(expected)
1368   }
1369 
1370   @Test
1371   fun `keep import elements only mentioned in kdoc, single line`() {
1372     assertFormatted(
1373         """
1374             |import com.shopping.Bag
1375             |
1376             |/**
1377             | * Some summary.
1378             | *
1379             | * @param count you can fit this many in a [Bag]
1380             | */
1381             |fun fetchBananas(count: Int)
1382             |"""
1383             .trimMargin())
1384   }
1385 
1386   @Test
1387   fun `keep import elements only mentioned in kdoc, multiline`() {
1388     assertFormatted(
1389         """
1390             |import com.shopping.Bag
1391             |
1392             |/**
1393             | * Some summary.
1394             | *
1395             | * @param count this is how many of these wonderful fruit you can fit into the useful object that
1396             | *   you may refer to as a [Bag]
1397             | */
1398             |fun fetchBananas(count: Int)
1399             |"""
1400             .trimMargin())
1401   }
1402 
1403   @Test
1404   fun `keep component imports`() =
1405       assertFormatted(
1406           """
1407               |import com.example.component1
1408               |import com.example.component10
1409               |import com.example.component120
1410               |import com.example.component2
1411               |import com.example.component3
1412               |import com.example.component4
1413               |import com.example.component5
1414               |"""
1415               .trimMargin())
1416 
1417   @Test
1418   fun `keep operator imports`() =
1419       assertFormatted(
1420           """
1421               |import com.example.and
1422               |import com.example.compareTo
1423               |import com.example.contains
1424               |import com.example.dec
1425               |import com.example.div
1426               |import com.example.divAssign
1427               |import com.example.equals
1428               |import com.example.get
1429               |import com.example.getValue
1430               |import com.example.hasNext
1431               |import com.example.inc
1432               |import com.example.invoke
1433               |import com.example.iterator
1434               |import com.example.minus
1435               |import com.example.minusAssign
1436               |import com.example.mod
1437               |import com.example.modAssign
1438               |import com.example.next
1439               |import com.example.not
1440               |import com.example.or
1441               |import com.example.plus
1442               |import com.example.plusAssign
1443               |import com.example.provideDelegate
1444               |import com.example.rangeTo
1445               |import com.example.rem
1446               |import com.example.remAssign
1447               |import com.example.set
1448               |import com.example.setValue
1449               |import com.example.times
1450               |import com.example.timesAssign
1451               |import com.example.unaryMinus
1452               |import com.example.unaryPlus
1453               |"""
1454               .trimMargin())
1455 
1456   @Test
1457   fun `keep unused imports when formatting options has feature turned off`() {
1458     val code =
1459         """
1460             |import com.unused.FooBarBaz as Baz
1461             |import com.unused.Sample
1462             |import com.unused.a as `when`
1463             |import com.unused.a as wow
1464             |import com.unused.a.*
1465             |import com.unused.b as `if`
1466             |import com.unused.b as we
1467             |import com.unused.bar // test
1468             |import com.unused.`class`
1469             |"""
1470             .trimMargin()
1471 
1472     assertThatFormatting(code)
1473         .withOptions(FormattingOptions(removeUnusedImports = false))
1474         .isEqualTo(code)
1475   }
1476 
1477   @Test
1478   fun `comments between imports are moved above import list`() {
1479     val code =
1480         """
1481             |package com.facebook.ktfmt
1482             |
1483             |/* leading comment */
1484             |import com.example.abc
1485             |/* internal comment 1 */
1486             |import com.example.bcd
1487             |// internal comment 2
1488             |import com.example.Sample
1489             |// trailing comment
1490             |
1491             |val x = Sample(abc, bcd)
1492             |"""
1493             .trimMargin()
1494     val expected =
1495         """
1496             |package com.facebook.ktfmt
1497             |
1498             |/* leading comment */
1499             |/* internal comment 1 */
1500             |// internal comment 2
1501             |import com.example.Sample
1502             |import com.example.abc
1503             |import com.example.bcd
1504             |
1505             |// trailing comment
1506             |
1507             |val x = Sample(abc, bcd)
1508             |"""
1509             .trimMargin()
1510     assertThatFormatting(code).isEqualTo(expected)
1511   }
1512 
1513   @Test
1514   fun `no redundant newlines when there are no imports`() =
1515       assertFormatted(
1516           """
1517               |package foo123
1518               |
1519               |/*
1520               |bar
1521               |*/
1522               |"""
1523               .trimMargin())
1524 
1525   @Test
1526   fun `basic annotations`() =
1527       assertFormatted(
1528           """
1529       |@Fancy
1530       |class Foo {
1531       |  @Fancy
1532       |  fun baz(@Fancy foo: Int) {
1533       |    @Fancy val a = 1 + foo
1534       |  }
1535       |}
1536       |"""
1537               .trimMargin())
1538 
1539   @Test
function calls with multiple argumentsnull1540   fun `function calls with multiple arguments`() =
1541       assertFormatted(
1542           """
1543       |fun f() {
1544       |  foo(1, 2, 3)
1545       |
1546       |  foo(
1547       |      123456789012345678901234567890,
1548       |      123456789012345678901234567890,
1549       |      123456789012345678901234567890)
1550       |}
1551       |"""
1552               .trimMargin())
1553 
1554   @Test
function calls with multiple named argumentsnull1555   fun `function calls with multiple named arguments`() =
1556       assertFormatted(
1557           """
1558       |fun f() {
1559       |  foo(1, b = 2, c = 3)
1560       |
1561       |  foo(
1562       |      123456789012345678901234567890,
1563       |      b = 23456789012345678901234567890,
1564       |      c = 3456789012345678901234567890)
1565       |}
1566       |"""
1567               .trimMargin())
1568 
1569   @Test
named arguments indent their value expressionnull1570   fun `named arguments indent their value expression`() =
1571       assertFormatted(
1572           """
1573       |fun f() =
1574       |    Bar(
1575       |        tokens =
1576       |            mutableListOf<Token>().apply {
1577       |              // Printing
1578       |              print()
1579       |            },
1580       |        duration = duration)
1581       |"""
1582               .trimMargin())
1583 
1584   @Test
Arguments are blocksnull1585   fun `Arguments are blocks`() =
1586       assertFormatted(
1587           """
1588       |//////////////////////////////////////////////////
1589       |override fun visitProperty(property: KtProperty) {
1590       |  builder.sync(property)
1591       |  builder.block(ZERO) {
1592       |    declareOne(
1593       |        kind = DeclarationKind.FIELD,
1594       |        modifiers = property.modifierList,
1595       |        valOrVarKeyword =
1596       |            property.valOrVarKeyword.text,
1597       |        typeParameters =
1598       |            property.typeParameterList,
1599       |        receiver = property.receiverTypeReference,
1600       |        name = property.nameIdentifier?.text,
1601       |        type = property.typeReference,
1602       |        typeConstraintList =
1603       |            property.typeConstraintList,
1604       |        delegate = property.delegate,
1605       |        initializer = property.initializer)
1606       |  }
1607       |}
1608       |"""
1609               .trimMargin(),
1610           deduceMaxWidth = true)
1611 
1612   @Test
anonymous functionnull1613   fun `anonymous function`() =
1614       assertFormatted(
1615           """
1616       |fun f() {
1617       |  setListener(
1618       |      fun(number: Int) {
1619       |        println(number)
1620       |      })
1621       |}
1622       |"""
1623               .trimMargin())
1624 
1625   @Test
anonymous function with receivernull1626   fun `anonymous function with receiver`() =
1627       assertFormatted(
1628           """
1629       |fun f() {
1630       |  setListener(
1631       |      fun View.() {
1632       |        println(this)
1633       |      })
1634       |}
1635       |"""
1636               .trimMargin())
1637 
1638   @Test
when() with a subject expressionnull1639   fun `when() with a subject expression`() =
1640       assertFormatted(
1641           """
1642       |fun f(x: Int) {
1643       |  when (x) {
1644       |    1 -> print(1)
1645       |    2 -> print(2)
1646       |    3 ->
1647       |        // Comment
1648       |        print(3)
1649       |    else -> {
1650       |      print("else")
1651       |    }
1652       |  }
1653       |}
1654       |"""
1655               .trimMargin())
1656 
1657   @Test
when() expression with complex predicatesnull1658   fun `when() expression with complex predicates`() =
1659       assertFormatted(
1660           """
1661       |fun f(x: Int) {
1662       |  when {
1663       |    x == 1 || x == 2 -> print(1)
1664       |    x == 3 && x != 4 -> print(2)
1665       |    else -> {
1666       |      print(3)
1667       |    }
1668       |  }
1669       |}
1670       |"""
1671               .trimMargin())
1672 
1673   @Test
when() expression with several conditionsnull1674   fun `when() expression with several conditions`() =
1675       assertFormatted(
1676           """
1677       |fun f(x: Int) {
1678       |  when {
1679       |    0,
1680       |    1 -> print(1)
1681       |    else -> print(0)
1682       |  }
1683       |}
1684       |"""
1685               .trimMargin())
1686 
1687   @Test
when() expression with is and innull1688   fun `when() expression with is and in`() =
1689       assertFormatted(
1690           """
1691       |fun f(x: Int) {
1692       |  when (x) {
1693       |    is String -> print(1)
1694       |    !is String -> print(2)
1695       |    in 1..3 -> print()
1696       |    in a..b -> print()
1697       |    in a..3 -> print()
1698       |    in 1..b -> print()
1699       |    !in 1..b -> print()
1700       |    in 1..<b -> print()
1701       |    else -> print(3)
1702       |  }
1703       |}
1704       |"""
1705               .trimMargin())
1706 
1707   @Test
when() expression with enum valuesnull1708   fun `when() expression with enum values`() =
1709       assertFormatted(
1710           """
1711       |fun f(x: Color) {
1712       |  when (x) {
1713       |    is Color.Red -> print(1)
1714       |    is Color.Green -> print(2)
1715       |    else -> print(3)
1716       |  }
1717       |}
1718       |"""
1719               .trimMargin())
1720 
1721   @Test
when() expression with generic matcher and exhaustivenull1722   fun `when() expression with generic matcher and exhaustive`() =
1723       assertFormatted(
1724           """
1725       |fun f(x: Result) {
1726       |  when (x) {
1727       |    is Success<*> -> print(1)
1728       |    is Failure -> print(2)
1729       |  }.exhaustive
1730       |}
1731       |"""
1732               .trimMargin())
1733 
1734   @Test
when() expression with multiline conditionnull1735   fun `when() expression with multiline condition`() =
1736       assertFormatted(
1737           """
1738       |//////////////////////////
1739       |fun foo() {
1740       |  when (expressions1 +
1741       |      expression2 +
1742       |      expression3) {
1743       |    1 -> print(1)
1744       |    2 -> print(2)
1745       |  }
1746       |
1747       |  when (foo(
1748       |      expressions1 &&
1749       |          expression2 &&
1750       |          expression3)) {
1751       |    1 -> print(1)
1752       |    2 -> print(2)
1753       |  }
1754       |}
1755       |"""
1756               .trimMargin(),
1757           deduceMaxWidth = true)
1758 
1759   @Test
lambda assigned to variable does not break before bracenull1760   fun `lambda assigned to variable does not break before brace`() =
1761       assertFormatted(
1762           """
1763       |fun doIt() {
1764       |  val lambda = {
1765       |    doItOnce()
1766       |    doItTwice()
1767       |  }
1768       |}
1769       |
1770       |fun foo() = {
1771       |  doItOnce()
1772       |  doItTwice()
1773       |}
1774       |"""
1775               .trimMargin())
1776 
1777   @Test
when() expression storing in local variablenull1778   fun `when() expression storing in local variable`() =
1779       assertFormatted(
1780           """
1781       |fun f(x: Result) {
1782       |  when (val y = x.improved()) {
1783       |    is Success<*> -> print(y)
1784       |    is Failure -> print(2)
1785       |  }
1786       |}
1787       |"""
1788               .trimMargin())
1789 
1790   @Test
line breaks inside when expressions and conditionsnull1791   fun `line breaks inside when expressions and conditions`() =
1792       assertFormatted(
1793           """
1794       |fun f() {
1795       |  return Text.create(c)
1796       |      .onTouch {
1797       |        when (it.motionEvent.action) {
1798       |          ACTION_DOWN ->
1799       |              Toast.makeText(it.view.context, "Down!", Toast.LENGTH_SHORT, blablabla).show()
1800       |          ACTION_UP -> Toast.makeText(it.view.context, "Up!", Toast.LENGTH_SHORT).show()
1801       |          ACTION_DOWN ->
1802       |              Toast.makeText(
1803       |                      it.view.context, "Down!", Toast.LENGTH_SHORT, blablabla, blablabl, blabla)
1804       |                  .show()
1805       |        }
1806       |      }
1807       |      .build()
1808       |}
1809       |"""
1810               .trimMargin())
1811 
1812   @Test
function return typesnull1813   fun `function return types`() =
1814       assertFormatted(
1815           """
1816       |fun f1(): Int = 0
1817       |
1818       |fun f2(): Int {}
1819       |"""
1820               .trimMargin())
1821 
1822   @Test
multi line function without a block bodynull1823   fun `multi line function without a block body`() =
1824       assertFormatted(
1825           """
1826       |/////////////////////////
1827       |fun longFunctionNoBlock():
1828       |    Int =
1829       |    1234567 + 1234567
1830       |
1831       |fun shortFun(): Int =
1832       |    1234567 + 1234567
1833       |"""
1834               .trimMargin(),
1835           deduceMaxWidth = true)
1836 
1837   @Test
1838   fun `return type doesn't fit in one line`() =
1839       assertFormatted(
1840           """
1841       |//////////////////////////////////////////////////
1842       |interface X {
1843       |  fun f(
1844       |      arg1: Arg1Type,
1845       |      arg2: Arg2Type
1846       |  ): Map<String, Map<String, Double>>? {
1847       |    //
1848       |  }
1849       |
1850       |  fun functionWithGenericReturnType(
1851       |      arg1: Arg1Type,
1852       |      arg2: Arg2Type
1853       |  ): Map<String, Map<String, Double>>? {
1854       |    //
1855       |  }
1856       |}
1857       |"""
1858               .trimMargin(),
1859           deduceMaxWidth = true)
1860 
1861   @Test
list of superclassesnull1862   fun `list of superclasses`() =
1863       assertFormatted(
1864           """
1865       |class Derived2 : Super1, Super2 {}
1866       |
1867       |class Derived1 : Super1, Super2
1868       |
1869       |class Derived3(a: Int) : Super1(a)
1870       |
1871       |class Derived4 : Super1()
1872       |
1873       |class Derived5 : Super3<Int>()
1874       |"""
1875               .trimMargin())
1876 
1877   @Test
list of superclasses over multiple linesnull1878   fun `list of superclasses over multiple lines`() =
1879       assertFormatted(
1880           """
1881       |////////////////////
1882       |class Derived2 :
1883       |    Super1,
1884       |    Super2 {}
1885       |
1886       |class Derived1 :
1887       |    Super1, Super2
1888       |
1889       |class Derived3(
1890       |    a: Int
1891       |) : Super1(a)
1892       |
1893       |class Derived4 :
1894       |    Super1()
1895       |
1896       |class Derived5 :
1897       |    Super3<Int>()
1898       |"""
1899               .trimMargin(),
1900           deduceMaxWidth = true)
1901 
1902   @Test
annotations with parametersnull1903   fun `annotations with parameters`() =
1904       assertFormatted(
1905           """
1906       |@AnnWithArrayValue(1, 2, 3) class C
1907       |"""
1908               .trimMargin())
1909 
1910   @Test
1911   fun `method modifiers`() =
1912       assertFormatted(
1913           """
1914       |override internal fun f() {}
1915       |"""
1916               .trimMargin())
1917 
1918   @Test
class modifiersnull1919   fun `class modifiers`() =
1920       assertFormatted(
1921           """
1922       |abstract class Foo
1923       |
1924       |inner class Foo
1925       |
1926       |final class Foo
1927       |
1928       |open class Foo
1929       |"""
1930               .trimMargin())
1931 
1932   @Test
1933   fun `kdoc comments`() {
1934     val code =
1935         """
1936       |/**
1937       | * foo
1938       | */ class F {
1939       |
1940       | }
1941       |"""
1942             .trimMargin()
1943     val expected =
1944         """
1945       |/** foo */
1946       |class F {}
1947       |"""
1948             .trimMargin()
1949     assertThatFormatting(code).isEqualTo(expected)
1950   }
1951 
1952   @Test
nested kdoc commentsnull1953   fun `nested kdoc comments`() {
1954     val code =
1955         """
1956       |/**
1957       | * foo /* bla */
1958       | */ class F {
1959       |
1960       | }
1961       |"""
1962             .trimMargin()
1963     val expected =
1964         """
1965       |/** foo /* bla */ */
1966       |class F {}
1967       |"""
1968             .trimMargin()
1969     assertThatFormatting(code).isEqualTo(expected)
1970   }
1971 
1972   @Test
nested kdoc inside code blocknull1973   fun `nested kdoc inside code block`() =
1974       assertFormatted(
1975           """
1976       |/**
1977       | * ```
1978       | * edit -> { /* open edit screen */ }
1979       | * ```
1980       | */
1981       |fun foo() {}
1982       |"""
1983               .trimMargin())
1984 
1985   @Test
formatting kdoc doesn't add p HTML tagsnull1986   fun `formatting kdoc doesn't add p HTML tags`() =
1987       assertFormatted(
1988           """
1989       |/**
1990       | * Bla bla bla bla
1991       | *
1992       | * This is an inferred paragraph, and as you can see, we don't add a p tag to it, even though bla
1993       | * bla.
1994       | *
1995       | * <p>On the other hand, we respect existing tags, and don't remove them.
1996       | */
1997       |"""
1998               .trimMargin())
1999 
2000   @Test
2001   fun `formatting kdoc preserves lists`() =
2002       assertFormatted(
2003           """
2004       |/**
2005       | * Here are some fruit I like:
2006       | * - Banana
2007       | * - Apple
2008       | *
2009       | * This is another paragraph
2010       | */
2011       |"""
2012               .trimMargin())
2013 
2014   @Test
2015   fun `formatting kdoc lists with line wraps breaks and merges correctly`() {
2016     val code =
2017         """
2018       |/**
2019       | * Here are some fruit I like:
2020       | * - Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana
2021       | * - Apple Apple Apple Apple
2022       | *   Apple Apple
2023       | *
2024       | * This is another paragraph
2025       | */
2026       |"""
2027             .trimMargin()
2028     val expected =
2029         """
2030       |/**
2031       | * Here are some fruit I like:
2032       | * - Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana
2033       | *   Banana Banana Banana Banana Banana
2034       | * - Apple Apple Apple Apple Apple Apple
2035       | *
2036       | * This is another paragraph
2037       | */
2038       |"""
2039             .trimMargin()
2040     assertThatFormatting(code).isEqualTo(expected)
2041   }
2042 
2043   @Test
2044   fun `formatting kdoc preserves lists of asterisks`() =
2045       assertFormatted(
2046           """
2047       |/**
2048       | * Here are some fruit I like:
2049       | * * Banana
2050       | * * Apple
2051       | *
2052       | * This is another paragraph
2053       | */
2054       |"""
2055               .trimMargin())
2056 
2057   @Test
2058   fun `formatting kdoc preserves numbered`() =
2059       assertFormatted(
2060           """
2061       |/**
2062       | * Here are some fruit I like:
2063       | * 1. Banana
2064       | * 2. Apple
2065       | *
2066       | * This is another paragraph
2067       | */
2068       |"""
2069               .trimMargin())
2070 
2071   @Test
2072   fun `formatting kdoc with markdown errors`() =
2073       assertFormatted(
2074           """
2075       |/** \[ */
2076       |fun markdownError() = Unit
2077       |"""
2078               .trimMargin())
2079 
2080   @Test
2081   fun `return statement with value`() =
2082       assertFormatted(
2083           """
2084       |fun random(): Int {
2085       |  return 4
2086       |}
2087       |"""
2088               .trimMargin())
2089 
2090   @Test
return statement without valuenull2091   fun `return statement without value`() =
2092       assertFormatted(
2093           """
2094       |fun print(b: Boolean) {
2095       |  print(b)
2096       |  return
2097       |}
2098       |"""
2099               .trimMargin())
2100 
2101   @Test
return expression without valuenull2102   fun `return expression without value`() =
2103       assertFormatted(
2104           """
2105       |fun print(b: Boolean?) {
2106       |  print(b ?: return)
2107       |}
2108       |"""
2109               .trimMargin())
2110 
2111   @Test
if statement without elsenull2112   fun `if statement without else`() =
2113       assertFormatted(
2114           """
2115       |fun maybePrint(b: Boolean) {
2116       |  if (b) {
2117       |    println(b)
2118       |  }
2119       |}
2120       |"""
2121               .trimMargin())
2122 
2123   @Test
if statement with elsenull2124   fun `if statement with else`() =
2125       assertFormatted(
2126           """
2127       |fun maybePrint(b: Boolean) {
2128       |  if (b) {
2129       |    println(2)
2130       |  } else {
2131       |    println(1)
2132       |  }
2133       |}
2134       |"""
2135               .trimMargin())
2136 
2137   @Test
if expression with elsenull2138   fun `if expression with else`() =
2139       assertFormatted(
2140           """
2141       |fun maybePrint(b: Boolean) {
2142       |  println(if (b) 1 else 2)
2143       |  println(
2144       |      if (b) {
2145       |        val a = 1 + 1
2146       |        2 * a
2147       |      } else 2)
2148       |  return if (b) 1 else 2
2149       |}
2150       |"""
2151               .trimMargin())
2152 
2153   @Test
if expression with break before elsenull2154   fun `if expression with break before else`() =
2155       assertFormatted(
2156           """
2157       |//////////////////////////////
2158       |fun compute(b: Boolean) {
2159       |  val c =
2160       |      if (a + b < 20) a + b
2161       |      else a
2162       |  return if (a + b < 20) a + b
2163       |  else c
2164       |}
2165       |"""
2166               .trimMargin(),
2167           deduceMaxWidth = true)
2168 
2169   @Test
if expression with break before expressionsnull2170   fun `if expression with break before expressions`() =
2171       assertFormatted(
2172           """
2173       |//////////////////////////
2174       |fun compute(b: Boolean) {
2175       |  val c =
2176       |      if (a + b < 20)
2177       |          a + b
2178       |      else if (a < 20) a
2179       |      else
2180       |          a + b + b + 1000
2181       |  return if (a + b < 20)
2182       |      a + b
2183       |  else c
2184       |}
2185       |"""
2186               .trimMargin(),
2187           deduceMaxWidth = true)
2188 
2189   @Test
blocky expressions in if-elsenull2190   fun `blocky expressions in if-else`() =
2191       assertFormatted(
2192           """
2193       |fun numbers() {
2194       |  if (true)
2195       |      do {
2196       |        eat("is")
2197       |        matches += type()
2198       |      } while (eat(","))
2199       |  else
2200       |      while (1 < 2) {
2201       |        println("Everything is okay")
2202       |      }
2203       |}
2204       |"""
2205               .trimMargin())
2206 
2207   @Test
if expression with multiline conditionnull2208   fun `if expression with multiline condition`() =
2209       assertFormatted(
2210           """
2211       |////////////////////////////
2212       |fun foo() {
2213       |  if (expressions1 &&
2214       |      expression2 &&
2215       |      expression3) {
2216       |    bar()
2217       |  }
2218       |
2219       |  if (foo(
2220       |      expressions1 &&
2221       |          expression2 &&
2222       |          expression3)) {
2223       |    bar()
2224       |  }
2225       |}
2226       |"""
2227               .trimMargin(),
2228           deduceMaxWidth = true)
2229 
2230   @Test
assignment expression on multiple linesnull2231   fun `assignment expression on multiple lines`() =
2232       assertFormatted(
2233           """
2234       |//////////////////////////////////////////////////
2235       |fun f() {
2236       |  var myVariable = 5
2237       |  myVariable =
2238       |      function1(4, 60, 8) + function2(57, 39, 20)
2239       |}
2240       |"""
2241               .trimMargin(),
2242           deduceMaxWidth = true)
2243 
2244   @Test
A program that tickled a bug in KotlinInputnull2245   fun `A program that tickled a bug in KotlinInput`() =
2246       assertFormatted(
2247           """
2248       |val x = 2
2249       |"""
2250               .trimMargin())
2251 
2252   @Test
2253   fun `a few variations of constructors`() =
2254       assertFormatted(
2255           """
2256       |//////////////////////////////////////////////////////
2257       |class Foo constructor(number: Int) {}
2258       |
2259       |class Foo2 private constructor(number: Int) {}
2260       |
2261       |class Foo3 @Inject constructor(number: Int) {}
2262       |
2263       |class Foo4 @Inject private constructor(number: Int) {}
2264       |
2265       |class Foo5
2266       |@Inject
2267       |private constructor(
2268       |    number: Int,
2269       |    number2: Int,
2270       |    number3: Int,
2271       |    number4: Int,
2272       |    number5: Int,
2273       |    number6: Int
2274       |) {}
2275       |
2276       |class Foo6
2277       |@Inject
2278       |private constructor(hasSpaceForAnnos: Innnt) {
2279       |  //                                           @Inject
2280       |}
2281       |
2282       |class FooTooLongForCtorAndSupertypes
2283       |@Inject
2284       |private constructor(x: Int) : NoooooooSpaceForAnnos {}
2285       |"""
2286               .trimMargin(),
2287           deduceMaxWidth = true)
2288 
2289   @Test
a primary constructor without a class bodynull2290   fun `a primary constructor without a class body `() =
2291       assertFormatted(
2292           """
2293       |/////////////////////////
2294       |data class Foo(
2295       |    val number: Int = 0
2296       |)
2297       |"""
2298               .trimMargin(),
2299           deduceMaxWidth = true)
2300 
2301   @Test
2302   fun `a secondary constructor without a body`() =
2303       assertFormatted(
2304           """
2305       |///////////////////////////
2306       |data class Foo {
2307       |  constructor(
2308       |      val number: Int = 0
2309       |  )
2310       |}
2311       |"""
2312               .trimMargin(),
2313           deduceMaxWidth = true)
2314 
2315   @Test
a secondary constructor with a body breaks before closing parenthesisnull2316   fun `a secondary constructor with a body breaks before closing parenthesis`() =
2317       assertFormatted(
2318           """
2319       |///////////////////////////
2320       |data class Foo {
2321       |  constructor(
2322       |      val number: Int = 0
2323       |  ) {}
2324       |}
2325       |"""
2326               .trimMargin(),
2327           deduceMaxWidth = true)
2328 
2329   @Test
a constructor with many arguments over breaking to next linenull2330   fun `a constructor with many arguments over breaking to next line`() =
2331       assertFormatted(
2332           """
2333       |data class Foo(
2334       |    val number: Int,
2335       |    val name: String,
2336       |    val age: Int,
2337       |    val title: String,
2338       |    val offspring2: List<Foo>
2339       |) {}
2340       |"""
2341               .trimMargin())
2342 
2343   @Test
a constructor with keyword and many arguments over breaking to next linenull2344   fun `a constructor with keyword and many arguments over breaking to next line`() =
2345       assertFormatted(
2346           """
2347       |data class Foo
2348       |constructor(
2349       |    val name: String,
2350       |    val age: Int,
2351       |    val title: String,
2352       |    val offspring: List<Foo>,
2353       |    val foo: String
2354       |) {}
2355       |"""
2356               .trimMargin())
2357 
2358   @Test
a constructor with many arguments over multiple linesnull2359   fun `a constructor with many arguments over multiple lines`() =
2360       assertFormatted(
2361           """
2362       |//////////////////////////////////////////////////
2363       |data class Foo
2364       |constructor(
2365       |    val number: Int,
2366       |    val name: String,
2367       |    val age: Int,
2368       |    val title: String,
2369       |    val offspring: List<Foo>
2370       |) {}
2371       |"""
2372               .trimMargin(),
2373           deduceMaxWidth = true)
2374 
2375   @Test
handle secondary constructorsnull2376   fun `handle secondary constructors`() =
2377       assertFormatted(
2378           """
2379       |class Foo private constructor(number: Int) {
2380       |  private constructor(n: Float) : this(1)
2381       |
2382       |  private constructor(n: Double) : this(1) {
2383       |    println("built")
2384       |  }
2385       |}
2386       |"""
2387               .trimMargin())
2388 
2389   @Test
a secondary constructor with many arguments over multiple linesnull2390   fun `a secondary constructor with many arguments over multiple lines`() =
2391       assertFormatted(
2392           """
2393       |//////////////////////////////////////////////////
2394       |data class Foo {
2395       |  constructor(
2396       |      val number: Int,
2397       |      val name: String,
2398       |      val age: Int,
2399       |      val title: String,
2400       |      val offspring: List<Foo>
2401       |  )
2402       |}
2403       |"""
2404               .trimMargin(),
2405           deduceMaxWidth = true)
2406 
2407   @Test
a secondary constructor with many arguments passed to delegatenull2408   fun `a secondary constructor with many arguments passed to delegate`() =
2409       assertFormatted(
2410           """
2411       |//////////////////////////////////////////////////
2412       |data class Foo {
2413       |  constructor(
2414       |      val number: Int,
2415       |      val name: String,
2416       |      val age: Int,
2417       |      val title: String,
2418       |      val offspring: List<Foo>
2419       |  ) : this(
2420       |      number,
2421       |      name,
2422       |      age,
2423       |      title,
2424       |      offspring,
2425       |      offspring)
2426       |}
2427       |"""
2428               .trimMargin(),
2429           deduceMaxWidth = true)
2430 
2431   @Test
a secondary constructor with no arguments passed to delegatenull2432   fun `a secondary constructor with no arguments passed to delegate`() =
2433       assertFormatted(
2434           """
2435       |//////////////////////////////////////////////////
2436       |data class Foo {
2437       |  constructor() :
2438       |      this(
2439       |          Foo.createSpeciallyDesignedParameter(),
2440       |          Foo.createSpeciallyDesignedParameter(),
2441       |      )
2442       |}
2443       |"""
2444               .trimMargin(),
2445           deduceMaxWidth = true)
2446 
2447   @Test
secondary constructor with param list that fits in one line, with delegatenull2448   fun `secondary constructor with param list that fits in one line, with delegate`() =
2449       assertFormatted(
2450           """
2451       |class C {
2452       |  constructor(
2453       |      context: Context?,
2454       |      attrs: AttributeSet?,
2455       |      defStyleAttr: Int,
2456       |      defStyleRes: Int
2457       |  ) : super(context, attrs, defStyleAttr, defStyleRes) {
2458       |    init(attrs)
2459       |  }
2460       |}
2461       |"""
2462               .trimMargin())
2463 
2464   @Test
handle calling super constructor in secondary constructornull2465   fun `handle calling super constructor in secondary constructor`() =
2466       assertFormatted(
2467           """
2468       |class Foo : Bar {
2469       |  internal constructor(number: Int) : super(number) {}
2470       |}
2471       |"""
2472               .trimMargin())
2473 
2474   @Test
handle super statement with with type argumentnull2475   fun `handle super statement with with type argument`() =
2476       assertFormatted(
2477           """
2478       |class Foo : Bar(), FooBar {
2479       |  override fun doIt() {
2480       |    super<FooBar>.doIt()
2481       |  }
2482       |}
2483       |"""
2484               .trimMargin())
2485 
2486   @Test
handle super statement with with label argumentnull2487   fun `handle super statement with with label argument`() =
2488       assertFormatted(
2489           """
2490       |class Foo : Bar(), FooBar {
2491       |  override fun doIt() {
2492       |    foo.doThat {
2493       |      super<FooBar>@Foo.doIt()
2494       |
2495       |      // this one is actually generics on the call expression, not super
2496       |      super@Foo<FooBar>.doIt()
2497       |    }
2498       |  }
2499       |}
2500       |"""
2501               .trimMargin())
2502 
2503   @Test
primary constructor without parameters with a KDocnull2504   fun `primary constructor without parameters with a KDoc`() =
2505       assertFormatted(
2506           """
2507       |class Class
2508       |/** A comment */
2509       |constructor() {}
2510       |"""
2511               .trimMargin())
2512 
2513   @Test
handle objectsnull2514   fun `handle objects`() =
2515       assertFormatted(
2516           """
2517       |object Foo(n: Int) {}
2518       |"""
2519               .trimMargin())
2520 
2521   @Test
handle object expressionnull2522   fun `handle object expression`() =
2523       assertFormatted(
2524           """
2525       |fun f(): Any {
2526       |  return object : Adapter() {}
2527       |}
2528       |"""
2529               .trimMargin())
2530 
2531   @Test
handle object expression in parenthesisnull2532   fun `handle object expression in parenthesis`() =
2533       assertFormatted(
2534           """
2535       |fun f(): Any {
2536       |  return (object : Adapter() {})
2537       |}
2538       |"""
2539               .trimMargin())
2540 
2541   @Test
handle array indexing operatornull2542   fun `handle array indexing operator`() =
2543       assertFormatted(
2544           """
2545       |fun f(a: Magic) {
2546       |  a[3]
2547       |  b[3, 4]
2548       |}
2549       |"""
2550               .trimMargin())
2551 
2552   @Test
keep array indexing grouped with expression is possiblenull2553   fun `keep array indexing grouped with expression is possible`() =
2554       assertFormatted(
2555           """
2556       |///////////////////////
2557       |fun f(a: Magic) {
2558       |  foo.bar()
2559       |      .foobar[1, 2, 3]
2560       |  foo.bar()
2561       |      .foobar[
2562       |          1,
2563       |          2,
2564       |          3,
2565       |          4,
2566       |          5]
2567       |  foo.bar()
2568       |      .foobar[1, 2, 3]
2569       |      .barfoo[3, 2, 1]
2570       |}
2571       |"""
2572               .trimMargin(),
2573           deduceMaxWidth = true)
2574 
2575   @Test
mixed chainsnull2576   fun `mixed chains`() =
2577       assertFormatted(
2578           """
2579       |///////////////////////
2580       |fun f(a: Magic) {
2581       |  foo.bar()
2582       |      .foobar[1, 2, 3]
2583       |  foo.bar()
2584       |      .foobar[
2585       |          1,
2586       |          2,
2587       |          3,
2588       |          4,
2589       |          5]
2590       |  foo.bar()
2591       |      .foobar[1, 2, 3]
2592       |      .barfoo[3, 2, 1]
2593       |}
2594       |"""
2595               .trimMargin(),
2596           deduceMaxWidth = true)
2597 
2598   @Test
handle destructuring declarationnull2599   fun `handle destructuring declaration`() =
2600       assertFormatted(
2601           """
2602       |///////////////////////////////////////////////
2603       |fun f() {
2604       |  val (a, b: Int) = listOf(1, 2)
2605       |  val (asd, asd, asd, asd, asd, asd, asd) =
2606       |      foo.bar(asdasd, asdasd)
2607       |
2608       |  val (accountType, accountId) =
2609       |      oneTwoThreeFourFiveSixSeven(
2610       |          foo, bar, zed, boo)
2611       |}
2612       |"""
2613               .trimMargin(),
2614           deduceMaxWidth = true)
2615 
2616   @Test
chains with derferences and array indexingnull2617   fun `chains with derferences and array indexing`() =
2618       assertFormatted(
2619           """
2620       |///////////////////////
2621       |fun f() {
2622       |  foo.bam()
2623       |      .uber!![0, 1, 2]
2624       |      .boom()[1, 3, 5]
2625       |      .lah
2626       |      .doo { it }
2627       |      .feep[1]
2628       |      as Boo
2629       |}
2630       |"""
2631               .trimMargin(),
2632           deduceMaxWidth = true)
2633 
2634   @Test
block like syntax after dereferences and indexing with short linesnull2635   fun `block like syntax after dereferences and indexing with short lines`() =
2636       assertFormatted(
2637           """
2638       |///////////////////////
2639       |fun f() {
2640       |  foo.bam()
2641       |      .uber!![0, 1, 2]
2642       |      .forEach {
2643       |        println(it)
2644       |      }
2645       |}
2646       |"""
2647               .trimMargin(),
2648           deduceMaxWidth = true)
2649 
2650   @Test
block like syntax after dereferences and indexing with long linesnull2651   fun `block like syntax after dereferences and indexing with long lines`() =
2652       assertFormatted(
2653           """
2654       |//////////////////////////////////
2655       |fun f() {
2656       |  foo.uber!![0, 1, 2].forEach {
2657       |    println(it)
2658       |  }
2659       |}
2660       |"""
2661               .trimMargin(),
2662           deduceMaxWidth = true)
2663 
2664   @Test
try to keep type names togethernull2665   fun `try to keep type names together`() =
2666       assertFormatted(
2667           """
2668       |///////////////////////
2669       |fun f() {
2670       |  com.facebook.foo.Foo(
2671       |      1, 2)
2672       |  com.facebook.foo
2673       |      .Foo(1, 2)
2674       |      .andAlsoThis()
2675       |  com.facebook.Foo.foo(
2676       |      1, 2)
2677       |  com.facebook
2678       |      .foobarFoo
2679       |      .foo(1, 2)
2680       |  foo.invoke(
2681       |      foo, bar, bar)
2682       |  foo.invoke(foo, bar)
2683       |      .invoke()
2684       |  FooFoo.foooooooo()
2685       |      .foooooooo()
2686       |}
2687       |"""
2688               .trimMargin(),
2689           deduceMaxWidth = true)
2690 
2691   @Test
avoid breaking brackets and keep them with array namenull2692   fun `avoid breaking brackets and keep them with array name`() =
2693       assertFormatted(
2694           """
2695       |/////////////////////////////////////////////////////////////////////////
2696       |fun f() {
2697       |  val a =
2698       |      invokeIt(context.packageName)
2699       |          .getInternalMutablePackageInfo(context.packageName)
2700       |          .someItems[0]
2701       |          .getInternalMutablePackageInfo(context.packageName)
2702       |          .someItems[0]
2703       |          .doIt()
2704       |}
2705       |"""
2706               .trimMargin(),
2707           deduceMaxWidth = true)
2708 
2709   @Test
keep function call with type name even if array expression is nextnull2710   fun `keep function call with type name even if array expression is next`() =
2711       assertFormatted(
2712           """
2713       |class f {
2714       |  private val somePropertyWithBackingOne
2715       |    get() =
2716       |        _somePropertyWithBackingOne
2717       |            ?: Classname.getStuff<SomePropertyRelatedClassProvider>(requireContext())[
2718       |                    somePropertiesProvider, somePropertyCallbacks]
2719       |                .also { _somePropertyWithBackingOne = it }
2720       |}
2721       |"""
2722               .trimMargin())
2723 
2724   @Test
array access in middle of chain and end of it behaves similarlynull2725   fun `array access in middle of chain and end of it behaves similarly`() =
2726       assertFormatted(
2727           """
2728       |//////////////////////////////////////
2729       |fun f() {
2730       |  if (aaaaa == null ||
2731       |      aaaaa.bbbbb[0] == null ||
2732       |      aaaaa.bbbbb[0].cc == null ||
2733       |      aaaaa.bbbbb[0].dddd == null) {
2734       |    println()
2735       |  }
2736       |}
2737       |"""
2738               .trimMargin(),
2739           deduceMaxWidth = true)
2740 
2741   @Test
handle qmark for nullable typesnull2742   fun `handle qmark for nullable types`() =
2743       assertFormatted(
2744           """
2745       |var x: Int? = null
2746       |var x: (Int)? = null
2747       |var x: (Int?) = null
2748       |var x: ((Int))? = null
2749       |var x: ((Int?)) = null
2750       |var x: ((Int)?) = null
2751       |
2752       |var x: @Anno Int? = null
2753       |var x: @Anno() (Int)? = null
2754       |var x: @Anno (Int?) = null
2755       |var x: (@Anno Int)? = null
2756       |var x: (@Anno Int?) = null
2757       |var x: (@Anno() (Int))? = null
2758       |var x: (@Anno (Int?)) = null
2759       |var x: (@Anno() (Int)?) = null
2760       |"""
2761               .trimMargin())
2762 
2763   @Test
2764   fun `nullable function type`() =
2765       assertFormatted(
2766           """
2767       |var listener: ((Boolean) -> Unit)? = null
2768       |"""
2769               .trimMargin())
2770 
2771   @Test
2772   fun `redundant parenthesis in function types`() =
2773       assertFormatted(
2774           """
2775       |val a: (Int) = 7
2776       |
2777       |var listener: ((Boolean) -> Unit) = foo
2778       |"""
2779               .trimMargin())
2780 
2781   @Test
2782   fun `handle string literals`() =
2783       assertFormatted(
2784           """
2785       |fun doIt(world: String) {
2786       |  println("Hello world!")
2787       |  println("Hello! ${'$'}world")
2788       |  println("Hello! ${'$'}{"wor" + "ld"}")
2789       |}
2790       |"""
2791               .trimMargin())
2792 
2793   @Test
handle multiline string literalsnull2794   fun `handle multiline string literals`() =
2795       assertFormatted(
2796           """
2797       |fun doIt(world: String) {
2798       |  println(
2799       |      ${TQ}Hello
2800       |      world!${TQ})
2801       |  println(
2802       |      ${TQ}Hello
2803       |      world!${TQ},
2804       |      ${TQ}Goodbye
2805       |      world!${TQ})
2806       |}
2807       |"""
2808               .trimMargin())
2809 
2810   @Test
Trailing whitespaces are preserved in multiline stringsnull2811   fun `Trailing whitespaces are preserved in multiline strings`() {
2812     val code =
2813         listOf(
2814                 "fun doIt(world: String) {",
2815                 "  println(",
2816                 "      ${TQ}This line has trailing whitespace         ",
2817                 "      world!${TQ})",
2818                 "  println(",
2819                 "      ${TQ}This line has trailing whitespace \$s     ",
2820                 "      world!${TQ})",
2821                 "  println(",
2822                 "      ${TQ}This line has trailing whitespace \${s}   ",
2823                 "      world!${TQ})",
2824                 "  println(",
2825                 "      ${TQ}This line has trailing whitespace \$      ",
2826                 "      world!${TQ})",
2827                 "}",
2828                 "")
2829             .joinToString("\n")
2830     assertThatFormatting(code).allowTrailingWhitespace().isEqualTo(code)
2831   }
2832 
2833   @Test
2834   fun `Consecutive line breaks in multiline strings are preserved`() =
2835       assertFormatted(
2836           """
2837       |val x =
2838       |    $TQ
2839       |
2840       |
2841       |
2842       |Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
2843       |$TQ
2844       |"""
2845               .trimMargin())
2846 
2847   @Test
2848   fun `Trailing spaces in a comment are not preserved`() {
2849     val before =
2850         listOf("// trailing spaces in a comment are not preserved       ", "").joinToString("\n")
2851     val after = listOf("// trailing spaces in a comment are not preserved", "").joinToString("\n")
2852     assertThatFormatting(before).allowTrailingWhitespace().isEqualTo(after)
2853   }
2854 
2855   @Test
2856   fun `Code with tombstones is not supported`() {
2857     val code =
2858         """
2859       |fun good() {
2860       |  // ${'\u0003'}
2861       |}
2862       |"""
2863             .trimMargin()
2864     try {
2865       Formatter.format(code)
2866       fail()
2867     } catch (e: ParseError) {
2868       assertThat(e.errorDescription).contains("\\u0003")
2869       assertThat(e.lineColumn.line).isEqualTo(1)
2870       assertThat(e.lineColumn.column).isEqualTo(5)
2871     }
2872   }
2873 
2874   @Test
handle some basic generics scenariosnull2875   fun `handle some basic generics scenarios`() =
2876       assertFormatted(
2877           """
2878       |fun <T> doIt(a: List<T>): List<Int>? {
2879       |  val b: List<Int> = convert<Int>(listOf(5, 4))
2880       |  return b
2881       |}
2882       |
2883       |class Foo<T>
2884       |"""
2885               .trimMargin())
2886 
2887   @Test
handle for loopsnull2888   fun `handle for loops`() =
2889       assertFormatted(
2890           """
2891       |fun f(a: List<Int>) {
2892       |  for (i in a.indices) {
2893       |    println(i)
2894       |  }
2895       |}
2896       |"""
2897               .trimMargin())
2898 
2899   @Test
handle for loops with long dot chainsnull2900   fun `handle for loops with long dot chains`() =
2901       assertFormatted(
2902           """
2903       |///////////////////////////////////
2904       |fun f(a: Node<Int>) {
2905       |  for (child in node.next.data()) {
2906       |    println(child)
2907       |  }
2908       |  for (child in
2909       |      node.next.next.data()) {
2910       |    println(child)
2911       |  }
2912       |  for (child in
2913       |      node.next.next.next.next
2914       |          .data()) {
2915       |    println(child)
2916       |  }
2917       |}
2918       |"""
2919               .trimMargin(),
2920           deduceMaxWidth = true)
2921 
2922   @Test
when two lambdas following a call, indent the lambda properlynull2923   fun `when two lambdas following a call, indent the lambda properly`() =
2924       assertFormatted(
2925           """
2926       |////////////////////////////
2927       |fun f() {
2928       |  doIt()
2929       |      .apply {
2930       |        number =
2931       |            computeNumber1()
2932       |      }
2933       |      .apply {
2934       |        number = 2 * number
2935       |      }
2936       |}
2937       |"""
2938               .trimMargin(),
2939           deduceMaxWidth = true)
2940 
2941   @Test
when two lambdas following a field, indent the lambda properlynull2942   fun `when two lambdas following a field, indent the lambda properly`() =
2943       assertFormatted(
2944           """
2945       |////////////////////////////
2946       |fun f() {
2947       |  field
2948       |      .apply {
2949       |        number =
2950       |            computeNumber1()
2951       |      }
2952       |      .apply {
2953       |        number = 2 * number
2954       |      }
2955       |}
2956       |"""
2957               .trimMargin(),
2958           deduceMaxWidth = true)
2959 
2960   @Test
break after 'four' (even though it's 4 chars long) because there's a lambda afterwardsnull2961   fun `break after 'four' (even though it's 4 chars long) because there's a lambda afterwards`() =
2962       assertFormatted(
2963           """
2964       |fun f() {
2965       |  four
2966       |      .let {
2967       |        //
2968       |        foo()
2969       |      }
2970       |      .methodCall()
2971       |}
2972       |"""
2973               .trimMargin())
2974 
2975   @Test
keep last expression in qualified indentednull2976   fun `keep last expression in qualified indented`() =
2977       assertFormatted(
2978           """
2979       |////////////////////////////
2980       |fun f() {
2981       |  Stuff()
2982       |      .doIt(
2983       |          Foo.doIt()
2984       |              .doThat())
2985       |      .doIt(
2986       |          Foo.doIt()
2987       |              .doThat())
2988       |}
2989       |"""
2990               .trimMargin(),
2991           deduceMaxWidth = true)
2992 
2993   @Test
properly place lambda arguments into blocksnull2994   fun `properly place lambda arguments into blocks`() =
2995       assertFormatted(
2996           """
2997       |///////////////////////
2998       |fun f() {
2999       |  foo {
3000       |    red.orange.yellow()
3001       |  }
3002       |
3003       |  foo.bar {
3004       |    red.orange.yellow()
3005       |  }
3006       |}
3007       |"""
3008               .trimMargin(),
3009           deduceMaxWidth = true)
3010 
3011   @Test
properly handle one statement lambda with commentnull3012   fun `properly handle one statement lambda with comment`() =
3013       assertFormatted(
3014           """
3015       |///////////////////////
3016       |fun f() {
3017       |  foo {
3018       |    // this is a comment
3019       |    red.orange.yellow()
3020       |  }
3021       |  foo {
3022       |    /* this is also a comment */
3023       |    red.orange.yellow()
3024       |  }
3025       |  foo.bar {
3026       |    // this is a comment
3027       |    red.orange.yellow()
3028       |  }
3029       |  foo.bar() {
3030       |    // this is a comment
3031       |    red.orange.yellow()
3032       |  }
3033       |  foo.bar {
3034       |    /* this is also a comment */
3035       |    red.orange.yellow()
3036       |  }
3037       |}
3038       |"""
3039               .trimMargin(),
3040           deduceMaxWidth = true)
3041 
3042   @Test
properly handle one statement lambda with comment after body statementsnull3043   fun `properly handle one statement lambda with comment after body statements`() =
3044       assertFormatted(
3045           """
3046       |///////////////////////
3047       |fun f() {
3048       |  foo {
3049       |    red.orange.yellow()
3050       |    // this is a comment
3051       |  }
3052       |  foo {
3053       |    red.orange.yellow()
3054       |    /* this is also a comment */
3055       |  }
3056       |  foo.bar {
3057       |    red.orange.yellow()
3058       |    // this is a comment
3059       |  }
3060       |  foo.bar() {
3061       |    red.orange.yellow()
3062       |    // this is a comment
3063       |  }
3064       |  foo.bar {
3065       |    red.orange.yellow()
3066       |    /* this is also a comment */
3067       |  }
3068       |  red.orange.yellow()
3069       |  // this is a comment
3070       |}
3071       |"""
3072               .trimMargin(),
3073           deduceMaxWidth = true)
3074 
3075   @Test
try to keep expression in the same line until the first lambdanull3076   fun `try to keep expression in the same line until the first lambda`() =
3077       assertFormatted(
3078           """
3079       |/////////////////////////
3080       |fun f() {
3081       |  foo.bar.bar?.let {
3082       |    a()
3083       |  }
3084       |  foo.bar.bar?.let {
3085       |    action()
3086       |    action2()
3087       |  }
3088       |  foo.bar.bar.bar.bar
3089       |      ?.let { a() }
3090       |  foo.bar.bar.bar.bar
3091       |      ?.let {
3092       |        action()
3093       |        action2()
3094       |      }
3095       |}
3096       |"""
3097               .trimMargin(),
3098           deduceMaxWidth = true)
3099 
3100   @Test
different indentation in chained callsnull3101   fun `different indentation in chained calls`() =
3102       assertFormatted(
3103           """
3104       |///////////////////////////
3105       |fun f() {
3106       |  fooDdoIt(
3107       |      foo1, foo2, foo3)
3108       |  foo.doIt(
3109       |      foo1, foo2, foo3)
3110       |  foo.doIt(
3111       |          foo1, foo2, foo3)
3112       |      .doThat()
3113       |}
3114       |"""
3115               .trimMargin(),
3116           deduceMaxWidth = true)
3117 
3118   @Test
always add a conditional break for a lambda which is not lastnull3119   fun `always add a conditional break for a lambda which is not last`() =
3120       assertFormatted(
3121           """
3122       |////////////////////
3123       |fun f() {
3124       |  foofoo
3125       |      .doIt {
3126       |        doStuff()
3127       |      }
3128       |      .doIt {
3129       |        doStuff()
3130       |      }
3131       |}
3132       |"""
3133               .trimMargin(),
3134           deduceMaxWidth = true)
3135 
3136   @Test
keep parenthesis and braces together when there's only one lambda argumentnull3137   fun `keep parenthesis and braces together when there's only one lambda argument`() =
3138       assertFormatted(
3139           """
3140       |fun f() {
3141       |  doIt({})
3142       |  doIt({ it + it })
3143       |  doIt({
3144       |    val a = it
3145       |    a + a
3146       |  })
3147       |  doIt(functor = { it + it })
3148       |  doIt(
3149       |      functor = {
3150       |        val a = it
3151       |        a + a
3152       |      })
3153       |}
3154       |"""
3155               .trimMargin())
3156 
3157   @Test
Qualified typenull3158   fun `Qualified type`() =
3159       assertFormatted(
3160           """
3161       |fun f() {
3162       |  var plusFour: Indent.Const
3163       |  var x: Map.Entry<String, Integer>
3164       |  var x: List<String>.Iterator
3165       |}
3166       |"""
3167               .trimMargin())
3168 
3169   @Test
handle destructuring declaration in for loopnull3170   fun `handle destructuring declaration in for loop`() =
3171       assertFormatted(
3172           """
3173       |fun f(a: List<Pair<Int, Int>>) {
3174       |  for ((x, y: Int) in a) {}
3175       |}
3176       |"""
3177               .trimMargin())
3178 
3179   @Test
handle function referencesnull3180   fun `handle function references`() =
3181       assertFormatted(
3182           """
3183       |////////////////////////////////
3184       |fun f(a: List<Int>) {
3185       |  a.forEach(::println)
3186       |  a.map(Int::toString)
3187       |  a.map(String?::isNullOrEmpty)
3188       |  a.map(
3189       |      SuperLongClassName?::
3190       |          functionName)
3191       |  val f =
3192       |      SuperLongClassName::
3193       |          functionName
3194       |  val g =
3195       |      invoke(a, b)::functionName
3196       |  val h =
3197       |      invoke(a, b, c)::
3198       |          functionName
3199       |}
3200       |"""
3201               .trimMargin(),
3202           deduceMaxWidth = true)
3203 
3204   @Test
handle escaped identifiernull3205   fun `handle escaped identifier`() =
3206       assertFormatted(
3207           """
3208       |import foo as `foo foo`
3209       |import org.mockito.Mockito.`when` as `yay yay`
3210       |
3211       |fun `spaces in functions`() {
3212       |  val `when` = NEVER
3213       |  val (`do not`, `ever write`) = SERIOUSLY
3214       |  val `a a`: Int
3215       |  `yay yay`(`foo foo`)
3216       |}
3217       |
3218       |class `more spaces`
3219       |"""
3220               .trimMargin())
3221 
3222   @Test
handle annotations with argumentsnull3223   fun `handle annotations with arguments`() =
3224       assertFormatted(
3225           """
3226       |@Px fun f(): Int = 5
3227       |
3228       |@Dimenstion(unit = DP) fun g(): Int = 5
3229       |
3230       |@RunWith(MagicRunner::class)
3231       |@Px
3232       |class Test {
3233       |  //
3234       |}
3235       |"""
3236               .trimMargin())
3237 
3238   @Test
no newlines after annotations if entire expr fits in one linenull3239   fun `no newlines after annotations if entire expr fits in one line`() =
3240       assertFormatted(
3241           """
3242       |///////////////////////////////////////////////
3243       |@Px @Px fun f(): Int = 5
3244       |
3245       |@Px
3246       |@Px
3247       |@Px
3248       |@Px
3249       |@Px
3250       |@Px
3251       |@Px
3252       |@Px
3253       |fun f(): Int = 5
3254       |
3255       |@Px
3256       |@Px
3257       |fun f(): Int {
3258       |  return 5
3259       |}
3260       |
3261       |@Dimenstion(unit = DP) @Px fun g(): Int = 5
3262       |
3263       |@Dimenstion(unit = DP)
3264       |@Px
3265       |fun g(): Int {
3266       |  return 5
3267       |}
3268       |
3269       |@RunWith @Px class Test
3270       |
3271       |@RunWith(MagicRunner::class) @Px class Test
3272       |
3273       |@RunWith @Px class Test {}
3274       |
3275       |@RunWith(MagicRunner::class) @Px class Test {}
3276       |
3277       |@RunWith(MagicRunner::class)
3278       |@Px
3279       |@Px
3280       |class Test {}
3281       |
3282       |@RunWith(MagicRunner::class)
3283       |@Px
3284       |class Test {
3285       |  //
3286       |}
3287       |
3288       |fun f() {
3289       |  if (@Stuff(Magic::class) isGood()) {
3290       |    println("")
3291       |  }
3292       |}
3293       |"""
3294               .trimMargin(),
3295           deduceMaxWidth = true)
3296 
3297   @Test
no newlines after annotations on properties if entire expression fits in one linenull3298   fun `no newlines after annotations on properties if entire expression fits in one line`() =
3299       assertFormatted(
3300           """
3301       |////////////////////////////////////////////
3302       |@Suppress("UnsafeCast")
3303       |val ClassA.methodA
3304       |  get() = foo as Bar
3305       |"""
3306               .trimMargin(),
3307           deduceMaxWidth = true)
3308 
3309   @Test
3310   fun `when annotations cause line breaks, and constant has no type dont break before value`() =
3311       assertFormatted(
3312           """
3313       |//////////////////////////////////////////////////////////
3314       |object Foo {
3315       |  @LongLongLongLongAnnotation
3316       |  @LongLongLongLongLongAnnotation
3317       |  private val ROW_HEIGHT = 72
3318       |}
3319       |"""
3320               .trimMargin(),
3321           deduceMaxWidth = true)
3322 
3323   @Test
annotations in literal function typesnull3324   fun `annotations in literal function types`() =
3325       assertFormatted(
3326           """
3327       |val callback: (@Anno List<@JvmSuppressWildcards String>) -> Unit = foo
3328       |"""
3329               .trimMargin())
3330 
3331   @Test
3332   fun `annotations on type parameters`() =
3333       assertFormatted(
3334           """
3335       |class Foo<@Anno out @Anno T, @Anno in @Anno U> {
3336       |  inline fun <@Anno reified @Anno X, @Anno reified @Anno Y> bar() {}
3337       |}
3338       |"""
3339               .trimMargin())
3340 
3341   @Test
annotations on type constraintsnull3342   fun `annotations on type constraints`() =
3343       assertFormatted(
3344           """
3345       |class Foo<T : @Anno Kip, U> where U : @Anno Kip, U : @Anno Qux {
3346       |  fun <T : @Anno Kip, U> bar() where U : @Anno Kip, U : @Anno Qux {}
3347       |}
3348       |"""
3349               .trimMargin())
3350 
3351   @Test
annotations on type argumentsnull3352   fun `annotations on type arguments`() =
3353       assertFormatted(
3354           """
3355       |fun foo(x: Foo<in @Anno Int>) {}
3356       |"""
3357               .trimMargin())
3358 
3359   @Test
annotations on destructuring declaration elementsnull3360   fun `annotations on destructuring declaration elements`() =
3361       assertFormatted(
3362           """
3363       |val x = { (@Anno x, @Anno y) -> x }
3364       |"""
3365               .trimMargin())
3366 
3367   @Test
annotations on exceptionsnull3368   fun `annotations on exceptions`() =
3369       assertFormatted(
3370           """
3371       |fun doIt() {
3372       |  try {
3373       |    doItAgain()
3374       |  } catch (@Nullable e: Exception) {
3375       |    //
3376       |  } catch (@Suppress("GeneralException") e: Exception) {}
3377       |}
3378       |"""
3379               .trimMargin())
3380 
3381   @Test
Unary prefix expressionsnull3382   fun `Unary prefix expressions`() =
3383       assertFormatted(
3384           """
3385       |fun f() {
3386       |  !a
3387       |  -4
3388       |  val x = -foo()
3389       |  +4
3390       |  ++a
3391       |  --a
3392       |
3393       |  + +a
3394       |  +-a
3395       |  +!a
3396       |  -+a
3397       |  - -a
3398       |  -!a
3399       |  !+a
3400       |  !a
3401       |  ! !a
3402       |
3403       |  + ++a
3404       |  +--a
3405       |  -++a
3406       |  - --a
3407       |  !++a
3408       |  !--a
3409       |}
3410       |"""
3411               .trimMargin())
3412 
3413   @Test
Unary postfix expressionsnull3414   fun `Unary postfix expressions`() =
3415       assertFormatted(
3416           """
3417       |fun f() {
3418       |  a!!
3419       |  a++
3420       |  a--
3421       |
3422       |  a--!!
3423       |  a++!!
3424       |
3425       |  a!! !!
3426       |}
3427       |"""
3428               .trimMargin())
3429 
3430   @Test
handle wildcard genericsnull3431   fun `handle wildcard generics`() =
3432       assertFormatted(
3433           """
3434       |fun f() {
3435       |  val l: List<*>
3436       |  val p: Pair<*, *>
3437       |}
3438       |"""
3439               .trimMargin())
3440 
3441   @Test
handle intersection genericsnull3442   fun `handle intersection generics`() =
3443       assertFormatted(
3444           """
3445       |fun f() {
3446       |  val l: Decl<A & B & C>
3447       |  val p = Ctor<A & B & C, T & Y & Z>
3448       |}
3449       |"""
3450               .trimMargin())
3451 
3452   @Test
handle covariant and contravariant type argumentsnull3453   fun `handle covariant and contravariant type arguments`() =
3454       assertFormatted(
3455           """
3456       |val p: Pair<in T, out S>
3457       |"""
3458               .trimMargin())
3459 
3460   @Test
3461   fun `handle covariant and contravariant type parameters`() =
3462       assertFormatted(
3463           """
3464       |class Foo<in T, out S>
3465       |"""
3466               .trimMargin())
3467 
3468   @Test
3469   fun `handle bounds for type parameters`() =
3470       assertFormatted(
3471           """
3472       |class Foo<in T : List<*>, out S : Any?>
3473       |"""
3474               .trimMargin())
3475 
3476   @Test
3477   fun `handle compound generic bounds on classes`() =
3478       assertFormatted(
3479           """
3480       |class Foo<T>(n: Int) where T : Bar, T : FooBar {}
3481       |"""
3482               .trimMargin())
3483 
3484   @Test
handle compound generic bounds on functionsnull3485   fun `handle compound generic bounds on functions`() =
3486       assertFormatted(
3487           """
3488       |fun <T> foo(n: Int) where T : Bar, T : FooBar {}
3489       |"""
3490               .trimMargin())
3491 
3492   @Test
handle compound generic bounds on propertiesnull3493   fun `handle compound generic bounds on properties`() =
3494       assertFormatted(
3495           """
3496       |val <T> List<T>.twiceSum: Int where T : Int
3497       |  get() {
3498       |    return 2 * sum()
3499       |  }
3500       |"""
3501               .trimMargin())
3502 
3503   @Test
handle compound generic bounds on class with delegatenull3504   fun `handle compound generic bounds on class with delegate`() =
3505       assertFormatted(
3506           """
3507       |class Foo<T>() : Bar by bar
3508       |where T : Qux
3509       |"""
3510               .trimMargin())
3511 
3512   @Test
3513   fun `explicit type on property getter`() =
3514       assertFormatted(
3515           """
3516       |class Foo {
3517       |  val silly: Int
3518       |    get(): Int = 1
3519       |}
3520       |"""
3521               .trimMargin())
3522 
3523   @Test
handle method calls with lambda arg onlynull3524   fun `handle method calls with lambda arg only`() =
3525       assertFormatted(
3526           """
3527       |fun f() {
3528       |  val a = g { 1 + 1 }
3529       |}
3530       |"""
3531               .trimMargin())
3532 
3533   @Test
handle method calls value args and a lambda argnull3534   fun `handle method calls value args and a lambda arg`() =
3535       assertFormatted(
3536           """
3537       |fun f() {
3538       |  val a = g(1, 2) { 1 + 1 }
3539       |}
3540       |"""
3541               .trimMargin())
3542 
3543   @Test
handle top level constantsnull3544   fun `handle top level constants`() =
3545       assertFormatted(
3546           """
3547       |/////////////////////////////
3548       |val a = 5
3549       |
3550       |const val b = "a"
3551       |
3552       |val a = 5
3553       |"""
3554               .trimMargin(),
3555           deduceMaxWidth = true)
3556 
3557   @Test
3558   fun `handle lambda arg with named arguments`() =
3559       assertFormatted(
3560           """
3561       |fun f() {
3562       |  val b = { x: Int, y: Int -> x + y }
3563       |}
3564       |"""
3565               .trimMargin())
3566 
3567   @Test
avoid newline before lambda argument if it is namednull3568   fun `avoid newline before lambda argument if it is named`() =
3569       assertFormatted(
3570           """
3571       |private fun f(items: List<Int>) {
3572       |  doSomethingCool(
3573       |      items,
3574       |      lambdaArgument = {
3575       |        step1()
3576       |        step2()
3577       |      }) {
3578       |        it.doIt()
3579       |      }
3580       |}
3581       |"""
3582               .trimMargin())
3583 
3584   @Test
handle labeled this pointernull3585   fun `handle labeled this pointer`() =
3586       assertFormatted(
3587           """
3588       |class Foo {
3589       |  fun f() {
3590       |    g { println(this@Foo) }
3591       |  }
3592       |}
3593       |"""
3594               .trimMargin())
3595 
3596   @Test
handle extension and operator functionsnull3597   fun `handle extension and operator functions`() =
3598       assertFormatted(
3599           """
3600       |operator fun Point.component1() = x
3601       |"""
3602               .trimMargin())
3603 
3604   @Test
3605   fun `handle extension methods with very long names`() =
3606       assertFormatted(
3607           """
3608       |//////////////////////////////////////////
3609       |fun LongReceiverNameThatRequiresBreaking
3610       |    .doIt() {}
3611       |
3612       |fun LongButNotTooLong.doIt(
3613       |    n: Int,
3614       |    f: Float
3615       |) {}
3616       |"""
3617               .trimMargin(),
3618           deduceMaxWidth = true)
3619 
3620   @Test
handle extension propertiesnull3621   fun `handle extension properties`() =
3622       assertFormatted(
3623           """
3624       |val Int.isPrime: Boolean
3625       |  get() = runMillerRabinPrimality(this)
3626       |"""
3627               .trimMargin())
3628 
3629   @Test
3630   fun `generic extension property`() =
3631       assertFormatted(
3632           """
3633       |val <T> List<T>.twiceSize = 2 * size()
3634       |"""
3635               .trimMargin())
3636 
3637   @Test
3638   fun `handle file annotations`() {
3639     assertFormatted(
3640         """
3641       |@file:JvmName("DifferentName")
3642       |
3643       |package com.somecompany.example
3644       |
3645       |import com.somecompany.example2
3646       |
3647       |class Foo {
3648       |  val a = example2("and 1")
3649       |}
3650       |"""
3651             .trimMargin())
3652 
3653     assertFormatted(
3654         """
3655       |@file:JvmName("DifferentName") // Comment
3656       |
3657       |package com.somecompany.example
3658       |
3659       |import com.somecompany.example2
3660       |
3661       |class Foo {
3662       |  val a = example2("and 1")
3663       |}
3664       |"""
3665             .trimMargin())
3666 
3667     assertFormatted(
3668         """
3669       |@file:JvmName("DifferentName")
3670       |
3671       |// Comment
3672       |
3673       |package com.somecompany.example
3674       |
3675       |import com.somecompany.example2
3676       |
3677       |class Foo {
3678       |  val a = example2("and 1")
3679       |}
3680       |"""
3681             .trimMargin())
3682 
3683     assertFormatted(
3684         """
3685       |@file:JvmName("DifferentName")
3686       |
3687       |// Comment
3688       |package com.somecompany.example
3689       |
3690       |import com.somecompany.example2
3691       |
3692       |class Foo {
3693       |  val a = example2("and 1")
3694       |}
3695       |"""
3696             .trimMargin())
3697   }
3698 
3699   @Test
handle init blocknull3700   fun `handle init block`() =
3701       assertFormatted(
3702           """
3703       |class Foo {
3704       |  init {
3705       |    println("Init!")
3706       |  }
3707       |}
3708       |"""
3709               .trimMargin())
3710 
3711   @Test
handle interface delegationnull3712   fun `handle interface delegation`() =
3713       assertFormatted(
3714           """
3715       |class MyList(impl: List<Int>) : Collection<Int> by impl
3716       |"""
3717               .trimMargin())
3718 
3719   @Test
3720   fun `handle property delegation`() =
3721       assertFormatted(
3722           """
3723       |val a by lazy { 1 + 1 }
3724       |"""
3725               .trimMargin())
3726 
3727   @Test
handle property delegation with type and breaksnull3728   fun `handle property delegation with type and breaks`() =
3729       assertFormatted(
3730           """
3731       |/////////////////////////////////
3732       |val importantValue: Int by lazy {
3733       |  1 + 1
3734       |}
3735       |
3736       |val importantValue: Int by lazy {
3737       |  val b = 1 + 1
3738       |  b + b
3739       |}
3740       |
3741       |val importantValueLonger:
3742       |    Int by lazy { 1 + 1 }
3743       |
3744       |val importantValue: Int by
3745       |    doIt(1 + 1)
3746       |"""
3747               .trimMargin(),
3748           deduceMaxWidth = true)
3749 
3750   @Test
handle multi-annotations with use-site targetsnull3751   fun `handle multi-annotations with use-site targets`() =
3752       assertFormatted(
3753           """
3754     |class Something {
3755     |  @field:[Inject Named("WEB_VIEW")]
3756     |  internal lateinit var httpClient: OkHttpClient
3757     |
3758     |  @field:[Inject Named("WEB_VIEW")]
3759     |  var httpClient: OkHttpClient
3760     |
3761     |  @Px
3762     |  @field:[Inject Named("WEB_VIEW")]
3763     |  var httpClient: OkHttpClient
3764     |}
3765     |
3766     """
3767               .trimMargin())
3768 
3769   @Test
handle parameters with annoations with parametersnull3770   fun `handle parameters with annoations with parameters`() =
3771       assertFormatted(
3772           """
3773     |class Something {
3774     |  fun doIt(@Magic(withHat = true) foo: Foo) {
3775     |    println(foo)
3776     |  }
3777     |}
3778     |
3779     """
3780               .trimMargin())
3781 
3782   @Test
handle lambda typesnull3783   fun `handle lambda types`() =
3784       assertFormatted(
3785           """
3786       |val listener1: (Boolean) -> Unit = { b -> !b }
3787       |
3788       |val listener2: () -> Unit = {}
3789       |
3790       |val listener3: (Int, Double) -> Int = { a, b -> a }
3791       |
3792       |val listener4: Int.(Int, Boolean) -> Unit
3793       |"""
3794               .trimMargin())
3795 
3796   @Test
handle unicode in string literalsnull3797   fun `handle unicode in string literals`() =
3798       assertFormatted(
3799           """
3800       |val a = "\uD83D\uDC4D"
3801       |"""
3802               .trimMargin())
3803 
3804   @Test
3805   fun `handle casting`() =
3806       assertFormatted(
3807           """
3808       |fun castIt(o: Object) {
3809       |  println(o is Double)
3810       |  println(o !is Double)
3811       |  doIt(o as Int)
3812       |  doIt(o as? Int)
3813       |}
3814       |"""
3815               .trimMargin())
3816 
3817   @Test
handle casting with breaksnull3818   fun `handle casting with breaks`() =
3819       assertFormatted(
3820           """
3821       |///////////////////////
3822       |fun castIt(
3823       |    something: Any
3824       |) {
3825       |  doIt(
3826       |      something
3827       |          as List<*>)
3828       |  doIt(
3829       |      something
3830       |          is List<*>)
3831       |  println(
3832       |      something
3833       |          is
3834       |          List<String>)
3835       |  doIt(
3836       |      something
3837       |          as
3838       |          List<String>)
3839       |  println(
3840       |      something
3841       |          is
3842       |          PairList<
3843       |              String,
3844       |              Int>)
3845       |  doIt(
3846       |      something
3847       |          as
3848       |          PairList<
3849       |              String,
3850       |              Int>)
3851       |  println(
3852       |      a is Int &&
3853       |          b is String)
3854       |  l.b?.s?.sOrNull() is
3855       |      SomethingLongEnough
3856       |}
3857       |
3858       |val a =
3859       |    l.sOrNull() is
3860       |        SomethingLongEnough
3861       |"""
3862               .trimMargin(),
3863           deduceMaxWidth = true)
3864 
3865   @Test
handle collection literals in annotationsnull3866   fun `handle collection literals in annotations`() =
3867       assertFormatted(
3868           """
3869       |@Foo(a = [1, 2])
3870       |fun doIt(o: Object) {
3871       |  //
3872       |}
3873       |"""
3874               .trimMargin())
3875 
3876   @Test
handle try, catch and finallynull3877   fun `handle try, catch and finally`() =
3878       assertFormatted(
3879           """
3880       |fun foo() {
3881       |  try {
3882       |    bar()
3883       |  } catch (e: Exception) {
3884       |    throw e
3885       |  } finally {
3886       |    println("finally")
3887       |  }
3888       |}
3889       |"""
3890               .trimMargin())
3891 
3892   @Test
handle infix methodsnull3893   fun `handle infix methods`() =
3894       assertFormatted(
3895           """
3896       |fun numbers() {
3897       |  (0 until 100).size
3898       |}
3899       |"""
3900               .trimMargin())
3901 
3902   @Test
handle while loopsnull3903   fun `handle while loops`() =
3904       assertFormatted(
3905           """
3906       |fun numbers() {
3907       |  while (1 < 2) {
3908       |    println("Everything is okay")
3909       |  }
3910       |}
3911       |"""
3912               .trimMargin())
3913 
3914   @Test
handle do while loopsnull3915   fun `handle do while loops`() =
3916       assertFormatted(
3917           """
3918       |fun numbers() {
3919       |  do {
3920       |    println("Everything is okay")
3921       |  } while (1 < 2)
3922       |
3923       |  do while (1 < 2)
3924       |}
3925       |"""
3926               .trimMargin())
3927 
3928   @Test
handle break and continuenull3929   fun `handle break and continue`() =
3930       assertFormatted(
3931           """
3932       |fun numbers() {
3933       |  while (1 < 2) {
3934       |    if (true) {
3935       |      break
3936       |    }
3937       |    if (false) {
3938       |      continue
3939       |    }
3940       |  }
3941       |}
3942       |"""
3943               .trimMargin())
3944 
3945   @Test
handle all kinds of labels and jumpsnull3946   fun `handle all kinds of labels and jumps`() =
3947       assertFormatted(
3948           """
3949       |fun f(a: List<Int>) {
3950       |  a.map {
3951       |    myloop@ for (i in a) {
3952       |      if (true) {
3953       |        break@myloop
3954       |      } else if (false) {
3955       |        continue@myloop
3956       |      } else {
3957       |        a.map `inner map`@{
3958       |          return@`inner map`
3959       |        }
3960       |      }
3961       |    }
3962       |    return@map 2 * it
3963       |  }
3964       |}
3965       |"""
3966               .trimMargin())
3967 
3968   @Test
don't crash on top level statements with semicolonsnull3969   fun `don't crash on top level statements with semicolons`() {
3970     val code =
3971         """
3972       |val x = { 0 };
3973       |
3974       |foo({ 0 });
3975       |
3976       |foo { 0 };
3977       |
3978       |val fill = 0;
3979       |"""
3980             .trimMargin()
3981     val expected =
3982         """
3983       |val x = { 0 }
3984       |
3985       |foo({ 0 })
3986       |
3987       |foo { 0 }
3988       |
3989       |val fill = 0
3990       |"""
3991             .trimMargin()
3992     assertThatFormatting(code).isEqualTo(expected)
3993   }
3994 
3995   @Test
preserve semicolons in enumsnull3996   fun `preserve semicolons in enums`() {
3997     val code =
3998         """
3999       |enum class SemiColonIsNotRequired {
4000       |  TRUE, FALSE;
4001       |}
4002       |
4003       |enum class SemiColonIsRequired {
4004       |  ONE, TWO;
4005       |
4006       |  fun isOne(): Boolean = this == ONE
4007       |}
4008       |"""
4009             .trimMargin()
4010     val expected =
4011         """
4012       |enum class SemiColonIsNotRequired {
4013       |  TRUE,
4014       |  FALSE
4015       |}
4016       |
4017       |enum class SemiColonIsRequired {
4018       |  ONE,
4019       |  TWO;
4020       |
4021       |  fun isOne(): Boolean = this == ONE
4022       |}
4023       |"""
4024             .trimMargin()
4025     assertThatFormatting(code).isEqualTo(expected)
4026   }
4027 
4028   @Test
preserve semicolons in comments and stringsnull4029   fun `preserve semicolons in comments and strings`() {
4030     val code =
4031         """
4032       |fun f() {
4033       |  val x = ";"
4034       |  val x = $TQ  don't touch ; in raw strings $TQ
4035       |}
4036       |
4037       |// Don't touch ; inside comments.
4038       |
4039       |/** Don't touch ; inside comments. */
4040       |"""
4041             .trimMargin()
4042     val expected =
4043         """
4044       |fun f() {
4045       |  val x = ";"
4046       |  val x = $TQ  don't touch ; in raw strings $TQ
4047       |}
4048       |
4049       |// Don't touch ; inside comments.
4050       |
4051       |/** Don't touch ; inside comments. */
4052       |"""
4053             .trimMargin()
4054     assertThatFormatting(code).isEqualTo(expected)
4055   }
4056 
4057   @Test
4058   fun `preserve semicolons in empty if-s and while-s`() {
4059     val code =
4060         """
4061       |fun f() {
4062       |  while (true);
4063       |  while (true) /** a */ ;
4064       |
4065       |  if (true);
4066       |  if (true) /** a */ ;
4067       |
4068       |  if (true)
4069       |    else
4070       |  ;
4071       |}
4072       |"""
4073             .trimMargin()
4074     val expected =
4075         """
4076       |fun f() {
4077       |  while (true) ;
4078       |  while (true)
4079       |  /** a */
4080       |  ;
4081       |
4082       |  if (true) ;
4083       |  if (true)
4084       |  /** a */
4085       |   ;
4086       |
4087       |  if (true)  else ;
4088       |}
4089       |"""
4090             .trimMargin()
4091     assertThatFormatting(code).isEqualTo(expected)
4092   }
4093 
4094   @Test
4095   fun `preserve semicolons between calls and dead lambdas`() {
4096     val code =
4097         """
4098       |fun f() {
4099       |  foo(0); { dead -> lambda }
4100       |
4101       |  foo(0) ; { dead -> lambda }
4102       |
4103       |  foo(0) /** a */ ; /** b */ { dead -> lambda }
4104       |
4105       |  foo(0) { trailing -> lambda }; { dead -> lambda }
4106       |
4107       |  foo { trailing -> lambda }; { dead -> lambda }
4108       |
4109       |  val x = foo(); { dead -> lambda }
4110       |
4111       |  val x = bar() && foo(); { dead -> lambda }
4112       |
4113       |  // `z` has a property and a method both named `bar`
4114       |  val x = z.bar; { dead -> lambda }
4115       |
4116       |  // `this` has a property and a method both named `bar`
4117       |  val x = bar; { dead -> lambda }
4118       |
4119       |  // Literally any callable expression is dangerous
4120       |  val x = (if (cond) x::foo else x::bar); { dead -> lambda }
4121       |}
4122       |"""
4123             .trimMargin()
4124     val expected =
4125         """
4126       |fun f() {
4127       |  foo(0);
4128       |  { dead -> lambda }
4129       |
4130       |  foo(0);
4131       |  { dead -> lambda }
4132       |
4133       |  foo(0)
4134       |  /** a */
4135       |  ;
4136       |  /** b */
4137       |  { dead -> lambda }
4138       |
4139       |  foo(0) { trailing -> lambda };
4140       |  { dead -> lambda }
4141       |
4142       |  foo { trailing -> lambda };
4143       |  { dead -> lambda }
4144       |
4145       |  val x = foo();
4146       |  { dead -> lambda }
4147       |
4148       |  val x = bar() && foo();
4149       |  { dead -> lambda }
4150       |
4151       |  // `z` has a property and a method both named `bar`
4152       |  val x = z.bar;
4153       |  { dead -> lambda }
4154       |
4155       |  // `this` has a property and a method both named `bar`
4156       |  val x = bar;
4157       |  { dead -> lambda }
4158       |
4159       |  // Literally any callable expression is dangerous
4160       |  val x = (if (cond) x::foo else x::bar);
4161       |  { dead -> lambda }
4162       |}
4163       |"""
4164             .trimMargin()
4165     assertThatFormatting(code).isEqualTo(expected)
4166   }
4167 
4168   @Test
4169   fun `drop redundant semicolons`() {
4170     val code =
4171         """
4172       |package org.examples;
4173       |import org.examples.wow.MuchWow;
4174       |import org.examples.wow.ManyAmaze
4175       |
4176       |typealias Int2 = Int;
4177       |
4178       |fun f() {
4179       |  val a = 3;
4180       |  val x = 5 ; val y = ManyAmaze();
4181       |  myThingMap.forEach { val (key, value) = it; println("mapped ${"$"}MuchWow") }
4182       |  when {
4183       |    true -> "1"; false -> "0"
4184       |  }
4185       |  someLongVariableName.let {
4186       |    someReallyLongFunctionNameThatMakesThisNotFitInOneLineWithTheAboveVariable();
4187       |  }
4188       |  if (cond) ; else 6
4189       |} ;
4190       |
4191       |"""
4192             .trimMargin()
4193     val expected =
4194         """
4195       |package org.examples
4196       |
4197       |import org.examples.wow.ManyAmaze
4198       |import org.examples.wow.MuchWow
4199       |
4200       |typealias Int2 = Int
4201       |
4202       |fun f() {
4203       |  val a = 3
4204       |  val x = 5
4205       |  val y = ManyAmaze()
4206       |  myThingMap.forEach {
4207       |    val (key, value) = it
4208       |    println("mapped ${"$"}MuchWow")
4209       |  }
4210       |  when {
4211       |    true -> "1"
4212       |    false -> "0"
4213       |  }
4214       |  someLongVariableName.let {
4215       |    someReallyLongFunctionNameThatMakesThisNotFitInOneLineWithTheAboveVariable()
4216       |  }
4217       |  if (cond)  else 6
4218       |}
4219       |"""
4220             .trimMargin()
4221     assertThatFormatting(code).isEqualTo(expected)
4222   }
4223 
4224   @Test
4225   fun `pretty-print after dropping redundant semicolons`() {
4226     val code =
4227         """
4228       |fun f() {
4229       |  val veryLongName = 5;
4230       |}
4231       |"""
4232             .trimMargin()
4233     val expected =
4234         """
4235       |fun f() {
4236       |  val veryLongName = 5
4237       |}
4238       |"""
4239             .trimMargin()
4240     assertThatFormatting(code).withOptions(FormattingOptions(maxWidth = 22)).isEqualTo(expected)
4241   }
4242 
4243   @Test
4244   fun `handle no parenthesis in lambda calls`() =
4245       assertFormatted(
4246           """
4247       |fun f() {
4248       |  a { println("a") }
4249       |}
4250       |"""
4251               .trimMargin())
4252 
4253   @Test
4254   fun `handle multi statement lambdas`() =
4255       assertFormatted(
4256           """
4257       |fun f() {
4258       |  a {
4259       |    println("a")
4260       |    println("b")
4261       |  }
4262       |}
4263       |"""
4264               .trimMargin())
4265 
4266   @Test
4267   fun `handle multi line one statement lambda`() =
4268       assertFormatted(
4269           """
4270       |/////////////////////////
4271       |fun f() {
4272       |  a {
4273       |    println(foo.bar.boom)
4274       |  }
4275       |}
4276       |"""
4277               .trimMargin(),
4278           deduceMaxWidth = true)
4279 
4280   @Test
4281   fun `statements are wrapped in blocks`() =
4282       assertFormatted(
4283           """
4284       |fun f() {
4285       |  builder.block {
4286       |    getArgumentName().accept
4287       |    return
4288       |  }
4289       |}
4290       |"""
4291               .trimMargin())
4292 
4293   @Test
4294   fun `properly break fully qualified nested user types`() =
4295       assertFormatted(
4296           """
4297       |///////////////////////////////////////////////////////
4298       |val complicated:
4299       |    com.example.interesting.SomeType<
4300       |        com.example.interesting.SomeType<Int, Nothing>,
4301       |        com.example.interesting.SomeType<
4302       |            com.example.interesting.SomeType<
4303       |                Int, Nothing>,
4304       |            Nothing>> =
4305       |    DUMMY
4306       |"""
4307               .trimMargin(),
4308           deduceMaxWidth = true)
4309 
4310   @Test
4311   fun `handle multi-line lambdas within lambdas and calling chains`() =
4312       assertFormatted(
4313           """
4314       |fun f() {
4315       |  builder.block(ZERO) {
4316       |    builder.token("when")
4317       |    expression1.let { subjectExp ->
4318       |      builder.token(")")
4319       |      return
4320       |    }
4321       |  }
4322       |  builder.block(ZERO) {
4323       |    expression2.subjectExpression.let { subjectExp ->
4324       |      builder.token(")")
4325       |      return
4326       |    }
4327       |  }
4328       |  builder.block(ZERO) {
4329       |    expression2.subjectExpression
4330       |        .let { subjectExp ->
4331       |          builder.token(")")
4332       |          return
4333       |        }
4334       |        .sum
4335       |  }
4336       |}
4337       |"""
4338               .trimMargin())
4339 
4340   @Test
4341   fun `handle multi line lambdas with explicit args`() =
4342       assertFormatted(
4343           """
4344       |////////////////////
4345       |fun f() {
4346       |  a { (x, y) ->
4347       |    x + y
4348       |  }
4349       |}
4350       |"""
4351               .trimMargin(),
4352           deduceMaxWidth = true)
4353 
4354   @Test
4355   fun `handle lambda with destructuring and type`() =
4356       assertFormatted(
4357           """
4358       |fun f() {
4359       |  g { (a, b): List<Int> -> a }
4360       |  g { (a, b): List<Int>, (c, d): List<Int> -> a }
4361       |}
4362       |"""
4363               .trimMargin())
4364 
4365   @Test
4366   fun `handle parenthesis in lambda calls for now`() =
4367       assertFormatted(
4368           """
4369       |fun f() {
4370       |  a() { println("a") }
4371       |}
4372       |"""
4373               .trimMargin())
4374 
4375   @Test
4376   fun `handle chaining of calls with lambdas`() =
4377       assertFormatted(
4378           """
4379       |fun f() {
4380       |  bobby
4381       |      .map { x -> x * x }
4382       |      .map { x -> x * x }
4383       |      ?.map { x ->
4384       |        val y = x * x
4385       |        y
4386       |      }
4387       |      .sum
4388       |}
4389       |"""
4390               .trimMargin())
4391 
4392   @Test
4393   fun `handle break of lambda args per line with indentation`() =
4394       assertFormatted(
4395           """
4396       |///////////
4397       |fun f() {
4398       |  a() {
4399       |      arg1,
4400       |      arg2,
4401       |      x ->
4402       |    doIt()
4403       |    doIt()
4404       |  }
4405       |  a() {
4406       |      arg1,
4407       |      arg2,
4408       |      arg3
4409       |    ->
4410       |    doIt()
4411       |    doIt()
4412       |  }
4413       |}
4414       |"""
4415               .trimMargin(),
4416           deduceMaxWidth = true)
4417 
4418   @Test
4419   fun `handle trailing comma in lambda`() =
4420       assertFormatted(
4421           """
4422       |///////////
4423       |fun f() {
4424       |  a() {
4425       |      arg1,
4426       |      arg2,
4427       |      x,
4428       |    ->
4429       |    doIt()
4430       |    doIt()
4431       |  }
4432       |}
4433       |"""
4434               .trimMargin(),
4435           deduceMaxWidth = true)
4436 
4437   @Test
4438   fun `break before Elvis operator`() =
4439       assertFormatted(
4440           """
4441         |//////////////////////////////////////////////////
4442         |fun f() {
4443         |  someObject
4444         |      .someMethodReturningCollection()
4445         |      .map { it.someProperty }
4446         |      .find { it.contains(someSearchValue) }
4447         |      ?: someDefaultValue
4448         |}
4449         |"""
4450               .trimMargin(),
4451           deduceMaxWidth = true)
4452 
4453   @Test
4454   fun `chain of Elvis operator`() =
4455       assertFormatted(
4456           """
4457         |///////////////////////////
4458         |fun f() {
4459         |  return option1()
4460         |      ?: option2()
4461         |      ?: option3()
4462         |      ?: option4()
4463         |      ?: option5()
4464         |}
4465         |"""
4466               .trimMargin(),
4467           deduceMaxWidth = true)
4468 
4469   @Test
4470   fun `Elvis operator mixed with plus operator breaking on plus`() =
4471       assertFormatted(
4472           """
4473         |////////////////////////
4474         |fun f() {
4475         |  return option1()
4476         |      ?: option2() +
4477         |          option3()
4478         |      ?: option4() +
4479         |          option5()
4480         |}
4481         |"""
4482               .trimMargin(),
4483           deduceMaxWidth = true)
4484 
4485   @Test
4486   fun `Elvis operator mixed with plus operator breaking on elvis`() =
4487       assertFormatted(
4488           """
4489         |/////////////////////////////////
4490         |fun f() {
4491         |  return option1()
4492         |      ?: option2() + option3()
4493         |      ?: option4() + option5()
4494         |}
4495         |"""
4496               .trimMargin(),
4497           deduceMaxWidth = true)
4498 
4499   @Test
4500   fun `handle comments in the middle of calling chain`() =
4501       assertFormatted(
4502           """
4503         |///////////////////////////
4504         |fun f() {
4505         |  someObject
4506         |      .letsDoIt()
4507         |      // this is a comment
4508         |      .doItOnce()
4509         |      // this is a comment
4510         |      .doItTwice()
4511         |}
4512         |"""
4513               .trimMargin(),
4514           deduceMaxWidth = true)
4515 
4516   @Test
4517   fun `handle reified types`() =
4518       assertFormatted(
4519           """
4520       |inline fun <reified T> foo(t: T) {
4521       |  println(t)
4522       |}
4523       |
4524       |inline fun <reified in T> foo2(t: T) {
4525       |  println(t)
4526       |}
4527       |"""
4528               .trimMargin())
4529 
4530   @Test
4531   fun `handle suspended types`() =
4532       assertFormatted(
4533           """
4534       |private val reader: suspend (Key) -> Output?
4535       |
4536       |private val delete: (suspend (Key) -> Unit)? = null
4537       |
4538       |inline fun <R> foo(noinline block: suspend () -> R): suspend () -> R
4539       |
4540       |inline fun <R> bar(noinline block: (suspend () -> R)?): (suspend () -> R)?
4541       |"""
4542               .trimMargin())
4543 
4544   @Test
4545   fun `handle simple enum classes`() =
4546       assertFormatted(
4547           """
4548       |enum class BetterBoolean {
4549       |  TRUE,
4550       |  FALSE,
4551       |  FILE_NOT_FOUND,
4552       |}
4553       |"""
4554               .trimMargin())
4555 
4556   @Test
4557   fun `handle enum class with functions`() =
4558       assertFormatted(
4559           """
4560       |enum class BetterBoolean {
4561       |  TRUE,
4562       |  FALSE,
4563       |  FILE_NOT_FOUND;
4564       |
4565       |  fun isGood(): Boolean {
4566       |    return true
4567       |  }
4568       |}
4569       |"""
4570               .trimMargin())
4571 
4572   @Test
4573   fun `handle enum with annotations`() =
4574       assertFormatted(
4575           """
4576       |enum class BetterBoolean {
4577       |  @True TRUE,
4578       |  @False @WhatIsTruth FALSE,
4579       |}
4580       |"""
4581               .trimMargin())
4582 
4583   @Test
4584   fun `handle enum constructor calls`() =
4585       assertFormatted(
4586           """
4587       |enum class BetterBoolean(val name: String, val value: Boolean = true) {
4588       |  TRUE("true"),
4589       |  FALSE("false", false),
4590       |}
4591       |"""
4592               .trimMargin())
4593 
4594   @Test
4595   fun `handle enum entries with body`() =
4596       assertFormatted(
4597           """
4598       |enum class Animal(canWalk: Boolean = true) {
4599       |  DOG {
4600       |    fun speak() = "woof"
4601       |  },
4602       |  FISH(false) {},
4603       |}
4604       |"""
4605               .trimMargin())
4606 
4607   @Test
4608   fun `handle empty enum`() =
4609       assertFormatted(
4610           """
4611       |enum class YTho {}
4612       |"""
4613               .trimMargin())
4614 
4615   @Test
4616   fun `expect enum class`() =
4617       assertFormatted(
4618           """
4619       |expect enum class ExpectedEnum
4620       |"""
4621               .trimMargin())
4622 
4623   @Test
4624   fun `enum without trailing comma`() =
4625       assertFormatted(
4626           """
4627       |enum class Highlander {
4628       |  ONE
4629       |}
4630       |"""
4631               .trimMargin())
4632 
4633   @Test
4634   fun `enum comma and semicolon`() {
4635     assertThatFormatting(
4636             """
4637         |enum class Highlander {
4638         |  ONE,;
4639         |}
4640         |"""
4641                 .trimMargin())
4642         .isEqualTo(
4643             """
4644         |enum class Highlander {
4645         |  ONE,
4646         |}
4647         |"""
4648                 .trimMargin())
4649   }
4650 
4651   @Test
4652   fun `empty enum with semicolons`() {
4653     assertThatFormatting(
4654             """
4655         |enum class Empty {
4656         |  ;
4657         |}
4658         |"""
4659                 .trimMargin())
4660         .isEqualTo(
4661             """
4662         |enum class Empty {}
4663         |"""
4664                 .trimMargin())
4665 
4666     assertThatFormatting(
4667             """
4668         |enum class Empty {
4669         |  ;
4670         |  ;
4671         |  ;
4672         |}
4673         |"""
4674                 .trimMargin())
4675         .isEqualTo(
4676             """
4677         |enum class Empty {}
4678         |"""
4679                 .trimMargin())
4680   }
4681 
4682   @Test
4683   fun `semicolon is placed on next line when there's a trailing comma in an enum declaration`() =
4684       assertFormatted(
4685           """
4686         |enum class Highlander {
4687         |  ONE,
4688         |  TWO,
4689         |  ;
4690         |
4691         |  fun f() {}
4692         |}
4693         |"""
4694               .trimMargin())
4695 
4696   @Test
4697   fun `semicolon is removed from empty enum`() {
4698     val code =
4699         """
4700         |enum class SingleSemi {
4701         |  ;
4702         |}
4703         |
4704         |enum class MultSemi {
4705         |  // a
4706         |  ;
4707         |  // b
4708         |  ;
4709         |  // c
4710         |  ;
4711         |}
4712         |"""
4713             .trimMargin()
4714     val expected =
4715         """
4716         |enum class SingleSemi {}
4717         |
4718         |enum class MultSemi {
4719         |  // a
4720         |
4721         |  // b
4722         |
4723         |  // c
4724         |
4725         |}
4726         |"""
4727             .trimMargin()
4728     assertThatFormatting(code).isEqualTo(expected)
4729   }
4730 
4731   @Test
4732   fun `semicolon management in enum with no entries but other members`() {
4733     val code =
4734         """
4735         |enum class Empty {
4736         |  ;
4737         |
4738         |  fun f() {}
4739         |  ;
4740         |  fun g() {}
4741         |}
4742         |"""
4743             .trimMargin()
4744     val expected =
4745         """
4746         |enum class Empty {
4747         |  ;
4748         |
4749         |  fun f() {}
4750         |
4751         |  fun g() {}
4752         |}
4753         |"""
4754             .trimMargin()
4755     assertThatFormatting(code).isEqualTo(expected)
4756   }
4757 
4758   @Test
4759   fun `handle varargs and spread operator`() =
4760       assertFormatted(
4761           """
4762       |fun foo(vararg args: String) {
4763       |  foo2(*args)
4764       |  foo3(options = *args)
4765       |}
4766       |"""
4767               .trimMargin())
4768 
4769   @Test
4770   fun `handle typealias`() =
4771       assertFormatted(
4772           """
4773       |//////////////////////////////////////////////
4774       |private typealias TextChangedListener =
4775       |    (string: String) -> Unit
4776       |
4777       |typealias PairPair<X, Y> = Pair<Pair<X, Y>, X>
4778       |
4779       |class Foo
4780       |"""
4781               .trimMargin(),
4782           deduceMaxWidth = true)
4783 
4784   @Test
4785   fun `handle the 'dynamic' type`() =
4786       assertFormatted(
4787           """
4788       |fun x(): dynamic = "x"
4789       |
4790       |val dyn: dynamic = 1
4791       |"""
4792               .trimMargin())
4793 
4794   @Test
4795   fun `handle class expression with generics`() =
4796       assertFormatted(
4797           """
4798       |fun f() {
4799       |  println(Array<String>::class.java)
4800       |}
4801       |"""
4802               .trimMargin())
4803 
4804   @Test
4805   fun `ParseError contains correct line and column numbers`() {
4806     val code =
4807         """
4808       |// Foo
4809       |fun good() {
4810       |  //
4811       |}
4812       |
4813       |fn (
4814       |"""
4815             .trimMargin()
4816     try {
4817       Formatter.format(code)
4818       fail()
4819     } catch (e: ParseError) {
4820       assertThat(e.lineColumn.line).isEqualTo(6)
4821       assertThat(e.lineColumn.column).isEqualTo(0)
4822       assertThat(e.errorDescription).contains("Expecting an expression")
4823     }
4824   }
4825 
4826   @Test
4827   fun `fail() reports line+column number`() {
4828     val code =
4829         """
4830       |// Foo
4831       |fun good() {
4832       |  return@ 5
4833       |}
4834       |"""
4835             .trimMargin()
4836     try {
4837       Formatter.format(code)
4838       fail()
4839     } catch (e: ParseError) {
4840       assertThat(e.lineColumn.line).isEqualTo(2)
4841       assertThat(e.lineColumn.column).isEqualTo(8)
4842     }
4843   }
4844 
4845   @Test
4846   fun `annotations on class, fun, parameters and literals`() =
4847       assertFormatted(
4848           """
4849       |@Fancy
4850       |class Foo {
4851       |  @Fancy
4852       |  fun baz(@Fancy foo: Int): Int {
4853       |    return (@Fancy 1)
4854       |  }
4855       |}
4856       |"""
4857               .trimMargin())
4858 
4859   @Test
4860   fun `annotations on function types`() =
4861       assertFormatted(
4862           """
4863       |fun foo(bar: @StringRes Int) {}
4864       |
4865       |fun foo(error: @Composable ((x) -> Unit)) {}
4866       |
4867       |fun foo(error: (@Composable (x) -> Unit)) {}
4868       |
4869       |fun foo(
4870       |    error:
4871       |        @field:[Inject Named("WEB_VIEW")]
4872       |        ((x) -> Unit)
4873       |) {}
4874       |
4875       |fun foo(
4876       |    error:
4877       |        (@field:[Inject Named("WEB_VIEW")]
4878       |        (x) -> Unit)
4879       |) {}
4880       |"""
4881               .trimMargin())
4882 
4883   @Test
4884   fun `handle annotations with use-site targets`() =
4885       assertFormatted(
4886           """
4887       |class FooTest {
4888       |  @get:Rule val exceptionRule: ExpectedException = ExpectedException.none()
4889       |
4890       |  @set:Magic(name = "Jane") var field: String
4891       |}
4892       |"""
4893               .trimMargin())
4894 
4895   @Test
4896   fun `handle annotations mixed with keywords since we cannot reorder them for now`() =
4897       assertFormatted(
4898           """
4899       |public @Magic final class Foo
4900       |
4901       |public @Magic(1) final class Foo
4902       |
4903       |@Magic(1) public final class Foo
4904       |"""
4905               .trimMargin())
4906 
4907   @Test
4908   fun `handle annotations more`() =
4909       assertFormatted(
4910           """
4911       |/////////////////////////////////////////////////
4912       |@Anno1
4913       |@Anno2(param = Param1::class)
4914       |@Anno3
4915       |@Anno4(param = Param2::class)
4916       |class MyClass {}
4917       |
4918       |fun f() {
4919       |  @Suppress("MagicNumber") add(10)
4920       |
4921       |  @Annotation // test a comment after annotations
4922       |  return 5
4923       |}
4924       |"""
4925               .trimMargin(),
4926           deduceMaxWidth = true)
4927 
4928   @Test
4929   fun `annotated expressions`() =
4930       assertFormatted(
4931           """
4932       |////////////////////////////////////////////////
4933       |fun f() {
4934       |  @Suppress("MagicNumber") add(10) && add(20)
4935       |
4936       |  @Suppress("MagicNumber")
4937       |  add(10) && add(20)
4938       |
4939       |  @Anno1 @Anno2(param = Param1::class)
4940       |  add(10) && add(20)
4941       |
4942       |  @Anno1
4943       |  @Anno2(param = Param1::class)
4944       |  @Anno3
4945       |  @Anno4(param = Param2::class)
4946       |  add(10) && add(20)
4947       |
4948       |  @Anno1
4949       |  @Anno2(param = Param1::class)
4950       |  @Anno3
4951       |  @Anno4(param = Param2::class)
4952       |  add(10) && add(20)
4953       |
4954       |  @Suppress("MagicNumber") add(10) &&
4955       |      add(20) &&
4956       |      add(30)
4957       |
4958       |  add(@Suppress("MagicNumber") 10) &&
4959       |      add(20) &&
4960       |      add(30)
4961       |}
4962       |"""
4963               .trimMargin(),
4964           deduceMaxWidth = true)
4965 
4966   @Test
4967   fun `annotated function declarations`() =
4968       assertFormatted(
4969           """
4970       |@Anno
4971       |fun f() {
4972       |  add(10)
4973       |}
4974       |
4975       |@Anno(param = 1)
4976       |fun f() {
4977       |  add(10)
4978       |}
4979       |"""
4980               .trimMargin())
4981 
4982   @Test
4983   fun `annotated class declarations`() =
4984       assertFormatted(
4985           """
4986       |@Anno class F
4987       |
4988       |@Anno(param = 1) class F
4989       |
4990       |@Anno(P)
4991       |// Foo
4992       |@Anno("param")
4993       |class F
4994       |"""
4995               .trimMargin())
4996 
4997   @Test
4998   fun `handle type arguments in annotations`() =
4999       assertFormatted(
5000           """
5001       |@TypeParceler<UUID, UUIDParceler>() class MyClass {}
5002       |"""
5003               .trimMargin())
5004 
5005   @Test
5006   fun `handle one line KDoc`() =
5007       assertFormatted(
5008           """
5009       |/** Hi, I am a one line kdoc */
5010       |class MyClass {}
5011       |"""
5012               .trimMargin())
5013 
5014   @Test
5015   fun `handle KDoc with Link`() =
5016       assertFormatted(
5017           """
5018       |/** This links to [AnotherClass] */
5019       |class MyClass {}
5020       |"""
5021               .trimMargin())
5022 
5023   @Test
5024   fun `handle KDoc with paragraphs`() =
5025       assertFormatted(
5026           """
5027       |/**
5028       | * Hi, I am a two paragraphs kdoc
5029       | *
5030       | * There's a space line to preserve between them
5031       | */
5032       |class MyClass {}
5033       |"""
5034               .trimMargin())
5035 
5036   @Test
5037   fun `handle KDoc with blocks`() =
5038       assertFormatted(
5039           """
5040       |/**
5041       | * Hi, I am a two paragraphs kdoc
5042       | *
5043       | * @param param1 this is param1
5044       | * @param[param2] this is param2
5045       | */
5046       |class MyClass {}
5047       |"""
5048               .trimMargin())
5049 
5050   @Test
5051   fun `handle KDoc with code examples`() =
5052       assertFormatted(
5053           """
5054       |/**
5055       | * This is how you write a simple hello world in Kotlin:
5056       | * ```
5057       | * fun main(args: Array<String>) {
5058       | *   println("Hello World!")
5059       | * }
5060       | * ```
5061       | *
5062       | * Amazing ah?
5063       | *
5064       | * ```
5065       | * fun `code can be with a blank line above it` () {}
5066       | * ```
5067       | *
5068       | * Or after it!
5069       | */
5070       |class MyClass {}
5071       |"""
5072               .trimMargin())
5073 
5074   @Test
5075   fun `handle KDoc with tagged code examples`() =
5076       assertFormatted(
5077           """
5078       |/**
5079       | * ```kotlin
5080       | * fun main(args: Array<String>) {
5081       | *   println("Hello World!")
5082       | * }
5083       | * ```
5084       | */
5085       |class MyClass {}
5086       |"""
5087               .trimMargin())
5088 
5089   @Test
5090   fun `handle stray code markers in lines and produce stable output`() {
5091     val code =
5092         """
5093       |/**
5094       | * Look! code: ``` aaa
5095       | * fun f() = Unit
5096       | * foo
5097       | * ```
5098       | */
5099       |class MyClass {}
5100       |"""
5101             .trimMargin()
5102     assertFormatted(Formatter.format(code))
5103   }
5104 
5105   @Test
5106   fun `code block with triple backtick`() {
5107     val code =
5108         """
5109       |/**
5110       | * Look! code:
5111       | * ```
5112       | * aaa ``` wow
5113       | * ```
5114       | */
5115       |class MyClass {}
5116       |"""
5117             .trimMargin()
5118     val expected =
5119         """
5120       |/**
5121       | * Look! code:
5122       | * ```
5123       | * aaa ``` wow
5124       | * ```
5125       | */
5126       |class MyClass {}
5127       |"""
5128             .trimMargin()
5129     assertThatFormatting(code).isEqualTo(expected)
5130   }
5131 
5132   @Test
5133   fun `when code closer in mid of line, produce stable output`() {
5134     val code =
5135         """
5136       |/**
5137       | * Look! code: ``` aaa
5138       | * fun f() = Unit
5139       | * foo ``` wow
5140       | */
5141       |class MyClass {}
5142       |"""
5143             .trimMargin()
5144     assertFormatted(Formatter.format(code))
5145   }
5146 
5147   @Test
5148   fun `handle KDoc with link reference`() =
5149       assertFormatted(
5150           """
5151       |/** Doc line with a reference to [AnotherClass] in the middle of a sentence */
5152       |class MyClass {}
5153       |"""
5154               .trimMargin())
5155 
5156   @Test
5157   fun `handle KDoc with links one after another`() =
5158       assertFormatted(
5159           """
5160       |/** Here are some links [AnotherClass] [AnotherClass2] */
5161       |class MyClass {}
5162       |"""
5163               .trimMargin())
5164 
5165   @Test
5166   fun `don't add spaces after links in Kdoc`() =
5167       assertFormatted(
5168           """
5169       |/** Here are some links [AnotherClass][AnotherClass2]hello */
5170       |class MyClass {}
5171       |"""
5172               .trimMargin())
5173 
5174   @Test
5175   fun `don't remove spaces after links in Kdoc`() =
5176       assertFormatted(
5177           """
5178       |/** Please see [onNext] (which has more details) */
5179       |class MyClass {}
5180       |"""
5181               .trimMargin())
5182 
5183   @Test
5184   fun `link anchor in KDoc are preserved`() =
5185       assertFormatted(
5186           """
5187       |/** [link anchor](the URL for the link anchor goes here) */
5188       |class MyClass {}
5189       |"""
5190               .trimMargin())
5191 
5192   @Test
5193   fun `don't add spaces between links in KDoc (because they're actually references)`() =
5194       assertFormatted(
5195           """
5196       |/** Here are some links [AnotherClass][AnotherClass2] */
5197       |class MyClass {}
5198       |
5199       |/** The final produced value may have [size][ByteString.size] < [bufferSize]. */
5200       |class MyClass {}
5201       |"""
5202               .trimMargin())
5203 
5204   @Test
5205   fun `collapse spaces after links in KDoc`() {
5206     val code =
5207         """
5208       |/** Here are some links [Class1], [Class2]   [Class3]. hello */
5209       |class MyClass {}
5210       |"""
5211             .trimMargin()
5212     val expected =
5213         """
5214       |/** Here are some links [Class1], [Class2] [Class3]. hello */
5215       |class MyClass {}
5216       |"""
5217             .trimMargin()
5218     assertThatFormatting(code).isEqualTo(expected)
5219   }
5220 
5221   @Test
5222   fun `collapse newlines after links in KDoc`() {
5223     val code =
5224         """
5225       |/**
5226       | * Here are some links [Class1]
5227       | * [Class2]
5228       | */
5229       |class MyClass {}
5230       |"""
5231             .trimMargin()
5232     val expected =
5233         """
5234       |/** Here are some links [Class1] [Class2] */
5235       |class MyClass {}
5236       |"""
5237             .trimMargin()
5238     assertThatFormatting(code).isEqualTo(expected)
5239   }
5240 
5241   @Test
5242   fun `do not crash because of malformed KDocs and produce stable output`() {
5243     val code =
5244         """
5245       |/** Surprise ``` */
5246       |class MyClass {}
5247       |"""
5248             .trimMargin()
5249     assertFormatted(Formatter.format(code))
5250   }
5251 
5252   @Test
5253   fun `Respect spacing of text after link`() =
5254       assertFormatted(
5255           """
5256       |/** Enjoy this link [linkstuff]. */
5257       |class MyClass {}
5258       |
5259       |/** There are many [FooObject]s. */
5260       |class MyClass {}
5261       |"""
5262               .trimMargin())
5263 
5264   @Test
5265   fun `handle KDoc with multiple separated param tags, breaking and merging lines and missing asterisk`() {
5266     val code =
5267         """
5268       |/**
5269       | * Trims leading whitespace characters followed by [marginPrefix] from every line of a source string and removes
5270       | * the first and the last lines if they are blank (notice difference blank vs empty).
5271       |
5272       | * Doesn't affect a line if it doesn't contain [marginPrefix] except the first and the last blank lines.
5273       | *
5274       | * Doesn't preserve the original line endings.
5275       | *
5276       | * @param marginPrefix non-blank string, which is used as a margin delimiter. Default is `|` (pipe character).
5277       | *
5278       | * @sample samples.text.Strings.trimMargin
5279       | * @see trimIndent
5280       | * @see kotlin.text.isWhitespace
5281       | */
5282       |class ThisWasCopiedFromTheTrimMarginMethod {}
5283       |"""
5284             .trimMargin()
5285     val expected =
5286         """
5287       |/**
5288       | * Trims leading whitespace characters followed by [marginPrefix] from every line of a source string
5289       | * and removes the first and the last lines if they are blank (notice difference blank vs empty).
5290       | *
5291       | * Doesn't affect a line if it doesn't contain [marginPrefix] except the first and the last blank
5292       | * lines.
5293       | *
5294       | * Doesn't preserve the original line endings.
5295       | *
5296       | * @param marginPrefix non-blank string, which is used as a margin delimiter. Default is `|` (pipe
5297       | *   character).
5298       | * @sample samples.text.Strings.trimMargin
5299       | * @see trimIndent
5300       | * @see kotlin.text.isWhitespace
5301       | */
5302       |class ThisWasCopiedFromTheTrimMarginMethod {}
5303       |"""
5304             .trimMargin()
5305     assertThatFormatting(code).isEqualTo(expected)
5306   }
5307 
5308   @Test
5309   fun `KDoc is reflowed`() {
5310     val code =
5311         """
5312       |/** Lorem ipsum dolor sit amet, consectetur */
5313       |class MyClass {}
5314       |"""
5315             .trimMargin()
5316     val expected =
5317         """
5318       |/**
5319       | * Lorem ipsum dolor sit amet,
5320       | * consectetur
5321       | */
5322       |class MyClass {}
5323       |"""
5324             .trimMargin()
5325     assertThatFormatting(code).withOptions(FormattingOptions(maxWidth = 33)).isEqualTo(expected)
5326   }
5327 
5328   @Test
5329   fun `sanity - block and continuation indents are 4`() {
5330     val code =
5331         """
5332         |fun f() {
5333         |    for (child in
5334         |        node.next.next.next.next
5335         |            .data()) {
5336         |        println(child)
5337         |    }
5338         |}
5339         |"""
5340             .trimMargin()
5341     assertThatFormatting(code)
5342         .withOptions(FormattingOptions(maxWidth = 35, blockIndent = 4, continuationIndent = 4))
5343         .isEqualTo(code)
5344   }
5345 
5346   @Test
5347   fun `comment after a block is stable and does not add space lines`() =
5348       assertFormatted(
5349           """
5350       |fun doIt() {}
5351       |
5352       |/* this is the first comment */
5353       |"""
5354               .trimMargin())
5355 
5356   @Test
5357   fun `preserve LF, CRLF and CR line endings`() {
5358     val lines = listOf("fun main() {", "  println(\"test\")", "}")
5359     for (ending in listOf("\n", "\r\n", "\r")) {
5360       val code = lines.joinToString(ending) + ending
5361       assertThatFormatting(code).isEqualTo(code)
5362     }
5363   }
5364 
5365   @Test
5366   fun `handle trailing commas (constructors)`() =
5367       assertFormatted(
5368           """
5369       |////////////////////
5370       |class Foo(
5371       |    a: Int,
5372       |)
5373       |
5374       |class Foo(
5375       |    a: Int,
5376       |    b: Int,
5377       |)
5378       |
5379       |class Foo(
5380       |    a: Int,
5381       |    b: Int
5382       |)
5383       |"""
5384               .trimMargin(),
5385           deduceMaxWidth = true)
5386 
5387   @Test
5388   fun `handle trailing commas (explicit constructors)`() =
5389       assertFormatted(
5390           """
5391       |////////////////////////
5392       |class Foo
5393       |constructor(
5394       |    a: Int,
5395       |)
5396       |
5397       |class Foo
5398       |constructor(
5399       |    a: Int,
5400       |    b: Int,
5401       |)
5402       |
5403       |class Foo
5404       |constructor(
5405       |    a: Int,
5406       |    b: Int
5407       |)
5408       |"""
5409               .trimMargin(),
5410           deduceMaxWidth = true)
5411 
5412   @Test
5413   fun `handle trailing commas (secondary constructors)`() =
5414       assertFormatted(
5415           """
5416       |////////////////////////
5417       |class Foo {
5418       |  constructor(
5419       |      a: Int,
5420       |  )
5421       |}
5422       |
5423       |class Foo {
5424       |  constructor(
5425       |      a: Int,
5426       |      b: Int,
5427       |  )
5428       |}
5429       |
5430       |class Foo {
5431       |  constructor(
5432       |      a: Int,
5433       |      b: Int
5434       |  )
5435       |}
5436       |"""
5437               .trimMargin(),
5438           deduceMaxWidth = true)
5439 
5440   @Test
5441   fun `handle trailing commas (function definitions)`() =
5442       assertFormatted(
5443           """
5444       |////////////////////////
5445       |fun <
5446       |    T,
5447       |> foo() {}
5448       |
5449       |fun <
5450       |    T,
5451       |    S,
5452       |> foo() {}
5453       |
5454       |fun foo(
5455       |    a: Int,
5456       |) {}
5457       |
5458       |fun foo(
5459       |    a: Int,
5460       |    b: Int
5461       |) {}
5462       |
5463       |fun foo(
5464       |    a: Int,
5465       |    b: Int,
5466       |) {}
5467       |
5468       |fun foo(
5469       |    a: Int,
5470       |    b: Int,
5471       |    c: Int,
5472       |) {}
5473       |"""
5474               .trimMargin(),
5475           deduceMaxWidth = true)
5476 
5477   @Test
5478   fun `handle trailing commas (function calls)`() =
5479       assertFormatted(
5480           """
5481       |////////////////////////
5482       |fun main() {
5483       |  foo(
5484       |      3,
5485       |  )
5486       |
5487       |  foo<Int>(
5488       |      3,
5489       |  )
5490       |
5491       |  foo<
5492       |      Int,
5493       |  >(
5494       |      3,
5495       |  )
5496       |
5497       |  foo<Int>(
5498       |      "asdf", "asdf")
5499       |
5500       |  foo<
5501       |      Int,
5502       |  >(
5503       |      "asd",
5504       |      "asd",
5505       |  )
5506       |
5507       |  foo<
5508       |      Int,
5509       |      Boolean,
5510       |  >(
5511       |      3,
5512       |  )
5513       |}
5514       |"""
5515               .trimMargin(),
5516           deduceMaxWidth = true)
5517 
5518   @Test
5519   fun `handle trailing commas (proprties)`() =
5520       assertFormatted(
5521           """
5522       |//////////////////////////
5523       |val foo: String
5524       |  set(
5525       |      value,
5526       |  ) {}
5527       |"""
5528               .trimMargin(),
5529           deduceMaxWidth = true)
5530 
5531   @Test
5532   fun `handle trailing commas (higher-order functions)`() =
5533       assertFormatted(
5534           """
5535       |//////////////////////////
5536       |fun foo(
5537       |    x:
5538       |        (
5539       |            Int,
5540       |        ) -> Unit
5541       |) {}
5542       |"""
5543               .trimMargin(),
5544           deduceMaxWidth = true)
5545 
5546   @Test
5547   fun `handle trailing commas (after lambda arg)`() =
5548       assertFormatted(
5549           """
5550       |//////////////////////////
5551       |fun foo() {
5552       |  foo(
5553       |      { it },
5554       |  )
5555       |}
5556       |"""
5557               .trimMargin(),
5558           deduceMaxWidth = true)
5559 
5560   @Test
5561   fun `handle trailing commas (other)`() =
5562       assertFormatted(
5563           """
5564       |//////////////////////////
5565       |fun main() {
5566       |  val (
5567       |      x: Int,
5568       |  ) = foo()
5569       |  val (
5570       |      x: Int,
5571       |      y: Int,
5572       |  ) = foo()
5573       |
5574       |  val (
5575       |      x: Int,
5576       |  ) = foo(
5577       |      blablablablFoobar,
5578       |      alskdjasld)
5579       |
5580       |  val (
5581       |      x: Int,
5582       |      y: Int,
5583       |  ) = foo(
5584       |      blablablablFoobar,
5585       |      asldkalsd)
5586       |
5587       |  a[
5588       |      0,
5589       |  ] = 43
5590       |  a[
5591       |      0,
5592       |      1,
5593       |  ] = 43
5594       |
5595       |  [
5596       |      0,
5597       |  ]
5598       |  [
5599       |      0,
5600       |      1,
5601       |  ]
5602       |
5603       |  when (foo) {
5604       |    'x', -> 43
5605       |    'x',
5606       |    'y', -> 43
5607       |    'x',
5608       |    'y',
5609       |    'z',
5610       |    'w',
5611       |    'a',
5612       |    'b', -> 43
5613       |  }
5614       |
5615       |  try {
5616       |    //
5617       |  } catch (e: Error,) {
5618       |    //
5619       |  }
5620       |}
5621       |"""
5622               .trimMargin(),
5623           deduceMaxWidth = true)
5624 
5625   @Test
5626   fun `assignment of a scoping function`() =
5627       assertFormatted(
5628           """
5629       |////////////////////////////
5630       |val foo = coroutineScope {
5631       |  foo()
5632       |  //
5633       |}
5634       |
5635       |fun foo() = coroutineScope {
5636       |  foo()
5637       |  //
5638       |}
5639       |
5640       |fun foo() = use { x ->
5641       |  foo()
5642       |  //
5643       |}
5644       |
5645       |fun foo() = scope label@{
5646       |  foo()
5647       |  //
5648       |}
5649       |
5650       |fun foo() =
5651       |    coroutineScope { x ->
5652       |      foo()
5653       |      //
5654       |    }
5655       |
5656       |fun foo() =
5657       |    coroutineScope label@{
5658       |      foo()
5659       |      //
5660       |    }
5661       |
5662       |fun foo() =
5663       |    Runnable @Px {
5664       |      foo()
5665       |      //
5666       |    }
5667       |
5668       |fun longName() =
5669       |    coroutineScope {
5670       |      foo()
5671       |      //
5672       |    }
5673       |"""
5674               .trimMargin(),
5675           deduceMaxWidth = true)
5676 
5677   @Test
5678   fun `top level properties with other types preserve newline spacing`() {
5679     assertFormatted(
5680         """
5681       |/////////////////////////////////
5682       |fun something() {
5683       |  println("hi")
5684       |}
5685       |
5686       |const val SOME_CONST = 1
5687       |val SOME_STR = "hi"
5688       |// Single comment
5689       |val SOME_INT = 1
5690       |
5691       |// Intentional space above single comment
5692       |val SOME_INT2 = 1
5693       |
5694       |val FOO = 2
5695       |const val BAR = 3
5696       |
5697       |fun baz() = 1
5698       |
5699       |val d = 1
5700       |
5701       |class Bar {}
5702       |
5703       |val e = 1
5704       |/** Doc block */
5705       |val f = 1
5706       |
5707       |/** Intent. space above doc */
5708       |val g = 1
5709       |
5710       |data class Qux(val foo: String)
5711       |"""
5712             .trimMargin(),
5713         deduceMaxWidth = true)
5714 
5715     assertThatFormatting(
5716             """
5717       |import com.example.foo
5718       |import com.example.bar
5719       |const val SOME_CONST = foo.a
5720       |val SOME_STR = bar.a
5721       |"""
5722                 .trimMargin())
5723         .isEqualTo(
5724             """
5725       |import com.example.bar
5726       |import com.example.foo
5727       |
5728       |const val SOME_CONST = foo.a
5729       |val SOME_STR = bar.a
5730       |"""
5731                 .trimMargin())
5732   }
5733 
5734   @Test
5735   fun `first line is never empty`() =
5736       assertThatFormatting(
5737               """
5738       |
5739       |fun f() {}
5740       |"""
5741                   .trimMargin())
5742           .isEqualTo(
5743               """
5744       |fun f() {}
5745       |"""
5746                   .trimMargin())
5747 
5748   @Test
5749   fun `at most one newline between any adjacent top-level elements`() =
5750       assertThatFormatting(
5751               """
5752       |import com.Bar
5753       |
5754       |
5755       |import com.Foo
5756       |
5757       |
5758       |fun f() {}
5759       |
5760       |
5761       |fun f() {}
5762       |
5763       |
5764       |class C {}
5765       |
5766       |
5767       |class C {}
5768       |
5769       |
5770       |val x = Foo()
5771       |
5772       |
5773       |val x = Bar()
5774       |"""
5775                   .trimMargin())
5776           .isEqualTo(
5777               """
5778       |import com.Bar
5779       |import com.Foo
5780       |
5781       |fun f() {}
5782       |
5783       |fun f() {}
5784       |
5785       |class C {}
5786       |
5787       |class C {}
5788       |
5789       |val x = Foo()
5790       |
5791       |val x = Bar()
5792       |"""
5793                   .trimMargin())
5794 
5795   @Test
5796   fun `at least one newline between any adjacent top-level elements, unless it's a property`() =
5797       assertThatFormatting(
5798               """
5799       |import com.Bar
5800       |import com.Foo
5801       |fun f() {}
5802       |fun f() {}
5803       |class C {}
5804       |class C {}
5805       |val x = Foo()
5806       |val x = Bar()
5807       |"""
5808                   .trimMargin())
5809           .isEqualTo(
5810               """
5811       |import com.Bar
5812       |import com.Foo
5813       |
5814       |fun f() {}
5815       |
5816       |fun f() {}
5817       |
5818       |class C {}
5819       |
5820       |class C {}
5821       |
5822       |val x = Foo()
5823       |val x = Bar()
5824       |"""
5825                   .trimMargin())
5826 
5827   @Test
5828   fun `handle array of annotations with field prefix`() {
5829     val code: String =
5830         """
5831     |class MyClass {
5832     |  @field:[JvmStatic Volatile]
5833     |  var myVar: String? = null
5834     |}
5835     |
5836     """
5837             .trimMargin()
5838     assertThatFormatting(code).isEqualTo(code)
5839   }
5840 
5841   @Test
5842   fun `handle array of annotations without field prefix`() {
5843     val code: String =
5844         """
5845     |class MyClass {
5846     |  @[JvmStatic Volatile]
5847     |  var myVar: String? = null
5848     |}
5849     |
5850     """
5851             .trimMargin()
5852     assertThatFormatting(code).isEqualTo(code)
5853   }
5854 
5855   // Regression test against https://github.com/facebook/ktfmt/issues/243
5856   @Test
5857   fun `regression test against Issue 243`() {
5858     val code =
5859         """
5860       |class Foo {
5861       |  companion object {
5862       |    var instance: Foo? = null
5863       |
5864       |    fun getInstance() {
5865       |      return instance ?: synchronized(Foo::class) {
5866       |        Foo().also { instance = it }
5867       |      }
5868       |    }
5869       |  }
5870       |}
5871       |"""
5872             .trimMargin()
5873 
5874     // Don't throw.
5875     Formatter.format(code)
5876   }
5877 
5878   @Test
5879   fun `lambda with required arrow`() =
5880       assertFormatted(
5881           """
5882       |val a = { x: Int -> }
5883       |val b = { x: Int -> 0 }
5884       |val c = { x: Int ->
5885       |  val y = 0
5886       |  y
5887       |}
5888       |"""
5889               .trimMargin())
5890 
5891   @Test
5892   fun `lambda with optional arrow`() =
5893       assertFormatted(
5894           """
5895       |val a = { -> }
5896       |val b = { -> 0 }
5897       |val c = { ->
5898       |  val y = 0
5899       |  y
5900       |}
5901       |"""
5902               .trimMargin())
5903 
5904   @Test
5905   fun `lambda missing optional arrow`() =
5906       assertFormatted(
5907           """
5908       |val a = {}
5909       |val b = { 0 }
5910       |val c = {
5911       |  val y = 0
5912       |  y
5913       |}
5914       |"""
5915               .trimMargin())
5916 
5917   @Test
5918   fun `lambda with only comments`() {
5919     assertFormatted(
5920         """
5921         |val a = { /* do nothing */ }
5922         |val b = { /* do nothing */ /* also do nothing */ }
5923         |val c = { -> /* do nothing */ }
5924         |val d = { _ -> /* do nothing */ }
5925         |private val e = Runnable {
5926         |  // do nothing
5927         |}
5928         |private val f: () -> Unit = {
5929         |  // no-op
5930         |}
5931         |private val g: () -> Unit = { /* no-op */ }
5932         |"""
5933             .trimMargin())
5934 
5935     assertFormatted(
5936         """
5937         |//////////////////////////////
5938         |val a = { /* do nothing */ }
5939         |val b =
5940         |    { /* do nothing */ /* also do nothing */
5941         |    }
5942         |val c = { -> /* do nothing */
5943         |}
5944         |val d =
5945         |    { _ -> /* do nothing */
5946         |    }
5947         |private val e = Runnable {
5948         |  // do nothing
5949         |}
5950         |private val f: () -> Unit = {
5951         |  // no-op
5952         |}
5953         |private val g: () -> Unit =
5954         |    { /* no-op */
5955         |    }
5956         |"""
5957             .trimMargin(),
5958         deduceMaxWidth = true)
5959   }
5960 
5961   @Test
5962   fun `lambda block with single and multiple statements`() =
5963       assertFormatted(
5964           """
5965       |private val a = Runnable {
5966       |  foo()
5967       |  TODO("implement me")
5968       |}
5969       |
5970       |private val b = Runnable { TODO("implement me") }
5971       |
5972       |private val c: () -> Unit = {
5973       |  foo()
5974       |  TODO("implement me")
5975       |}
5976       |
5977       |private val d: () -> Unit = { TODO("implement me") }
5978       |"""
5979               .trimMargin())
5980 
5981   @Test
5982   fun `lambda block with comments and statements mix`() =
5983       assertFormatted(
5984           """
5985       |private val a = Runnable {
5986       |  // no-op
5987       |  TODO("implement me")
5988       |}
5989       |
5990       |private val b = Runnable {
5991       |  TODO("implement me")
5992       |  // no-op
5993       |}
5994       |
5995       |private val c: () -> Unit = {
5996       |  /* no-op */ TODO("implement me")
5997       |}
5998       |
5999       |private val d: () -> Unit = { ->
6000       |  /* no-op */ TODO("implement me")
6001       |}
6002       |
6003       |private val e: (String, Int) -> Unit = { _, i -> foo(i) /* do nothing ... */ }
6004       |"""
6005               .trimMargin())
6006 
6007   @Test
6008   fun `lambda block with comments and with statements have same formatting treatment`() =
6009       assertFormatted(
6010           """
6011       |private val a = Runnable { /* no-op */ }
6012       |private val A = Runnable { TODO("...") }
6013       |
6014       |private val b = Runnable {
6015       |  /* no-op 1 */
6016       |  /* no-op 2 */
6017       |}
6018       |private val B = Runnable {
6019       |  TODO("no-op")
6020       |  TODO("no-op")
6021       |}
6022       |
6023       |private val c: () -> Unit = {
6024       |  /* no-op */
6025       |}
6026       |private val C: () -> Unit = { TODO("...") }
6027       |
6028       |private val d: () -> Unit = {
6029       |  /*.*/
6030       |  /* do nothing ... */
6031       |}
6032       |private val D: () -> Unit = {
6033       |  foo()
6034       |  TODO("implement me")
6035       |}
6036       |"""
6037               .trimMargin())
6038 
6039   @Test
6040   fun `last parameter with comment and with statements have same formatting treatment`() {
6041     assertFormatted(
6042         """
6043         |private val a =
6044         |    call(param) {
6045         |      // no-op
6046         |      /* comment */
6047         |    }
6048         |private val A =
6049         |    call(param) {
6050         |      a.run()
6051         |      TODO("implement me")
6052         |    }
6053         |
6054         |private val b = call(param) { /* no-op */ }
6055         |private val B = call(param) { TODO("implement me") }
6056         |
6057         |private val c = firstCall().prop.call(param) { /* no-op */ }
6058         |private val C = firstCall().prop.call(param) { TODO("implement me") }
6059         |"""
6060             .trimMargin())
6061 
6062     assertFormatted(
6063         """
6064         |////////////////////////////////////////
6065         |private val a =
6066         |    firstCall().prop.call(
6067         |        mySuperInterestingParameter) {
6068         |          /* no-op */
6069         |        }
6070         |private val A =
6071         |    firstCall().prop.call(
6072         |        mySuperInterestingParameter) {
6073         |          TODO("...")
6074         |        }
6075         |
6076         |fun b() {
6077         |  myProp.funCall(param) { /* 12345 */ }
6078         |  myProp.funCall(param) { TODO("123") }
6079         |
6080         |  myProp.funCall(param) { /* 123456 */ }
6081         |  myProp.funCall(param) { TODO("1234") }
6082         |
6083         |  myProp.funCall(param) { /* 1234567 */
6084         |  }
6085         |  myProp.funCall(param) {
6086         |    TODO("12345")
6087         |  }
6088         |
6089         |  myProp.funCall(param) { /* 12345678 */
6090         |  }
6091         |  myProp.funCall(param) {
6092         |    TODO("123456")
6093         |  }
6094         |
6095         |  myProp.funCall(
6096         |      param) { /* 123456789 */
6097         |      }
6098         |  myProp.funCall(param) {
6099         |    TODO("1234567")
6100         |  }
6101         |
6102         |  myProp.funCall(
6103         |      param) { /* very_very_long_comment_that_should_go_on_its_own_line */
6104         |      }
6105         |  myProp.funCall(param) {
6106         |    TODO(
6107         |        "_a_very_long_comment_that_should_go_on_its_own_line")
6108         |  }
6109         |}
6110         |
6111         |private val c =
6112         |    firstCall().prop.call(param) {
6113         |      /* no-op */
6114         |    }
6115         |private val C =
6116         |    firstCall().prop.call(param) {
6117         |      TODO("...")
6118         |    }
6119         |"""
6120             .trimMargin(),
6121         deduceMaxWidth = true)
6122   }
6123 
6124   @Test
6125   fun `chaining - many dereferences`() =
6126       assertFormatted(
6127           """
6128       |/////////////////////////
6129       |rainbow.red.orange.yellow
6130       |    .green
6131       |    .blue
6132       |    .indigo
6133       |    .violet
6134       |    .cyan
6135       |    .magenta
6136       |    .key
6137       |"""
6138               .trimMargin(),
6139           deduceMaxWidth = true)
6140 
6141   @Test
6142   fun `chaining - many dereferences, fit on one line`() =
6143       assertFormatted(
6144           """
6145       |///////////////////////////////////////////////////////////////////////////
6146       |rainbow.red.orange.yellow.green.blue.indigo.violet.cyan.magenta.key
6147       |"""
6148               .trimMargin(),
6149           deduceMaxWidth = true)
6150 
6151   @Test
6152   fun `chaining - many dereferences, one invocation at end`() =
6153       assertFormatted(
6154           """
6155       |/////////////////////////
6156       |rainbow.red.orange.yellow
6157       |    .green
6158       |    .blue
6159       |    .indigo
6160       |    .violet
6161       |    .cyan
6162       |    .magenta
6163       |    .key
6164       |    .build()
6165       |"""
6166               .trimMargin(),
6167           deduceMaxWidth = true)
6168 
6169   @Test
6170   fun `chaining - many dereferences, one invocation at end, fit on one line`() =
6171       assertFormatted(
6172           """
6173       |///////////////////////////////////////////////////////////////////////////
6174       |rainbow.red.orange.yellow.green.blue.indigo.violet.cyan.magenta.key.build()
6175       |"""
6176               .trimMargin(),
6177           deduceMaxWidth = true)
6178 
6179   @Test
6180   fun `chaining - many dereferences, two invocations at end`() =
6181       assertFormatted(
6182           """
6183       |/////////////////////////
6184       |rainbow.red.orange.yellow
6185       |    .green
6186       |    .blue
6187       |    .indigo
6188       |    .violet
6189       |    .cyan
6190       |    .magenta
6191       |    .key
6192       |    .build()
6193       |    .shine()
6194       |"""
6195               .trimMargin(),
6196           deduceMaxWidth = true)
6197 
6198   @Test
6199   fun `chaining - many dereferences, one invocation in the middle`() =
6200       assertFormatted(
6201           """
6202       |/////////////////////////
6203       |rainbow.red.orange.yellow
6204       |    .green
6205       |    .blue
6206       |    .shine()
6207       |    .indigo
6208       |    .violet
6209       |    .cyan
6210       |    .magenta
6211       |    .key
6212       |"""
6213               .trimMargin(),
6214           deduceMaxWidth = true)
6215 
6216   @Test
6217   fun `chaining - many dereferences, two invocations in the middle`() =
6218       assertFormatted(
6219           """
6220       |/////////////////////////
6221       |rainbow.red.orange.yellow
6222       |    .green
6223       |    .blue
6224       |    .indigo
6225       |    .shine()
6226       |    .bright()
6227       |    .violet
6228       |    .cyan
6229       |    .magenta
6230       |    .key
6231       |"""
6232               .trimMargin(),
6233           deduceMaxWidth = true)
6234 
6235   @Test
6236   fun `chaining - many dereferences, one lambda at end`() =
6237       assertFormatted(
6238           """
6239       |/////////////////////////
6240       |rainbow.red.orange.yellow
6241       |    .green
6242       |    .blue
6243       |    .indigo
6244       |    .violet
6245       |    .cyan
6246       |    .magenta
6247       |    .key
6248       |    .build { it.appear }
6249       |"""
6250               .trimMargin(),
6251           deduceMaxWidth = true)
6252 
6253   @Test
6254   fun `chaining - many dereferences, one short lambda at end`() =
6255       assertFormatted(
6256           """
6257       |/////////////////////////
6258       |rainbow.red.orange.yellow
6259       |    .green
6260       |    .blue
6261       |    .indigo
6262       |    .violet
6263       |    .cyan
6264       |    .magenta
6265       |    .key
6266       |    .z { it }
6267       |"""
6268               .trimMargin(),
6269           deduceMaxWidth = true)
6270 
6271   @Test
6272   fun `chaining - many dereferences, one multiline lambda at end`() =
6273       assertFormatted(
6274           """
6275       |/////////////////////////
6276       |rainbow.red.orange.yellow
6277       |    .green
6278       |    .blue
6279       |    .indigo
6280       |    .violet
6281       |    .cyan
6282       |    .magenta
6283       |    .key
6284       |    .z {
6285       |      it
6286       |      it
6287       |    }
6288       |"""
6289               .trimMargin(),
6290           deduceMaxWidth = true)
6291 
6292   @Test
6293   fun `chaining - many dereferences, one short lambda in the middle`() =
6294       assertFormatted(
6295           """
6296       |/////////////////////////
6297       |rainbow.red.orange.yellow
6298       |    .green
6299       |    .blue
6300       |    .z { it }
6301       |    .indigo
6302       |    .violet
6303       |    .cyan
6304       |    .magenta
6305       |    .key
6306       |"""
6307               .trimMargin(),
6308           deduceMaxWidth = true)
6309 
6310   @Test
6311   fun `chaining - many dereferences, one multiline lambda in the middle`() =
6312       assertFormatted(
6313           """
6314       |/////////////////////////
6315       |rainbow.red.orange.yellow
6316       |    .green
6317       |    .blue
6318       |    .z {
6319       |      it
6320       |      it
6321       |    }
6322       |    .indigo
6323       |    .violet
6324       |    .cyan
6325       |    .magenta
6326       |    .key
6327       |"""
6328               .trimMargin(),
6329           deduceMaxWidth = true)
6330 
6331   @Test
6332   fun `chaining - many dereferences, one multiline lambda in the middle, remainder could fit on one line`() =
6333       assertFormatted(
6334           """
6335       |/////////////////////////////////////////////////////////////////////////////////////////
6336       |rainbow.red.orange.yellow.green.blue
6337       |    .z {
6338       |      it
6339       |      it
6340       |    }
6341       |    .indigo
6342       |    .violet
6343       |    .cyan
6344       |    .magenta
6345       |    .key
6346       |"""
6347               .trimMargin(),
6348           deduceMaxWidth = true)
6349 
6350   @Test
6351   fun `chaining - many dereferences, one multiline lambda and two invocations in the middle, remainder could fit on one line`() =
6352       assertFormatted(
6353           """
6354       |/////////////////////////////////////////////////////////////////////////////////////////
6355       |rainbow.red.orange.yellow.green.blue
6356       |    .z {
6357       |      it
6358       |      it
6359       |    }
6360       |    .shine()
6361       |    .bright()
6362       |    .indigo
6363       |    .violet
6364       |    .cyan
6365       |    .magenta
6366       |    .key
6367       |"""
6368               .trimMargin(),
6369           deduceMaxWidth = true)
6370 
6371   @Test
6372   fun `chaining - many dereferences, one lambda and invocation at end`() =
6373       assertFormatted(
6374           """
6375       |/////////////////////////
6376       |rainbow.red.orange.yellow
6377       |    .green
6378       |    .blue
6379       |    .indigo
6380       |    .violet
6381       |    .cyan
6382       |    .magenta
6383       |    .key
6384       |    .z { it }
6385       |    .shine()
6386       |"""
6387               .trimMargin(),
6388           deduceMaxWidth = true)
6389 
6390   @Test
6391   fun `chaining - many dereferences, one multiline lambda and invocation at end`() =
6392       assertFormatted(
6393           """
6394       |/////////////////////////
6395       |rainbow.red.orange.yellow
6396       |    .green
6397       |    .blue
6398       |    .indigo
6399       |    .violet
6400       |    .cyan
6401       |    .magenta
6402       |    .key
6403       |    .z {
6404       |      it
6405       |      it
6406       |    }
6407       |    .shine()
6408       |"""
6409               .trimMargin(),
6410           deduceMaxWidth = true)
6411 
6412   @Test
6413   fun `chaining - many dereferences, one invocation and lambda at end`() =
6414       assertFormatted(
6415           """
6416       |/////////////////////////
6417       |rainbow.red.orange.yellow
6418       |    .green
6419       |    .blue
6420       |    .indigo
6421       |    .violet
6422       |    .cyan
6423       |    .magenta
6424       |    .key
6425       |    .shine()
6426       |    .z { it }
6427       |"""
6428               .trimMargin(),
6429           deduceMaxWidth = true)
6430 
6431   @Test
6432   fun `chaining - many dereferences, one short lambda and invocation in the middle`() =
6433       assertFormatted(
6434           """
6435       |/////////////////////////
6436       |rainbow.red.orange.yellow
6437       |    .green
6438       |    .blue
6439       |    .indigo
6440       |    .z { it }
6441       |    .shine()
6442       |    .violet
6443       |    .cyan
6444       |    .magenta
6445       |    .key
6446       |"""
6447               .trimMargin(),
6448           deduceMaxWidth = true)
6449 
6450   @Test
6451   fun `chaining - many dereferences, invocation and one short lambda in the middle`() =
6452       assertFormatted(
6453           """
6454       |/////////////////////////
6455       |rainbow.red.orange.yellow
6456       |    .green
6457       |    .blue
6458       |    .indigo
6459       |    .shine()
6460       |    .z { it }
6461       |    .violet
6462       |    .cyan
6463       |    .magenta
6464       |    .key
6465       |"""
6466               .trimMargin(),
6467           deduceMaxWidth = true)
6468 
6469   @Test
6470   fun `chaining - many dereferences, starting with this`() =
6471       assertFormatted(
6472           """
6473       |/////////////////////////
6474       |this.red.orange.yellow
6475       |    .green
6476       |    .blue
6477       |    .indigo
6478       |    .violet
6479       |    .cyan
6480       |    .magenta
6481       |    .key
6482       |"""
6483               .trimMargin(),
6484           deduceMaxWidth = true)
6485 
6486   @Test
6487   fun `chaining - many dereferences, starting with this, one invocation at end`() =
6488       assertFormatted(
6489           """
6490       |/////////////////////////
6491       |this.red.orange.yellow
6492       |    .green
6493       |    .blue
6494       |    .indigo
6495       |    .violet
6496       |    .cyan
6497       |    .magenta
6498       |    .key
6499       |    .build()
6500       |"""
6501               .trimMargin(),
6502           deduceMaxWidth = true)
6503 
6504   @Test
6505   fun `chaining - many dereferences, starting with super`() =
6506       assertFormatted(
6507           """
6508       |/////////////////////////
6509       |super.red.orange.yellow
6510       |    .green
6511       |    .blue
6512       |    .indigo
6513       |    .violet
6514       |    .cyan
6515       |    .magenta
6516       |    .key
6517       |"""
6518               .trimMargin(),
6519           deduceMaxWidth = true)
6520 
6521   @Test
6522   fun `chaining - many dereferences, starting with super, one invocation at end`() =
6523       assertFormatted(
6524           """
6525       |/////////////////////////
6526       |super.red.orange.yellow
6527       |    .green
6528       |    .blue
6529       |    .indigo
6530       |    .violet
6531       |    .cyan
6532       |    .magenta
6533       |    .key
6534       |    .build()
6535       |"""
6536               .trimMargin(),
6537           deduceMaxWidth = true)
6538 
6539   @Test
6540   fun `chaining - many dereferences, starting with short variable`() =
6541       assertFormatted(
6542           """
6543       |/////////////////////////
6544       |z123.red.orange.yellow
6545       |    .green
6546       |    .blue
6547       |    .indigo
6548       |    .violet
6549       |    .cyan
6550       |    .magenta
6551       |    .key
6552       |"""
6553               .trimMargin(),
6554           deduceMaxWidth = true)
6555 
6556   @Test
6557   fun `chaining - many dereferences, starting with short variable, one invocation at end`() =
6558       assertFormatted(
6559           """
6560       |/////////////////////////
6561       |z123.red.orange.yellow
6562       |    .green
6563       |    .blue
6564       |    .indigo
6565       |    .violet
6566       |    .cyan
6567       |    .magenta
6568       |    .key
6569       |    .build()
6570       |"""
6571               .trimMargin(),
6572           deduceMaxWidth = true)
6573 
6574   @Test
6575   fun `chaining - many dereferences, starting with short variable and lambda, invocation at end`() =
6576       assertFormatted(
6577           """
6578       |/////////////////////////
6579       |z12.z { it }
6580       |    .red
6581       |    .orange
6582       |    .yellow
6583       |    .green
6584       |    .blue
6585       |    .indigo
6586       |    .violet
6587       |    .cyan
6588       |    .magenta
6589       |    .key
6590       |    .shine()
6591       |"""
6592               .trimMargin(),
6593           deduceMaxWidth = true)
6594 
6595   @Test
6596   fun `chaining - many dereferences, starting with this and lambda, invocation at end`() =
6597       assertFormatted(
6598           """
6599       |/////////////////////////
6600       |this.z { it }
6601       |    .red
6602       |    .orange
6603       |    .yellow
6604       |    .green
6605       |    .blue
6606       |    .indigo
6607       |    .violet
6608       |    .cyan
6609       |    .magenta
6610       |    .key
6611       |    .shine()
6612       |"""
6613               .trimMargin(),
6614           deduceMaxWidth = true)
6615 
6616   @Test
6617   fun `chaining - many invocations`() =
6618       assertFormatted(
6619           """
6620       |/////////////////////////
6621       |rainbow.a().b().c()
6622       |"""
6623               .trimMargin(),
6624           deduceMaxWidth = true)
6625 
6626   @Test
6627   fun `chaining - many invocations, with multiline lambda at end`() =
6628       assertFormatted(
6629           """
6630       |/////////////////////////
6631       |rainbow.a().b().c().zz {
6632       |  it
6633       |  it
6634       |}
6635       |"""
6636               .trimMargin(),
6637           deduceMaxWidth = true)
6638 
6639   @Test
6640   fun `chaining - many dereferences, starting type name`() =
6641       assertFormatted(
6642           """
6643       |/////////////////////////
6644       |com.sky.Rainbow.red
6645       |    .orange
6646       |    .yellow
6647       |    .green
6648       |    .blue
6649       |    .indigo
6650       |    .violet
6651       |    .cyan
6652       |    .magenta
6653       |    .key
6654       |"""
6655               .trimMargin(),
6656           deduceMaxWidth = true)
6657 
6658   @Test
6659   fun `chaining - many invocations, starting with short variable, lambda at end`() =
6660       assertFormatted(
6661           """
6662       |/////////////
6663       |z12.shine()
6664       |    .bright()
6665       |    .z { it }
6666       |"""
6667               .trimMargin(),
6668           deduceMaxWidth = true)
6669 
6670   @Test
6671   fun `chaining - start with invocation, lambda at end`() =
6672       assertFormatted(
6673           """
6674       |/////////////////////
6675       |getRainbow(
6676       |        aa, bb, cc)
6677       |    .z { it }
6678       |"""
6679               .trimMargin(),
6680           deduceMaxWidth = true)
6681 
6682   @Test
6683   fun `chaining - many invocations, start with lambda`() =
6684       assertFormatted(
6685           """
6686       |/////////////////////
6687       |z { it }
6688       |    .shine()
6689       |    .bright()
6690       |"""
6691               .trimMargin(),
6692           deduceMaxWidth = true)
6693 
6694   @Test
6695   fun `chaining - start with type name, end with invocation`() =
6696       assertFormatted(
6697           """
6698       |/////////////////////////
6699       |com.sky.Rainbow
6700       |    .colorFactory
6701       |    .build()
6702       |"""
6703               .trimMargin(),
6704           deduceMaxWidth = true)
6705 
6706   @Test
6707   fun `chaining (indentation) - multiline lambda`() =
6708       assertFormatted(
6709           """
6710       |/////////////////////////
6711       |rainbow.z {
6712       |  it
6713       |  it
6714       |}
6715       |"""
6716               .trimMargin(),
6717           deduceMaxWidth = true)
6718 
6719   @Test
6720   fun `chaining (indentation) - multiline lambda with trailing dereferences`() =
6721       assertFormatted(
6722           """
6723       |/////////////////////////
6724       |rainbow
6725       |    .z {
6726       |      it
6727       |      it
6728       |    }
6729       |    .red
6730       |"""
6731               .trimMargin(),
6732           deduceMaxWidth = true)
6733 
6734   @Test
6735   fun `chaining (indentation) - multiline lambda with long name`() =
6736       assertFormatted(
6737           """
6738       |/////////////////////////
6739       |rainbow
6740       |    .someLongLambdaName {
6741       |      it
6742       |      it
6743       |    }
6744       |"""
6745               .trimMargin(),
6746           deduceMaxWidth = true)
6747 
6748   @Test
6749   fun `chaining (indentation) - multiline lambda with long name and trailing dereferences`() =
6750       assertFormatted(
6751           """
6752       |/////////////////////////
6753       |rainbow
6754       |    .someLongLambdaName {
6755       |      it
6756       |      it
6757       |    }
6758       |    .red
6759       |"""
6760               .trimMargin(),
6761           deduceMaxWidth = true)
6762 
6763   @Test
6764   fun `chaining (indentation) - multiline lambda with prefix`() =
6765       assertFormatted(
6766           """
6767       |/////////////////////////
6768       |rainbow.red.z {
6769       |  it
6770       |  it
6771       |}
6772       |"""
6773               .trimMargin(),
6774           deduceMaxWidth = true)
6775 
6776   @Test
6777   fun `chaining (indentation) - multiline lambda with prefix, forced to next line`() =
6778       assertFormatted(
6779           """
6780       |/////////////////////////
6781       |rainbow.red.orange.yellow
6782       |    .longLambdaName {
6783       |      it
6784       |      it
6785       |    }
6786       |"""
6787               .trimMargin(),
6788           deduceMaxWidth = true)
6789 
6790   @Test
6791   fun `chaining (indentation) - multiline lambda with prefix, forced to next line with another expression`() =
6792       assertFormatted(
6793           """
6794       |/////////////////////////
6795       |rainbow.red.orange.yellow
6796       |    .key
6797       |    .longLambdaName {
6798       |      it
6799       |      it
6800       |    }
6801       |"""
6802               .trimMargin(),
6803           deduceMaxWidth = true)
6804 
6805   @Test
6806   fun `chaining (indentation) - multiline arguments`() =
6807       assertFormatted(
6808           """
6809       |/////////////////////////
6810       |rainbow.shine(
6811       |    infrared,
6812       |    ultraviolet,
6813       |)
6814       |"""
6815               .trimMargin(),
6816           deduceMaxWidth = true)
6817 
6818   @Test
6819   fun `chaining (indentation) - multiline arguments with trailing dereferences`() =
6820       assertFormatted(
6821           """
6822       |/////////////////////////
6823       |rainbow
6824       |    .shine(
6825       |        infrared,
6826       |        ultraviolet,
6827       |    )
6828       |    .red
6829       |"""
6830               .trimMargin(),
6831           deduceMaxWidth = true)
6832 
6833   @Test
6834   fun `chaining (indentation) - multiline arguments, forced to next line`() =
6835       assertFormatted(
6836           """
6837       |/////////////////////////
6838       |rainbow.red.orange.yellow
6839       |    .shine(
6840       |        infrared,
6841       |        ultraviolet,
6842       |    )
6843       |"""
6844               .trimMargin(),
6845           deduceMaxWidth = true)
6846 
6847   @Test
6848   fun `chaining (indentation) - multiline arguments, forced to next line with another expression`() =
6849       assertFormatted(
6850           """
6851       |/////////////////////////
6852       |rainbow.red.orange.yellow
6853       |    .key
6854       |    .shine(
6855       |        infrared,
6856       |        ultraviolet,
6857       |    )
6858       |"""
6859               .trimMargin(),
6860           deduceMaxWidth = true)
6861 
6862   @Test
6863   fun `chaining (indentation) - multiline arguments, forced to next line with another expression, with trailing dereferences`() =
6864       assertFormatted(
6865           """
6866       |/////////////////////////
6867       |rainbow.red.orange.yellow
6868       |    .key
6869       |    .shine(
6870       |        infrared,
6871       |        ultraviolet,
6872       |    )
6873       |    .red
6874       |"""
6875               .trimMargin(),
6876           deduceMaxWidth = true)
6877 
6878   @Test
6879   fun `chaining (indentation) - multiline arguments, with trailing invocation`() =
6880       assertFormatted(
6881           """
6882       |/////////////////////////
6883       |rainbow
6884       |    .shine(
6885       |        infrared,
6886       |        ultraviolet,
6887       |    )
6888       |    .bright()
6889       |"""
6890               .trimMargin(),
6891           deduceMaxWidth = true)
6892 
6893   @Test
6894   fun `chaining (indentation) - multiline arguments, with trailing lambda`() =
6895       assertFormatted(
6896           """
6897       |/////////////////////////
6898       |rainbow
6899       |    .shine(
6900       |        infrared,
6901       |        ultraviolet,
6902       |    )
6903       |    .z { it }
6904       |"""
6905               .trimMargin(),
6906           deduceMaxWidth = true)
6907 
6908   @Test
6909   fun `chaining (indentation) - multiline arguments, prefixed with super, with trailing invocation`() =
6910       assertFormatted(
6911           """
6912       |/////////////////////////
6913       |super.shine(
6914       |        infrared,
6915       |        ultraviolet,
6916       |    )
6917       |    .bright()
6918       |"""
6919               .trimMargin(),
6920           deduceMaxWidth = true)
6921 
6922   @Test
6923   fun `chaining (indentation) - multiline arguments, starting with short variable, with trailing invocation`() =
6924       assertFormatted(
6925           """
6926       |/////////////////////////
6927       |z12.shine(
6928       |        infrared,
6929       |        ultraviolet,
6930       |    )
6931       |    .bright()
6932       |"""
6933               .trimMargin(),
6934           deduceMaxWidth = true)
6935 
6936   @Test
6937   fun `chaining (indentation) - start with multiline arguments`() =
6938       assertFormatted(
6939           """
6940       |/////////////////////////
6941       |getRainbow(
6942       |    infrared,
6943       |    ultraviolet,
6944       |)
6945       |"""
6946               .trimMargin(),
6947           deduceMaxWidth = true)
6948 
6949   @Test
6950   fun `chaining (indentation) - start with multiline arguments, with trailing invocation`() =
6951       assertFormatted(
6952           """
6953       |/////////////////////////
6954       |getRainbow(
6955       |        infrared,
6956       |        ultraviolet,
6957       |    )
6958       |    .z { it }
6959       |"""
6960               .trimMargin(),
6961           deduceMaxWidth = true)
6962 
6963   @Test
6964   fun `annotations for expressions`() =
6965       assertFormatted(
6966           """
6967       |fun f() {
6968       |  var b
6969       |  @Suppress("UNCHECKED_CAST") b = f(1) as Int
6970       |  @Suppress("UNCHECKED_CAST")
6971       |  b = f(1) as Int
6972       |
6973       |  @Suppress("UNCHECKED_CAST") b = f(1) to 5
6974       |  @Suppress("UNCHECKED_CAST")
6975       |  b = f(1) to 5
6976       |
6977       |  @Suppress("UNCHECKED_CAST") f(1) as Int + 5
6978       |  @Suppress("UNCHECKED_CAST")
6979       |  f(1) as Int + 5
6980       |
6981       |  @Anno1 /* comment */ @Anno2 f(1) as Int
6982       |}
6983       |"""
6984               .trimMargin())
6985 
6986   @Test
6987   fun `annotations for expressions 2`() {
6988     val code =
6989         """
6990       |fun f() {
6991       |  @Suppress("UNCHECKED_CAST") f(1 + f(1) as Int)
6992       |  @Suppress("UNCHECKED_CAST")
6993       |  f(1 + f(1) as Int)
6994       |}
6995       |"""
6996             .trimMargin()
6997 
6998     val expected =
6999         """
7000       |fun f() {
7001       |  @Suppress("UNCHECKED_CAST") f(1 + f(1) as Int)
7002       |  @Suppress("UNCHECKED_CAST") f(1 + f(1) as Int)
7003       |}
7004       |"""
7005             .trimMargin()
7006 
7007     assertThatFormatting(code).isEqualTo(expected)
7008   }
7009 
7010   @Test
7011   fun `function call following long multiline string`() =
7012       assertFormatted(
7013           """
7014       |////////////////////////////////
7015       |fun stringFitsButNotMethod() {
7016       |  val str1 =
7017       |      $TQ Some string $TQ
7018       |          .trimIndent()
7019       |
7020       |  val str2 =
7021       |      $TQ Some string $TQ
7022       |          .trimIndent(someArg)
7023       |}
7024       |
7025       |fun stringTooLong() {
7026       |  val str1 =
7027       |      $TQ
7028       |      Some very long string that might mess things up
7029       |      $TQ
7030       |          .trimIndent()
7031       |
7032       |  val str2 =
7033       |      $TQ
7034       |      Some very long string that might mess things up
7035       |      $TQ
7036       |          .trimIndent(someArg)
7037       |}
7038       |"""
7039               .trimMargin(),
7040           deduceMaxWidth = true)
7041 
7042   @Test
7043   fun `array-literal in annotation`() =
7044       assertFormatted(
7045           """
7046       |////////////////////////////////
7047       |@Anno(
7048       |    array =
7049       |        [
7050       |            someItem,
7051       |            andAnother,
7052       |            noTrailingComma])
7053       |class Host
7054       |
7055       |@Anno(
7056       |    array =
7057       |        [
7058       |            someItem,
7059       |            andAnother,
7060       |            withTrailingComma,
7061       |        ])
7062       |class Host
7063       |
7064       |@Anno(
7065       |    array =
7066       |        [
7067       |            // Comment
7068       |            someItem,
7069       |            // Comment
7070       |            andAnother,
7071       |            // Comment
7072       |            withTrailingComment
7073       |            // Comment
7074       |            // Comment
7075       |            ])
7076       |class Host
7077       |"""
7078               .trimMargin(),
7079           deduceMaxWidth = true)
7080 
7081   @Test
7082   fun `force blank line between class members`() {
7083     val code =
7084         """
7085       |class Foo {
7086       |  val x = 0
7087       |  fun foo() {}
7088       |  class Bar {}
7089       |  enum class Enum {
7090       |    A {
7091       |      val x = 0
7092       |      fun foo() {}
7093       |    };
7094       |    abstract fun foo(): Unit
7095       |  }
7096       |}
7097       |"""
7098             .trimMargin()
7099 
7100     val expected =
7101         """
7102       |class Foo {
7103       |  val x = 0
7104       |
7105       |  fun foo() {}
7106       |
7107       |  class Bar {}
7108       |
7109       |  enum class Enum {
7110       |    A {
7111       |      val x = 0
7112       |
7113       |      fun foo() {}
7114       |    };
7115       |
7116       |    abstract fun foo(): Unit
7117       |  }
7118       |}
7119       |"""
7120             .trimMargin()
7121 
7122     assertThatFormatting(code).isEqualTo(expected)
7123   }
7124 
7125   @Test
7126   fun `preserve blank line between class members between properties`() {
7127     val code =
7128         """
7129       |class Foo {
7130       |  val x = 0
7131       |  val x = 0
7132       |
7133       |  val x = 0
7134       |}
7135       |"""
7136             .trimMargin()
7137 
7138     assertThatFormatting(code).isEqualTo(code)
7139   }
7140 
7141   @Test
7142   fun `force blank line between class members preserved between properties with accessors`() {
7143     val code =
7144         """
7145       |class Foo {
7146       |  val _x = 0
7147       |  val x = 0
7148       |    private get
7149       |  val y = 0
7150       |}
7151       |
7152       |class Foo {
7153       |  val _x = 0
7154       |  val x = 0
7155       |    private set
7156       |  val y = 0
7157       |}
7158       |"""
7159             .trimMargin()
7160 
7161     val expected =
7162         """
7163       |class Foo {
7164       |  val _x = 0
7165       |  val x = 0
7166       |    private get
7167       |
7168       |  val y = 0
7169       |}
7170       |
7171       |class Foo {
7172       |  val _x = 0
7173       |  val x = 0
7174       |    private set
7175       |
7176       |  val y = 0
7177       |}
7178       |"""
7179             .trimMargin()
7180 
7181     assertThatFormatting(code).isEqualTo(expected)
7182   }
7183 
7184   @Test
7185   fun `context receivers`() {
7186     val code =
7187         """
7188       |context(Something)
7189       |
7190       |class A {
7191       |  context(
7192       |  // Test comment.
7193       |  Logger, Raise<Error>)
7194       |
7195       |  @SomeAnnotation
7196       |
7197       |  fun doNothing() {}
7198       |
7199       |  context(SomethingElse)
7200       |
7201       |  private class NestedClass {}
7202       |
7203       |  fun <T> testSuspend(
7204       |    mock: T,
7205       |    block: suspend context(SomeContext) T.() -> Unit,
7206       |  ) = startCoroutine {
7207       |    T.block()
7208       |  }
7209       |}
7210       |"""
7211             .trimMargin()
7212 
7213     val expected =
7214         """
7215       |context(Something)
7216       |class A {
7217       |  context(
7218       |  // Test comment.
7219       |  Logger,
7220       |  Raise<Error>)
7221       |  @SomeAnnotation
7222       |  fun doNothing() {}
7223       |
7224       |  context(SomethingElse)
7225       |  private class NestedClass {}
7226       |
7227       |  fun <T> testSuspend(
7228       |      mock: T,
7229       |      block:
7230       |          suspend context(SomeContext)
7231       |          T.() -> Unit,
7232       |  ) = startCoroutine { T.block() }
7233       |}
7234       |"""
7235             .trimMargin()
7236 
7237     assertThatFormatting(code).isEqualTo(expected)
7238   }
7239 
7240   @Test
7241   fun `trailing comment after function in class`() =
7242       assertFormatted(
7243           """
7244       |class Host {
7245       |  fun fooBlock() {
7246       |    return
7247       |  } // Trailing after fn
7248       |  // Hanging after fn
7249       |
7250       |  // End of class
7251       |}
7252       |
7253       |class Host {
7254       |  fun fooExpr() = 0 // Trailing after fn
7255       |  // Hanging after fn
7256       |
7257       |  // End of class
7258       |}
7259       |
7260       |class Host {
7261       |  constructor() {} // Trailing after fn
7262       |  // Hanging after fn
7263       |
7264       |  // End of class
7265       |}
7266       |
7267       |class Host
7268       |// Primary constructor
7269       |constructor() // Trailing after fn
7270       |  // Hanging after fn
7271       |{
7272       |  // End of class
7273       |}
7274       |
7275       |class Host {
7276       |  fun fooBlock() {
7277       |    return
7278       |  }
7279       |
7280       |  // Between elements
7281       |
7282       |  fun fooExpr() = 0
7283       |
7284       |  // Between elements
7285       |
7286       |  fun fooBlock() {
7287       |    return
7288       |  }
7289       |}
7290       |"""
7291               .trimMargin())
7292 
7293   @Test
7294   fun `trailing comment after function top-level`() {
7295     assertFormatted(
7296         """
7297       |fun fooBlock() {
7298       |  return
7299       |} // Trailing after fn
7300       |// Hanging after fn
7301       |
7302       |// End of file
7303       |"""
7304             .trimMargin())
7305 
7306     assertFormatted(
7307         """
7308       |fun fooExpr() = 0 // Trailing after fn
7309       |// Hanging after fn
7310       |
7311       |// End of file
7312       |"""
7313             .trimMargin())
7314 
7315     assertFormatted(
7316         """
7317       |fun fooBlock() {
7318       |  return
7319       |}
7320       |
7321       |// Between elements
7322       |
7323       |fun fooExpr() = 0
7324       |
7325       |// Between elements
7326       |
7327       |fun fooBlock() {
7328       |  return
7329       |}
7330       |"""
7331             .trimMargin())
7332   }
7333 
7334   @Test
7335   fun `line break on base class`() =
7336       assertFormatted(
7337           """
7338       |///////////////////////////
7339       |class Basket<T>() :
7340       |    WovenObject {
7341       |  // some body
7342       |}
7343       |"""
7344               .trimMargin(),
7345           deduceMaxWidth = true)
7346 
7347   @Test
7348   fun `line break on type specifier`() =
7349       assertFormatted(
7350           """
7351       |///////////////////////////
7352       |class Basket<T>() where
7353       |T : Fruit {
7354       |  // some body
7355       |}
7356       |"""
7357               .trimMargin(),
7358           deduceMaxWidth = true)
7359 
7360   @Test
7361   fun `don't crash on empty enum with semicolons`() {
7362     assertFormatted(
7363         """
7364       |///////////////////////////
7365       |enum class Foo {
7366       |  ;
7367       |
7368       |  fun foo(): Unit
7369       |}
7370       |"""
7371             .trimMargin(),
7372         deduceMaxWidth = true)
7373 
7374     assertFormatted(
7375         """
7376       |///////////////////////////
7377       |enum class Foo {
7378       |  ;
7379       |
7380       |  companion object Bar
7381       |}
7382       |"""
7383             .trimMargin(),
7384         deduceMaxWidth = true)
7385 
7386     assertThatFormatting(
7387             """
7388       |enum class Foo {
7389       |  ;
7390       |  ;
7391       |  ;
7392       |
7393       |  fun foo(): Unit
7394       |}
7395       |"""
7396                 .trimMargin())
7397         .isEqualTo(
7398             """
7399       |enum class Foo {
7400       |  ;
7401       |
7402       |  fun foo(): Unit
7403       |}
7404       |"""
7405                 .trimMargin())
7406   }
7407 
7408   companion object {
7409     /** Triple quotes, useful to use within triple-quoted strings. */
7410     private const val TQ = "\"\"\""
7411   }
7412 }
7413