// Pexp_ident
let pi = /* before */ Math.pi // after

// Pexp_constant
let one = /* before */ 1 // after

// Pexp_let
let x = {
  let /* before a */ a /* after a */ = /* before 1 */ 1 // after 1
  /* before ident */ Pexp.ident /* after ident */
}

let x = {
  let /* before a */ a /* after a */ = /* before 1 */ 1 // after 1
  let /* before b */ b /* after b */ = /* before 2 */ 2 // after 2
  /* before ident */ Pexp.ident /* after ident */
}

let x = {
  let /* before a */ a /* after a */ = /* before 1 */ 1 // after 1
  let /* before b */ b /* after b */ = /* before 2 */ 2 // after 2
  /* before const */ "a string" /* after const */
}

// Pexp_extension
let x = /* c0 */ %ext(/* before */ "test" /* after */) /* c1 */

// Pexp_open
let x = {
  /* before open */ open /* c0 */ Belt /* c1 */ // after open
  /* before const */ "a string" /* after const */
}

let x = {
  /* before open */ open /* c0 */ Belt /* c1 */ // after open
  /* before open */ open! /* c0 */ Unsafe /* c1 */ // after open
  /* before const */ "a string" /* after const */
}

let x = {
  /* before let */ let a = 1 // after let
  open /* before ident */ Belt // after open
  /* before const */ "test" /* after const */
}

let x = {
  open /* before ident */ Belt // after open
  /* before let */ let a = 1 // after let
  /* before const */ "test" /* after const */
}

// Pexp_letexception
let x = {
  /* before */ exception /* c0 */ Foo /* c1 */ // after
  /* before */ "test" /* after */
}

// Pexp_letmodule
let x = {
  /* before */ module /* c0 */ B /* c1 */ = Belt // after
  /* before */ "test" /* after */
}

// Pexp_assert
let x = /* here */ assert(/* c0 */ true /* c1 */)

// Pexp_constraint
let x = (/* c0 */ "string" /* c1 */: /* c2 */ string /* c3 */) // after

// Pexp_construct
let x = /* before */ true /* after */
let x = /* before */ Red /* after */
let x = /* before */ Red(/* c0 */ shade /* c1 */) /* after */
let x = /* before */ Red /* after Red */(
  /* c0 */ r /* c1 */,
  /* c2 */ g /* c3 */,
  /* c4 */ b /* c5 */,
) /* after */

// lists
let x = /* c0 */ list{/* c1 */} /* c2 */
/* c0 */ list{/* c1 */} /* c2 */

let x = /* c0 */ list{/* c1 */ a /* c2 */} /* c3 */
/* c0 */ list{/* c1 */ a /* c2 */} /* c3 */

let x = /* c0 */ list{/* c1 */ a /* c2 */, /* c3 */ b /* c4 */} /* c5 */
/* c0 */ list{/* c1 */ a /* c2 */, /* c3 */ b /* c4 */} /* c5 */

let x = /* c0 */ list{/* c1 */ a /* c2 */, /* c3 */ b /* c4 */, /* c5 */ c /* c6 */} /* c7 */
/* c0 */ list{/* c1 */ a /* c2 */, /* c3 */ b /* c4 */, /* c5 */ c /* c6 */} /* c7 */

// Pexp_array
let x = [/* c0 */ a /* c1 */, /* c2 */ b /* c3 */, /* c4 */ c /* c5 */]
let x = [/* a */]
let x = [
  // test
]

// Pexp_record
let user = /* before */ {
  // above name
  /* c0 */ name /* c1 */: /* c2 */ "Steve" /* c3 */,
  // above age
  /* c4 */ age /* c5 */: /* c6 */ 31 /* c7 */,
} // after

// Pexp_record with empty record
let user = /* before */ {
  /* comment1 */
  // comment2
} // after

let user = /* before */ {/* comment1 */ /* comments2 */} // after

// bs object sugar
let user = /* before */ {
  // above name
  /* c0 */ "name" /* c1 */: /* c2 */ "Steve" /* c3 */,
  // above age
  /* c4 */ "age" /* c5 */: /* c6 */ 31 /* c7 */,
} // after

let spreadUser = {/* before */ ...user1 /* after */, /* c0 */ age /* c1 */: /* c2 */ 32 /* c3 */}

// Pexp_field
let x = /* before */ user /* c0 */./* c1 */ name /* c2 */

// Pexp_setfield
/* before */ user /* c0 */./* c1 */ name /* c2 */ = /* c3 */ "Steve" /* c4 */

// Pexp_ifthenelse
if /* c0 */ user.name === "Steve" /* c1 */ {
  /* c2 */ Js.log("It's Steve") /* c3 */
} // trailing

if /* c0 */ user.name === "John" /* c1 */ {
  /* c2 */ Js.log("It's John…") /* c3 */
} else {
  // c4
  /* c5 */ Js.log("we need John") /* c6 */
} // trailing

