###############################################################################
###############################################################################
###############################################################################
#group type signatures
###############################################################################
###############################################################################
###############################################################################

#test simple001
func :: a -> a

#test long typeVar
func
  :: lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
  -> lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd

#test keep linebreak mode
func
  :: lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
  -> lakjsdlkjasldkj
  -> lakjsdlkjasldkj

#test simple parens 1
func :: ((a))

#test simple parens 2
func :: (a -> a) -> a

#test simple parens 3
func :: a -> (a -> a)

#test did anyone say parentheses?
func :: (((((((((())))))))))

-- current output is.. funny. wonder if that can/needs to be improved..
#test give me more!
#pending
func :: ((((((((((((((((((((((((((((((((((((((((((()))))))))))))))))))))))))))))))))))))))))))

#test unit
func :: ()


###############################################################################

#test paren'd func 1
func
  :: (  lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
     -> lakjsdlkjasldkj
     -> lakjsdlkjasldkj
     )

#test paren'd func 2
func
  :: lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
  -> (lakjsdlkjasldkj -> lakjsdlkjasldkj)

#test paren'd func 3
func
  :: (lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd -> lakjsdlkjasldkj)
  -> lakjsdlkjasldkj

#test paren'd func 4
func
  :: (  lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
     -> lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
     )
  -> lakjsdlkjasldkj

#test paren'd func 5
func
  :: ( (  lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       -> lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       )
     )

###############################################################################

#test type application 1
func :: asd -> Either a b

#test type application 2
func
  :: asd
  -> Either
       lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd

#test type application 3
func
  :: asd
  -> Trither
       lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd

#test type application 4
func
  :: Trither
       lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
  -> asd

#test type application 5
func
  :: Trither
       lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       (lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd -> asd)

#test type application 6
func
  :: Trither
       asd
       lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       (  lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       -> lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       )

#test type application paren 1
func
  :: asd
  -> ( Trither
         lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
         lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
         lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
     )

#test type application paren 2
func
  :: asd
  -> ( Trither
         lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
         lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
     )
       lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd

#test type application paren 3
func
  :: ( Trither
         lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
         lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
     )
       lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
  -> asd

###############################################################################

#test list simple
func :: [a -> b]

#test list func
func
  :: [  lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
     -> lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
     ]

#test list paren
func
  :: [ (  lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       -> lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       )
     ]

################################################################## -- #############

#test tuple type 1
func :: (a, b, c)

#test tuple type 2
func :: ((a, b, c), (a, b, c), (a, b, c))

#test tuple type long
func
  :: ( lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
     , lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
     , lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
     )

#test tuple type nested
func
  :: ( ( lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       , (lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd)
       , lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       )
     )

#test tuple type function
func
  :: [ ( lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       , lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       , lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       )
     ]
###############################################################################
#test type operator stuff
#pending
test050 :: a :+: b
test051 ::  lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
        :+: lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
test052 ::  lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
        ->  lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
        :+: lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
        ->  lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd

###############################################################################

