• 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       |  fun method() {}
268       |  class Bar
269       |}
270       |"""
271               .trimMargin())
272 
273   @Test
274   fun `properties and fields with modifiers`() =
275       assertFormatted(
276           """
277       |class Foo(public val p1: Int, private val p2: Int, open val p3: Int, final val p4: Int) {
278       |  private var f1 = 0
279       |  public var f2 = 0
280       |  open var f3 = 0
281       |  final var f4 = 0
282       |}
283       |"""
284               .trimMargin())
285 
286   @Test
287   fun `properties with multiple modifiers`() =
288       assertFormatted(
289           """
290       |class Foo(public open inner val p1: Int) {
291       |  public open inner var f2 = 0
292       |}
293       |"""
294               .trimMargin())
295 
296   @Test
297   fun `spaces around binary operations`() =
298       assertFormatted(
299           """
300       |fun foo() {
301       |  a = 5
302       |  x + 1
303       |}
304       |"""
305               .trimMargin())
306 
307   @Test
308   fun `breaking long binary operations`() =
309       assertFormatted(
310           """
311       |--------------------
312       |fun foo() {
313       |  val finalWidth =
314       |      value1 +
315       |          value2 +
316       |          (value3 +
317       |              value4 +
318       |              value5) +
319       |          foo(v) +
320       |          (1 + 2) +
321       |          function(
322       |              value7,
323       |              value8) +
324       |          value9
325       |}
326       |"""
327               .trimMargin(),
328           deduceMaxWidth = true)
329 
330   @Test
331   fun `prioritize according to associativity`() =
332       assertFormatted(
333           """
334       |--------------------------------------
335       |fun foo() {
336       |  return expression1 != expression2 ||
337       |      expression2 != expression1
338       |}
339       |"""
340               .trimMargin(),
341           deduceMaxWidth = true)
342 
343   @Test
344   fun `once a binary expression is broken, split on every line`() =
345       assertFormatted(
346           """
347         |--------------------------------------
348         |fun foo() {
349         |  val sentence =
350         |      "The" +
351         |          "quick" +
352         |          ("brown" + "fox") +
353         |          "jumps" +
354         |          "over" +
355         |          "the" +
356         |          "lazy" +
357         |          "dog"
358         |}
359         |"""
360               .trimMargin(),
361           deduceMaxWidth = true)
362 
363   @Test
364   fun `long binary expressions with ranges in the middle`() =
365       assertFormatted(
366           """
367         |--------------------------------------
368         |fun foo() {
369         |  val sentence =
370         |      "The" +
371         |          "quick" +
372         |          ("brown".."fox") +
373         |          "jumps" +
374         |          "over" +
375         |          "the".."lazy" + "dog"
376         |}
377         |"""
378               .trimMargin(),
379           deduceMaxWidth = true)
380 
381   @Test
382   fun `assignment expressions with scoping functions are block-like`() =
383       assertFormatted(
384           """
385         |---------------------------
386         |fun f() {
387         |  name.sub = scope { x ->
388         |    //
389         |  }
390         |  name.sub += scope { x ->
391         |    //
392         |  }
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         |}
406         |
407         |fun h() {
408         |  long.name.sub =
409         |      scope { x ->
410         |        //
411         |      }
412         |  long.name.sub +=
413         |      scope { x ->
414         |        //
415         |      }
416         |  long.name.sub -=
417         |      scope { x ->
418         |        //
419         |      }
420         |  long.name.sub *=
421         |      scope { x ->
422         |        //
423         |      }
424         |  long.name.sub /=
425         |      scope { x ->
426         |        //
427         |      }
428         |  long.name.sub %=
429         |      scope { x ->
430         |        //
431         |      }
432         |}
433         |"""
434               .trimMargin(),
435           deduceMaxWidth = true)
436 
437   @Test
438   fun `don't keep adding newlines between these two comments when they're at end of file`() =
439       assertFormatted(
440           """
441      |package foo
442      |// a
443      |
444      |/* Another comment */
445      |"""
446               .trimMargin())
447 
448   @Test
449   fun `properties with line comment above initializer`() =
450       assertFormatted(
451           """
452       |class Foo {
453       |  var x: Int =
454       |      // Comment
455       |      0
456       |
457       |  var y: Int =
458       |      // Comment
459       |      scope {
460       |        0 //
461       |      }
462       |
463       |  var z: Int =
464       |      // Comment
465       |      if (cond) {
466       |        0
467       |      } else {
468       |        1
469       |      }
470       |}
471       |"""
472               .trimMargin())
473 
474   @Test
475   fun `properties with line comment above delegate`() =
476       assertFormatted(
477           """
478       |class Foo {
479       |  var x: Int by
480       |      // Comment
481       |      0
482       |
483       |  var y: Int by
484       |      // Comment
485       |      scope {
486       |        0 //
487       |      }
488       |
489       |  var z: Int by
490       |      // Comment
491       |      if (cond) {
492       |        0
493       |      } else {
494       |        1
495       |      }
496       |}
497       |"""
498               .trimMargin())
499 
500   @Test
501   fun `properties with accessors`() =
502       assertFormatted(
503           """
504       |class Foo {
505       |  var x: Int
506       |    get() = field
507       |  var y: Boolean
508       |    get() = x.equals(123)
509       |    set(value) {
510       |      field = value
511       |    }
512       |  var z: Boolean
513       |    get() {
514       |      x.equals(123)
515       |    }
516       |  var zz = false
517       |    private set
518       |}
519       |"""
520               .trimMargin())
521 
522   @Test
523   fun `properties with accessors and semicolons on same line`() {
524     val code =
525         """
526       |class Foo {
527       |  var x = false; private set
528       |  internal val a by lazy { 5 }; internal get
529       |  var foo: Int; get() = 6; set(x) {};
530       |}
531       |"""
532             .trimMargin()
533 
534     val expected =
535         """
536       |class Foo {
537       |  var x = false
538       |    private set
539       |  internal val a by lazy { 5 }
540       |    internal get
541       |  var foo: Int
542       |    get() = 6
543       |    set(x) {}
544       |}
545       |"""
546             .trimMargin()
547 
548     assertThatFormatting(code).isEqualTo(expected)
549   }
550 
551   @Test
a property with a too long name being broken on multiple linesnull552   fun `a property with a too long name being broken on multiple lines`() =
553       assertFormatted(
554           """
555       |--------------------
556       |class Foo {
557       |  val thisIsALongName:
558       |      String =
559       |      "Hello there this is long"
560       |    get() = field
561       |}
562       |"""
563               .trimMargin(),
564           deduceMaxWidth = true)
565 
566   @Test
567   fun `multi-character unary and binary operators such as ==`() =
568       assertFormatted(
569           """
570       |fun f() {
571       |  3 == 4
572       |  true && false
573       |  a++
574       |  a === b
575       |}
576       |"""
577               .trimMargin())
578 
579   @Test
580   fun `package names stay in one line`() {
581     val code =
582         """
583       | package  com  .example. subexample
584       |
585       |fun f() = 1
586       |"""
587             .trimMargin()
588     val expected =
589         """
590       |package com.example.subexample
591       |
592       |fun f() = 1
593       |"""
594             .trimMargin()
595 
596     assertThatFormatting(code).isEqualTo(expected)
597   }
598 
599   @Test
handle package name and imports with escapes and spacesnull600   fun `handle package name and imports with escapes and spaces`() =
601       assertFormatted(
602           """
603       |package com.`fun times`.`with package names`
604       |
605       |import `nothing stops`.`us`.`from doing this`
606       |
607       |fun f() = `from doing this`()
608       |"""
609               .trimMargin())
610 
611   @Test
612   fun `safe dot operator expression`() =
613       assertFormatted(
614           """
615       |fun f() {
616       |  node?.name
617       |}
618       |"""
619               .trimMargin())
620 
621   @Test
622   fun `safe dot operator expression with normal`() =
623       assertFormatted(
624           """
625       |fun f() {
626       |  node?.name.hello
627       |}
628       |"""
629               .trimMargin())
630 
631   @Test
632   fun `safe dot operator expression chain in expression function`() =
633       assertFormatted(
634           """
635       |--------------------------------------------------
636       |fun f(number: Int) =
637       |    Something.doStuff(number)?.size
638       |"""
639               .trimMargin(),
640           deduceMaxWidth = true)
641 
642   @Test
643   fun `avoid breaking suspected package names`() =
644       assertFormatted(
645           """
646       |-----------------------
647       |fun f() {
648       |  com.facebook.Foo
649       |      .format()
650       |  org.facebook.Foo
651       |      .format()
652       |  java.lang.stuff.Foo
653       |      .format()
654       |  javax.lang.stuff.Foo
655       |      .format()
656       |  kotlin.lang.Foo
657       |      .format()
658       |  foo.facebook.Foo
659       |      .format()
660       |}
661       |"""
662               .trimMargin(),
663           deduceMaxWidth = true)
664 
665   @Test
666   fun `an assortment of tests for emitQualifiedExpression`() =
667       assertFormatted(
668           """
669       |-------------------------------------
670       |fun f() {
671       |  // Regression test: https://github.com/facebookincubator/ktfmt/issues/56
672       |  kjsdfglkjdfgkjdfkgjhkerjghkdfj
673       |      ?.methodName1()
674       |
675       |  // a series of field accesses followed by a single call expression
676       |  // is kept together.
677       |  abcdefghijkl.abcdefghijkl
678       |      ?.methodName2()
679       |
680       |  // Similar to above.
681       |  abcdefghijkl.abcdefghijkl
682       |      ?.methodName3
683       |      ?.abcdefghijkl()
684       |
685       |  // Multiple call expressions cause each part of the expression
686       |  // to be placed on its own line.
687       |  abcdefghijkl
688       |      ?.abcdefghijkl
689       |      ?.methodName4()
690       |      ?.abcdefghijkl()
691       |
692       |  // Don't break first call expression if it fits.
693       |  foIt(something.something.happens())
694       |      .thenReturn(result)
695       |
696       |  // Break after `longerThanFour(` because it's longer than 4 chars
697       |  longerThanFour(
698       |          something.something
699       |              .happens())
700       |      .thenReturn(result)
701       |
702       |  // Similarly to above, when part of qualified expression.
703       |  foo.longerThanFour(
704       |          something.something
705       |              .happens())
706       |      .thenReturn(result)
707       |
708       |  // Keep 'super' attached to the method name
709       |  super.abcdefghijkl
710       |      .methodName4()
711       |      .abcdefghijkl()
712       |}
713       |"""
714               .trimMargin(),
715           deduceMaxWidth = true)
716 
717   @Test
718   fun `an assortment of tests for emitQualifiedExpression with lambdas`() =
719       assertFormatted(
720           """
721       |----------------------------------------------------------------------------
722       |fun f() {
723       |  val items =
724       |      items.toMutableList.apply {
725       |        //
726       |        foo
727       |      }
728       |
729       |  val items =
730       |      items.toMutableList().apply {
731       |        //
732       |        foo
733       |      }
734       |
735       |  // All dereferences are on one line (because they fit), even though
736       |  // the apply() at the end requires a line break.
737       |  val items =
738       |      items.toMutableList.sdfkjsdf.sdfjksdflk.sdlfkjsldfj.apply {
739       |        //
740       |        foo
741       |      }
742       |
743       |  // All method calls are on one line (because they fit), even though
744       |  // the apply() at the end requires a line break.
745       |  val items =
746       |      items.toMutableList().sdfkjsdf().sdfjksdflk().sdlfkjsldfj().apply {
747       |        //
748       |        foo
749       |      }
750       |
751       |  // All method calls with lambdas could fit, but we avoid a block like syntax
752       |  // and break to one call per line
753       |  val items =
754       |      items
755       |          .map { it + 1 }
756       |          .filter { it > 0 }
757       |          .apply {
758       |            //
759       |            foo
760       |          }
761       |
762       |  // the lambda is indented properly with the break before it
763       |  val items =
764       |      items.fieldName.sdfkjsdf.sdfjksdflk.sdlfkjsldfj.sdfjksdflk.sdlfkjsldfj
765       |          .sdlfkjsldfj
766       |          .apply {
767       |            //
768       |            foo
769       |          }
770       |  items.fieldName.sdfkjsdf.sdfjksdflk.sdlfkjsldfj.sdfjksdflk.sdlfkjsldfj
771       |      .apply {
772       |        //
773       |        foo
774       |      }
775       |
776       |  // When there are multiple method calls, and they don't fit on one
777       |  // line, put each on a new line.
778       |  val items =
779       |      items
780       |          .toMutableList()
781       |          .sdfkjsdf()
782       |          .sdfjksdflk()
783       |          .sdlfkjsldfj()
784       |          .sdfjksdflk()
785       |          .sdlfkjsldfj()
786       |          .apply {
787       |            //
788       |            foo
789       |          }
790       |}
791       |"""
792               .trimMargin(),
793           deduceMaxWidth = true)
794 
795   @Test
796   fun `when two lambdas are in a chain, avoid block syntax`() =
797       assertFormatted(
798           """
799       |class Foo : Bar() {
800       |  fun doIt() {
801       |    fruit.onlyBananas().forEach { banana ->
802       |      val seeds = banana.find { it.type == SEED }
803       |      println(seeds)
804       |    }
805       |
806       |    fruit
807       |        .filter { isBanana(it, Bananas.types) }
808       |        .forEach { banana ->
809       |          val seeds = banana.find { it.type == SEED }
810       |          println(seeds)
811       |        }
812       |  }
813       |}
814       |"""
815               .trimMargin())
816 
817   @Test
818   fun `don't one-line lambdas following argument breaks`() =
819       assertFormatted(
820           """
821       |------------------------------------------------------------------------
822       |class Foo : Bar() {
823       |  fun doIt() {
824       |    // don't break in lambda, no argument breaks found
825       |    fruit.forEach { eat(it) }
826       |
827       |    // break in the lambda, without comma
828       |    fruit.forEach(
829       |        someVeryLongParameterNameThatWillCauseABreak,
830       |        evenWithoutATrailingCommaOnTheParameterListSoLetsSeeIt) {
831       |          eat(it)
832       |        }
833       |
834       |    // break in the lambda, with comma
835       |    fruit.forEach(
836       |        fromTheVine = true,
837       |    ) {
838       |      eat(it)
839       |    }
840       |
841       |    // don't break in the inner lambda, as nesting doesn't respect outer levels
842       |    fruit.forEach(
843       |        fromTheVine = true,
844       |    ) {
845       |      fruit.forEach { eat(it) }
846       |    }
847       |
848       |    // don't break in the lambda, as breaks don't propagate
849       |    fruit
850       |        .onlyBananas(
851       |            fromTheVine = true,
852       |        )
853       |        .forEach { eat(it) }
854       |
855       |    // don't break in the inner lambda, as breaks don't propagate to parameters
856       |    fruit.onlyBananas(
857       |        fromTheVine = true,
858       |        processThem = { eat(it) },
859       |    ) {
860       |      eat(it)
861       |    }
862       |
863       |    // don't break in the inner lambda, as breaks don't propagate to the body
864       |    fruit.onlyBananas(
865       |        fromTheVine = true,
866       |    ) {
867       |      val anon = { eat(it) }
868       |    }
869       |  }
870       |}
871       |"""
872               .trimMargin(),
873           deduceMaxWidth = true)
874 
875   @Test
indent parameters after a break when there's a lambda afterwardsnull876   fun `indent parameters after a break when there's a lambda afterwards`() =
877       assertFormatted(
878           """
879       |---------------------------
880       |class C {
881       |  fun method() {
882       |    Foo.FooBar(
883       |            param1, param2)
884       |        .apply {
885       |          //
886       |          foo
887       |        }
888       |  }
889       |}
890       |"""
891               .trimMargin(),
892           deduceMaxWidth = true)
893 
894   @Test
no forward propagation of breaks in call expressions (at trailing lambda)null895   fun `no forward propagation of breaks in call expressions (at trailing lambda)`() =
896       assertFormatted(
897           """
898       |--------------------------
899       |fun test() {
900       |  foo_bar_baz__zip<A>(b) {
901       |    c
902       |  }
903       |  foo.bar(baz).zip<A>(b) {
904       |    c
905       |  }
906       |}
907       |"""
908               .trimMargin(),
909           deduceMaxWidth = true)
910 
911   @Test
forward propagation of breaks in call expressions (at value args)null912   fun `forward propagation of breaks in call expressions (at value args)`() =
913       assertFormatted(
914           """
915       |----------------------
916       |fun test() {
917       |  foo_bar_baz__zip<A>(
918       |      b) {
919       |        c
920       |      }
921       |}
922       |
923       |fun test() {
924       |  foo.bar(baz).zip<A>(
925       |      b) {
926       |        c
927       |      }
928       |}
929       |"""
930               .trimMargin(),
931           deduceMaxWidth = true)
932 
933   @Test
forward propagation of breaks in call expressions (at type args)null934   fun `forward propagation of breaks in call expressions (at type args)`() =
935       assertFormatted(
936           """
937       |-------------------
938       |fun test() {
939       |  foo_bar_baz__zip<
940       |      A>(
941       |      b) {
942       |        c
943       |      }
944       |  foo.bar(baz).zip<
945       |      A>(
946       |      b) {
947       |        c
948       |      }
949       |}
950       |"""
951               .trimMargin(),
952           deduceMaxWidth = true)
953 
954   @Test
expected indent in methods following single-line stringsnull955   fun `expected indent in methods following single-line strings`() =
956       assertFormatted(
957           """
958       |-------------------------
959       |"Hello %s".format(
960       |    someLongExpression)
961       |"""
962               .trimMargin(),
963           deduceMaxWidth = true)
964 
965   @Test
966   fun `forced break between multi-line strings and their selectors`() =
967       assertFormatted(
968           """
969       |-------------------------
970       |val STRING =
971       |    $TQ
972       |    |foo
973       |    |$TQ
974       |        .wouldFit()
975       |
976       |val STRING =
977       |    $TQ
978       |    |foo
979       |    |----------------------------------$TQ
980       |        .wouldntFit()
981       |
982       |val STRING =
983       |    $TQ
984       |    |foo
985       |    |$TQ
986       |        .firstLink()
987       |        .secondLink()
988       |"""
989               .trimMargin(),
990           deduceMaxWidth = true)
991 
992   @Test
993   fun `import list`() {
994     val code =
995         """
996       | import  com .example.common.reality. FooBar
997       |  import  com .example.common.reality. FooBar2  as  foosBars
998       |   import com .example.common.reality. *
999       | import  foo.bar // Test
1000       |  import  abc.def /*
1001       |                  test */
1002       |
1003       |val x = FooBar.def { foosBars(bar) }
1004       |"""
1005             .trimMargin()
1006     val expected =
1007         """
1008       |import abc.def /*
1009       |               test */
1010       |import com.example.common.reality.*
1011       |import com.example.common.reality.FooBar
1012       |import com.example.common.reality.FooBar2 as foosBars
1013       |import foo.bar // Test
1014       |
1015       |val x = FooBar.def { foosBars(bar) }
1016       |"""
1017             .trimMargin()
1018     assertThatFormatting(code).isEqualTo(expected)
1019   }
1020 
1021   @Test
imports with trailing comments and expressionsnull1022   fun `imports with trailing comments and expressions`() {
1023     val code =
1024         """
1025         |import com.example.zab // test
1026         |import com.example.foo ; val x = Sample(foo, zab)
1027         |"""
1028             .trimMargin()
1029 
1030     val expected =
1031         """
1032         |import com.example.foo
1033         |import com.example.zab // test
1034         |
1035         |val x = Sample(foo, zab)
1036         |"""
1037             .trimMargin()
1038 
1039     assertThatFormatting(code).isEqualTo(expected)
1040   }
1041 
1042   @Test
backticks are ignored in import sort ordernull1043   fun `backticks are ignored in import sort order`() =
1044       assertFormatted(
1045           """
1046       |import com.example.`if`
1047       |import com.example.we
1048       |import com.example.`when`
1049       |import com.example.wow
1050       |
1051       |val x = `if` { we.`when`(wow) }
1052       |"""
1053               .trimMargin())
1054 
1055   @Test
backticks are ignored in import sort order ('as' directory)null1056   fun `backticks are ignored in import sort order ('as' directory)`() =
1057       assertFormatted(
1058           """
1059       |import com.example.a as `if`
1060       |import com.example.a as we
1061       |import com.example.a as `when`
1062       |import com.example.a as wow
1063       |
1064       |val x = `if` { we.`when`(wow) }
1065       |"""
1066               .trimMargin())
1067 
1068   @Test
imports are deduplicatednull1069   fun `imports are deduplicated`() {
1070     val code =
1071         """
1072       |import com.example.b.*
1073       |import com.example.b
1074       |import com.example.a as `if`
1075       |import com.example.a as we
1076       |import com.example.a as `when`
1077       |import com.example.a as wow
1078       |import com.example.a as `when`
1079       |
1080       |val x = `if` { we.`when`(wow) } ?: b
1081       |"""
1082             .trimMargin()
1083     val expected =
1084         """
1085       |import com.example.a as `if`
1086       |import com.example.a as we
1087       |import com.example.a as `when`
1088       |import com.example.a as wow
1089       |import com.example.b
1090       |import com.example.b.*
1091       |
1092       |val x = `if` { we.`when`(wow) } ?: b
1093       |"""
1094             .trimMargin()
1095     assertThatFormatting(code).isEqualTo(expected)
1096   }
1097 
1098   @Test
unused imports are removednull1099   fun `unused imports are removed`() {
1100     val code =
1101         """
1102       |import com.unused.Sample
1103       |import com.used.FooBarBaz as Baz
1104       |import com.used.bar // test
1105       |import com.used.`class`
1106       |import com.used.a.*
1107       |import com.used.b as `if`
1108       |import com.used.b as we
1109       |import com.unused.a as `when`
1110       |import com.unused.a as wow
1111       |
1112       |fun test(input: we) {
1113       |  Baz(`class`)
1114       |  `if` { bar }
1115       |  val x = unused()
1116       |}
1117       |"""
1118             .trimMargin()
1119     val expected =
1120         """
1121       |import com.used.FooBarBaz as Baz
1122       |import com.used.a.*
1123       |import com.used.b as `if`
1124       |import com.used.b as we
1125       |import com.used.bar // test
1126       |import com.used.`class`
1127       |
1128       |fun test(input: we) {
1129       |  Baz(`class`)
1130       |  `if` { bar }
1131       |  val x = unused()
1132       |}
1133       |"""
1134             .trimMargin()
1135     assertThatFormatting(code).isEqualTo(expected)
1136   }
1137 
1138   @Test
imports from the same package are removednull1139   fun `imports from the same package are removed`() {
1140     val code =
1141         """
1142       |package com.example
1143       |
1144       |import com.example.Sample
1145       |import com.example.Sample.CONSTANT
1146       |import com.example.a.foo
1147       |
1148       |fun test() {
1149       |  foo(CONSTANT, Sample())
1150       |}
1151       |"""
1152             .trimMargin()
1153     val expected =
1154         """
1155       |package com.example
1156       |
1157       |import com.example.Sample.CONSTANT
1158       |import com.example.a.foo
1159       |
1160       |fun test() {
1161       |  foo(CONSTANT, Sample())
1162       |}
1163       |"""
1164             .trimMargin()
1165     assertThatFormatting(code).isEqualTo(expected)
1166   }
1167 
1168   @Test
keep import elements only mentioned in kdocnull1169   fun `keep import elements only mentioned in kdoc`() {
1170     val code =
1171         """
1172           |package com.example.kdoc
1173           |
1174           |import com.example.Bar
1175           |import com.example.Example
1176           |import com.example.Foo
1177           |import com.example.JavaDocLink
1178           |import com.example.Param
1179           |import com.example.R
1180           |import com.example.ReturnedValue
1181           |import com.example.Sample
1182           |import com.example.unused
1183           |import com.example.exception.AnException
1184           |import com.example.kdoc.Doc
1185           |
1186           |/**
1187           | * [Foo] is something only mentioned here, just like [R.layout.test] and [Doc].
1188           | *
1189           | * Old {@link JavaDocLink} that gets removed.
1190           | *
1191           | * @throws AnException
1192           | * @exception Sample.SampleException
1193           | * @param unused [Param]
1194           | * @property JavaDocLink [Param]
1195           | * @return [Unit] as [ReturnedValue]
1196           | * @sample Example
1197           | * @see Bar for more info
1198           | * @throws AnException
1199           | */
1200           |class Dummy
1201           |"""
1202             .trimMargin()
1203     val expected =
1204         """
1205           |package com.example.kdoc
1206           |
1207           |import com.example.Bar
1208           |import com.example.Example
1209           |import com.example.Foo
1210           |import com.example.Param
1211           |import com.example.R
1212           |import com.example.ReturnedValue
1213           |import com.example.Sample
1214           |import com.example.exception.AnException
1215           |
1216           |/**
1217           | * [Foo] is something only mentioned here, just like [R.layout.test] and [Doc].
1218           | *
1219           | * Old {@link JavaDocLink} that gets removed.
1220           | *
1221           | * @param unused [Param]
1222           | * @return [Unit] as [ReturnedValue]
1223           | * @property JavaDocLink [Param]
1224           | * @throws AnException
1225           | * @throws AnException
1226           | * @exception Sample.SampleException
1227           | * @sample Example
1228           | * @see Bar for more info
1229           | */
1230           |class Dummy
1231           |"""
1232             .trimMargin()
1233     assertThatFormatting(code).isEqualTo(expected)
1234   }
1235 
1236   @Test
1237   fun `keep import elements only mentioned in kdoc, single line`() {
1238     assertFormatted(
1239         """
1240           |import com.shopping.Bag
1241           |
1242           |/**
1243           | * Some summary.
1244           | *
1245           | * @param count you can fit this many in a [Bag]
1246           | */
1247           |fun fetchBananas(count: Int)
1248           |"""
1249             .trimMargin())
1250   }
1251 
1252   @Test
1253   fun `keep import elements only mentioned in kdoc, multiline`() {
1254     assertFormatted(
1255         """
1256           |import com.shopping.Bag
1257           |
1258           |/**
1259           | * Some summary.
1260           | *
1261           | * @param count this is how many of these wonderful fruit you can fit into the useful object that
1262           | *   you may refer to as a [Bag]
1263           | */
1264           |fun fetchBananas(count: Int)
1265           |"""
1266             .trimMargin())
1267   }
1268 
1269   @Test
1270   fun `keep component imports`() =
1271       assertFormatted(
1272           """
1273           |import com.example.component1
1274           |import com.example.component10
1275           |import com.example.component120
1276           |import com.example.component2
1277           |import com.example.component3
1278           |import com.example.component4
1279           |import com.example.component5
1280           |"""
1281               .trimMargin())
1282 
1283   @Test
1284   fun `keep operator imports`() =
1285       assertFormatted(
1286           """
1287           |import com.example.and
1288           |import com.example.compareTo
1289           |import com.example.contains
1290           |import com.example.dec
1291           |import com.example.div
1292           |import com.example.divAssign
1293           |import com.example.equals
1294           |import com.example.get
1295           |import com.example.getValue
1296           |import com.example.hasNext
1297           |import com.example.inc
1298           |import com.example.invoke
1299           |import com.example.iterator
1300           |import com.example.minus
1301           |import com.example.minusAssign
1302           |import com.example.mod
1303           |import com.example.modAssign
1304           |import com.example.next
1305           |import com.example.not
1306           |import com.example.or
1307           |import com.example.plus
1308           |import com.example.plusAssign
1309           |import com.example.provideDelegate
1310           |import com.example.rangeTo
1311           |import com.example.rem
1312           |import com.example.remAssign
1313           |import com.example.set
1314           |import com.example.setValue
1315           |import com.example.times
1316           |import com.example.timesAssign
1317           |import com.example.unaryMinus
1318           |import com.example.unaryPlus
1319           |"""
1320               .trimMargin())
1321 
1322   @Test
1323   fun `keep unused imports when formatting options has feature turned off`() {
1324     val code =
1325         """
1326       |import com.unused.FooBarBaz as Baz
1327       |import com.unused.Sample
1328       |import com.unused.a as `when`
1329       |import com.unused.a as wow
1330       |import com.unused.a.*
1331       |import com.unused.b as `if`
1332       |import com.unused.b as we
1333       |import com.unused.bar // test
1334       |import com.unused.`class`
1335       |"""
1336             .trimMargin()
1337 
1338     assertThatFormatting(code)
1339         .withOptions(FormattingOptions(removeUnusedImports = false))
1340         .isEqualTo(code)
1341   }
1342 
1343   @Test
1344   fun `comments between imports are moved above import list`() {
1345     val code =
1346         """
1347         |package com.facebook.ktfmt
1348         |
1349         |/* leading comment */
1350         |import com.example.abc
1351         |/* internal comment 1 */
1352         |import com.example.bcd
1353         |// internal comment 2
1354         |import com.example.Sample
1355         |// trailing comment
1356         |
1357         |val x = Sample(abc, bcd)
1358         |"""
1359             .trimMargin()
1360     val expected =
1361         """
1362         |package com.facebook.ktfmt
1363         |
1364         |/* leading comment */
1365         |/* internal comment 1 */
1366         |// internal comment 2
1367         |import com.example.Sample
1368         |import com.example.abc
1369         |import com.example.bcd
1370         |
1371         |// trailing comment
1372         |
1373         |val x = Sample(abc, bcd)
1374         |"""
1375             .trimMargin()
1376     assertThatFormatting(code).isEqualTo(expected)
1377   }
1378 
1379   @Test
1380   fun `no redundant newlines when there are no imports`() =
1381       assertFormatted(
1382           """
1383         |package foo123
1384         |
1385         |/*
1386         |bar
1387         |*/
1388         |"""
1389               .trimMargin())
1390 
1391   @Test
1392   fun `basic annotations`() =
1393       assertFormatted(
1394           """
1395       |@Fancy
1396       |class Foo {
1397       |  @Fancy
1398       |  fun baz(@Fancy foo: Int) {
1399       |    @Fancy val a = 1 + foo
1400       |  }
1401       |}
1402       |"""
1403               .trimMargin())
1404 
1405   @Test
function calls with multiple argumentsnull1406   fun `function calls with multiple arguments`() =
1407       assertFormatted(
1408           """
1409       |fun f() {
1410       |  foo(1, 2, 3)
1411       |
1412       |  foo(
1413       |      123456789012345678901234567890,
1414       |      123456789012345678901234567890,
1415       |      123456789012345678901234567890)
1416       |}
1417       |"""
1418               .trimMargin())
1419 
1420   @Test
function calls with multiple named argumentsnull1421   fun `function calls with multiple named arguments`() =
1422       assertFormatted(
1423           """
1424       |fun f() {
1425       |  foo(1, b = 2, c = 3)
1426       |
1427       |  foo(
1428       |      123456789012345678901234567890,
1429       |      b = 23456789012345678901234567890,
1430       |      c = 3456789012345678901234567890)
1431       |}
1432       |"""
1433               .trimMargin())
1434 
1435   @Test
named arguments indent their value expressionnull1436   fun `named arguments indent their value expression`() =
1437       assertFormatted(
1438           """
1439       |fun f() =
1440       |    Bar(
1441       |        tokens =
1442       |            mutableListOf<Token>().apply {
1443       |              // Printing
1444       |              print()
1445       |            },
1446       |        duration = duration)
1447       |"""
1448               .trimMargin())
1449 
1450   @Test
Arguments are blocksnull1451   fun `Arguments are blocks`() =
1452       assertFormatted(
1453           """
1454       |--------------------------------------------------
1455       |override fun visitProperty(property: KtProperty) {
1456       |  builder.sync(property)
1457       |  builder.block(ZERO) {
1458       |    declareOne(
1459       |        kind = DeclarationKind.FIELD,
1460       |        modifiers = property.modifierList,
1461       |        valOrVarKeyword =
1462       |            property.valOrVarKeyword.text,
1463       |        typeParameters =
1464       |            property.typeParameterList,
1465       |        receiver = property.receiverTypeReference,
1466       |        name = property.nameIdentifier?.text,
1467       |        type = property.typeReference,
1468       |        typeConstraintList =
1469       |            property.typeConstraintList,
1470       |        delegate = property.delegate,
1471       |        initializer = property.initializer)
1472       |  }
1473       |}
1474       |"""
1475               .trimMargin(),
1476           deduceMaxWidth = true)
1477 
1478   @Test
anonymous functionnull1479   fun `anonymous function`() =
1480       assertFormatted(
1481           """
1482       |fun f() {
1483       |  setListener(
1484       |      fun(number: Int) {
1485       |        println(number)
1486       |      })
1487       |}
1488       |"""
1489               .trimMargin())
1490 
1491   @Test
anonymous function with receivernull1492   fun `anonymous function with receiver`() =
1493       assertFormatted(
1494           """
1495       |fun f() {
1496       |  setListener(
1497       |      fun View.() {
1498       |        println(this)
1499       |      })
1500       |}
1501       |"""
1502               .trimMargin())
1503 
1504   @Test
when() with a subject expressionnull1505   fun `when() with a subject expression`() =
1506       assertFormatted(
1507           """
1508       |fun f(x: Int) {
1509       |  when (x) {
1510       |    1 -> print(1)
1511       |    2 -> print(2)
1512       |    3 ->
1513       |        // Comment
1514       |        print(3)
1515       |    else -> {
1516       |      print("else")
1517       |    }
1518       |  }
1519       |}
1520       |"""
1521               .trimMargin())
1522 
1523   @Test
when() expression with complex predicatesnull1524   fun `when() expression with complex predicates`() =
1525       assertFormatted(
1526           """
1527       |fun f(x: Int) {
1528       |  when {
1529       |    x == 1 || x == 2 -> print(1)
1530       |    x == 3 && x != 4 -> print(2)
1531       |    else -> {
1532       |      print(3)
1533       |    }
1534       |  }
1535       |}
1536       |"""
1537               .trimMargin())
1538 
1539   @Test
when() expression with several conditionsnull1540   fun `when() expression with several conditions`() =
1541       assertFormatted(
1542           """
1543       |fun f(x: Int) {
1544       |  when {
1545       |    0,
1546       |    1 -> print(1)
1547       |    else -> print(0)
1548       |  }
1549       |}
1550       |"""
1551               .trimMargin())
1552 
1553   @Test
when() expression with is and innull1554   fun `when() expression with is and in`() =
1555       assertFormatted(
1556           """
1557       |fun f(x: Int) {
1558       |  when (x) {
1559       |    is String -> print(1)
1560       |    !is String -> print(2)
1561       |    in 1..3 -> print()
1562       |    in a..b -> print()
1563       |    in a..3 -> print()
1564       |    in 1..b -> print()
1565       |    !in 1..b -> print()
1566       |    else -> print(3)
1567       |  }
1568       |}
1569       |"""
1570               .trimMargin())
1571 
1572   @Test
when() expression with enum valuesnull1573   fun `when() expression with enum values`() =
1574       assertFormatted(
1575           """
1576       |fun f(x: Color) {
1577       |  when (x) {
1578       |    is Color.Red -> print(1)
1579       |    is Color.Green -> print(2)
1580       |    else -> print(3)
1581       |  }
1582       |}
1583       |"""
1584               .trimMargin())
1585 
1586   @Test
when() expression with generic matcher and exhaustivenull1587   fun `when() expression with generic matcher and exhaustive`() =
1588       assertFormatted(
1589           """
1590       |fun f(x: Result) {
1591       |  when (x) {
1592       |    is Success<*> -> print(1)
1593       |    is Failure -> print(2)
1594       |  }.exhaustive
1595       |}
1596       |"""
1597               .trimMargin())
1598 
1599   @Test
when() expression with multiline conditionnull1600   fun `when() expression with multiline condition`() =
1601       assertFormatted(
1602           """
1603       |--------------------------
1604       |fun foo() {
1605       |  when (expressions1 +
1606       |      expression2 +
1607       |      expression3) {
1608       |    1 -> print(1)
1609       |    2 -> print(2)
1610       |  }
1611       |
1612       |  when (foo(
1613       |      expressions1 &&
1614       |          expression2 &&
1615       |          expression3)) {
1616       |    1 -> print(1)
1617       |    2 -> print(2)
1618       |  }
1619       |}
1620       |"""
1621               .trimMargin(),
1622           deduceMaxWidth = true)
1623 
1624   @Test
lambda assigned to variable does not break before bracenull1625   fun `lambda assigned to variable does not break before brace`() =
1626       assertFormatted(
1627           """
1628       |fun doIt() {
1629       |  val lambda = {
1630       |    doItOnce()
1631       |    doItTwice()
1632       |  }
1633       |}
1634       |
1635       |fun foo() = {
1636       |  doItOnce()
1637       |  doItTwice()
1638       |}
1639       |"""
1640               .trimMargin())
1641 
1642   @Test
when() expression storing in local variablenull1643   fun `when() expression storing in local variable`() =
1644       assertFormatted(
1645           """
1646       |fun f(x: Result) {
1647       |  when (val y = x.improved()) {
1648       |    is Success<*> -> print(y)
1649       |    is Failure -> print(2)
1650       |  }
1651       |}
1652       |"""
1653               .trimMargin())
1654 
1655   @Test
line breaks inside when expressions and conditionsnull1656   fun `line breaks inside when expressions and conditions`() =
1657       assertFormatted(
1658           """
1659       |fun f() {
1660       |  return Text.create(c)
1661       |      .onTouch {
1662       |        when (it.motionEvent.action) {
1663       |          ACTION_DOWN ->
1664       |              Toast.makeText(it.view.context, "Down!", Toast.LENGTH_SHORT, blablabla).show()
1665       |          ACTION_UP -> Toast.makeText(it.view.context, "Up!", Toast.LENGTH_SHORT).show()
1666       |          ACTION_DOWN ->
1667       |              Toast.makeText(
1668       |                      it.view.context, "Down!", Toast.LENGTH_SHORT, blablabla, blablabl, blabla)
1669       |                  .show()
1670       |        }
1671       |      }
1672       |      .build()
1673       |}
1674       |"""
1675               .trimMargin())
1676 
1677   @Test
function return typesnull1678   fun `function return types`() =
1679       assertFormatted(
1680           """
1681       |fun f1(): Int = 0
1682       |
1683       |fun f2(): Int {}
1684       |"""
1685               .trimMargin())
1686 
1687   @Test
multi line function without a block bodynull1688   fun `multi line function without a block body`() =
1689       assertFormatted(
1690           """
1691       |-------------------------
1692       |fun longFunctionNoBlock():
1693       |    Int =
1694       |    1234567 + 1234567
1695       |
1696       |fun shortFun(): Int =
1697       |    1234567 + 1234567
1698       |"""
1699               .trimMargin(),
1700           deduceMaxWidth = true)
1701 
1702   @Test
1703   fun `return type doesn't fit in one line`() =
1704       assertFormatted(
1705           """
1706       |--------------------------------------------------
1707       |interface X {
1708       |  fun f(
1709       |      arg1: Arg1Type,
1710       |      arg2: Arg2Type
1711       |  ): Map<String, Map<String, Double>>? {
1712       |    //
1713       |  }
1714       |
1715       |  fun functionWithGenericReturnType(
1716       |      arg1: Arg1Type,
1717       |      arg2: Arg2Type
1718       |  ): Map<String, Map<String, Double>>? {
1719       |    //
1720       |  }
1721       |}
1722       |"""
1723               .trimMargin(),
1724           deduceMaxWidth = true)
1725 
1726   @Test
list of superclassesnull1727   fun `list of superclasses`() =
1728       assertFormatted(
1729           """
1730       |class Derived2 : Super1, Super2 {}
1731       |
1732       |class Derived1 : Super1, Super2
1733       |
1734       |class Derived3(a: Int) : Super1(a)
1735       |
1736       |class Derived4 : Super1()
1737       |
1738       |class Derived5 : Super3<Int>()
1739       |"""
1740               .trimMargin())
1741 
1742   @Test
list of superclasses over multiple linesnull1743   fun `list of superclasses over multiple lines`() =
1744       assertFormatted(
1745           """
1746       |--------------------
1747       |class Derived2 :
1748       |    Super1,
1749       |    Super2 {}
1750       |
1751       |class Derived1 :
1752       |    Super1, Super2
1753       |
1754       |class Derived3(
1755       |    a: Int
1756       |) : Super1(a)
1757       |
1758       |class Derived4 :
1759       |    Super1()
1760       |
1761       |class Derived5 :
1762       |    Super3<Int>()
1763       |"""
1764               .trimMargin(),
1765           deduceMaxWidth = true)
1766 
1767   @Test
annotations with parametersnull1768   fun `annotations with parameters`() =
1769       assertFormatted(
1770           """
1771       |@AnnWithArrayValue(1, 2, 3) class C
1772       |"""
1773               .trimMargin())
1774 
1775   @Test
1776   fun `method modifiers`() =
1777       assertFormatted(
1778           """
1779       |override internal fun f() {}
1780       |"""
1781               .trimMargin())
1782 
1783   @Test
class modifiersnull1784   fun `class modifiers`() =
1785       assertFormatted(
1786           """
1787       |abstract class Foo
1788       |
1789       |inner class Foo
1790       |
1791       |final class Foo
1792       |
1793       |open class Foo
1794       |"""
1795               .trimMargin())
1796 
1797   @Test
1798   fun `kdoc comments`() {
1799     val code =
1800         """
1801       |/**
1802       | * foo
1803       | */ class F {
1804       |
1805       | }
1806       |"""
1807             .trimMargin()
1808     val expected =
1809         """
1810       |/** foo */
1811       |class F {}
1812       |"""
1813             .trimMargin()
1814     assertThatFormatting(code).isEqualTo(expected)
1815   }
1816 
1817   @Test
nested kdoc commentsnull1818   fun `nested kdoc comments`() {
1819     val code =
1820         """
1821       |/**
1822       | * foo /* bla */
1823       | */ class F {
1824       |
1825       | }
1826       |"""
1827             .trimMargin()
1828     val expected =
1829         """
1830       |/** foo /* bla */ */
1831       |class F {}
1832       |"""
1833             .trimMargin()
1834     assertThatFormatting(code).isEqualTo(expected)
1835   }
1836 
1837   @Test
nested kdoc inside code blocknull1838   fun `nested kdoc inside code block`() =
1839       assertFormatted(
1840           """
1841       |/**
1842       | * ```
1843       | * edit -> { /* open edit screen */ }
1844       | * ```
1845       | */
1846       |fun foo() {}
1847       |"""
1848               .trimMargin())
1849 
1850   @Test
formatting kdoc doesn't add p HTML tagsnull1851   fun `formatting kdoc doesn't add p HTML tags`() =
1852       assertFormatted(
1853           """
1854       |/**
1855       | * Bla bla bla bla
1856       | *
1857       | * This is an inferred paragraph, and as you can see, we don't add a p tag to it, even though bla
1858       | * bla.
1859       | *
1860       | * <p>On the other hand, we respect existing tags, and don't remove them.
1861       | */
1862       |"""
1863               .trimMargin())
1864 
1865   @Test
1866   fun `formatting kdoc preserves lists`() =
1867       assertFormatted(
1868           """
1869       |/**
1870       | * Here are some fruit I like:
1871       | * - Banana
1872       | * - Apple
1873       | *
1874       | * This is another paragraph
1875       | */
1876       |"""
1877               .trimMargin())
1878 
1879   @Test
1880   fun `formatting kdoc lists with line wraps breaks and merges correctly`() {
1881     val code =
1882         """
1883       |/**
1884       | * Here are some fruit I like:
1885       | * - Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana
1886       | * - Apple Apple Apple Apple
1887       | *   Apple Apple
1888       | *
1889       | * This is another paragraph
1890       | */
1891       |"""
1892             .trimMargin()
1893     val expected =
1894         """
1895       |/**
1896       | * Here are some fruit I like:
1897       | * - Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana Banana
1898       | *   Banana Banana Banana Banana Banana
1899       | * - Apple Apple Apple Apple Apple Apple
1900       | *
1901       | * This is another paragraph
1902       | */
1903       |"""
1904             .trimMargin()
1905     assertThatFormatting(code).isEqualTo(expected)
1906   }
1907 
1908   @Test
1909   fun `formatting kdoc preserves lists of asterisks`() =
1910       assertFormatted(
1911           """
1912       |/**
1913       | * Here are some fruit I like:
1914       | * * Banana
1915       | * * Apple
1916       | *
1917       | * This is another paragraph
1918       | */
1919       |"""
1920               .trimMargin())
1921 
1922   @Test
1923   fun `formatting kdoc preserves numbered`() =
1924       assertFormatted(
1925           """
1926       |/**
1927       | * Here are some fruit I like:
1928       | * 1. Banana
1929       | * 2. Apple
1930       | *
1931       | * This is another paragraph
1932       | */
1933       |"""
1934               .trimMargin())
1935 
1936   @Test
1937   fun `formatting kdoc with markdown errors`() =
1938       assertFormatted(
1939           """
1940       |/** \[ */
1941       |fun markdownError() = Unit
1942       |"""
1943               .trimMargin())
1944 
1945   @Test
1946   fun `return statement with value`() =
1947       assertFormatted(
1948           """
1949       |fun random(): Int {
1950       |  return 4
1951       |}
1952       |"""
1953               .trimMargin())
1954 
1955   @Test
return statement without valuenull1956   fun `return statement without value`() =
1957       assertFormatted(
1958           """
1959       |fun print(b: Boolean) {
1960       |  print(b)
1961       |  return
1962       |}
1963       |"""
1964               .trimMargin())
1965 
1966   @Test
return expression without valuenull1967   fun `return expression without value`() =
1968       assertFormatted(
1969           """
1970       |fun print(b: Boolean?) {
1971       |  print(b ?: return)
1972       |}
1973       |"""
1974               .trimMargin())
1975 
1976   @Test
if statement without elsenull1977   fun `if statement without else`() =
1978       assertFormatted(
1979           """
1980       |fun maybePrint(b: Boolean) {
1981       |  if (b) {
1982       |    println(b)
1983       |  }
1984       |}
1985       |"""
1986               .trimMargin())
1987 
1988   @Test
if statement with elsenull1989   fun `if statement with else`() =
1990       assertFormatted(
1991           """
1992       |fun maybePrint(b: Boolean) {
1993       |  if (b) {
1994       |    println(2)
1995       |  } else {
1996       |    println(1)
1997       |  }
1998       |}
1999       |"""
2000               .trimMargin())
2001 
2002   @Test
if expression with elsenull2003   fun `if expression with else`() =
2004       assertFormatted(
2005           """
2006       |fun maybePrint(b: Boolean) {
2007       |  println(if (b) 1 else 2)
2008       |  println(
2009       |      if (b) {
2010       |        val a = 1 + 1
2011       |        2 * a
2012       |      } else 2)
2013       |  return if (b) 1 else 2
2014       |}
2015       |"""
2016               .trimMargin())
2017 
2018   @Test
if expression with break before elsenull2019   fun `if expression with break before else`() =
2020       assertFormatted(
2021           """
2022       |------------------------------
2023       |fun compute(b: Boolean) {
2024       |  val c =
2025       |      if (a + b < 20) a + b
2026       |      else a
2027       |  return if (a + b < 20) a + b
2028       |  else c
2029       |}
2030       |"""
2031               .trimMargin(),
2032           deduceMaxWidth = true)
2033 
2034   @Test
if expression with break before expressionsnull2035   fun `if expression with break before expressions`() =
2036       assertFormatted(
2037           """
2038       |--------------------------
2039       |fun compute(b: Boolean) {
2040       |  val c =
2041       |      if (a + b < 20)
2042       |          a + b
2043       |      else if (a < 20) a
2044       |      else
2045       |          a + b + b + 1000
2046       |  return if (a + b < 20)
2047       |      a + b
2048       |  else c
2049       |}
2050       |"""
2051               .trimMargin(),
2052           deduceMaxWidth = true)
2053 
2054   @Test
blocky expressions in if-elsenull2055   fun `blocky expressions in if-else`() =
2056       assertFormatted(
2057           """
2058       |fun numbers() {
2059       |  if (true)
2060       |      do {
2061       |        eat("is")
2062       |        matches += type()
2063       |      } while (eat(","))
2064       |  else
2065       |      while (1 < 2) {
2066       |        println("Everything is okay")
2067       |      }
2068       |}
2069       |"""
2070               .trimMargin())
2071 
2072   @Test
if expression with multiline conditionnull2073   fun `if expression with multiline condition`() =
2074       assertFormatted(
2075           """
2076       |----------------------------
2077       |fun foo() {
2078       |  if (expressions1 &&
2079       |      expression2 &&
2080       |      expression3) {
2081       |    bar()
2082       |  }
2083       |
2084       |  if (foo(
2085       |      expressions1 &&
2086       |          expression2 &&
2087       |          expression3)) {
2088       |    bar()
2089       |  }
2090       |}
2091       |"""
2092               .trimMargin(),
2093           deduceMaxWidth = true)
2094 
2095   @Test
assignment expression on multiple linesnull2096   fun `assignment expression on multiple lines`() =
2097       assertFormatted(
2098           """
2099       |--------------------------------------------------
2100       |fun f() {
2101       |  var myVariable = 5
2102       |  myVariable =
2103       |      function1(4, 60, 8) + function2(57, 39, 20)
2104       |}
2105       |"""
2106               .trimMargin(),
2107           deduceMaxWidth = true)
2108 
2109   @Test
A program that tickled a bug in KotlinInputnull2110   fun `A program that tickled a bug in KotlinInput`() =
2111       assertFormatted(
2112           """
2113       |val x = 2
2114       |"""
2115               .trimMargin())
2116 
2117   @Test
2118   fun `a few variations of constructors`() =
2119       assertFormatted(
2120           """
2121       |class Foo constructor(number: Int) {}
2122       |
2123       |class Foo2 private constructor(number: Int) {}
2124       |
2125       |class Foo3 @Inject constructor(number: Int) {}
2126       |
2127       |class Foo4 @Inject private constructor(number: Int) {}
2128       |
2129       |class Foo5
2130       |@Inject
2131       |private constructor(
2132       |    number: Int,
2133       |    number2: Int,
2134       |    number3: Int,
2135       |    number4: Int,
2136       |    number5: Int,
2137       |    number6: Int
2138       |) {}
2139       |"""
2140               .trimMargin())
2141 
2142   @Test
a primary constructor without a class bodynull2143   fun `a primary constructor without a class body `() =
2144       assertFormatted(
2145           """
2146       |-------------------------
2147       |data class Foo(
2148       |    val number: Int = 0
2149       |)
2150       |"""
2151               .trimMargin(),
2152           deduceMaxWidth = true)
2153 
2154   @Test
2155   fun `a secondary constructor without a body`() =
2156       assertFormatted(
2157           """
2158       |---------------------------
2159       |data class Foo {
2160       |  constructor(
2161       |      val number: Int = 0
2162       |  )
2163       |}
2164       |"""
2165               .trimMargin(),
2166           deduceMaxWidth = true)
2167 
2168   @Test
a secondary constructor with a body breaks before closing parenthesisnull2169   fun `a secondary constructor with a body breaks before closing parenthesis`() =
2170       assertFormatted(
2171           """
2172       |---------------------------
2173       |data class Foo {
2174       |  constructor(
2175       |      val number: Int = 0
2176       |  ) {}
2177       |}
2178       |"""
2179               .trimMargin(),
2180           deduceMaxWidth = true)
2181 
2182   @Test
a constructor with many arguments over breaking to next linenull2183   fun `a constructor with many arguments over breaking to next line`() =
2184       assertFormatted(
2185           """
2186       |data class Foo(
2187       |    val number: Int,
2188       |    val name: String,
2189       |    val age: Int,
2190       |    val title: String,
2191       |    val offspring2: List<Foo>
2192       |) {}
2193       |"""
2194               .trimMargin())
2195 
2196   @Test
a constructor with keyword and many arguments over breaking to next linenull2197   fun `a constructor with keyword and many arguments over breaking to next line`() =
2198       assertFormatted(
2199           """
2200       |data class Foo
2201       |constructor(
2202       |    val name: String,
2203       |    val age: Int,
2204       |    val title: String,
2205       |    val offspring: List<Foo>,
2206       |    val foo: String
2207       |) {}
2208       |"""
2209               .trimMargin())
2210 
2211   @Test
a constructor with many arguments over multiple linesnull2212   fun `a constructor with many arguments over multiple lines`() =
2213       assertFormatted(
2214           """
2215       |--------------------------------------------------
2216       |data class Foo
2217       |constructor(
2218       |    val number: Int,
2219       |    val name: String,
2220       |    val age: Int,
2221       |    val title: String,
2222       |    val offspring: List<Foo>
2223       |) {}
2224       |"""
2225               .trimMargin(),
2226           deduceMaxWidth = true)
2227 
2228   @Test
handle secondary constructorsnull2229   fun `handle secondary constructors`() =
2230       assertFormatted(
2231           """
2232       |class Foo private constructor(number: Int) {
2233       |  private constructor(n: Float) : this(1)
2234       |  private constructor(n: Double) : this(1) {
2235       |    println("built")
2236       |  }
2237       |}
2238       |"""
2239               .trimMargin())
2240 
2241   @Test
a secondary constructor with many arguments over multiple linesnull2242   fun `a secondary constructor with many arguments over multiple lines`() =
2243       assertFormatted(
2244           """
2245       |--------------------------------------------------
2246       |data class Foo {
2247       |  constructor(
2248       |      val number: Int,
2249       |      val name: String,
2250       |      val age: Int,
2251       |      val title: String,
2252       |      val offspring: List<Foo>
2253       |  )
2254       |}
2255       |"""
2256               .trimMargin(),
2257           deduceMaxWidth = true)
2258 
2259   @Test
a secondary constructor with many arguments passed to delegatenull2260   fun `a secondary constructor with many arguments passed to delegate`() =
2261       assertFormatted(
2262           """
2263       |--------------------------------------------------
2264       |data class Foo {
2265       |  constructor(
2266       |      val number: Int,
2267       |      val name: String,
2268       |      val age: Int,
2269       |      val title: String,
2270       |      val offspring: List<Foo>
2271       |  ) : this(
2272       |      number,
2273       |      name,
2274       |      age,
2275       |      title,
2276       |      offspring,
2277       |      offspring)
2278       |}
2279       |"""
2280               .trimMargin(),
2281           deduceMaxWidth = true)
2282 
2283   @Test
a secondary constructor with no arguments passed to delegatenull2284   fun `a secondary constructor with no arguments passed to delegate`() =
2285       assertFormatted(
2286           """
2287       |--------------------------------------------------
2288       |data class Foo {
2289       |  constructor() :
2290       |      this(
2291       |          Foo.createSpeciallyDesignedParameter(),
2292       |          Foo.createSpeciallyDesignedParameter(),
2293       |      )
2294       |}
2295       |"""
2296               .trimMargin(),
2297           deduceMaxWidth = true)
2298 
2299   @Test
secondary constructor with param list that fits in one line, with delegatenull2300   fun `secondary constructor with param list that fits in one line, with delegate`() =
2301       assertFormatted(
2302           """
2303       |class C {
2304       |  constructor(
2305       |      context: Context?,
2306       |      attrs: AttributeSet?,
2307       |      defStyleAttr: Int,
2308       |      defStyleRes: Int
2309       |  ) : super(context, attrs, defStyleAttr, defStyleRes) {
2310       |    init(attrs)
2311       |  }
2312       |}
2313       |"""
2314               .trimMargin())
2315 
2316   @Test
handle calling super constructor in secondary constructornull2317   fun `handle calling super constructor in secondary constructor`() =
2318       assertFormatted(
2319           """
2320       |class Foo : Bar {
2321       |  internal constructor(number: Int) : super(number) {}
2322       |}
2323       |"""
2324               .trimMargin())
2325 
2326   @Test
handle super statement with with type argumentnull2327   fun `handle super statement with with type argument`() =
2328       assertFormatted(
2329           """
2330       |class Foo : Bar(), FooBar {
2331       |  override fun doIt() {
2332       |    super<FooBar>.doIt()
2333       |  }
2334       |}
2335       |"""
2336               .trimMargin())
2337 
2338   @Test
handle super statement with with label argumentnull2339   fun `handle super statement with with label argument`() =
2340       assertFormatted(
2341           """
2342       |class Foo : Bar(), FooBar {
2343       |  override fun doIt() {
2344       |    foo.doThat {
2345       |      super<FooBar>@Foo.doIt()
2346       |
2347       |      // this one is actually generics on the call expression, not super
2348       |      super@Foo<FooBar>.doIt()
2349       |    }
2350       |  }
2351       |}
2352       |"""
2353               .trimMargin())
2354 
2355   @Test
primary constructor without parameters with a KDocnull2356   fun `primary constructor without parameters with a KDoc`() =
2357       assertFormatted(
2358           """
2359       |class Class
2360       |/** A comment */
2361       |constructor() {}
2362       |"""
2363               .trimMargin())
2364 
2365   @Test
handle objectsnull2366   fun `handle objects`() =
2367       assertFormatted(
2368           """
2369       |object Foo(n: Int) {}
2370       |"""
2371               .trimMargin())
2372 
2373   @Test
handle object expressionnull2374   fun `handle object expression`() =
2375       assertFormatted(
2376           """
2377       |fun f(): Any {
2378       |  return object : Adapter() {}
2379       |}
2380       |"""
2381               .trimMargin())
2382 
2383   @Test
handle object expression in parenthesisnull2384   fun `handle object expression in parenthesis`() =
2385       assertFormatted(
2386           """
2387       |fun f(): Any {
2388       |  return (object : Adapter() {})
2389       |}
2390       |"""
2391               .trimMargin())
2392 
2393   @Test
handle array indexing operatornull2394   fun `handle array indexing operator`() =
2395       assertFormatted(
2396           """
2397       |fun f(a: Magic) {
2398       |  a[3]
2399       |  b[3, 4]
2400       |}
2401       |"""
2402               .trimMargin())
2403 
2404   @Test
keep array indexing grouped with expression is possiblenull2405   fun `keep array indexing grouped with expression is possible`() =
2406       assertFormatted(
2407           """
2408       |-----------------------
2409       |fun f(a: Magic) {
2410       |  foo.bar()
2411       |      .foobar[1, 2, 3]
2412       |  foo.bar()
2413       |      .foobar[
2414       |          1,
2415       |          2,
2416       |          3,
2417       |          4,
2418       |          5]
2419       |  foo.bar()
2420       |      .foobar[1, 2, 3]
2421       |      .barfoo[3, 2, 1]
2422       |}
2423       |"""
2424               .trimMargin(),
2425           deduceMaxWidth = true)
2426 
2427   @Test
mixed chainsnull2428   fun `mixed chains`() =
2429       assertFormatted(
2430           """
2431       |-----------------------
2432       |fun f(a: Magic) {
2433       |  foo.bar()
2434       |      .foobar[1, 2, 3]
2435       |  foo.bar()
2436       |      .foobar[
2437       |          1,
2438       |          2,
2439       |          3,
2440       |          4,
2441       |          5]
2442       |  foo.bar()
2443       |      .foobar[1, 2, 3]
2444       |      .barfoo[3, 2, 1]
2445       |}
2446       |"""
2447               .trimMargin(),
2448           deduceMaxWidth = true)
2449 
2450   @Test
handle destructuring declarationnull2451   fun `handle destructuring declaration`() =
2452       assertFormatted(
2453           """
2454       |-----------------------------------------------
2455       |fun f() {
2456       |  val (a, b: Int) = listOf(1, 2)
2457       |  val (asd, asd, asd, asd, asd, asd, asd) =
2458       |      foo.bar(asdasd, asdasd)
2459       |
2460       |  val (accountType, accountId) =
2461       |      oneTwoThreeFourFiveSixSeven(
2462       |          foo, bar, zed, boo)
2463       |}
2464       |"""
2465               .trimMargin(),
2466           deduceMaxWidth = true)
2467   @Test
chains with derferences and array indexingnull2468   fun `chains with derferences and array indexing`() =
2469       assertFormatted(
2470           """
2471       |-----------------------
2472       |fun f() {
2473       |  foo.bam()
2474       |      .uber!![0, 1, 2]
2475       |      .boom()[1, 3, 5]
2476       |      .lah
2477       |      .doo { it }
2478       |      .feep[1]
2479       |      as Boo
2480       |}
2481       |"""
2482               .trimMargin(),
2483           deduceMaxWidth = true)
2484 
2485   @Test
block like syntax after dereferences and indexing with short linesnull2486   fun `block like syntax after dereferences and indexing with short lines`() =
2487       assertFormatted(
2488           """
2489       |-----------------------
2490       |fun f() {
2491       |  foo.bam()
2492       |      .uber!![0, 1, 2]
2493       |      .forEach {
2494       |        println(it)
2495       |      }
2496       |}
2497       |"""
2498               .trimMargin(),
2499           deduceMaxWidth = true)
2500 
2501   @Test
block like syntax after dereferences and indexing with long linesnull2502   fun `block like syntax after dereferences and indexing with long lines`() =
2503       assertFormatted(
2504           """
2505       |----------------------------------
2506       |fun f() {
2507       |  foo.uber!![0, 1, 2].forEach {
2508       |    println(it)
2509       |  }
2510       |}
2511       |"""
2512               .trimMargin(),
2513           deduceMaxWidth = true)
2514 
2515   @Test
try to keep type names togethernull2516   fun `try to keep type names together`() =
2517       assertFormatted(
2518           """
2519       |-----------------------
2520       |fun f() {
2521       |  com.facebook.foo.Foo(
2522       |      1, 2)
2523       |  com.facebook.foo
2524       |      .Foo(1, 2)
2525       |      .andAlsoThis()
2526       |  com.facebook.Foo.foo(
2527       |      1, 2)
2528       |  com.facebook
2529       |      .foobarFoo
2530       |      .foo(1, 2)
2531       |  foo.invoke(
2532       |      foo, bar, bar)
2533       |  foo.invoke(foo, bar)
2534       |      .invoke()
2535       |  FooFoo.foooooooo()
2536       |      .foooooooo()
2537       |}
2538       |"""
2539               .trimMargin(),
2540           deduceMaxWidth = true)
2541 
2542   @Test
avoid breaking brackets and keep them with array namenull2543   fun `avoid breaking brackets and keep them with array name`() =
2544       assertFormatted(
2545           """
2546       |-------------------------------------------------------------------------
2547       |fun f() {
2548       |  val a =
2549       |      invokeIt(context.packageName)
2550       |          .getInternalMutablePackageInfo(context.packageName)
2551       |          .someItems[0]
2552       |          .getInternalMutablePackageInfo(context.packageName)
2553       |          .someItems[0]
2554       |          .doIt()
2555       |}
2556       |"""
2557               .trimMargin(),
2558           deduceMaxWidth = true)
2559 
2560   @Test
keep function call with type name even if array expression is nextnull2561   fun `keep function call with type name even if array expression is next`() =
2562       assertFormatted(
2563           """
2564       |class f {
2565       |  private val somePropertyWithBackingOne
2566       |    get() =
2567       |        _somePropertyWithBackingOne
2568       |            ?: Classname.getStuff<SomePropertyRelatedClassProvider>(requireContext())[
2569       |                    somePropertiesProvider, somePropertyCallbacks]
2570       |                .also { _somePropertyWithBackingOne = it }
2571       |}
2572       |"""
2573               .trimMargin())
2574 
2575   @Test
array access in middle of chain and end of it behaves similarlynull2576   fun `array access in middle of chain and end of it behaves similarly`() =
2577       assertFormatted(
2578           """
2579       |--------------------------------------
2580       |fun f() {
2581       |  if (aaaaa == null ||
2582       |      aaaaa.bbbbb[0] == null ||
2583       |      aaaaa.bbbbb[0].cc == null ||
2584       |      aaaaa.bbbbb[0].dddd == null) {
2585       |    println()
2586       |  }
2587       |}
2588       |"""
2589               .trimMargin(),
2590           deduceMaxWidth = true)
2591 
2592   @Test
handle qmark for nullalble typesnull2593   fun `handle qmark for nullalble types`() =
2594       assertFormatted(
2595           """
2596       |fun doItWithNullReturns(a: String, b: String): Int? {
2597       |  return 5
2598       |}
2599       |
2600       |fun doItWithNulls(a: String, b: String?) {}
2601       |"""
2602               .trimMargin())
2603 
2604   @Test
nullable function typenull2605   fun `nullable function type`() =
2606       assertFormatted(
2607           """
2608       |var listener: ((Boolean) -> Unit)? = null
2609       |"""
2610               .trimMargin())
2611 
2612   @Test
2613   fun `redundant parenthesis in function types`() =
2614       assertFormatted(
2615           """
2616       |val a: (Int) = 7
2617       |
2618       |var listener: ((Boolean) -> Unit) = foo
2619       |"""
2620               .trimMargin())
2621 
2622   @Test
2623   fun `handle string literals`() =
2624       assertFormatted(
2625           """
2626       |fun doIt(world: String) {
2627       |  println("Hello world!")
2628       |  println("Hello! ${'$'}world")
2629       |  println("Hello! ${'$'}{"wor" + "ld"}")
2630       |}
2631       |"""
2632               .trimMargin())
2633 
2634   @Test
handle multiline string literalsnull2635   fun `handle multiline string literals`() =
2636       assertFormatted(
2637           """
2638       |fun doIt(world: String) {
2639       |  println(${"\"".repeat(3)}Hello
2640       |      world!${"\"".repeat(3)})
2641       |}
2642       |"""
2643               .trimMargin())
2644 
2645   @Test
Trailing whitespaces are preserved in multiline stringsnull2646   fun `Trailing whitespaces are preserved in multiline strings`() {
2647     val code =
2648         listOf(
2649                 "fun doIt(world: String) {",
2650                 "  println(\"\"\"This line has trailing whitespace         ",
2651                 "      world!\"\"\")",
2652                 "  println(\"\"\"This line has trailing whitespace \$s     ",
2653                 "      world!\"\"\")",
2654                 "  println(\"\"\"This line has trailing whitespace \${s}   ",
2655                 "      world!\"\"\")",
2656                 "  println(\"\"\"This line has trailing whitespace \$      ",
2657                 "      world!\"\"\")",
2658                 "}",
2659                 "")
2660             .joinToString("\n")
2661     assertThatFormatting(code).allowTrailingWhitespace().isEqualTo(code)
2662   }
2663 
2664   @Test
2665   fun `Consecutive line breaks in multiline strings are preserved`() =
2666       assertFormatted(
2667           """
2668       |val x = $TQ
2669       |
2670       |
2671       |
2672       |Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
2673       |$TQ
2674       |"""
2675               .trimMargin())
2676 
2677   @Test
2678   fun `Trailing spaces in a comment are not preserved`() {
2679     val before =
2680         listOf("// trailing spaces in a comment are not preserved       ", "").joinToString("\n")
2681     val after = listOf("// trailing spaces in a comment are not preserved", "").joinToString("\n")
2682     assertThatFormatting(before).allowTrailingWhitespace().isEqualTo(after)
2683   }
2684 
2685   @Test
2686   fun `Code with tombstones is not supported`() {
2687     val code =
2688         """
2689       |fun good() {
2690       |  // ${'\u0003'}
2691       |}
2692       |"""
2693             .trimMargin()
2694     try {
2695       Formatter.format(code)
2696       fail()
2697     } catch (e: ParseError) {
2698       assertThat(e.errorDescription).contains("\\u0003")
2699       assertThat(e.lineColumn.line).isEqualTo(1)
2700       assertThat(e.lineColumn.column).isEqualTo(5)
2701     }
2702   }
2703 
2704   @Test
handle some basic generics scenariosnull2705   fun `handle some basic generics scenarios`() =
2706       assertFormatted(
2707           """
2708       |fun <T> doIt(a: List<T>): List<Int>? {
2709       |  val b: List<Int> = convert<Int>(listOf(5, 4))
2710       |  return b
2711       |}
2712       |
2713       |class Foo<T>
2714       |"""
2715               .trimMargin())
2716 
2717   @Test
handle for loopsnull2718   fun `handle for loops`() =
2719       assertFormatted(
2720           """
2721       |fun f(a: List<Int>) {
2722       |  for (i in a.indices) {
2723       |    println(i)
2724       |  }
2725       |}
2726       |"""
2727               .trimMargin())
2728 
2729   @Test
handle for loops with long dot chainsnull2730   fun `handle for loops with long dot chains`() =
2731       assertFormatted(
2732           """
2733       |-----------------------------------
2734       |fun f(a: Node<Int>) {
2735       |  for (child in node.next.data()) {
2736       |    println(child)
2737       |  }
2738       |  for (child in
2739       |      node.next.next.data()) {
2740       |    println(child)
2741       |  }
2742       |  for (child in
2743       |      node.next.next.next.next
2744       |          .data()) {
2745       |    println(child)
2746       |  }
2747       |}
2748       |"""
2749               .trimMargin(),
2750           deduceMaxWidth = true)
2751 
2752   @Test
when two lambdas following a call, indent the lambda properlynull2753   fun `when two lambdas following a call, indent the lambda properly`() =
2754       assertFormatted(
2755           """
2756       |----------------------------
2757       |fun f() {
2758       |  doIt()
2759       |      .apply {
2760       |        number =
2761       |            computeNumber1()
2762       |      }
2763       |      .apply {
2764       |        number = 2 * number
2765       |      }
2766       |}
2767       |"""
2768               .trimMargin(),
2769           deduceMaxWidth = true)
2770 
2771   @Test
when two lambdas following a field, indent the lambda properlynull2772   fun `when two lambdas following a field, indent the lambda properly`() =
2773       assertFormatted(
2774           """
2775       |----------------------------
2776       |fun f() {
2777       |  field
2778       |      .apply {
2779       |        number =
2780       |            computeNumber1()
2781       |      }
2782       |      .apply {
2783       |        number = 2 * number
2784       |      }
2785       |}
2786       |"""
2787               .trimMargin(),
2788           deduceMaxWidth = true)
2789 
2790   @Test
break after 'four' (even though it's 4 chars long) because there's a lambda afterwardsnull2791   fun `break after 'four' (even though it's 4 chars long) because there's a lambda afterwards`() =
2792       assertFormatted(
2793           """
2794       |fun f() {
2795       |  four
2796       |      .let {
2797       |        //
2798       |        foo()
2799       |      }
2800       |      .methodCall()
2801       |}
2802       |"""
2803               .trimMargin())
2804 
2805   @Test
keep last expression in qualified indentednull2806   fun `keep last expression in qualified indented`() =
2807       assertFormatted(
2808           """
2809       |----------------------------
2810       |fun f() {
2811       |  Stuff()
2812       |      .doIt(
2813       |          Foo.doIt()
2814       |              .doThat())
2815       |      .doIt(
2816       |          Foo.doIt()
2817       |              .doThat())
2818       |}
2819       |"""
2820               .trimMargin(),
2821           deduceMaxWidth = true)
2822 
2823   @Test
properly place lambda arguments into blocksnull2824   fun `properly place lambda arguments into blocks`() =
2825       assertFormatted(
2826           """
2827       |-----------------------
2828       |fun f() {
2829       |  foo {
2830       |    red.orange.yellow()
2831       |  }
2832       |
2833       |  foo.bar {
2834       |    red.orange.yellow()
2835       |  }
2836       |}
2837       |"""
2838               .trimMargin(),
2839           deduceMaxWidth = true)
2840 
2841   @Test
properly handle one statement lambda with commentnull2842   fun `properly handle one statement lambda with comment`() =
2843       assertFormatted(
2844           """
2845       |-----------------------
2846       |fun f() {
2847       |  foo {
2848       |    // this is a comment
2849       |    red.orange.yellow()
2850       |  }
2851       |  foo {
2852       |    /* this is also a comment */
2853       |    red.orange.yellow()
2854       |  }
2855       |  foo.bar {
2856       |    // this is a comment
2857       |    red.orange.yellow()
2858       |  }
2859       |  foo.bar() {
2860       |    // this is a comment
2861       |    red.orange.yellow()
2862       |  }
2863       |  foo.bar {
2864       |    /* this is also a comment */
2865       |    red.orange.yellow()
2866       |  }
2867       |}
2868       |"""
2869               .trimMargin(),
2870           deduceMaxWidth = true)
2871 
2872   @Test
properly handle one statement lambda with comment after body statementsnull2873   fun `properly handle one statement lambda with comment after body statements`() =
2874       assertFormatted(
2875           """
2876       |-----------------------
2877       |fun f() {
2878       |  foo {
2879       |    red.orange.yellow()
2880       |    // this is a comment
2881       |  }
2882       |  foo {
2883       |    red.orange.yellow()
2884       |    /* this is also a comment */
2885       |  }
2886       |  foo.bar {
2887       |    red.orange.yellow()
2888       |    // this is a comment
2889       |  }
2890       |  foo.bar() {
2891       |    red.orange.yellow()
2892       |    // this is a comment
2893       |  }
2894       |  foo.bar {
2895       |    red.orange.yellow()
2896       |    /* this is also a comment */
2897       |  }
2898       |  red.orange.yellow()
2899       |  // this is a comment
2900       |}
2901       |"""
2902               .trimMargin(),
2903           deduceMaxWidth = true)
2904 
2905   @Test
try to keep expression in the same line until the first lambdanull2906   fun `try to keep expression in the same line until the first lambda`() =
2907       assertFormatted(
2908           """
2909       |-------------------------
2910       |fun f() {
2911       |  foo.bar.bar?.let {
2912       |    a()
2913       |  }
2914       |  foo.bar.bar?.let {
2915       |    action()
2916       |    action2()
2917       |  }
2918       |  foo.bar.bar.bar.bar
2919       |      ?.let { a() }
2920       |  foo.bar.bar.bar.bar
2921       |      ?.let {
2922       |        action()
2923       |        action2()
2924       |      }
2925       |}
2926       |"""
2927               .trimMargin(),
2928           deduceMaxWidth = true)
2929 
2930   @Test
different indentation in chained callsnull2931   fun `different indentation in chained calls`() =
2932       assertFormatted(
2933           """
2934       |---------------------------
2935       |fun f() {
2936       |  fooDdoIt(
2937       |      foo1, foo2, foo3)
2938       |  foo.doIt(
2939       |      foo1, foo2, foo3)
2940       |  foo.doIt(
2941       |          foo1, foo2, foo3)
2942       |      .doThat()
2943       |}
2944       |"""
2945               .trimMargin(),
2946           deduceMaxWidth = true)
2947 
2948   @Test
always add a conditional break for a lambda which is not lastnull2949   fun `always add a conditional break for a lambda which is not last`() =
2950       assertFormatted(
2951           """
2952       |--------------------
2953       |fun f() {
2954       |  foofoo
2955       |      .doIt {
2956       |        doStuff()
2957       |      }
2958       |      .doIt {
2959       |        doStuff()
2960       |      }
2961       |}
2962       |"""
2963               .trimMargin(),
2964           deduceMaxWidth = true)
2965 
2966   @Test
keep parenthesis and braces together when there's only one lambda argumentnull2967   fun `keep parenthesis and braces together when there's only one lambda argument`() =
2968       assertFormatted(
2969           """
2970       |fun f() {
2971       |  doIt({})
2972       |  doIt({ it + it })
2973       |  doIt({
2974       |    val a = it
2975       |    a + a
2976       |  })
2977       |  doIt(functor = { it + it })
2978       |  doIt(
2979       |      functor = {
2980       |        val a = it
2981       |        a + a
2982       |      })
2983       |}
2984       |"""
2985               .trimMargin())
2986 
2987   @Test
Qualified typenull2988   fun `Qualified type`() =
2989       assertFormatted(
2990           """
2991       |fun f() {
2992       |  var plusFour: Indent.Const
2993       |  var x: Map.Entry<String, Integer>
2994       |  var x: List<String>.Iterator
2995       |}
2996       |"""
2997               .trimMargin())
2998 
2999   @Test
handle destructuring declaration in for loopnull3000   fun `handle destructuring declaration in for loop`() =
3001       assertFormatted(
3002           """
3003       |fun f(a: List<Pair<Int, Int>>) {
3004       |  for ((x, y: Int) in a) {}
3005       |}
3006       |"""
3007               .trimMargin())
3008 
3009   @Test
handle function referencesnull3010   fun `handle function references`() =
3011       assertFormatted(
3012           """
3013       |--------------------------------
3014       |fun f(a: List<Int>) {
3015       |  a.forEach(::println)
3016       |  a.map(Int::toString)
3017       |  a.map(String?::isNullOrEmpty)
3018       |  a.map(
3019       |      SuperLongClassName?::
3020       |          functionName)
3021       |  val f =
3022       |      SuperLongClassName::
3023       |          functionName
3024       |  val g =
3025       |      invoke(a, b)::functionName
3026       |  val h =
3027       |      invoke(a, b, c)::
3028       |          functionName
3029       |}
3030       |"""
3031               .trimMargin(),
3032           deduceMaxWidth = true)
3033 
3034   @Test
handle escaped identifiernull3035   fun `handle escaped identifier`() =
3036       assertFormatted(
3037           """
3038       |import foo as `foo foo`
3039       |import org.mockito.Mockito.`when` as `yay yay`
3040       |
3041       |fun `spaces in functions`() {
3042       |  val `when` = NEVER
3043       |  val (`do not`, `ever write`) = SERIOUSLY
3044       |  val `a a`: Int
3045       |  `yay yay`(`foo foo`)
3046       |}
3047       |
3048       |class `more spaces`
3049       |"""
3050               .trimMargin())
3051 
3052   @Test
handle annotations with argumentsnull3053   fun `handle annotations with arguments`() =
3054       assertFormatted(
3055           """
3056       |@Px fun f(): Int = 5
3057       |
3058       |@Dimenstion(unit = DP) fun g(): Int = 5
3059       |
3060       |@RunWith(MagicRunner::class)
3061       |@Px
3062       |class Test {
3063       |  //
3064       |}
3065       |"""
3066               .trimMargin())
3067 
3068   @Test
no newlines after annotations if entire expr fits in one linenull3069   fun `no newlines after annotations if entire expr fits in one line`() =
3070       assertFormatted(
3071           """
3072       |-----------------------------------------------
3073       |@Px @Px fun f(): Int = 5
3074       |
3075       |@Px
3076       |@Px
3077       |@Px
3078       |@Px
3079       |@Px
3080       |@Px
3081       |@Px
3082       |@Px
3083       |fun f(): Int = 5
3084       |
3085       |@Px
3086       |@Px
3087       |fun f(): Int {
3088       |  return 5
3089       |}
3090       |
3091       |@Dimenstion(unit = DP) @Px fun g(): Int = 5
3092       |
3093       |@Dimenstion(unit = DP)
3094       |@Px
3095       |fun g(): Int {
3096       |  return 5
3097       |}
3098       |
3099       |@RunWith @Px class Test
3100       |
3101       |@RunWith(MagicRunner::class) @Px class Test
3102       |
3103       |@RunWith @Px class Test {}
3104       |
3105       |@RunWith(MagicRunner::class) @Px class Test {}
3106       |
3107       |@RunWith(MagicRunner::class)
3108       |@Px
3109       |@Px
3110       |class Test {}
3111       |
3112       |@RunWith(MagicRunner::class)
3113       |@Px
3114       |class Test {
3115       |  //
3116       |}
3117       |
3118       |fun f() {
3119       |  if (@Stuff(Magic::class) isGood()) {
3120       |    println("")
3121       |  }
3122       |}
3123       |"""
3124               .trimMargin(),
3125           deduceMaxWidth = true)
3126 
3127   @Test
no newlines after annotations on properties if entire expression fits in one linenull3128   fun `no newlines after annotations on properties if entire expression fits in one line`() =
3129       assertFormatted(
3130           """
3131       |--------------------------------------------
3132       |@Suppress("UnsafeCast")
3133       |val ClassA.methodA
3134       |  get() = foo as Bar
3135       |"""
3136               .trimMargin(),
3137           deduceMaxWidth = true)
3138 
3139   @Test
3140   fun `when annotations cause line breaks, and constant has no type dont break before value`() =
3141       assertFormatted(
3142           """
3143       |----------------------------------------------------------
3144       |object Foo {
3145       |  @LongLongLongLongAnnotation
3146       |  @LongLongLongLongLongAnnotation
3147       |  private val ROW_HEIGHT = 72
3148       |}
3149       |"""
3150               .trimMargin(),
3151           deduceMaxWidth = true)
3152 
3153   @Test
annotations in literal function typesnull3154   fun `annotations in literal function types`() =
3155       assertFormatted(
3156           """
3157       |val callback: (@Anno List<@JvmSuppressWildcards String>) -> Unit = foo
3158       |"""
3159               .trimMargin())
3160 
3161   @Test
3162   fun `annotations on type parameters`() =
3163       assertFormatted(
3164           """
3165       |class Foo<@Anno out @Anno T, @Anno in @Anno U> {
3166       |  inline fun <@Anno reified @Anno X, @Anno reified @Anno Y> bar() {}
3167       |}
3168       |"""
3169               .trimMargin())
3170 
3171   @Test
annotations on type constraintsnull3172   fun `annotations on type constraints`() =
3173       assertFormatted(
3174           """
3175       |class Foo<T : @Anno Kip, U> where U : @Anno Kip, U : @Anno Qux {
3176       |  fun <T : @Anno Kip, U> bar() where U : @Anno Kip, U : @Anno Qux {}
3177       |}
3178       |"""
3179               .trimMargin())
3180 
3181   @Test
annotations on type argumentsnull3182   fun `annotations on type arguments`() =
3183       assertFormatted(
3184           """
3185       |fun foo(x: Foo<in @Anno Int>) {}
3186       |"""
3187               .trimMargin())
3188 
3189   @Test
annotations on destructuring declaration elementsnull3190   fun `annotations on destructuring declaration elements`() =
3191       assertFormatted(
3192           """
3193       |val x = { (@Anno x, @Anno y) -> x }
3194       |"""
3195               .trimMargin())
3196 
3197   @Test
annotations on exceptionsnull3198   fun `annotations on exceptions`() =
3199       assertFormatted(
3200           """
3201       |fun doIt() {
3202       |  try {
3203       |    doItAgain()
3204       |  } catch (@Nullable e: Exception) {
3205       |    //
3206       |  } catch (@Suppress("GeneralException") e: Exception) {}
3207       |}
3208       |"""
3209               .trimMargin())
3210 
3211   @Test
Unary prefix expressionsnull3212   fun `Unary prefix expressions`() =
3213       assertFormatted(
3214           """
3215       |fun f() {
3216       |  !a
3217       |  -4
3218       |  val x = -foo()
3219       |  +4
3220       |  ++a
3221       |  --a
3222       |
3223       |  + +a
3224       |  +-a
3225       |  +!a
3226       |  -+a
3227       |  - -a
3228       |  -!a
3229       |  !+a
3230       |  !a
3231       |  ! !a
3232       |
3233       |  + ++a
3234       |  +--a
3235       |  -++a
3236       |  - --a
3237       |  !++a
3238       |  !--a
3239       |}
3240       |"""
3241               .trimMargin())
3242 
3243   @Test
Unary postfix expressionsnull3244   fun `Unary postfix expressions`() =
3245       assertFormatted(
3246           """
3247       |fun f() {
3248       |  a!!
3249       |  a++
3250       |  a--
3251       |
3252       |  a--!!
3253       |  a++!!
3254       |
3255       |  a!! !!
3256       |}
3257       |"""
3258               .trimMargin())
3259 
3260   @Test
handle wildcard genericsnull3261   fun `handle wildcard generics`() =
3262       assertFormatted(
3263           """
3264       |fun f() {
3265       |  val l: List<*>
3266       |  val p: Pair<*, *>
3267       |}
3268       |"""
3269               .trimMargin())
3270 
3271   @Test
handle intersection genericsnull3272   fun `handle intersection generics`() =
3273       assertFormatted(
3274           """
3275       |fun f() {
3276       |  val l: Decl<A & B & C>
3277       |  val p = Ctor<A & B & C, T & Y & Z>
3278       |}
3279       |"""
3280               .trimMargin())
3281 
3282   @Test
handle covariant and contravariant type argumentsnull3283   fun `handle covariant and contravariant type arguments`() =
3284       assertFormatted(
3285           """
3286       |val p: Pair<in T, out S>
3287       |"""
3288               .trimMargin())
3289 
3290   @Test
3291   fun `handle covariant and contravariant type parameters`() =
3292       assertFormatted(
3293           """
3294       |class Foo<in T, out S>
3295       |"""
3296               .trimMargin())
3297 
3298   @Test
3299   fun `handle bounds for type parameters`() =
3300       assertFormatted(
3301           """
3302       |class Foo<in T : List<*>, out S : Any?>
3303       |"""
3304               .trimMargin())
3305 
3306   @Test
3307   fun `handle compound generic bounds on classes`() =
3308       assertFormatted(
3309           """
3310       |class Foo<T>(n: Int) where T : Bar, T : FooBar {}
3311       |"""
3312               .trimMargin())
3313 
3314   @Test
handle compound generic bounds on functionsnull3315   fun `handle compound generic bounds on functions`() =
3316       assertFormatted(
3317           """
3318       |fun <T> foo(n: Int) where T : Bar, T : FooBar {}
3319       |"""
3320               .trimMargin())
3321 
3322   @Test
handle compound generic bounds on propertiesnull3323   fun `handle compound generic bounds on properties`() =
3324       assertFormatted(
3325           """
3326       |val <T> List<T>.twiceSum: Int where T : Int
3327       |  get() {
3328       |    return 2 * sum()
3329       |  }
3330       |"""
3331               .trimMargin())
3332 
3333   @Test
handle compound generic bounds on class with delegatenull3334   fun `handle compound generic bounds on class with delegate`() =
3335       assertFormatted(
3336           """
3337       |class Foo<T>() : Bar by bar
3338       |where T : Qux
3339       |"""
3340               .trimMargin())
3341 
3342   @Test
3343   fun `explicit type on property getter`() =
3344       assertFormatted(
3345           """
3346       |class Foo {
3347       |  val silly: Int
3348       |    get(): Int = 1
3349       |}
3350       |"""
3351               .trimMargin())
3352 
3353   @Test
handle method calls with lambda arg onlynull3354   fun `handle method calls with lambda arg only`() =
3355       assertFormatted(
3356           """
3357       |fun f() {
3358       |  val a = g { 1 + 1 }
3359       |}
3360       |"""
3361               .trimMargin())
3362 
3363   @Test
handle method calls value args and a lambda argnull3364   fun `handle method calls value args and a lambda arg`() =
3365       assertFormatted(
3366           """
3367       |fun f() {
3368       |  val a = g(1, 2) { 1 + 1 }
3369       |}
3370       |"""
3371               .trimMargin())
3372 
3373   @Test
handle top level constantsnull3374   fun `handle top level constants`() =
3375       assertFormatted(
3376           """
3377       |-----------------------------
3378       |val a = 5
3379       |
3380       |const val b = "a"
3381       |
3382       |val a = 5
3383       |"""
3384               .trimMargin(),
3385           deduceMaxWidth = true)
3386 
3387   @Test
3388   fun `handle lambda arg with named arguments`() =
3389       assertFormatted(
3390           """
3391       |fun f() {
3392       |  val b = { x: Int, y: Int -> x + y }
3393       |}
3394       |"""
3395               .trimMargin())
3396 
3397   @Test
avoid newline before lambda argument if it is namednull3398   fun `avoid newline before lambda argument if it is named`() =
3399       assertFormatted(
3400           """
3401       |private fun f(items: List<Int>) {
3402       |  doSomethingCool(
3403       |      items,
3404       |      lambdaArgument = {
3405       |        step1()
3406       |        step2()
3407       |      }) {
3408       |        it.doIt()
3409       |      }
3410       |}
3411       |"""
3412               .trimMargin())
3413 
3414   @Test
handle labeled this pointernull3415   fun `handle labeled this pointer`() =
3416       assertFormatted(
3417           """
3418       |class Foo {
3419       |  fun f() {
3420       |    g { println(this@Foo) }
3421       |  }
3422       |}
3423       |"""
3424               .trimMargin())
3425 
3426   @Test
handle extension and operator functionsnull3427   fun `handle extension and operator functions`() =
3428       assertFormatted(
3429           """
3430       |operator fun Point.component1() = x
3431       |"""
3432               .trimMargin())
3433 
3434   @Test
3435   fun `handle extension methods with very long names`() =
3436       assertFormatted(
3437           """
3438       |------------------------------------------
3439       |fun LongReceiverNameThatRequiresBreaking
3440       |    .doIt() {}
3441       |
3442       |fun LongButNotTooLong.doIt(
3443       |    n: Int,
3444       |    f: Float
3445       |) {}
3446       |"""
3447               .trimMargin(),
3448           deduceMaxWidth = true)
3449 
3450   @Test
handle extension propertiesnull3451   fun `handle extension properties`() =
3452       assertFormatted(
3453           """
3454       |val Int.isPrime: Boolean
3455       |  get() = runMillerRabinPrimality(this)
3456       |"""
3457               .trimMargin())
3458 
3459   @Test
3460   fun `generic extension property`() =
3461       assertFormatted(
3462           """
3463       |val <T> List<T>.twiceSize = 2 * size()
3464       |"""
3465               .trimMargin())
3466 
3467   @Test
3468   fun `handle file annotations`() =
3469       assertFormatted(
3470           """
3471       |@file:JvmName("DifferentName")
3472       |
3473       |package com.somecompany.example
3474       |
3475       |import com.somecompany.example2
3476       |
3477       |class Foo {
3478       |  val a = example2("and 1")
3479       |}
3480       |"""
3481               .trimMargin())
3482 
3483   @Test
handle init blocknull3484   fun `handle init block`() =
3485       assertFormatted(
3486           """
3487       |class Foo {
3488       |  init {
3489       |    println("Init!")
3490       |  }
3491       |}
3492       |"""
3493               .trimMargin())
3494 
3495   @Test
handle interface delegationnull3496   fun `handle interface delegation`() =
3497       assertFormatted(
3498           """
3499       |class MyList(impl: List<Int>) : Collection<Int> by impl
3500       |"""
3501               .trimMargin())
3502 
3503   @Test
3504   fun `handle property delegation`() =
3505       assertFormatted(
3506           """
3507       |val a by lazy { 1 + 1 }
3508       |"""
3509               .trimMargin())
3510 
3511   @Test
handle property delegation with type and breaksnull3512   fun `handle property delegation with type and breaks`() =
3513       assertFormatted(
3514           """
3515       |---------------------------------
3516       |val importantValue: Int by lazy {
3517       |  1 + 1
3518       |}
3519       |
3520       |val importantValue: Int by lazy {
3521       |  val b = 1 + 1
3522       |  b + b
3523       |}
3524       |
3525       |val importantValueLonger:
3526       |    Int by lazy { 1 + 1 }
3527       |
3528       |val importantValue: Int by
3529       |    doIt(1 + 1)
3530       |"""
3531               .trimMargin(),
3532           deduceMaxWidth = true)
3533 
3534   @Test
handle multi-annotations with use-site targetsnull3535   fun `handle multi-annotations with use-site targets`() =
3536       assertFormatted(
3537           """
3538     |class Something {
3539     |  @field:[Inject Named("WEB_VIEW")]
3540     |  internal lateinit var httpClient: OkHttpClient
3541     |
3542     |  @field:[Inject Named("WEB_VIEW")]
3543     |  var httpClient: OkHttpClient
3544     |
3545     |  @Px
3546     |  @field:[Inject Named("WEB_VIEW")]
3547     |  var httpClient: OkHttpClient
3548     |}
3549     |
3550     """
3551               .trimMargin())
3552 
3553   @Test
handle parameters with annoations with parametersnull3554   fun `handle parameters with annoations with parameters`() =
3555       assertFormatted(
3556           """
3557     |class Something {
3558     |  fun doIt(@Magic(withHat = true) foo: Foo) {
3559     |    println(foo)
3560     |  }
3561     |}
3562     |
3563     """
3564               .trimMargin())
3565 
3566   @Test
handle lambda typesnull3567   fun `handle lambda types`() =
3568       assertFormatted(
3569           """
3570       |val listener1: (Boolean) -> Unit = { b -> !b }
3571       |
3572       |val listener2: () -> Unit = {}
3573       |
3574       |val listener3: (Int, Double) -> Int = { a, b -> a }
3575       |
3576       |val listener4: Int.(Int, Boolean) -> Unit
3577       |"""
3578               .trimMargin())
3579 
3580   @Test
handle unicode in string literalsnull3581   fun `handle unicode in string literals`() =
3582       assertFormatted(
3583           """
3584       |val a = "\uD83D\uDC4D"
3585       |"""
3586               .trimMargin())
3587 
3588   @Test
3589   fun `handle casting`() =
3590       assertFormatted(
3591           """
3592       |fun castIt(o: Object) {
3593       |  println(o is Double)
3594       |  println(o !is Double)
3595       |  doIt(o as Int)
3596       |  doIt(o as? Int)
3597       |}
3598       |"""
3599               .trimMargin())
3600 
3601   @Test
handle casting with breaksnull3602   fun `handle casting with breaks`() =
3603       assertFormatted(
3604           """
3605       |-----------------------
3606       |fun castIt(
3607       |    something: Any
3608       |) {
3609       |  doIt(
3610       |      something
3611       |          as List<*>)
3612       |  doIt(
3613       |      something
3614       |          is List<*>)
3615       |  println(
3616       |      something
3617       |          is
3618       |          List<String>)
3619       |  doIt(
3620       |      something
3621       |          as
3622       |          List<String>)
3623       |  println(
3624       |      something
3625       |          is
3626       |          PairList<
3627       |              String,
3628       |              Int>)
3629       |  doIt(
3630       |      something
3631       |          as
3632       |          PairList<
3633       |              String,
3634       |              Int>)
3635       |  println(
3636       |      a is Int &&
3637       |          b is String)
3638       |  l.b?.s?.sOrNull() is
3639       |      SomethingLongEnough
3640       |}
3641       |
3642       |val a =
3643       |    l.sOrNull() is
3644       |        SomethingLongEnough
3645       |"""
3646               .trimMargin(),
3647           deduceMaxWidth = true)
3648 
3649   @Test
handle collection literals in annotationsnull3650   fun `handle collection literals in annotations`() =
3651       assertFormatted(
3652           """
3653       |@Foo(a = [1, 2])
3654       |fun doIt(o: Object) {
3655       |  //
3656       |}
3657       |"""
3658               .trimMargin())
3659 
3660   @Test
handle try, catch and finallynull3661   fun `handle try, catch and finally`() =
3662       assertFormatted(
3663           """
3664       |fun foo() {
3665       |  try {
3666       |    bar()
3667       |  } catch (e: Exception) {
3668       |    throw e
3669       |  } finally {
3670       |    println("finally")
3671       |  }
3672       |}
3673       |"""
3674               .trimMargin())
3675 
3676   @Test
handle infix methodsnull3677   fun `handle infix methods`() =
3678       assertFormatted(
3679           """
3680       |fun numbers() {
3681       |  (0 until 100).size
3682       |}
3683       |"""
3684               .trimMargin())
3685 
3686   @Test
handle while loopsnull3687   fun `handle while loops`() =
3688       assertFormatted(
3689           """
3690       |fun numbers() {
3691       |  while (1 < 2) {
3692       |    println("Everything is okay")
3693       |  }
3694       |}
3695       |"""
3696               .trimMargin())
3697 
3698   @Test
handle do while loopsnull3699   fun `handle do while loops`() =
3700       assertFormatted(
3701           """
3702       |fun numbers() {
3703       |  do {
3704       |    println("Everything is okay")
3705       |  } while (1 < 2)
3706       |
3707       |  do while (1 < 2)
3708       |}
3709       |"""
3710               .trimMargin())
3711 
3712   @Test
handle break and continuenull3713   fun `handle break and continue`() =
3714       assertFormatted(
3715           """
3716       |fun numbers() {
3717       |  while (1 < 2) {
3718       |    if (true) {
3719       |      break
3720       |    }
3721       |    if (false) {
3722       |      continue
3723       |    }
3724       |  }
3725       |}
3726       |"""
3727               .trimMargin())
3728 
3729   @Test
handle all kinds of labels and jumpsnull3730   fun `handle all kinds of labels and jumps`() =
3731       assertFormatted(
3732           """
3733       |fun f(a: List<Int>) {
3734       |  a.map {
3735       |    myloop@ for (i in a) {
3736       |      if (true) {
3737       |        break@myloop
3738       |      } else if (false) {
3739       |        continue@myloop
3740       |      } else {
3741       |        a.map `inner map`@{
3742       |          return@`inner map`
3743       |        }
3744       |      }
3745       |    }
3746       |    return@map 2 * it
3747       |  }
3748       |}
3749       |"""
3750               .trimMargin())
3751 
3752   @Test
don't crash on top level statements with semicolonsnull3753   fun `don't crash on top level statements with semicolons`() {
3754     val code =
3755         """
3756       |val x = { 0 };
3757       |
3758       |foo({ 0 });
3759       |
3760       |foo { 0 };
3761       |
3762       |val fill = 0;
3763       |"""
3764             .trimMargin()
3765     val expected =
3766         """
3767       |val x = { 0 }
3768       |
3769       |foo({ 0 })
3770       |
3771       |foo { 0 }
3772       |
3773       |val fill = 0
3774       |"""
3775             .trimMargin()
3776     assertThatFormatting(code).isEqualTo(expected)
3777   }
3778 
3779   @Test
preserve semicolons in enumsnull3780   fun `preserve semicolons in enums`() {
3781     val code =
3782         """
3783       |enum class SemiColonIsNotRequired {
3784       |  TRUE, FALSE;
3785       |}
3786       |
3787       |enum class SemiColonIsRequired {
3788       |  ONE, TWO;
3789       |
3790       |  fun isOne(): Boolean = this == ONE
3791       |}
3792       |"""
3793             .trimMargin()
3794     val expected =
3795         """
3796       |enum class SemiColonIsNotRequired {
3797       |  TRUE,
3798       |  FALSE
3799       |}
3800       |
3801       |enum class SemiColonIsRequired {
3802       |  ONE,
3803       |  TWO;
3804       |
3805       |  fun isOne(): Boolean = this == ONE
3806       |}
3807       |"""
3808             .trimMargin()
3809     assertThatFormatting(code).isEqualTo(expected)
3810   }
3811 
3812   @Test
preserve semicolons in comments and stringsnull3813   fun `preserve semicolons in comments and strings`() {
3814     val code =
3815         """
3816       |fun f() {
3817       |  val x = ";"
3818       |  val x = $TQ  don't touch ; in raw strings $TQ
3819       |}
3820       |
3821       |// Don't touch ; inside comments.
3822       |
3823       |/** Don't touch ; inside comments. */
3824       |"""
3825             .trimMargin()
3826     val expected =
3827         """
3828       |fun f() {
3829       |  val x = ";"
3830       |  val x = $TQ  don't touch ; in raw strings $TQ
3831       |}
3832       |
3833       |// Don't touch ; inside comments.
3834       |
3835       |/** Don't touch ; inside comments. */
3836       |"""
3837             .trimMargin()
3838     assertThatFormatting(code).isEqualTo(expected)
3839   }
3840 
3841   @Test
3842   fun `preserve semicolons in empty if-s and while-s`() {
3843     val code =
3844         """
3845       |fun f() {
3846       |  while (true);
3847       |  while (true) /** a */ ;
3848       |
3849       |  if (true);
3850       |  if (true) /** a */ ;
3851       |
3852       |  if (true)
3853       |    else
3854       |  ;
3855       |}
3856       |"""
3857             .trimMargin()
3858     val expected =
3859         """
3860       |fun f() {
3861       |  while (true) ;
3862       |  while (true)
3863       |  /** a */
3864       |  ;
3865       |
3866       |  if (true) ;
3867       |  if (true)
3868       |  /** a */
3869       |   ;
3870       |
3871       |  if (true)  else ;
3872       |}
3873       |"""
3874             .trimMargin()
3875     assertThatFormatting(code).isEqualTo(expected)
3876   }
3877 
3878   @Test
3879   fun `preserve semicolons between calls and dead lambdas`() {
3880     val code =
3881         """
3882       |fun f() {
3883       |  foo(0); { dead -> lambda }
3884       |
3885       |  foo(0) ; { dead -> lambda }
3886       |
3887       |  foo(0) /** a */ ; /** b */ { dead -> lambda }
3888       |
3889       |  foo(0) { trailing -> lambda }; { dead -> lambda }
3890       |
3891       |  foo { trailing -> lambda }; { dead -> lambda }
3892       |
3893       |  val x = foo(); { dead -> lambda }
3894       |
3895       |  val x = bar() && foo(); { dead -> lambda }
3896       |
3897       |  // `z` has a property and a method both named `bar`
3898       |  val x = z.bar; { dead -> lambda }
3899       |
3900       |  // `this` has a property and a method both named `bar`
3901       |  val x = bar; { dead -> lambda }
3902       |
3903       |  // Literally any callable expression is dangerous
3904       |  val x = (if (cond) x::foo else x::bar); { dead -> lambda }
3905       |}
3906       |"""
3907             .trimMargin()
3908     val expected =
3909         """
3910       |fun f() {
3911       |  foo(0);
3912       |  { dead -> lambda }
3913       |
3914       |  foo(0);
3915       |  { dead -> lambda }
3916       |
3917       |  foo(0)
3918       |  /** a */
3919       |  ;
3920       |  /** b */
3921       |  { dead -> lambda }
3922       |
3923       |  foo(0) { trailing -> lambda };
3924       |  { dead -> lambda }
3925       |
3926       |  foo { trailing -> lambda };
3927       |  { dead -> lambda }
3928       |
3929       |  val x = foo();
3930       |  { dead -> lambda }
3931       |
3932       |  val x = bar() && foo();
3933       |  { dead -> lambda }
3934       |
3935       |  // `z` has a property and a method both named `bar`
3936       |  val x = z.bar;
3937       |  { dead -> lambda }
3938       |
3939       |  // `this` has a property and a method both named `bar`
3940       |  val x = bar;
3941       |  { dead -> lambda }
3942       |
3943       |  // Literally any callable expression is dangerous
3944       |  val x = (if (cond) x::foo else x::bar);
3945       |  { dead -> lambda }
3946       |}
3947       |"""
3948             .trimMargin()
3949     assertThatFormatting(code).isEqualTo(expected)
3950   }
3951 
3952   @Test
3953   fun `drop redundant semicolons`() {
3954     val code =
3955         """
3956       |package org.examples;
3957       |import org.examples.wow.MuchWow;
3958       |import org.examples.wow.ManyAmaze
3959       |
3960       |typealias Int2 = Int;
3961       |
3962       |fun f() {
3963       |  val a = 3;
3964       |  val x = 5 ; val y = ManyAmaze();
3965       |  myThingMap.forEach { val (key, value) = it; println("mapped ${"$"}MuchWow") }
3966       |  when {
3967       |    true -> "1"; false -> "0"
3968       |  }
3969       |  someLongVariableName.let {
3970       |    someReallyLongFunctionNameThatMakesThisNotFitInOneLineWithTheAboveVariable();
3971       |  }
3972       |  if (cond) ; else 6
3973       |} ;
3974       |
3975       |"""
3976             .trimMargin()
3977     val expected =
3978         """
3979       |package org.examples
3980       |
3981       |import org.examples.wow.ManyAmaze
3982       |import org.examples.wow.MuchWow
3983       |
3984       |typealias Int2 = Int
3985       |
3986       |fun f() {
3987       |  val a = 3
3988       |  val x = 5
3989       |  val y = ManyAmaze()
3990       |  myThingMap.forEach {
3991       |    val (key, value) = it
3992       |    println("mapped ${"$"}MuchWow")
3993       |  }
3994       |  when {
3995       |    true -> "1"
3996       |    false -> "0"
3997       |  }
3998       |  someLongVariableName.let {
3999       |    someReallyLongFunctionNameThatMakesThisNotFitInOneLineWithTheAboveVariable()
4000       |  }
4001       |  if (cond)  else 6
4002       |}
4003       |"""
4004             .trimMargin()
4005     assertThatFormatting(code).isEqualTo(expected)
4006   }
4007 
4008   @Test
4009   fun `pretty-print after dropping redundant semicolons`() {
4010     val code =
4011         """
4012       |fun f() {
4013       |  val veryLongName = 5;
4014       |}
4015       |"""
4016             .trimMargin()
4017     val expected =
4018         """
4019       |fun f() {
4020       |  val veryLongName = 5
4021       |}
4022       |"""
4023             .trimMargin()
4024     assertThatFormatting(code).withOptions(FormattingOptions(maxWidth = 22)).isEqualTo(expected)
4025   }
4026 
4027   @Test
4028   fun `handle no parenthesis in lambda calls`() =
4029       assertFormatted(
4030           """
4031       |fun f() {
4032       |  a { println("a") }
4033       |}
4034       |"""
4035               .trimMargin())
4036 
4037   @Test
4038   fun `handle multi statement lambdas`() =
4039       assertFormatted(
4040           """
4041       |fun f() {
4042       |  a {
4043       |    println("a")
4044       |    println("b")
4045       |  }
4046       |}
4047       |"""
4048               .trimMargin())
4049 
4050   @Test
4051   fun `handle multi line one statement lambda`() =
4052       assertFormatted(
4053           """
4054       |-------------------------
4055       |fun f() {
4056       |  a {
4057       |    println(foo.bar.boom)
4058       |  }
4059       |}
4060       |"""
4061               .trimMargin(),
4062           deduceMaxWidth = true)
4063 
4064   @Test
4065   fun `statements are wrapped in blocks`() =
4066       assertFormatted(
4067           """
4068       |fun f() {
4069       |  builder.block {
4070       |    getArgumentName().accept
4071       |    return
4072       |  }
4073       |}
4074       |"""
4075               .trimMargin())
4076 
4077   @Test
4078   fun `properly break fully qualified nested user types`() =
4079       assertFormatted(
4080           """
4081       |-------------------------------------------------------
4082       |val complicated:
4083       |    com.example.interesting.SomeType<
4084       |        com.example.interesting.SomeType<Int, Nothing>,
4085       |        com.example.interesting.SomeType<
4086       |            com.example.interesting.SomeType<
4087       |                Int, Nothing>,
4088       |            Nothing>> =
4089       |    DUMMY
4090       |"""
4091               .trimMargin(),
4092           deduceMaxWidth = true)
4093 
4094   @Test
4095   fun `handle multi-line lambdas within lambdas and calling chains`() =
4096       assertFormatted(
4097           """
4098       |fun f() {
4099       |  builder.block(ZERO) {
4100       |    builder.token("when")
4101       |    expression1.let { subjectExp ->
4102       |      builder.token(")")
4103       |      return
4104       |    }
4105       |  }
4106       |  builder.block(ZERO) {
4107       |    expression2.subjectExpression.let { subjectExp ->
4108       |      builder.token(")")
4109       |      return
4110       |    }
4111       |  }
4112       |  builder.block(ZERO) {
4113       |    expression2.subjectExpression
4114       |        .let { subjectExp ->
4115       |          builder.token(")")
4116       |          return
4117       |        }
4118       |        .sum
4119       |  }
4120       |}
4121       |"""
4122               .trimMargin())
4123 
4124   @Test
4125   fun `handle multi line lambdas with explicit args`() =
4126       assertFormatted(
4127           """
4128       |--------------------
4129       |fun f() {
4130       |  a { (x, y) ->
4131       |    x + y
4132       |  }
4133       |}
4134       |"""
4135               .trimMargin(),
4136           deduceMaxWidth = true)
4137 
4138   @Test
4139   fun `handle lambda with destructuring and type`() =
4140       assertFormatted(
4141           """
4142       |fun f() {
4143       |  g { (a, b): List<Int> -> a }
4144       |  g { (a, b): List<Int>, (c, d): List<Int> -> a }
4145       |}
4146       |"""
4147               .trimMargin())
4148 
4149   @Test
4150   fun `handle parenthesis in lambda calls for now`() =
4151       assertFormatted(
4152           """
4153       |fun f() {
4154       |  a() { println("a") }
4155       |}
4156       |"""
4157               .trimMargin())
4158 
4159   @Test
4160   fun `handle chaining of calls with lambdas`() =
4161       assertFormatted(
4162           """
4163       |fun f() {
4164       |  bobby
4165       |      .map { x -> x * x }
4166       |      .map { x -> x * x }
4167       |      ?.map { x ->
4168       |        val y = x * x
4169       |        y
4170       |      }
4171       |      .sum
4172       |}
4173       |"""
4174               .trimMargin())
4175 
4176   @Test
4177   fun `handle break of lambda args per line with indentation`() =
4178       assertFormatted(
4179           """
4180       |-----------
4181       |fun f() {
4182       |  a() {
4183       |      arg1,
4184       |      arg2,
4185       |      x ->
4186       |    doIt()
4187       |    doIt()
4188       |  }
4189       |  a() {
4190       |      arg1,
4191       |      arg2,
4192       |      arg3
4193       |    ->
4194       |    doIt()
4195       |    doIt()
4196       |  }
4197       |}
4198       |"""
4199               .trimMargin(),
4200           deduceMaxWidth = true)
4201 
4202   @Test
4203   fun `handle trailing comma in lambda`() =
4204       assertFormatted(
4205           """
4206       |-----------
4207       |fun f() {
4208       |  a() {
4209       |      arg1,
4210       |      arg2,
4211       |      x,
4212       |    ->
4213       |    doIt()
4214       |    doIt()
4215       |  }
4216       |}
4217       |"""
4218               .trimMargin(),
4219           deduceMaxWidth = true)
4220 
4221   @Test
4222   fun `break before Elvis operator`() =
4223       assertFormatted(
4224           """
4225         |--------------------------------------------------
4226         |fun f() {
4227         |  someObject
4228         |      .someMethodReturningCollection()
4229         |      .map { it.someProperty }
4230         |      .find { it.contains(someSearchValue) }
4231         |      ?: someDefaultValue
4232         |}
4233         |"""
4234               .trimMargin(),
4235           deduceMaxWidth = true)
4236 
4237   @Test
4238   fun `handle comments in the middle of calling chain`() =
4239       assertFormatted(
4240           """
4241         |---------------------------
4242         |fun f() {
4243         |  someObject
4244         |      .letsDoIt()
4245         |      // this is a comment
4246         |      .doItOnce()
4247         |      // this is a comment
4248         |      .doItTwice()
4249         |}
4250         |"""
4251               .trimMargin(),
4252           deduceMaxWidth = true)
4253 
4254   @Test
4255   fun `handle reified types`() =
4256       assertFormatted(
4257           """
4258       |inline fun <reified T> foo(t: T) {
4259       |  println(t)
4260       |}
4261       |
4262       |inline fun <reified in T> foo2(t: T) {
4263       |  println(t)
4264       |}
4265       |"""
4266               .trimMargin())
4267 
4268   @Test
4269   fun `handle suspended types`() =
4270       assertFormatted(
4271           """
4272       |private val reader: suspend (Key) -> Output?
4273       |
4274       |private val delete: (suspend (Key) -> Unit)? = null
4275       |
4276       |inline fun <R> foo(noinline block: suspend () -> R): suspend () -> R
4277       |
4278       |inline fun <R> bar(noinline block: (suspend () -> R)?): (suspend () -> R)?
4279       |"""
4280               .trimMargin())
4281 
4282   @Test
4283   fun `handle simple enum classes`() =
4284       assertFormatted(
4285           """
4286       |enum class BetterBoolean {
4287       |  TRUE,
4288       |  FALSE,
4289       |  FILE_NOT_FOUND,
4290       |}
4291       |"""
4292               .trimMargin())
4293 
4294   @Test
4295   fun `handle enum class with functions`() =
4296       assertFormatted(
4297           """
4298       |enum class BetterBoolean {
4299       |  TRUE,
4300       |  FALSE,
4301       |  FILE_NOT_FOUND;
4302       |  fun isGood(): Boolean {
4303       |    return true
4304       |  }
4305       |}
4306       |"""
4307               .trimMargin())
4308 
4309   @Test
4310   fun `handle enum with annotations`() =
4311       assertFormatted(
4312           """
4313       |enum class BetterBoolean {
4314       |  @True TRUE,
4315       |  @False @WhatIsTruth FALSE,
4316       |}
4317       |"""
4318               .trimMargin())
4319 
4320   @Test
4321   fun `handle enum constructor calls`() =
4322       assertFormatted(
4323           """
4324       |enum class BetterBoolean(val name: String, val value: Boolean = true) {
4325       |  TRUE("true"),
4326       |  FALSE("false", false),
4327       |}
4328       |"""
4329               .trimMargin())
4330 
4331   @Test
4332   fun `handle enum entries with body`() =
4333       assertFormatted(
4334           """
4335       |enum class Animal(canWalk: Boolean = true) {
4336       |  DOG {
4337       |    fun speak() = "woof"
4338       |  },
4339       |  FISH(false) {},
4340       |}
4341       |"""
4342               .trimMargin())
4343 
4344   @Test
4345   fun `handle empty enum`() =
4346       assertFormatted(
4347           """
4348       |enum class YTho {
4349       |}
4350       |"""
4351               .trimMargin())
4352 
4353   @Test
4354   fun `expect enum class`() =
4355       assertFormatted(
4356           """
4357       |expect enum class ExpectedEnum
4358       |"""
4359               .trimMargin())
4360 
4361   @Test
4362   fun `enum without trailing comma`() =
4363       assertFormatted(
4364           """
4365       |enum class Highlander {
4366       |  ONE
4367       |}
4368       |"""
4369               .trimMargin())
4370 
4371   @Test
4372   fun `enum comma and semicolon`() {
4373     assertThatFormatting(
4374             """
4375         |enum class Highlander {
4376         |  ONE,;
4377         |}
4378         |"""
4379                 .trimMargin())
4380         .isEqualTo(
4381             """
4382         |enum class Highlander {
4383         |  ONE,
4384         |}
4385         |"""
4386                 .trimMargin())
4387   }
4388 
4389   @Test
4390   fun `semicolon is placed on next line when there's a trailing comma in an enum declaration`() =
4391       assertFormatted(
4392           """
4393         |enum class Highlander {
4394         |  ONE,
4395         |  TWO,
4396         |  ;
4397         |
4398         |  fun f() {}
4399         |}
4400         |"""
4401               .trimMargin())
4402 
4403   @Test
4404   fun `handle varargs and spread operator`() =
4405       assertFormatted(
4406           """
4407       |fun foo(vararg args: String) {
4408       |  foo2(*args)
4409       |  foo3(options = *args)
4410       |}
4411       |"""
4412               .trimMargin())
4413 
4414   @Test
4415   fun `handle typealias`() =
4416       assertFormatted(
4417           """
4418       |----------------------------------------------
4419       |private typealias TextChangedListener =
4420       |    (string: String) -> Unit
4421       |
4422       |typealias PairPair<X, Y> = Pair<Pair<X, Y>, X>
4423       |
4424       |class Foo
4425       |"""
4426               .trimMargin(),
4427           deduceMaxWidth = true)
4428 
4429   @Test
4430   fun `handle the 'dynamic' type`() =
4431       assertFormatted(
4432           """
4433       |fun x(): dynamic = "x"
4434       |
4435       |val dyn: dynamic = 1
4436       |"""
4437               .trimMargin())
4438 
4439   @Test
4440   fun `handle class expression with generics`() =
4441       assertFormatted(
4442           """
4443       |fun f() {
4444       |  println(Array<String>::class.java)
4445       |}
4446       |"""
4447               .trimMargin())
4448 
4449   @Test
4450   fun `ParseError contains correct line and column numbers`() {
4451     val code =
4452         """
4453       |// Foo
4454       |fun good() {
4455       |  //
4456       |}
4457       |
4458       |fn (
4459       |"""
4460             .trimMargin()
4461     try {
4462       Formatter.format(code)
4463       fail()
4464     } catch (e: ParseError) {
4465       assertThat(e.lineColumn.line).isEqualTo(6)
4466       assertThat(e.lineColumn.column).isEqualTo(0)
4467       assertThat(e.errorDescription).contains("Expecting an expression")
4468     }
4469   }
4470 
4471   @Test
4472   fun `fail() reports line+column number`() {
4473     val code =
4474         """
4475       |// Foo
4476       |fun good() {
4477       |  return@ 5
4478       |}
4479       |"""
4480             .trimMargin()
4481     try {
4482       Formatter.format(code)
4483       fail()
4484     } catch (e: ParseError) {
4485       assertThat(e.lineColumn.line).isEqualTo(2)
4486       assertThat(e.lineColumn.column).isEqualTo(8)
4487     }
4488   }
4489 
4490   @Test
4491   fun `annotations on class, fun, parameters and literals`() =
4492       assertFormatted(
4493           """
4494       |@Fancy
4495       |class Foo {
4496       |  @Fancy
4497       |  fun baz(@Fancy foo: Int): Int {
4498       |    return (@Fancy 1)
4499       |  }
4500       |}
4501       |"""
4502               .trimMargin())
4503 
4504   @Test
4505   fun `annotations on function types`() =
4506       assertFormatted(
4507           """
4508       |fun foo(bar: @StringRes Int) {}
4509       |
4510       |fun foo(error: @Composable ((x) -> Unit)) {}
4511       |
4512       |fun foo(error: (@Composable (x) -> Unit)) {}
4513       |
4514       |fun foo(
4515       |    error:
4516       |        @field:[Inject Named("WEB_VIEW")]
4517       |        ((x) -> Unit)
4518       |) {}
4519       |
4520       |fun foo(
4521       |    error:
4522       |        (@field:[Inject Named("WEB_VIEW")]
4523       |        (x) -> Unit)
4524       |) {}
4525       |"""
4526               .trimMargin())
4527 
4528   @Test
4529   fun `handle annotations with use-site targets`() =
4530       assertFormatted(
4531           """
4532       |class FooTest {
4533       |  @get:Rule val exceptionRule: ExpectedException = ExpectedException.none()
4534       |
4535       |  @set:Magic(name = "Jane") var field: String
4536       |}
4537       |"""
4538               .trimMargin())
4539 
4540   @Test
4541   fun `handle annotations mixed with keywords since we cannot reorder them for now`() =
4542       assertFormatted(
4543           """
4544       |public @Magic final class Foo
4545       |
4546       |public @Magic(1) final class Foo
4547       |
4548       |@Magic(1) public final class Foo
4549       |"""
4550               .trimMargin())
4551 
4552   @Test
4553   fun `handle annotations more`() =
4554       assertFormatted(
4555           """
4556       |-------------------------------------------------
4557       |@Anno1
4558       |@Anno2(param = Param1::class)
4559       |@Anno3
4560       |@Anno4(param = Param2::class)
4561       |class MyClass {}
4562       |
4563       |fun f() {
4564       |  @Suppress("MagicNumber") add(10)
4565       |
4566       |  @Annotation // test a comment after annotations
4567       |  return 5
4568       |}
4569       |"""
4570               .trimMargin(),
4571           deduceMaxWidth = true)
4572 
4573   @Test
4574   fun `annotated expressions`() =
4575       assertFormatted(
4576           """
4577       |------------------------------------------------
4578       |fun f() {
4579       |  @Suppress("MagicNumber") add(10) && add(20)
4580       |
4581       |  @Suppress("MagicNumber")
4582       |  add(10) && add(20)
4583       |
4584       |  @Anno1 @Anno2(param = Param1::class)
4585       |  add(10) && add(20)
4586       |
4587       |  @Anno1
4588       |  @Anno2(param = Param1::class)
4589       |  @Anno3
4590       |  @Anno4(param = Param2::class)
4591       |  add(10) && add(20)
4592       |
4593       |  @Anno1
4594       |  @Anno2(param = Param1::class)
4595       |  @Anno3
4596       |  @Anno4(param = Param2::class)
4597       |  add(10) && add(20)
4598       |
4599       |  @Suppress("MagicNumber") add(10) &&
4600       |      add(20) &&
4601       |      add(30)
4602       |
4603       |  add(@Suppress("MagicNumber") 10) &&
4604       |      add(20) &&
4605       |      add(30)
4606       |}
4607       |"""
4608               .trimMargin(),
4609           deduceMaxWidth = true)
4610 
4611   @Test
4612   fun `annotated function declarations`() =
4613       assertFormatted(
4614           """
4615       |@Anno
4616       |fun f() {
4617       |  add(10)
4618       |}
4619       |
4620       |@Anno(param = 1)
4621       |fun f() {
4622       |  add(10)
4623       |}
4624       |"""
4625               .trimMargin())
4626 
4627   @Test
4628   fun `annotated class declarations`() =
4629       assertFormatted(
4630           """
4631       |@Anno class F
4632       |
4633       |@Anno(param = 1) class F
4634       |
4635       |@Anno(P)
4636       |// Foo
4637       |@Anno("param")
4638       |class F
4639       |"""
4640               .trimMargin())
4641 
4642   @Test
4643   fun `handle type arguments in annotations`() =
4644       assertFormatted(
4645           """
4646       |@TypeParceler<UUID, UUIDParceler>() class MyClass {}
4647       |"""
4648               .trimMargin())
4649 
4650   @Test
4651   fun `handle one line KDoc`() =
4652       assertFormatted(
4653           """
4654       |/** Hi, I am a one line kdoc */
4655       |class MyClass {}
4656       |"""
4657               .trimMargin())
4658 
4659   @Test
4660   fun `handle KDoc with Link`() =
4661       assertFormatted(
4662           """
4663       |/** This links to [AnotherClass] */
4664       |class MyClass {}
4665       |"""
4666               .trimMargin())
4667 
4668   @Test
4669   fun `handle KDoc with paragraphs`() =
4670       assertFormatted(
4671           """
4672       |/**
4673       | * Hi, I am a two paragraphs kdoc
4674       | *
4675       | * There's a space line to preserve between them
4676       | */
4677       |class MyClass {}
4678       |"""
4679               .trimMargin())
4680 
4681   @Test
4682   fun `handle KDoc with blocks`() =
4683       assertFormatted(
4684           """
4685       |/**
4686       | * Hi, I am a two paragraphs kdoc
4687       | *
4688       | * @param param1 this is param1
4689       | * @param[param2] this is param2
4690       | */
4691       |class MyClass {}
4692       |"""
4693               .trimMargin())
4694 
4695   @Test
4696   fun `handle KDoc with code examples`() =
4697       assertFormatted(
4698           """
4699       |/**
4700       | * This is how you write a simple hello world in Kotlin:
4701       | * ```
4702       | * fun main(args: Array<String>) {
4703       | *   println("Hello World!")
4704       | * }
4705       | * ```
4706       | *
4707       | * Amazing ah?
4708       | *
4709       | * ```
4710       | * fun `code can be with a blank line above it` () {}
4711       | * ```
4712       | *
4713       | * Or after it!
4714       | */
4715       |class MyClass {}
4716       |"""
4717               .trimMargin())
4718 
4719   @Test
4720   fun `handle KDoc with tagged code examples`() =
4721       assertFormatted(
4722           """
4723       |/**
4724       | * ```kotlin
4725       | * fun main(args: Array<String>) {
4726       | *   println("Hello World!")
4727       | * }
4728       | * ```
4729       | */
4730       |class MyClass {}
4731       |"""
4732               .trimMargin())
4733 
4734   @Test
4735   fun `handle stray code markers in lines and produce stable output`() {
4736     val code =
4737         """
4738       |/**
4739       | * Look! code: ``` aaa
4740       | * fun f() = Unit
4741       | * foo
4742       | * ```
4743       | */
4744       |class MyClass {}
4745       |"""
4746             .trimMargin()
4747     assertFormatted(Formatter.format(code))
4748   }
4749 
4750   @Test
4751   fun `code block with triple backtick`() {
4752     val code =
4753         """
4754       |/**
4755       | * Look! code:
4756       | * ```
4757       | * aaa ``` wow
4758       | * ```
4759       | */
4760       |class MyClass {}
4761       |"""
4762             .trimMargin()
4763     val expected =
4764         """
4765       |/**
4766       | * Look! code:
4767       | * ```
4768       | * aaa ``` wow
4769       | * ```
4770       | */
4771       |class MyClass {}
4772       |"""
4773             .trimMargin()
4774     assertThatFormatting(code).isEqualTo(expected)
4775   }
4776 
4777   @Test
4778   fun `when code closer in mid of line, produce stable output`() {
4779     val code =
4780         """
4781       |/**
4782       | * Look! code: ``` aaa
4783       | * fun f() = Unit
4784       | * foo ``` wow
4785       | */
4786       |class MyClass {}
4787       |"""
4788             .trimMargin()
4789     assertFormatted(Formatter.format(code))
4790   }
4791 
4792   @Test
4793   fun `handle KDoc with link reference`() =
4794       assertFormatted(
4795           """
4796       |/** Doc line with a reference to [AnotherClass] in the middle of a sentence */
4797       |class MyClass {}
4798       |"""
4799               .trimMargin())
4800 
4801   @Test
4802   fun `handle KDoc with links one after another`() =
4803       assertFormatted(
4804           """
4805       |/** Here are some links [AnotherClass] [AnotherClass2] */
4806       |class MyClass {}
4807       |"""
4808               .trimMargin())
4809 
4810   @Test
4811   fun `don't add spaces after links in Kdoc`() =
4812       assertFormatted(
4813           """
4814       |/** Here are some links [AnotherClass][AnotherClass2]hello */
4815       |class MyClass {}
4816       |"""
4817               .trimMargin())
4818 
4819   @Test
4820   fun `don't remove spaces after links in Kdoc`() =
4821       assertFormatted(
4822           """
4823       |/** Please see [onNext] (which has more details) */
4824       |class MyClass {}
4825       |"""
4826               .trimMargin())
4827 
4828   @Test
4829   fun `link anchor in KDoc are preserved`() =
4830       assertFormatted(
4831           """
4832       |/** [link anchor](the URL for the link anchor goes here) */
4833       |class MyClass {}
4834       |"""
4835               .trimMargin())
4836 
4837   @Test
4838   fun `don't add spaces between links in KDoc (because they're actually references)`() =
4839       assertFormatted(
4840           """
4841       |/** Here are some links [AnotherClass][AnotherClass2] */
4842       |class MyClass {}
4843       |
4844       |/** The final produced value may have [size][ByteString.size] < [bufferSize]. */
4845       |class MyClass {}
4846       |"""
4847               .trimMargin())
4848 
4849   @Test
4850   fun `collapse spaces after links in KDoc`() {
4851     val code =
4852         """
4853       |/** Here are some links [Class1], [Class2]   [Class3]. hello */
4854       |class MyClass {}
4855       |"""
4856             .trimMargin()
4857     val expected =
4858         """
4859       |/** Here are some links [Class1], [Class2] [Class3]. hello */
4860       |class MyClass {}
4861       |"""
4862             .trimMargin()
4863     assertThatFormatting(code).isEqualTo(expected)
4864   }
4865 
4866   @Test
4867   fun `collapse newlines after links in KDoc`() {
4868     val code =
4869         """
4870       |/**
4871       | * Here are some links [Class1]
4872       | * [Class2]
4873       | */
4874       |class MyClass {}
4875       |"""
4876             .trimMargin()
4877     val expected =
4878         """
4879       |/** Here are some links [Class1] [Class2] */
4880       |class MyClass {}
4881       |"""
4882             .trimMargin()
4883     assertThatFormatting(code).isEqualTo(expected)
4884   }
4885 
4886   @Test
4887   fun `do not crash because of malformed KDocs and produce stable output`() {
4888     val code =
4889         """
4890       |/** Surprise ``` */
4891       |class MyClass {}
4892       |"""
4893             .trimMargin()
4894     assertFormatted(Formatter.format(code))
4895   }
4896 
4897   @Test
4898   fun `Respect spacing of text after link`() =
4899       assertFormatted(
4900           """
4901       |/** Enjoy this link [linkstuff]. */
4902       |class MyClass {}
4903       |
4904       |/** There are many [FooObject]s. */
4905       |class MyClass {}
4906       |"""
4907               .trimMargin())
4908 
4909   @Test
4910   fun `handle KDoc with multiple separated param tags, breaking and merging lines and missing asterisk`() {
4911     val code =
4912         """
4913       |/**
4914       | * Trims leading whitespace characters followed by [marginPrefix] from every line of a source string and removes
4915       | * the first and the last lines if they are blank (notice difference blank vs empty).
4916       |
4917       | * Doesn't affect a line if it doesn't contain [marginPrefix] except the first and the last blank lines.
4918       | *
4919       | * Doesn't preserve the original line endings.
4920       | *
4921       | * @param marginPrefix non-blank string, which is used as a margin delimiter. Default is `|` (pipe character).
4922       | *
4923       | * @sample samples.text.Strings.trimMargin
4924       | * @see trimIndent
4925       | * @see kotlin.text.isWhitespace
4926       | */
4927       |class ThisWasCopiedFromTheTrimMarginMethod {}
4928       |"""
4929             .trimMargin()
4930     val expected =
4931         """
4932       |/**
4933       | * Trims leading whitespace characters followed by [marginPrefix] from every line of a source string
4934       | * and removes the first and the last lines if they are blank (notice difference blank vs empty).
4935       | *
4936       | * Doesn't affect a line if it doesn't contain [marginPrefix] except the first and the last blank
4937       | * lines.
4938       | *
4939       | * Doesn't preserve the original line endings.
4940       | *
4941       | * @param marginPrefix non-blank string, which is used as a margin delimiter. Default is `|` (pipe
4942       | *   character).
4943       | * @sample samples.text.Strings.trimMargin
4944       | * @see trimIndent
4945       | * @see kotlin.text.isWhitespace
4946       | */
4947       |class ThisWasCopiedFromTheTrimMarginMethod {}
4948       |"""
4949             .trimMargin()
4950     assertThatFormatting(code).isEqualTo(expected)
4951   }
4952 
4953   @Test
4954   fun `KDoc is reflowed`() {
4955     val code =
4956         """
4957       |/** Lorem ipsum dolor sit amet, consectetur */
4958       |class MyClass {}
4959       |"""
4960             .trimMargin()
4961     val expected =
4962         """
4963       |/**
4964       | * Lorem ipsum dolor sit amet,
4965       | * consectetur
4966       | */
4967       |class MyClass {}
4968       |"""
4969             .trimMargin()
4970     assertThatFormatting(code).withOptions(FormattingOptions(maxWidth = 33)).isEqualTo(expected)
4971   }
4972 
4973   @Test
4974   fun `sanity - block and continuation indents are 4`() {
4975     val code =
4976         """
4977         |fun f() {
4978         |    for (child in
4979         |        node.next.next.next.next
4980         |            .data()) {
4981         |        println(child)
4982         |    }
4983         |}
4984         |"""
4985             .trimMargin()
4986     assertThatFormatting(code)
4987         .withOptions(FormattingOptions(maxWidth = 35, blockIndent = 4, continuationIndent = 4))
4988         .isEqualTo(code)
4989   }
4990 
4991   @Test
4992   fun `comment after a block is stable and does not add space lines`() =
4993       assertFormatted(
4994           """
4995       |fun doIt() {}
4996       |
4997       |/* this is the first comment */
4998       |"""
4999               .trimMargin())
5000 
5001   @Test
5002   fun `preserve LF, CRLF and CR line endings`() {
5003     val lines = listOf("fun main() {", "  println(\"test\")", "}")
5004     for (ending in listOf("\n", "\r\n", "\r")) {
5005       val code = lines.joinToString(ending) + ending
5006       assertThatFormatting(code).isEqualTo(code)
5007     }
5008   }
5009 
5010   @Test
5011   fun `handle trailing commas (constructors)`() =
5012       assertFormatted(
5013           """
5014       |--------------------
5015       |class Foo(
5016       |    a: Int,
5017       |)
5018       |
5019       |class Foo(
5020       |    a: Int,
5021       |    b: Int,
5022       |)
5023       |
5024       |class Foo(
5025       |    a: Int,
5026       |    b: Int
5027       |)
5028       |"""
5029               .trimMargin(),
5030           deduceMaxWidth = true)
5031 
5032   @Test
5033   fun `handle trailing commas (explicit constructors)`() =
5034       assertFormatted(
5035           """
5036       |------------------------
5037       |class Foo
5038       |constructor(
5039       |    a: Int,
5040       |)
5041       |
5042       |class Foo
5043       |constructor(
5044       |    a: Int,
5045       |    b: Int,
5046       |)
5047       |
5048       |class Foo
5049       |constructor(
5050       |    a: Int,
5051       |    b: Int
5052       |)
5053       |"""
5054               .trimMargin(),
5055           deduceMaxWidth = true)
5056 
5057   @Test
5058   fun `handle trailing commas (secondary constructors)`() =
5059       assertFormatted(
5060           """
5061       |------------------------
5062       |class Foo {
5063       |  constructor(
5064       |      a: Int,
5065       |  )
5066       |}
5067       |
5068       |class Foo {
5069       |  constructor(
5070       |      a: Int,
5071       |      b: Int,
5072       |  )
5073       |}
5074       |
5075       |class Foo {
5076       |  constructor(
5077       |      a: Int,
5078       |      b: Int
5079       |  )
5080       |}
5081       |"""
5082               .trimMargin(),
5083           deduceMaxWidth = true)
5084 
5085   @Test
5086   fun `handle trailing commas (function definitions)`() =
5087       assertFormatted(
5088           """
5089       |------------------------
5090       |fun <
5091       |    T,
5092       |> foo() {}
5093       |
5094       |fun <
5095       |    T,
5096       |    S,
5097       |> foo() {}
5098       |
5099       |fun foo(
5100       |    a: Int,
5101       |) {}
5102       |
5103       |fun foo(
5104       |    a: Int,
5105       |    b: Int
5106       |) {}
5107       |
5108       |fun foo(
5109       |    a: Int,
5110       |    b: Int,
5111       |) {}
5112       |
5113       |fun foo(
5114       |    a: Int,
5115       |    b: Int,
5116       |    c: Int,
5117       |) {}
5118       |"""
5119               .trimMargin(),
5120           deduceMaxWidth = true)
5121 
5122   @Test
5123   fun `handle trailing commas (function calls)`() =
5124       assertFormatted(
5125           """
5126       |------------------------
5127       |fun main() {
5128       |  foo(
5129       |      3,
5130       |  )
5131       |
5132       |  foo<Int>(
5133       |      3,
5134       |  )
5135       |
5136       |  foo<
5137       |      Int,
5138       |  >(
5139       |      3,
5140       |  )
5141       |
5142       |  foo<Int>(
5143       |      "asdf", "asdf")
5144       |
5145       |  foo<
5146       |      Int,
5147       |  >(
5148       |      "asd",
5149       |      "asd",
5150       |  )
5151       |
5152       |  foo<
5153       |      Int,
5154       |      Boolean,
5155       |  >(
5156       |      3,
5157       |  )
5158       |}
5159       |"""
5160               .trimMargin(),
5161           deduceMaxWidth = true)
5162 
5163   @Test
5164   fun `handle trailing commas (proprties)`() =
5165       assertFormatted(
5166           """
5167       |--------------------------
5168       |val foo: String
5169       |  set(
5170       |      value,
5171       |  ) {}
5172       |"""
5173               .trimMargin(),
5174           deduceMaxWidth = true)
5175 
5176   @Test
5177   fun `handle trailing commas (higher-order functions)`() =
5178       assertFormatted(
5179           """
5180       |--------------------------
5181       |fun foo(
5182       |    x:
5183       |        (
5184       |            Int,
5185       |        ) -> Unit
5186       |) {}
5187       |"""
5188               .trimMargin(),
5189           deduceMaxWidth = true)
5190 
5191   @Test
5192   fun `handle trailing commas (after lambda arg)`() =
5193       assertFormatted(
5194           """
5195       |--------------------------
5196       |fun foo() {
5197       |  foo(
5198       |      { it },
5199       |  )
5200       |}
5201       |"""
5202               .trimMargin(),
5203           deduceMaxWidth = true)
5204 
5205   @Test
5206   fun `handle trailing commas (other)`() =
5207       assertFormatted(
5208           """
5209       |--------------------------
5210       |fun main() {
5211       |  val (
5212       |      x: Int,
5213       |  ) = foo()
5214       |  val (
5215       |      x: Int,
5216       |      y: Int,
5217       |  ) = foo()
5218       |
5219       |  val (
5220       |      x: Int,
5221       |  ) = foo(
5222       |      blablablablFoobar,
5223       |      alskdjasld)
5224       |
5225       |  val (
5226       |      x: Int,
5227       |      y: Int,
5228       |  ) = foo(
5229       |      blablablablFoobar,
5230       |      asldkalsd)
5231       |
5232       |  a[
5233       |      0,
5234       |  ] = 43
5235       |  a[
5236       |      0,
5237       |      1,
5238       |  ] = 43
5239       |
5240       |  [
5241       |      0,
5242       |  ]
5243       |  [
5244       |      0,
5245       |      1,
5246       |  ]
5247       |
5248       |  when (foo) {
5249       |    'x', -> 43
5250       |    'x',
5251       |    'y', -> 43
5252       |    'x',
5253       |    'y',
5254       |    'z',
5255       |    'w',
5256       |    'a',
5257       |    'b', -> 43
5258       |  }
5259       |
5260       |  try {
5261       |    //
5262       |  } catch (e: Error,) {
5263       |    //
5264       |  }
5265       |}
5266       |"""
5267               .trimMargin(),
5268           deduceMaxWidth = true)
5269 
5270   @Test
5271   fun `assignment of a scoping function`() =
5272       assertFormatted(
5273           """
5274       |----------------------------
5275       |val foo = coroutineScope {
5276       |  foo()
5277       |  //
5278       |}
5279       |
5280       |fun foo() = coroutineScope {
5281       |  foo()
5282       |  //
5283       |}
5284       |
5285       |fun foo() = use { x ->
5286       |  foo()
5287       |  //
5288       |}
5289       |
5290       |fun foo() =
5291       |    coroutineScope { x ->
5292       |      foo()
5293       |      //
5294       |    }
5295       |
5296       |fun foo() =
5297       |    Runnable @Px {
5298       |      foo()
5299       |      //
5300       |    }
5301       |
5302       |fun longName() =
5303       |    coroutineScope {
5304       |      foo()
5305       |      //
5306       |    }
5307       |"""
5308               .trimMargin(),
5309           deduceMaxWidth = true)
5310 
5311   @Test
5312   fun `top level properties with other types preserve newline spacing`() {
5313     assertFormatted(
5314         """
5315       |---------------------------------
5316       |fun something() {
5317       |  println("hi")
5318       |}
5319       |
5320       |const val SOME_CONST = 1
5321       |val SOME_STR = "hi"
5322       |// Single comment
5323       |val SOME_INT = 1
5324       |
5325       |// Intentional space above single comment
5326       |val SOME_INT2 = 1
5327       |
5328       |val FOO = 2
5329       |const val BAR = 3
5330       |
5331       |fun baz() = 1
5332       |
5333       |val d = 1
5334       |
5335       |class Bar {}
5336       |
5337       |val e = 1
5338       |/** Doc block */
5339       |val f = 1
5340       |
5341       |/** Intent. space above doc */
5342       |val g = 1
5343       |
5344       |data class Qux(val foo: String)
5345       |"""
5346             .trimMargin(),
5347         deduceMaxWidth = true)
5348 
5349     assertThatFormatting(
5350             """
5351       |import com.example.foo
5352       |import com.example.bar
5353       |const val SOME_CONST = foo.a
5354       |val SOME_STR = bar.a
5355       |"""
5356                 .trimMargin())
5357         .isEqualTo(
5358             """
5359       |import com.example.bar
5360       |import com.example.foo
5361       |
5362       |const val SOME_CONST = foo.a
5363       |val SOME_STR = bar.a
5364       |"""
5365                 .trimMargin())
5366   }
5367 
5368   @Test
5369   fun `first line is never empty`() =
5370       assertThatFormatting(
5371               """
5372       |
5373       |fun f() {}
5374       |"""
5375                   .trimMargin())
5376           .isEqualTo(
5377               """
5378       |fun f() {}
5379       |"""
5380                   .trimMargin())
5381 
5382   @Test
5383   fun `at most one newline between any adjacent top-level elements`() =
5384       assertThatFormatting(
5385               """
5386       |import com.Bar
5387       |
5388       |
5389       |import com.Foo
5390       |
5391       |
5392       |fun f() {}
5393       |
5394       |
5395       |fun f() {}
5396       |
5397       |
5398       |class C {}
5399       |
5400       |
5401       |class C {}
5402       |
5403       |
5404       |val x = Foo()
5405       |
5406       |
5407       |val x = Bar()
5408       |"""
5409                   .trimMargin())
5410           .isEqualTo(
5411               """
5412       |import com.Bar
5413       |import com.Foo
5414       |
5415       |fun f() {}
5416       |
5417       |fun f() {}
5418       |
5419       |class C {}
5420       |
5421       |class C {}
5422       |
5423       |val x = Foo()
5424       |
5425       |val x = Bar()
5426       |"""
5427                   .trimMargin())
5428 
5429   @Test
5430   fun `at least one newline between any adjacent top-level elements, unless it's a property`() =
5431       assertThatFormatting(
5432               """
5433       |import com.Bar
5434       |import com.Foo
5435       |fun f() {}
5436       |fun f() {}
5437       |class C {}
5438       |class C {}
5439       |val x = Foo()
5440       |val x = Bar()
5441       |"""
5442                   .trimMargin())
5443           .isEqualTo(
5444               """
5445       |import com.Bar
5446       |import com.Foo
5447       |
5448       |fun f() {}
5449       |
5450       |fun f() {}
5451       |
5452       |class C {}
5453       |
5454       |class C {}
5455       |
5456       |val x = Foo()
5457       |val x = Bar()
5458       |"""
5459                   .trimMargin())
5460 
5461   @Test
5462   fun `handle array of annotations with field prefix`() {
5463     val code: String =
5464         """
5465     |class MyClass {
5466     |  @field:[JvmStatic Volatile]
5467     |  var myVar: String? = null
5468     |}
5469     |
5470     """
5471             .trimMargin()
5472     assertThatFormatting(code).isEqualTo(code)
5473   }
5474 
5475   @Test
5476   fun `handle array of annotations without field prefix`() {
5477     val code: String =
5478         """
5479     |class MyClass {
5480     |  @[JvmStatic Volatile]
5481     |  var myVar: String? = null
5482     |}
5483     |
5484     """
5485             .trimMargin()
5486     assertThatFormatting(code).isEqualTo(code)
5487   }
5488 
5489   // Regression test against https://github.com/facebookincubator/ktfmt/issues/243
5490   @Test
5491   fun `regression test against Issue 243`() {
5492     val code =
5493         """
5494       |class Foo {
5495       |  companion object {
5496       |    var instance: Foo? = null
5497       |
5498       |    fun getInstance() {
5499       |      return instance ?: synchronized(Foo::class) {
5500       |        Foo().also { instance = it }
5501       |      }
5502       |    }
5503       |  }
5504       |}
5505       |"""
5506             .trimMargin()
5507 
5508     // Don't throw.
5509     Formatter.format(code)
5510   }
5511 
5512   @Test
5513   fun `lambda with required arrow`() =
5514       assertFormatted(
5515           """
5516       |val a = { x: Int -> }
5517       |val b = { x: Int -> 0 }
5518       |val c = { x: Int ->
5519       |  val y = 0
5520       |  y
5521       |}
5522       |"""
5523               .trimMargin())
5524 
5525   @Test
5526   fun `lambda with optional arrow`() =
5527       assertFormatted(
5528           """
5529       |val a = { -> }
5530       |val b = { -> 0 }
5531       |val c = { ->
5532       |  val y = 0
5533       |  y
5534       |}
5535       |"""
5536               .trimMargin())
5537 
5538   @Test
5539   fun `lambda missing optional arrow`() =
5540       assertFormatted(
5541           """
5542       |val a = {}
5543       |val b = { 0 }
5544       |val c = {
5545       |  val y = 0
5546       |  y
5547       |}
5548       |"""
5549               .trimMargin())
5550 
5551   @Test
5552   fun `chaining - many dereferences`() =
5553       assertFormatted(
5554           """
5555       |-------------------------
5556       |rainbow.red.orange.yellow
5557       |    .green
5558       |    .blue
5559       |    .indigo
5560       |    .violet
5561       |    .cyan
5562       |    .magenta
5563       |    .key
5564       |"""
5565               .trimMargin(),
5566           deduceMaxWidth = true)
5567 
5568   @Test
5569   fun `chaining - many dereferences, fit on one line`() =
5570       assertFormatted(
5571           """
5572       |---------------------------------------------------------------------------
5573       |rainbow.red.orange.yellow.green.blue.indigo.violet.cyan.magenta.key
5574       |"""
5575               .trimMargin(),
5576           deduceMaxWidth = true)
5577 
5578   @Test
5579   fun `chaining - many dereferences, one invocation at end`() =
5580       assertFormatted(
5581           """
5582       |-------------------------
5583       |rainbow.red.orange.yellow
5584       |    .green
5585       |    .blue
5586       |    .indigo
5587       |    .violet
5588       |    .cyan
5589       |    .magenta
5590       |    .key
5591       |    .build()
5592       |"""
5593               .trimMargin(),
5594           deduceMaxWidth = true)
5595 
5596   @Test
5597   fun `chaining - many dereferences, one invocation at end, fit on one line`() =
5598       assertFormatted(
5599           """
5600       |---------------------------------------------------------------------------
5601       |rainbow.red.orange.yellow.green.blue.indigo.violet.cyan.magenta.key.build()
5602       |"""
5603               .trimMargin(),
5604           deduceMaxWidth = true)
5605 
5606   @Test
5607   fun `chaining - many dereferences, two invocations at end`() =
5608       assertFormatted(
5609           """
5610       |-------------------------
5611       |rainbow.red.orange.yellow
5612       |    .green
5613       |    .blue
5614       |    .indigo
5615       |    .violet
5616       |    .cyan
5617       |    .magenta
5618       |    .key
5619       |    .build()
5620       |    .shine()
5621       |"""
5622               .trimMargin(),
5623           deduceMaxWidth = true)
5624 
5625   @Test
5626   fun `chaining - many dereferences, one invocation in the middle`() =
5627       assertFormatted(
5628           """
5629       |-------------------------
5630       |rainbow.red.orange.yellow
5631       |    .green
5632       |    .blue
5633       |    .shine()
5634       |    .indigo
5635       |    .violet
5636       |    .cyan
5637       |    .magenta
5638       |    .key
5639       |"""
5640               .trimMargin(),
5641           deduceMaxWidth = true)
5642 
5643   @Test
5644   fun `chaining - many dereferences, two invocations in the middle`() =
5645       assertFormatted(
5646           """
5647       |-------------------------
5648       |rainbow.red.orange.yellow
5649       |    .green
5650       |    .blue
5651       |    .indigo
5652       |    .shine()
5653       |    .bright()
5654       |    .violet
5655       |    .cyan
5656       |    .magenta
5657       |    .key
5658       |"""
5659               .trimMargin(),
5660           deduceMaxWidth = true)
5661 
5662   @Test
5663   fun `chaining - many dereferences, one lambda at end`() =
5664       assertFormatted(
5665           """
5666       |-------------------------
5667       |rainbow.red.orange.yellow
5668       |    .green
5669       |    .blue
5670       |    .indigo
5671       |    .violet
5672       |    .cyan
5673       |    .magenta
5674       |    .key
5675       |    .build { it.appear }
5676       |"""
5677               .trimMargin(),
5678           deduceMaxWidth = true)
5679 
5680   @Test
5681   fun `chaining - many dereferences, one short lambda at end`() =
5682       assertFormatted(
5683           """
5684       |-------------------------
5685       |rainbow.red.orange.yellow
5686       |    .green
5687       |    .blue
5688       |    .indigo
5689       |    .violet
5690       |    .cyan
5691       |    .magenta
5692       |    .key
5693       |    .z { it }
5694       |"""
5695               .trimMargin(),
5696           deduceMaxWidth = true)
5697 
5698   @Test
5699   fun `chaining - many dereferences, one multiline lambda at end`() =
5700       assertFormatted(
5701           """
5702       |-------------------------
5703       |rainbow.red.orange.yellow
5704       |    .green
5705       |    .blue
5706       |    .indigo
5707       |    .violet
5708       |    .cyan
5709       |    .magenta
5710       |    .key
5711       |    .z {
5712       |      it
5713       |      it
5714       |    }
5715       |"""
5716               .trimMargin(),
5717           deduceMaxWidth = true)
5718 
5719   @Test
5720   fun `chaining - many dereferences, one short lambda in the middle`() =
5721       assertFormatted(
5722           """
5723       |-------------------------
5724       |rainbow.red.orange.yellow
5725       |    .green
5726       |    .blue
5727       |    .z { it }
5728       |    .indigo
5729       |    .violet
5730       |    .cyan
5731       |    .magenta
5732       |    .key
5733       |"""
5734               .trimMargin(),
5735           deduceMaxWidth = true)
5736 
5737   @Test
5738   fun `chaining - many dereferences, one multiline lambda in the middle`() =
5739       assertFormatted(
5740           """
5741       |-------------------------
5742       |rainbow.red.orange.yellow
5743       |    .green
5744       |    .blue
5745       |    .z {
5746       |      it
5747       |      it
5748       |    }
5749       |    .indigo
5750       |    .violet
5751       |    .cyan
5752       |    .magenta
5753       |    .key
5754       |"""
5755               .trimMargin(),
5756           deduceMaxWidth = true)
5757 
5758   @Test
5759   fun `chaining - many dereferences, one multiline lambda in the middle, remainder could fit on one line`() =
5760       assertFormatted(
5761           """
5762       |-----------------------------------------------------------------------------------------
5763       |rainbow.red.orange.yellow.green.blue
5764       |    .z {
5765       |      it
5766       |      it
5767       |    }
5768       |    .indigo
5769       |    .violet
5770       |    .cyan
5771       |    .magenta
5772       |    .key
5773       |"""
5774               .trimMargin(),
5775           deduceMaxWidth = true)
5776 
5777   @Test
5778   fun `chaining - many dereferences, one multiline lambda and two invocations in the middle, remainder could fit on one line`() =
5779       assertFormatted(
5780           """
5781       |-----------------------------------------------------------------------------------------
5782       |rainbow.red.orange.yellow.green.blue
5783       |    .z {
5784       |      it
5785       |      it
5786       |    }
5787       |    .shine()
5788       |    .bright()
5789       |    .indigo
5790       |    .violet
5791       |    .cyan
5792       |    .magenta
5793       |    .key
5794       |"""
5795               .trimMargin(),
5796           deduceMaxWidth = true)
5797 
5798   @Test
5799   fun `chaining - many dereferences, one lambda and invocation at end`() =
5800       assertFormatted(
5801           """
5802       |-------------------------
5803       |rainbow.red.orange.yellow
5804       |    .green
5805       |    .blue
5806       |    .indigo
5807       |    .violet
5808       |    .cyan
5809       |    .magenta
5810       |    .key
5811       |    .z { it }
5812       |    .shine()
5813       |"""
5814               .trimMargin(),
5815           deduceMaxWidth = true)
5816 
5817   @Test
5818   fun `chaining - many dereferences, one multiline lambda and invocation at end`() =
5819       assertFormatted(
5820           """
5821       |-------------------------
5822       |rainbow.red.orange.yellow
5823       |    .green
5824       |    .blue
5825       |    .indigo
5826       |    .violet
5827       |    .cyan
5828       |    .magenta
5829       |    .key
5830       |    .z {
5831       |      it
5832       |      it
5833       |    }
5834       |    .shine()
5835       |"""
5836               .trimMargin(),
5837           deduceMaxWidth = true)
5838 
5839   @Test
5840   fun `chaining - many dereferences, one invocation and lambda at end`() =
5841       assertFormatted(
5842           """
5843       |-------------------------
5844       |rainbow.red.orange.yellow
5845       |    .green
5846       |    .blue
5847       |    .indigo
5848       |    .violet
5849       |    .cyan
5850       |    .magenta
5851       |    .key
5852       |    .shine()
5853       |    .z { it }
5854       |"""
5855               .trimMargin(),
5856           deduceMaxWidth = true)
5857 
5858   @Test
5859   fun `chaining - many dereferences, one short lambda and invocation in the middle`() =
5860       assertFormatted(
5861           """
5862       |-------------------------
5863       |rainbow.red.orange.yellow
5864       |    .green
5865       |    .blue
5866       |    .indigo
5867       |    .z { it }
5868       |    .shine()
5869       |    .violet
5870       |    .cyan
5871       |    .magenta
5872       |    .key
5873       |"""
5874               .trimMargin(),
5875           deduceMaxWidth = true)
5876 
5877   @Test
5878   fun `chaining - many dereferences, invocation and one short lambda in the middle`() =
5879       assertFormatted(
5880           """
5881       |-------------------------
5882       |rainbow.red.orange.yellow
5883       |    .green
5884       |    .blue
5885       |    .indigo
5886       |    .shine()
5887       |    .z { it }
5888       |    .violet
5889       |    .cyan
5890       |    .magenta
5891       |    .key
5892       |"""
5893               .trimMargin(),
5894           deduceMaxWidth = true)
5895 
5896   @Test
5897   fun `chaining - many dereferences, starting with this`() =
5898       assertFormatted(
5899           """
5900       |-------------------------
5901       |this.red.orange.yellow
5902       |    .green
5903       |    .blue
5904       |    .indigo
5905       |    .violet
5906       |    .cyan
5907       |    .magenta
5908       |    .key
5909       |"""
5910               .trimMargin(),
5911           deduceMaxWidth = true)
5912 
5913   @Test
5914   fun `chaining - many dereferences, starting with this, one invocation at end`() =
5915       assertFormatted(
5916           """
5917       |-------------------------
5918       |this.red.orange.yellow
5919       |    .green
5920       |    .blue
5921       |    .indigo
5922       |    .violet
5923       |    .cyan
5924       |    .magenta
5925       |    .key
5926       |    .build()
5927       |"""
5928               .trimMargin(),
5929           deduceMaxWidth = true)
5930 
5931   @Test
5932   fun `chaining - many dereferences, starting with super`() =
5933       assertFormatted(
5934           """
5935       |-------------------------
5936       |super.red.orange.yellow
5937       |    .green
5938       |    .blue
5939       |    .indigo
5940       |    .violet
5941       |    .cyan
5942       |    .magenta
5943       |    .key
5944       |"""
5945               .trimMargin(),
5946           deduceMaxWidth = true)
5947 
5948   @Test
5949   fun `chaining - many dereferences, starting with super, one invocation at end`() =
5950       assertFormatted(
5951           """
5952       |-------------------------
5953       |super.red.orange.yellow
5954       |    .green
5955       |    .blue
5956       |    .indigo
5957       |    .violet
5958       |    .cyan
5959       |    .magenta
5960       |    .key
5961       |    .build()
5962       |"""
5963               .trimMargin(),
5964           deduceMaxWidth = true)
5965 
5966   @Test
5967   fun `chaining - many dereferences, starting with short variable`() =
5968       assertFormatted(
5969           """
5970       |-------------------------
5971       |z123.red.orange.yellow
5972       |    .green
5973       |    .blue
5974       |    .indigo
5975       |    .violet
5976       |    .cyan
5977       |    .magenta
5978       |    .key
5979       |"""
5980               .trimMargin(),
5981           deduceMaxWidth = true)
5982 
5983   @Test
5984   fun `chaining - many dereferences, starting with short variable, one invocation at end`() =
5985       assertFormatted(
5986           """
5987       |-------------------------
5988       |z123.red.orange.yellow
5989       |    .green
5990       |    .blue
5991       |    .indigo
5992       |    .violet
5993       |    .cyan
5994       |    .magenta
5995       |    .key
5996       |    .build()
5997       |"""
5998               .trimMargin(),
5999           deduceMaxWidth = true)
6000 
6001   @Test
6002   fun `chaining - many dereferences, starting with short variable and lambda, invocation at end`() =
6003       assertFormatted(
6004           """
6005       |-------------------------
6006       |z12.z { it }
6007       |    .red
6008       |    .orange
6009       |    .yellow
6010       |    .green
6011       |    .blue
6012       |    .indigo
6013       |    .violet
6014       |    .cyan
6015       |    .magenta
6016       |    .key
6017       |    .shine()
6018       |"""
6019               .trimMargin(),
6020           deduceMaxWidth = true)
6021 
6022   @Test
6023   fun `chaining - many dereferences, starting with this and lambda, invocation at end`() =
6024       assertFormatted(
6025           """
6026       |-------------------------
6027       |this.z { it }
6028       |    .red
6029       |    .orange
6030       |    .yellow
6031       |    .green
6032       |    .blue
6033       |    .indigo
6034       |    .violet
6035       |    .cyan
6036       |    .magenta
6037       |    .key
6038       |    .shine()
6039       |"""
6040               .trimMargin(),
6041           deduceMaxWidth = true)
6042 
6043   @Test
6044   fun `chaining - many invocations`() =
6045       assertFormatted(
6046           """
6047       |-------------------------
6048       |rainbow.a().b().c()
6049       |"""
6050               .trimMargin(),
6051           deduceMaxWidth = true)
6052 
6053   @Test
6054   fun `chaining - many invocations, with multiline lambda at end`() =
6055       assertFormatted(
6056           """
6057       |-------------------------
6058       |rainbow.a().b().c().zz {
6059       |  it
6060       |  it
6061       |}
6062       |"""
6063               .trimMargin(),
6064           deduceMaxWidth = true)
6065 
6066   @Test
6067   fun `chaining - many dereferences, starting type name`() =
6068       assertFormatted(
6069           """
6070       |-------------------------
6071       |com.sky.Rainbow.red
6072       |    .orange
6073       |    .yellow
6074       |    .green
6075       |    .blue
6076       |    .indigo
6077       |    .violet
6078       |    .cyan
6079       |    .magenta
6080       |    .key
6081       |"""
6082               .trimMargin(),
6083           deduceMaxWidth = true)
6084 
6085   @Test
6086   fun `chaining - many invocations, starting with short variable, lambda at end`() =
6087       assertFormatted(
6088           """
6089       |-------------
6090       |z12.shine()
6091       |    .bright()
6092       |    .z { it }
6093       |"""
6094               .trimMargin(),
6095           deduceMaxWidth = true)
6096 
6097   @Test
6098   fun `chaining - start with invocation, lambda at end`() =
6099       assertFormatted(
6100           """
6101       |---------------------
6102       |getRainbow(
6103       |        aa, bb, cc)
6104       |    .z { it }
6105       |"""
6106               .trimMargin(),
6107           deduceMaxWidth = true)
6108 
6109   @Test
6110   fun `chaining - many invocations, start with lambda`() =
6111       assertFormatted(
6112           """
6113       |---------------------
6114       |z { it }
6115       |    .shine()
6116       |    .bright()
6117       |"""
6118               .trimMargin(),
6119           deduceMaxWidth = true)
6120 
6121   @Test
6122   fun `chaining - start with type name, end with invocation`() =
6123       assertFormatted(
6124           """
6125       |-------------------------
6126       |com.sky.Rainbow
6127       |    .colorFactory
6128       |    .build()
6129       |"""
6130               .trimMargin(),
6131           deduceMaxWidth = true)
6132 
6133   @Test
6134   fun `chaining (indentation) - multiline lambda`() =
6135       assertFormatted(
6136           """
6137       |-------------------------
6138       |rainbow.z {
6139       |  it
6140       |  it
6141       |}
6142       |"""
6143               .trimMargin(),
6144           deduceMaxWidth = true)
6145 
6146   @Test
6147   fun `chaining (indentation) - multiline lambda with trailing dereferences`() =
6148       assertFormatted(
6149           """
6150       |-------------------------
6151       |rainbow
6152       |    .z {
6153       |      it
6154       |      it
6155       |    }
6156       |    .red
6157       |"""
6158               .trimMargin(),
6159           deduceMaxWidth = true)
6160 
6161   @Test
6162   fun `chaining (indentation) - multiline lambda with long name`() =
6163       assertFormatted(
6164           """
6165       |-------------------------
6166       |rainbow
6167       |    .someLongLambdaName {
6168       |      it
6169       |      it
6170       |    }
6171       |"""
6172               .trimMargin(),
6173           deduceMaxWidth = true)
6174 
6175   @Test
6176   fun `chaining (indentation) - multiline lambda with long name and trailing dereferences`() =
6177       assertFormatted(
6178           """
6179       |-------------------------
6180       |rainbow
6181       |    .someLongLambdaName {
6182       |      it
6183       |      it
6184       |    }
6185       |    .red
6186       |"""
6187               .trimMargin(),
6188           deduceMaxWidth = true)
6189 
6190   @Test
6191   fun `chaining (indentation) - multiline lambda with prefix`() =
6192       assertFormatted(
6193           """
6194       |-------------------------
6195       |rainbow.red.z {
6196       |  it
6197       |  it
6198       |}
6199       |"""
6200               .trimMargin(),
6201           deduceMaxWidth = true)
6202 
6203   @Test
6204   fun `chaining (indentation) - multiline lambda with prefix, forced to next line`() =
6205       assertFormatted(
6206           """
6207       |-------------------------
6208       |rainbow.red.orange.yellow
6209       |    .longLambdaName {
6210       |      it
6211       |      it
6212       |    }
6213       |"""
6214               .trimMargin(),
6215           deduceMaxWidth = true)
6216 
6217   @Test
6218   fun `chaining (indentation) - multiline lambda with prefix, forced to next line with another expression`() =
6219       assertFormatted(
6220           """
6221       |-------------------------
6222       |rainbow.red.orange.yellow
6223       |    .key
6224       |    .longLambdaName {
6225       |      it
6226       |      it
6227       |    }
6228       |"""
6229               .trimMargin(),
6230           deduceMaxWidth = true)
6231 
6232   @Test
6233   fun `chaining (indentation) - multiline arguments`() =
6234       assertFormatted(
6235           """
6236       |-------------------------
6237       |rainbow.shine(
6238       |    infrared,
6239       |    ultraviolet,
6240       |)
6241       |"""
6242               .trimMargin(),
6243           deduceMaxWidth = true)
6244 
6245   @Test
6246   fun `chaining (indentation) - multiline arguments with trailing dereferences`() =
6247       assertFormatted(
6248           """
6249       |-------------------------
6250       |rainbow
6251       |    .shine(
6252       |        infrared,
6253       |        ultraviolet,
6254       |    )
6255       |    .red
6256       |"""
6257               .trimMargin(),
6258           deduceMaxWidth = true)
6259 
6260   @Test
6261   fun `chaining (indentation) - multiline arguments, forced to next line`() =
6262       assertFormatted(
6263           """
6264       |-------------------------
6265       |rainbow.red.orange.yellow
6266       |    .shine(
6267       |        infrared,
6268       |        ultraviolet,
6269       |    )
6270       |"""
6271               .trimMargin(),
6272           deduceMaxWidth = true)
6273 
6274   @Test
6275   fun `chaining (indentation) - multiline arguments, forced to next line with another expression`() =
6276       assertFormatted(
6277           """
6278       |-------------------------
6279       |rainbow.red.orange.yellow
6280       |    .key
6281       |    .shine(
6282       |        infrared,
6283       |        ultraviolet,
6284       |    )
6285       |"""
6286               .trimMargin(),
6287           deduceMaxWidth = true)
6288 
6289   @Test
6290   fun `chaining (indentation) - multiline arguments, forced to next line with another expression, with trailing dereferences`() =
6291       assertFormatted(
6292           """
6293       |-------------------------
6294       |rainbow.red.orange.yellow
6295       |    .key
6296       |    .shine(
6297       |        infrared,
6298       |        ultraviolet,
6299       |    )
6300       |    .red
6301       |"""
6302               .trimMargin(),
6303           deduceMaxWidth = true)
6304 
6305   @Test
6306   fun `chaining (indentation) - multiline arguments, with trailing invocation`() =
6307       assertFormatted(
6308           """
6309       |-------------------------
6310       |rainbow
6311       |    .shine(
6312       |        infrared,
6313       |        ultraviolet,
6314       |    )
6315       |    .bright()
6316       |"""
6317               .trimMargin(),
6318           deduceMaxWidth = true)
6319 
6320   @Test
6321   fun `chaining (indentation) - multiline arguments, with trailing lambda`() =
6322       assertFormatted(
6323           """
6324       |-------------------------
6325       |rainbow
6326       |    .shine(
6327       |        infrared,
6328       |        ultraviolet,
6329       |    )
6330       |    .z { it }
6331       |"""
6332               .trimMargin(),
6333           deduceMaxWidth = true)
6334 
6335   @Test
6336   fun `chaining (indentation) - multiline arguments, prefixed with super, with trailing invocation`() =
6337       assertFormatted(
6338           """
6339       |-------------------------
6340       |super.shine(
6341       |        infrared,
6342       |        ultraviolet,
6343       |    )
6344       |    .bright()
6345       |"""
6346               .trimMargin(),
6347           deduceMaxWidth = true)
6348 
6349   @Test
6350   fun `chaining (indentation) - multiline arguments, starting with short variable, with trailing invocation`() =
6351       assertFormatted(
6352           """
6353       |-------------------------
6354       |z12.shine(
6355       |        infrared,
6356       |        ultraviolet,
6357       |    )
6358       |    .bright()
6359       |"""
6360               .trimMargin(),
6361           deduceMaxWidth = true)
6362 
6363   @Test
6364   fun `chaining (indentation) - start with multiline arguments`() =
6365       assertFormatted(
6366           """
6367       |-------------------------
6368       |getRainbow(
6369       |    infrared,
6370       |    ultraviolet,
6371       |)
6372       |"""
6373               .trimMargin(),
6374           deduceMaxWidth = true)
6375 
6376   @Test
6377   fun `chaining (indentation) - start with multiline arguments, with trailing invocation`() =
6378       assertFormatted(
6379           """
6380       |-------------------------
6381       |getRainbow(
6382       |        infrared,
6383       |        ultraviolet,
6384       |    )
6385       |    .z { it }
6386       |"""
6387               .trimMargin(),
6388           deduceMaxWidth = true)
6389 
6390   @Test
6391   fun `annotations for expressions`() =
6392       assertFormatted(
6393           """
6394       |fun f() {
6395       |  var b
6396       |  @Suppress("UNCHECKED_CAST") b = f(1) as Int
6397       |  @Suppress("UNCHECKED_CAST")
6398       |  b = f(1) as Int
6399       |
6400       |  @Suppress("UNCHECKED_CAST") b = f(1) to 5
6401       |  @Suppress("UNCHECKED_CAST")
6402       |  b = f(1) to 5
6403       |
6404       |  @Suppress("UNCHECKED_CAST") f(1) as Int + 5
6405       |  @Suppress("UNCHECKED_CAST")
6406       |  f(1) as Int + 5
6407       |
6408       |  @Anno1 /* comment */ @Anno2 f(1) as Int
6409       |}
6410       |"""
6411               .trimMargin())
6412 
6413   @Test
6414   fun `annotations for expressions 2`() {
6415     val code =
6416         """
6417       |fun f() {
6418       |  @Suppress("UNCHECKED_CAST") f(1 + f(1) as Int)
6419       |  @Suppress("UNCHECKED_CAST")
6420       |  f(1 + f(1) as Int)
6421       |}
6422       |"""
6423             .trimMargin()
6424 
6425     val expected =
6426         """
6427       |fun f() {
6428       |  @Suppress("UNCHECKED_CAST") f(1 + f(1) as Int)
6429       |  @Suppress("UNCHECKED_CAST") f(1 + f(1) as Int)
6430       |}
6431       |"""
6432             .trimMargin()
6433 
6434     assertThatFormatting(code).isEqualTo(expected)
6435   }
6436 
6437   @Test
6438   fun `function call following long multiline string`() =
6439       assertFormatted(
6440           """
6441       |--------------------------------
6442       |fun f() {
6443       |  val str1 =
6444       |      $TQ
6445       |      Some very long string that might mess things up
6446       |      $TQ
6447       |          .trimIndent()
6448       |
6449       |  val str2 =
6450       |      $TQ
6451       |      Some very long string that might mess things up
6452       |      $TQ
6453       |          .trimIndent(someArg)
6454       |}
6455       |"""
6456               .trimMargin(),
6457           deduceMaxWidth = true)
6458 
6459   @Test
6460   fun `array-literal in annotation`() =
6461       assertFormatted(
6462           """
6463       |--------------------------------
6464       |@Anno(
6465       |    array =
6466       |        [
6467       |            someItem,
6468       |            andAnother,
6469       |            noTrailingComma])
6470       |class Host
6471       |
6472       |@Anno(
6473       |    array =
6474       |        [
6475       |            someItem,
6476       |            andAnother,
6477       |            withTrailingComma,
6478       |        ])
6479       |class Host
6480       |
6481       |@Anno(
6482       |    array =
6483       |        [
6484       |            // Comment
6485       |            someItem,
6486       |            // Comment
6487       |            andAnother,
6488       |            // Comment
6489       |            withTrailingComment
6490       |            // Comment
6491       |            // Comment
6492       |            ])
6493       |class Host
6494       |"""
6495               .trimMargin(),
6496           deduceMaxWidth = true)
6497 
6498   companion object {
6499     /** Triple quotes, useful to use within triple-quoted strings. */
6500     private const val TQ = "\"\"\""
6501   }
6502 }
6503