if a {
  b
} // test
else if c {
  d
}

let distXToTraverse = if deltaX < 0. {
  // wizard to the left
  if minRangeX >= -.deltaX {
    // already within min range, aka close enough
    0.
  } else {
    deltaX +. minRangeX
  }
} // wizard to the right
else if minRangeX >= deltaX {
  // already within min range, aka close enough
  0.
} else {
  deltaX -. minRangeX
}

// Pexp_while
while /* c0 */ condition.contents /* c1 */ {
  /* c2 */ doStuff() /* c3 */
} // trailing

// Pexp_for
for /* c0 */ i /* c1 */ in /* c2 */ 0 /* c3 */ to /* c4 */ 10 /* c5 */ {
  /* c6 */ doStuff() /* c7 */
} // trailing

// Pexp_pack
/* c0 */ module(/* c1 */ ModExpr /* c2 */) /* c3 */
/* c0 */ let /* c1 */ three /* c2 */ = /* c3 */ module(/* c4 */ Three /* c5 */) /* c6 */

/* c0 */ module(/* c1 */ ModExpr: /* c4 */ MyModule /* c5 */) /* c6 */
/* c0 */ let /* c1 */ three /* c2 */ = /* c3 */ module(
  /* c4 */ Three: /* c6 */ MyModule /* c7 */
) /* c8 */

/* c0 */ switch /* c1 */ color /* c2 */ {
// above Red
/* c0 */ | Red /* c1 */ => /* c2 */ printColor("red") /* ending */

// above Blue
/* c3 */ | Blue /* c4 */ => /* c5 */ printColor("blue") /* ending */
}

/* c0 */ try /* c2 */ unsafeIdentifier /* c3 */ catch {
// Above
/* before */ | InfiniteLoop /* after */ => /* here */ () /* trailing */

// Above2
/* before */ | InfiniteLoop2 /* after */ => /* here */ () /* trailing */
} // trailing

// Pexp_fun
let f = (/* c0 */ a /* c1 */, /* c2 */ b /* c3 */): /* c4 */ int /* c5 */ => /* c6 */ 20 /* c7 */
let multiply = (/* c0 */ m1 /* c1 */, /* c2 */ m2 /* c3 */) => {
  // here
  open Matrix4D

  let m3 = makeUninitializedUnsafe()

  // there

  // over there
  m3
  /* trailing */
  // test
}

let multiply = (~x=/* c0 */ m1 /* c1 */, ~y=/* c2 */ m2 /* c3 */) => ()

let f = (
  /* c0 */ ~greeting /* c1 */,
  /* c2 */ ~from as /* c3 */ /* c4 */ hometown /* c5 */,
  /* c6 */ ~x=?,
) => /* c7 */ ()

let multiply = (type /* c-2 */ t /* c-1 */, /* c0 */ m1 /* c1 */, /* c2 */ m2 /* c3 */) => ()
let multiply = (
  type /* c-4 */ t /* c-3 */ s,
  /* c0 */ m1 /* c1 */,
  /* c-2 */ /* c-1 */ /* c2 */ m2 /* c3 */,
) => ()

f(
  // a
  // b
  // c
  )

f(
  // a
  // b
  // c
  )

let x = {
  f(
    // a
    // b
    // c
    )

  f(
    // a
    // b
    // c
    )
}

f(() => 1)
// c1
f(_ => 1)
// c2
f(a => 1)
// c3
f((~a) =>
  // c4
  1
)

// ternary
let x = /* c0 */ test /* c1 */ ? /* c2 */ true /* c3 */ : /* c4 */ false /* c5 */

// Pexp_if case, don't duplicate comments
if next == Js.null {
  /* only one element */
  clear(q)
  Some(contentGet(x))
} else {
  lengthSet(q, lengthGet(q) - 1)
  firstSet(q, next)
  Some(contentGet(x))
}

// Pexp_if with parenthesized condition
if (
  /* Format.eprintf "@[%a@]@." Printtyp.raw_type_expr ty; */
  switch ty0.desc {
  | Tconstr(p, _, _) => Path.same(p, path)
  | _ => false
  }
) {
  ()
}

// add end of list of nodes
Doc.concat(
  privateFlag,
  rows,
  /* a */
)
Doc.concat(list{
  privateFlag,
  rows,
  /* a */
})

// More record spread test
type b = {
  // spread a
  ...a,
  // spread c
  ...c,
  // no spread
  b: string,
}

type a = {
  // spread from different module
  ...M.a,
  // spread c
  ...c,
  // no spread
  b: string,
}

let b = {
  // exotic
  ...\"let",
  // foo
  bar: "foo",
}

let b = {
  // quote
  ..."let",
  // foo
  bar: "foo",
}

let c = {
  // from different module
  ...M.a,
  // foo
  bar: "foo",
}