#test forall oneliner
{-# LANGUAGE ScopedTypeVariables #-}
func :: forall (a :: *) b . a -> b

#test forall context multiline
{-# LANGUAGE ScopedTypeVariables #-}
func
  :: forall m
   . Foo
  => ColMap2
  -> ColInfo
  -> ColInfo
  -> ColInfo
  -> ColInfo
  -> m ()

#test forall no-context multiline
{-# LANGUAGE ScopedTypeVariables #-}
func
  :: forall m
   . ColMap2
  -> ColInfo
  -> ColInfo
  -> ColInfo
  -> ColInfo
  -> ColInfo
  -> m ()

#test forall context multiline with comments
{-# LANGUAGE RankNTypes #-}
addFlagStringParam
  :: forall f out
   . (Applicative f)
  => String -- ^ short flag chars, i.e. "v" for -v
  -> [String] -- ^ list of long names, i.e. ["verbose"]
  -> String -- ^ param name
  -> Flag String -- ^ properties
  -> CmdParser f out String

#test language pragma issue
{-# LANGUAGE ScopedTypeVariables #-}
func :: forall (a :: *) b . a -> b

#test comments 1
func :: a -> b -- comment

#test comments 2
funcA :: a -> b -- comment A
funcB :: a -> b -- comment B

#test comments all
#pending
-- a
func -- b
  :: -- c
  a -- d
  -> -- e
  ( -- f
  c -- g
  , -- h
  d -- i
  ) -- j
-- k


###############################################################################
###############################################################################
###############################################################################
#group type signatures pragmas
###############################################################################
###############################################################################
###############################################################################

#test inline pragma 1
func = f
 where
  {-# INLINE f #-}
  f = id

#test inline pragma 2
func = ($)
 where
  {-# INLINE ($) #-}
  ($) = id

#test inline pragma 3
func = f
 where
  {-# INLINE CONLIKE [1] f #-}
  f = id

#test noinline pragma 1
{-# NOINLINE func #-}
func :: Int

#test inline pragma 4
#pending this does not work with the compiler version we currently use yet (i think). should work with ghc-8.0.2.
func = f
 where
  {-# INLINE [~] f #-}
  f = id


###############################################################################
###############################################################################
###############################################################################
#group data type declarations
###############################################################################
###############################################################################
###############################################################################

#test nullary data type
data Foo = Bar {}

data Biz = Baz

#test single record
data Foo = Bar
  { foo :: Baz
  }

#test record multiple names
data Foo = Bar
  { foo, bar :: Baz
  }

#test record multiple types
data Foo = Bar
  { foo  :: Baz
  , bars :: Bizzz
  }

#test record multiple types and names
data Foo = Bar
  { foo, biz :: Baz
  , bar      :: Bizzz
  }

#test record multiple types deriving
data Foo = Bar
  { fooz :: Baz
  , bar  :: Bizzz
  }
  deriving Show

#test record long field names
data MyRecord = MyConstructor
  { bar1, bar2
      :: Loooooooooooooooooooooooooooooooong
      -> Loooooooooooooooooooooooooooooooong
  , foo1, foo2
      :: Loooooooooooooooooooooooooooooooonger
      -> Loooooooooooooooooooooooooooooooonger
  }

#test record with DataTypeContexts
{-# LANGUAGE DatatypeContexts #-}
data
  ( LooooooooooooooooooooongConstraint a
  , LooooooooooooooooooooongConstraint b
  ) =>
  MyRecord a b
  = MyConstructor
    { foo1, foo2
        :: loooooooooooooooooooooooooooooooong
        -> loooooooooooooooooooooooooooooooong
    , bar  :: a
    , bazz :: b
    }

#test record single line layout
#pending config flag is disabled for now
{-# LANGUAGE ScopedTypeVariables #-}
-- brittany { lconfig_allowSinglelineRecord: true }
data MyRecord = forall a . Show a => MyCons { foo :: a -> a, i :: Int }

#test record no matching single line layout
{-# LANGUAGE ScopedTypeVariables #-}
-- brittany { lconfig_allowSinglelineRecord: true }
data MyRecord = forall a . Show a => Bar
  { foo :: abittoolongbutnotvery -> abittoolongbutnotvery
  }

#test record forall constraint multiline
{-# LANGUAGE ScopedTypeVariables #-}
data MyRecord
  = forall a
  . LooooooooooooooooooooongConstraint a =>
    LoooooooooooongConstructor
      { foo :: abittoolongbutnotvery -> abittoolongbutnotvery
      }

#test record forall constraint multiline more
{-# LANGUAGE ScopedTypeVariables #-}
data MyRecord
  = forall a b
  . ( Loooooooooooooooooooooooooooooooong a
    , Loooooooooooooooooooooooooooooooong b
    ) =>
    MyConstructor
      { a :: a
      , b :: b
      }

#test plain with forall and constraint
{-# LANGUAGE ScopedTypeVariables #-}
data MyStruct
  = forall a b
  . ( Loooooooooooooooooooooooooooooooong a
    , Loooooooooooooooooooooooooooooooong b
    ) =>
    MyConstructor (ToBriDocM BriDocNumbered)
                  (ToBriDocM BriDocNumbered)
                  (ToBriDocM BriDocNumbered)

#test record with many features
{-# LANGUAGE ScopedTypeVariables #-}
data MyRecord
  = forall a b
  . ( Loooooooooooooooooooooooooooooooong a
    , Loooooooooooooooooooooooooooooooong b
    ) =>
    MyConstructor
      { foo, foo2
          :: loooooooooooooooooooooooooooooooong
          -> loooooooooooooooooooooooooooooooong
      , bar  :: a
      , bazz :: b
      }
  deriving Show

#test record multiple types deriving
data Foo = Bar
  { foo  :: Baz
  , bars :: Bizzz
  }
  deriving (Show, Eq, Monad, Functor, Traversable, Foldable)

#test record multiple deriving strategies
#min-ghc 8.2
data Foo = Bar
  { foo  :: Baz
  , bars :: Bizzz
  }
  deriving Show
  deriving (Eq, Ord)
  deriving stock Show
  deriving stock (Eq, Ord)
  deriving anyclass Show
  deriving anyclass (Show, Eq, Monad, Functor)
  deriving newtype Show
  deriving newtype (Traversable, Foldable)

#test record deriving via
#min-ghc 8.6
data Foo = Bar
  { foo  :: Baz
  , bars :: Bizzz
  }
  deriving ToJSON via (SomeType)
  deriving (ToJSON, FromJSON) via (SomeType)

#test single record existential
{-# LANGUAGE ExistentialQuantification #-}

data Foo = forall a . Show a => Bar
  { foo :: a
  }

#test record multiple types existential
{-# LANGUAGE ExistentialQuantification #-}

data Foo = forall a b . (Show a, Eq b) => Bar
  { foo  :: a
  , bars :: b
  }

#test plain comment simple
-- before
data MyData = MyData Int
-- after

#test record newline comment
data MyRecord = MyRecord
  { a :: Int
    -- comment
  , b :: Int
  }

#test record comments simple
data Foo = Bar -- a
  { foo  :: Baz -- b
  , bars :: Bizzz -- c
  } -- d
  deriving (Show, Eq, Monad, Functor, Traversable, Foldable) -- e

#test record comments strange inline
data Foo = Bar
  {  -- a
    foo  -- b
         :: -- c
            Baz -- d
  , -- e
    bars :: Bizzz
  }
  deriving (Show, Eq, Monad, Functor, Traversable, Foldable)

#test record comments in deriving
## maybe we want to switch to a differnt layout when there are such comments.
## Don't hesitate to modify this testcase, it clearly is not the ideal layout
## for this.

data Foo = Bar
  { foo  :: Baz
  , bars :: Bizzz
  }
  -- a
  deriving --b
           ( -- c
            ToJSON -- d
                  , -- e
                    FromJSON --f
                            ) -- g

#test record comments in deriving via
## maybe we want to switch to a differnt layout when there are such comments.
## Don't hesitate to modify this testcase, it clearly is not the ideal layout
## for this.
#min-ghc 8.6

data Foo = Bar
  { foo  :: Baz
  , bars :: Bizzz
  }
  -- a
  deriving --a
           ToJSON --b
                  via  -- c
                      ( -- d
                       SomeType --e
                               , -- f
                                 ABC --g
                                    )

#test comment before equal sign
{-# LANGUAGE ExistentialQuantification #-}
data MyRecord
  -- test comment
  = forall a b
  . ( Loooooooooooooooooooooooooooooooong a
    , Loooooooooooooooooooooooooooooooong b
    ) =>
    MyConstructor a b

#test normal records on multi line indent policy left
-- brittany {lconfig_indentPolicy: IndentPolicyLeft }
data EnterpriseGrantsForCompanyResponse = EnterpriseGrantsForCompanyResponse
  Types.Company
  [EnterpriseGrantResponse]

#test normal records on multi line indent policy free
-- brittany {lconfig_indentPolicy: IndentPolicyFree }
data GrantsForCompanyResp = GrantsForCompanyResp Types.Company
                                                 [EnterpriseGrantResponse]

#test normal records on multi line indent policy free 2
-- brittany {lconfig_indentPolicy: IndentPolicyFree }
data EnterpriseGrantsForCompanyResponse = EnterpriseGrantsForCompanyResponse
                                            Types.Company
                                            [EnterpriseGrantResponse]

#test normal records on multi line indent policy multiple
-- brittany {lconfig_indentPolicy: IndentPolicyMultiple }
data GrantsForCompanyResp = GrantsForCompanyResp Types.Company
                                                 [EnterpriseGrantResponse]

#test large record with a comment
data XIILqcacwiuNiu = XIILqcacwiuNiu
  { oyyFtvbepgbOge_pebzVmuftEijwuj     :: Jgtoyuh HessJvNlo
  , wloQsiskdoxJop_xatiKrwedOxtu       :: Jgtoyuh [Inotg]
  , mmmJjcqtemyIyo_ovosDoreKeeoyamvove :: Jgtoyuh Eujo
  , mbiIatelofxOzr_uluxNngiiMjah       :: Jgtoyuh HessJvNlo
  , obxIskfcxpkIkb_uuviTuevcSkrgo      :: Jgtoyuh Int
  , wqrAtuvuecoHwr_ilotNxbuPleo        :: Jgtoyuh Ufaxdeq
  , lofAfuebdhpLuv_cnekPoyFxmg         :: Jgtoyuh Ufaxdeq
  , ouoFugtawzvUpk_oupiLzptugy         :: Jgtoyuh Eujo
  , iqiXjtziwogNsa_uiyvSunaTtgUsf3     :: Jgtoyuh Oaivn
  , odbIriaqnojUlz_onotoWuunehIpuy     :: Jgtoyuh Eujo
  , opjUxtkxzkiKse_luqjuZazt
      :: Jgtoyuh [(Eujo, Int, Int, Int, Int, Int, NELUxro)]
  -- , jcqRaqznxfhIpa_ywevMezmoYkutuwa        :: Jgtoyuh ()
  , vayOmuasyphOfd_bcsVljmvt               :: Jgtoyuh Eujo
  , rifArahilooRax_ufikecqdImsv            :: Jgtoyuh Oaivn
  , raqKtopcpszDwb_oqocubasZuqjcryoDojGkw  :: Jgtoyuh Oaivn
  , mluJiilpcijUtt_gaisklifVekfeyagRmfbyzz :: Jgtoyuh Oaivn
  , oqhPaahjupaSmi_gamwwoovKyxznecvEayluc  :: Jgtoyuh Oaivn
  , mazFubimwebZpa_itidehDodiDlboz         :: Jgtoyuh Vrep
  , jeyOcuesexaYoy_vpqn                    :: Jgtoyuh ()
  }

###############################################################################
###############################################################################
###############################################################################
#group equation.basic
###############################################################################
###############################################################################
###############################################################################
## some basic testing of different kinds of equations.
## some focus on column layouting for multiple-equation definitions.
## (that part probably is not implemented in any way yet.)

#test basic 1
func x = x

#test infix 1
x *** y = x

#test symbol prefix
(***) x y = x

#test infix more args simple
(f >=> g) k = f k >>= g

#test infix more args alignment
(Left  a <$$> Left  dd) e f = True
(Left  a <$$> Right d ) e f = True
(Right a <$$> Left  d ) e f = False
(Right a <$$> Right dd) e f = True


###############################################################################
###############################################################################
###############################################################################
#group equation.patterns
###############################################################################
###############################################################################
###############################################################################

#test wildcard
func _ = x

#test simple long pattern
#pending
func reallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongvariable
  = x

#test simple multiline pattern
#pending
func reallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongvariable
     reallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongvariable
  = x

#test another multiline pattern
#pending
func reallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongvariable
     a
     b
  = x

#test simple constructor
func (A a) = a

#test list constructor
func (x : xr) = x

#test some other constructor symbol
#pending
func (x :+: xr) = x

#test normal infix constructor
func (x `Foo` xr) = x


###############################################################################
###############################################################################
###############################################################################
#group equation.guards
###############################################################################
###############################################################################
###############################################################################
#test simple guard
func | True = x

#test multiple-clauses-1
func x | x         = simple expression
       | otherwise = 0

#test multiple-clauses-2
func x
  | a somewhat longer guard x = "and a somewhat longer expession that does not"
  | otherwise                 = "fit without putting the guards in new lines"

#test multiple-clauses-3
func x
  | very long guard, another rather long guard that refers to x = nontrivial
    expression
    foo
    bar
    alsdkjlasdjlasj
  | otherwise = 0

#test multiple-clauses-4
func x
  | very long guard, another rather long guard that refers to x
  = nontrivialexpression foo bar alsdkjlasdjlasj
  | otherwise
  = 0

#test multiple-clauses-5
func x
  | very loooooooooooooooooooooooooooooong guard
  , another rather long guard that refers to x
  = nontrivial expression foo bar alsdkjlasdjlasj
  | otherwise
  = 0


###############################################################################
###############################################################################
###############################################################################
#group expression.basic
###############################################################################
###############################################################################
###############################################################################

#test var
func = x

describe "infix op" $ do
#test 1
func = x + x

#test long
#pending
func = mweroiuxlskdfjlksjdflkjsdfljksldkjflkjsdflkj
     + mweroiuxlskdfjlksjdflkjsdfljksldkjflkjsdflkj

#test long keep linemode 1
#pending
func = mweroiuxlskdfjlksjdflkjsdfljksldkjflkjsdflkj
     + mweroiuxlskdfjlksj
     + mweroiuxlskdfjlksj

#test long keep linemode 2
#pending
func = mweroiuxlskdfjlksj
     + mweroiuxlskdfjlksj
     + mweroiuxlskdfjlksjdflkjsdfljksldkjflkjsdflkj

#test literals
func = 1
func = "abc"
func = 1.1e5
func = 'x'
func = 981409823458910394810928414192837123987123987123

#test lambda
func = \x -> abc

describe "app" $ do
#test 1
func = klajsdas klajsdas klajsdas

#test 2
func = lakjsdlajsdljasdlkjasldjasldjasldjalsdjlaskjd
  lakjsdlajsdljasdlkjasldjasldjasldjalsdjlaskjd
  lakjsdlajsdljasdlkjasldjasldjasldjalsdjlaskjd

#test 3
func = lakjsdlajsdljasdlkjasldjasldjasldjalsdjlaskjd lakjsdlajsdljas
                                                     lakjsdlajsdljas
                                                     lakjsdlajsdljas

###
#group expression.basic.sections
###

#test left
func = (1 +)

#test right
func = (+ 1)

#test left inf
func = (1 `abc`)

#test right inf
func = (`abc` 1)

###
#group tuples
###

#test pair
func = (abc, def)

#test pair section left
func = (abc, )

#test pair section right
func = (, abc)

#test quintuple section long
myTupleSection =
  ( verylaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaargefirstelement
  ,
  , verylaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaargethirdelement
  ,
  )

#test 2
#pending
func = (lakjsdlajsdljasdlkjasldjasldjasldjalsdjlaskjd
  , lakjsdlajsdljasdlkjasldjasldjasldjalsdjlaskjd)

#test comment-after-then
foo = if True
  then
      -- iiiiii
    "a                                                                         "
  else
    "b                                                                         "

#test comment-after-if-else-do
func = if cond
  then pure 42
  else do
    -- test
    abc

#test nonempty-case-short
func = case x of
  False -> False
  True  -> True

#test nonempty-case-long
func =
  case
      lakjsdlajsdljasdlkjasldjasldjasldjalsdjlaskjd
        lakjsdlajsdljasdlkjasldjasldjasldjalsdjlaskjd
    of
      False -> False
      True  -> True

#test nonempty-case-long-do
func = do
  case
      lakjsdlajsdljasdlkjasldjasldjasldjalsdjlaskjd
        lakjsdlajsdljasdlkjasldjasldjasldjalsdjlaskjd
    of
      False -> False
      True  -> True

#test empty-case-short
func = case x of {}

#test empty-case-long
func =
  case
      lakjsdlajsdljasdlkjasldjasldjasldjalsdjlaskjd
        lakjsdlajsdljasdlkjasldjasldjasldjalsdjlaskjd
    of {}

#test empty-case-long-do
func = do
  case
      lakjsdlajsdljasdlkjasldjasldjasldjalsdjlaskjd
        lakjsdlajsdljasdlkjasldjasldjasldjalsdjlaskjd
    of {}

###############################################################################
###############################################################################
###############################################################################
#group expression.do statements
###############################################################################
###############################################################################
###############################################################################

#test simple
func = do
  stmt
  stmt

#test bind
func = do
  x <- stmt
  stmt x

#test let
func = do
  let x = 13
  stmt x


###############################################################################
###############################################################################
###############################################################################
#group expression.lists
###############################################################################
###############################################################################
###############################################################################

#test monad-comprehension-case-of
func =
  foooooo
    $ [ case
          foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
        of
          _ -> True
      ]

###############################################################################
###############################################################################
###############################################################################
#group expression.let
###############################################################################
###############################################################################
###############################################################################

#test single-bind-comment-long
testMethod foo bar baz qux =
  let x = undefined foo bar baz qux qux baz bar :: String
  -- some comment explaining the in expression
  in  undefined foo x :: String

#test single-bind-comment-short
testMethod foo bar baz qux =
  let x = undefined :: String
  -- some comment explaining the in expression
  in  undefined :: String

#test single-bind-comment-before
testMethod foo bar baz qux =
  -- some comment explaining the in expression
  let x = undefined :: String in undefined :: String

#test multiple-binds-comment
foo foo bar baz qux =
  let a = 1
      b = 2
      c = 3
  -- some comment explaining the in expression
  in  undefined :: String


###############################################################################
###############################################################################
###############################################################################
#group stylisticspecialcases
###############################################################################
###############################################################################
###############################################################################

#test operatorprefixalignment-even-with-multiline-alignbreak
func =
  foo
    $  [ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
       , bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
       ]
    ++ [ccccccccccccccccccccccccccccccccccccccccccccccccccccccccc]


###############################################################################
###############################################################################
###############################################################################
#group module
###############################################################################
###############################################################################
###############################################################################

#test simple
module Main where

#test no-exports
module Main () where

#test one-export
module Main (main) where

#test several-exports
module Main (main, test1, test2) where

#test many-exports
module Main
  ( main
  , test1
  , test2
  , test3
  , test4
  , test5
  , test6
  , test7
  , test8
  , test9
  ) where

#test exports-with-comments
module Main
  ( main
  -- main
  , test1
  , test2
  -- Test 3
  , test3
  , test4
  -- Test 5
  , test5
  -- Test 6
  ) where

#test simple-export-with-things
module Main (Test(..)) where

#test simple-export-with-module-contents
module Main (module Main) where

#test export-with-things
module Main (Test(Test, a, b)) where

#test export-with-things-comment
-- comment1

module Main
  ( Test(Test, a, b)
  , foo -- comment2
  ) -- comment3
    where

#test export-with-empty-thing
module Main (Test()) where

#test empty-with-comment
-- Intentionally left empty

###############################################################################
###############################################################################
###############################################################################
#group module.import
###############################################################################
###############################################################################
###############################################################################

#test simple-import
import           Data.List

#test simple-import-alias
import           Data.List                               as L

#test simple-qualified-import
import qualified Data.List

#test simple-qualified-import-alias
import qualified Data.List                               as L

#test simple-safe
import safe      Data.List                               as L

#test simple-source
import {-# SOURCE #-} Data.List                           ( )

#test simple-safe-qualified
import safe qualified Data.List

#test simple-safe-qualified-source
import {-# SOURCE #-} safe qualified Data.List

#test simple-qualified-package
import qualified "base" Data.List

#test qualifier-effect
import {-# SOURCE #-} safe qualified "base" Data.List    as L
import {-# SOURCE #-} safe qualified "base" Data.List     ( )
import {-# SOURCE #-} safe qualified Data.List     hiding ( )

#test instances-only
import qualified Data.List                                ( )

#test one-element
import           Data.List                                ( nub )

#test several-elements
import           Data.List                                ( nub
                                                          , foldl'
                                                          , indexElem
                                                          )

#test a-ridiculous-amount-of-elements
import           Test                                     ( Long
                                                          , list
                                                          , with
                                                          , items
                                                          , that
                                                          , will
                                                          , not
                                                          , quite
                                                          , fit
                                                          , onA
                                                          , single
                                                          , line
                                                          , anymore
                                                          )

#test with-things
import           Test                                     ( T
                                                          , T2()
                                                          , T3(..)
                                                          , T4(T4)
                                                          , T5(T5, t5)
                                                          , T6((<|>))
                                                          , (+)
                                                          , (:.)
                                                          , (:.)(..)
                                                          , (:.)(T7, (:.), t7)
                                                          )

#test hiding
import           Test                              hiding ( )
import           Test                                    as T
                                                   hiding ( )

#test import-hiding-many
import           Prelude                                 as X
                                                   hiding ( head
                                                          , init
                                                          , last
                                                          , maximum
                                                          , minimum
                                                          , pred
                                                          , read
                                                          , readFile
                                                          , succ
                                                          , tail
                                                          , undefined
                                                          )

#test long-module-name-simple
import           TestJustShortEnoughModuleNameLikeThisOne ( )
import           TestJustAbitToLongModuleNameLikeThisOneIs
                                                          ( )

#test long-module-name-as
import           TestJustShortEnoughModuleNameLikeThisOn as T
import           TestJustAbitToLongModuleNameLikeThisOneI
                                                         as T

#test long-module-name-hiding
import           TestJustShortEnoughModuleNameLike hiding ( )
import           TestJustAbitToLongModuleNameLikeTh
                                                   hiding ( )

#test long-module-name-simple-items
import           MoreThanSufficientlyLongModuleNameWithSome
                                                          ( items
                                                          , that
                                                          , will
                                                          , not
                                                          , fit
                                                          , inA
                                                          , compact
                                                          , layout
                                                          )

#test long-module-name-hiding-items
import           TestJustShortEnoughModuleNameLike hiding ( abc
                                                          , def
                                                          , ghci
                                                          , jklm
                                                          )
import           TestJustAbitToLongModuleNameLikeTh
                                                   hiding ( abc
                                                          , def
                                                          , ghci
                                                          , jklm
                                                          )

#test long-module-name-other
import {-# SOURCE #-} safe qualified "qualifiers" AlsoAff ( )
import {-# SOURCE #-} safe qualified "qualifiers" AlsoAffe
                                                          ( )

import {-# SOURCE #-} safe qualified "qualifiers" AlsoAf as T
import {-# SOURCE #-} safe qualified "qualifiers" AlsoAff
                                                         as T
import {-# SOURCE #-} safe qualified "qualifier" A hiding ( )
import {-# SOURCE #-} safe qualified "qualifiers" A
                                                   hiding ( )

#test import-with-comments
-- Test
import           Data.List                                ( nub ) -- Test
{- Test -}
import qualified Data.List                               as L
                                                          ( foldl' ) {- Test -}

-- Test
import           Test                                     ( test )

#test import-with-comments-2

import           Test                                     ( abc
                                                          , def
                                                          -- comment
                                                          )

#test import-with-comments-3

import           Test                                     ( abc
                                                          -- comment
                                                          )

#test import-with-comments-4
import           Test                                     ( abc
                                                          -- comment
                                                          , def
                                                          , ghi
                                                          {- comment -}
                                                          , jkl
                                                          -- comment
                                                          )

#test import-with-comments-5
import           Test                                     ( -- comment
                                                          )

#test long-bindings
import           Test                                     ( longbindingNameThatoverflowsColum
                                                          )
import           Test                                     ( Long
                                                            ( List
                                                            , Of
                                                            , Things
                                                            )
                                                          )

#test things-with-with-comments
import           Test                                     ( Thing
                                                            ( -- Comments
                                                            )
                                                          )
import           Test                                     ( Thing
                                                            ( Item
                                                            -- and Comment
                                                            )
                                                          )
import           Test                                     ( Thing
                                                            ( With
                                                            -- Comments
                                                            , and
                                                            -- also
                                                            , items
                                                            -- !
                                                            )
                                                          )
#test prefer-dense-empty-list
import           VeryLongModuleNameThatCouldEvenCauseAnEmptyBindingListToExpandIntoMultipleLine
                                                          ( )

#test preamble full-preamble
{-# LANGUAGE BangPatterns #-}

{-
 - Test module
 -}
module Test
  ( test1
  -- ^ test
  , test2
  -- | test
  , test3
  , test4
  , test5
  , test6
  , test7
  , test8
  , test9
  , test10
  -- Test 10
  ) where

-- Test
import           Data.List                                ( nub ) -- Test
{- Test -}
import qualified Data.List                               as L
                                                          ( foldl' ) {- Test -}

-- Test
import           Test                                     ( test )


###############################################################################
###############################################################################
###############################################################################
#group type synonyms
###############################################################################
###############################################################################
###############################################################################

#test simple-synonym

type MySynonym = String

#test parameterised-synonym

type MySynonym a = [a]

#test long-function-synonym

-- | Important comment thrown in
type MySynonym b a
  = MySynonym a b -> MySynonym a b -> MyParamType a b -> MyParamType a b

#test overflowing-function-synonym

type MySynonym3 b a
  =  MySynonym a b
  -> MySynonym a b
  -- ^ RandomComment
  -> MyParamType a b
  -> MyParamType a b
  -> MySynonym2 b a

#test synonym-with-kind-sig

type MySynonym (a :: * -> *)
  =  MySynonym a b
  -> MySynonym a b
  -> MyParamType a b
  -> MyParamType a b
  -> MySynonym2 b a

#test synonym-with-constraint

type MySynonym a = Num a => a -> Int

#test synonym-overflowing-with-constraint

type MySynonym a
  =  Num a
  => AReallyLongTypeName
  -> AnotherReallyLongTypeName
  -> AThirdTypeNameToOverflow

#test synonym-forall

{-# LANGUAGE RankNTypes #-}

type MySynonym = forall a . [a]

#test synonym-operator

type (:+:) a b = (a, b)

#test synonym-infix

type a `MySynonym` b = a -> b

#test synonym-infix-operator

type a :+: b = (a, b)

#test synonym-infix-parens

type (a `Foo` b) c = (a, b, c)

#test synonym-comments

type Foo a -- fancy type comment
  = -- strange comment
    Int

#test synonym-type-operators
#pending

type (a :+: b) = (a, b)

#test synonym-multi-parens
#pending

type ((a :+: b) c) = (a, c)

#test synonym-tuple-type-many-comments

type Foo
  = ( -- t1
     A -- t2
      , -- t3
        B -- t4
         ) -- t5

###############################################################################
###############################################################################
###############################################################################
#group class.instance
###############################################################################
###############################################################################
###############################################################################

#test simple-instance

instance MyClass Int where
  myMethod x = x + 1

#test simple-method-comment

instance MyClass Int where
  myMethod x =
    -- insightful comment
    x + 1

#test simple-method-signature

instance MyClass Int where
  myMethod :: Int -> Int
  myMethod x = x + 1

#test simple-long-method-signature

instance MyClass Int where
  myMethod
    :: Int
    -> Int
    -> AReallyLongType
    -> AReallyLongType
    -> AReallyLongType
    -> Int
  myMethod x = x + 1

#test simple-two-methods

instance MyClass Int where
  myMethod x = x + 1
  myMethod2 x = x + 1

#test simple-two-signatures

instance MyClass Int where
  myMethod
    :: Int
    -> Int
    -> AReallyLongType
    -> AReallyLongType
    -> AReallyLongType
    -> Int
  myMethod x = x + 1

  myMethod2 :: Int -> Int
  myMethod2 x = x + 1

#test simple-instance-comment

-- | This instance should be commented on
instance MyClass Int where

  -- | This method is also comment-worthy
  myMethod x = x + 1

#test instance-with-type-family

instance MyClass Int where
  type MyType = Int

  myMethod :: MyType -> Int
  myMethod x = x + 1

#test instance-with-type-family-below-method

instance MyClass Int where

  type MyType = String

  myMethod :: MyType -> Int
  myMethod x = x + 1

  type MyType = Int

#test instance-with-data-family

instance MyClass Int where

  -- | This data is very important
  data MyData = IntData
    { intData  :: String
    , intData2 :: Int
    }

  myMethod :: MyData -> Int
  myMethod = intData2

#test instance-with-data-family-below-method

instance MyClass Int where
  -- | This data is important
  data MyData = Test Int Int

  myMethod :: MyData -> Int
  myMethod = intData2

  -- | This data is also important
  data MyData2 = IntData
    { intData  :: String
    -- ^ Interesting field
    , intData2 :: Int
    }

#test instance-with-newtype-family-and-deriving

{-# LANGUAGE TypeFamilies #-}

module Lib where

instance Foo () where
  newtype Bar () = Baz ()
    deriving (Eq, Ord, Show)
  bar = Baz

#test instance-with-newtype-family-and-record

instance Foo Int where
  newtype Bar Int = BarInt
    { unBarInt :: Int
    }


###############################################################################
###############################################################################
###############################################################################
#group whitespace-newlines
###############################################################################
###############################################################################
###############################################################################

#test module-import-newlines

module Main where

import           Prelude

firstDecl = True

#test function-where-newlines

func = do

  -- complex first step
  aaa

  -- complex second step
  bbb

 where

  helper :: Helper
  helper = helpful

  other :: Other
  other = True


###############################################################################
###############################################################################
###############################################################################
#group typefam.instance
###############################################################################
###############################################################################
###############################################################################

#test simple-typefam-instance

type instance MyFam Bool = String

#test simple-typefam-instance-param-type

type instance MyFam (Maybe a) = a -> Bool

#test simple-typefam-instance-parens
#pending the parens cause problems since ghc-8.8

type instance (MyFam (String -> Int)) = String

#test simple-typefam-instance-overflow

type instance MyFam ALongishType
  =  AMuchLongerTypeThanThat
  -> AnEvenLongerTypeThanTheLastOne
  -> ShouldDefinitelyOverflow

#test simple-typefam-instance-comments

-- | A happy family
type instance MyFam Bool -- This is an odd one
  = AnotherType -- Here's another

#test simple-typefam-instance-parens-comment
#pending the parens cause problems since ghc-8.8

-- | A happy family
type instance (MyFam Bool) -- This is an odd one
  = -- Here's another
    AnotherType