
###############################################################################
###############################################################################
###############################################################################
#group context-free/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 nested tuples over line length
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 HsOpTy
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 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
-- a
func -- b
  :: -- c
     a -- d
  -> -- e
     ( -- f
      c -- g
       , -- h
         d -- i
          ) -- j-- k

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

#test ImplicitParams 1
{-# LANGUAGE ImplicitParams #-}
func :: (?asd::Int) -> ()

#test ImplicitParams 2
{-# LANGUAGE ImplicitParams #-}
func
  :: ( ?asd
       :: lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
       -> lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
     )
  -> ()


###############################################################################
###############################################################################
###############################################################################
#group context-free/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 inline pragma 4
func = f
 where
  {-# INLINE [~1] f #-}
  f = id


###############################################################################
###############################################################################
###############################################################################
#group context-free/data type declarations
###############################################################################
###############################################################################
###############################################################################

#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
  , bar :: Bizzz
  }

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

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

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


###############################################################################
###############################################################################
###############################################################################
#group context-free/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


###############################################################################
###############################################################################
###############################################################################
#group context-free/equation.patterns
###############################################################################
###############################################################################
###############################################################################

#test wildcard
func _ = x

#test simple long pattern
func reallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongvariable =
  x

#test simple multiline pattern
func reallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongvariable reallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongvariable
  = x

#test another multiline pattern
func reallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongvariable a b
  = x

#test simple constructor
func (A a) = a

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

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


###############################################################################
###############################################################################
###############################################################################
#group context-free/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 context-free/expression.basic
###############################################################################
###############################################################################
###############################################################################

#test var
func = x

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

#test long
func =
  mweroiuxlskdfjlksjdflkjsdfljksldkjflkjsdflkj
    + mweroiuxlskdfjlksjdflkjsdfljksldkjflkjsdflkj

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

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

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

#test lambdacase
{-# LANGUAGE LambdaCase #-}
func = \case
  FooBar -> x
  Baz -> y

#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 context-free/expression.basic.sections
###

#test left
func = (1 +)

#test right
func = (+ 1)

#test left inf
## TODO: this could be improved..
func = (1 `abc`)

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

###
#group context-free/tuples
###

#test 1
func = (abc, def)

#test 2
func =
  ( lakjsdlajsdljasdlkjasldjasldjasldjalsdjlaskjd
  , lakjsdlajsdljasdlkjasldjasldjasldjalsdjlaskjd
  )

#test let in on single line
foo =
  let longIdentifierForShortValue = 1
  in longIdentifierForShortValue + longIdentifierForShortValue



###############################################################################
###############################################################################
###############################################################################
#group context-free/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 context-free/expression.lists
###############################################################################
###############################################################################
###############################################################################

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


###############################################################################
###############################################################################
###############################################################################
#group context-free/expression.multiwayif
###############################################################################
###############################################################################
###############################################################################

#test simple
{-# LANGUAGE MultiWayIf #-}
func = if
  | cond1 -> loooooooooooooooooooooooooooooong expr1
  | cond2 -> loooooooooooooooooooooooooooooong expr2

#test simplenested
{-# LANGUAGE MultiWayIf #-}
func = do
  foo
  bar $ if
    | cond1 -> loooooooooooooooooooooooooooooong expr1
    | cond2 -> loooooooooooooooooooooooooooooong expr2


###############################################################################
###############################################################################
###############################################################################
#group context-free/stylisticspecialcases
###############################################################################
###############################################################################
###############################################################################

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

###############################################################################
###############################################################################
###############################################################################
#group context-free/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-empty-thing
module Main (Test()) where

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

###############################################################################
###############################################################################
###############################################################################
#group context-free/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 hiding (nub)

#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 (foldl', indexElem, nub)

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

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

#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 MoreThanSufficientlyLongModuleNameWithSome
  (compact, fit, inA, items, layout, not, that, will)
import TestJustAbitToLongModuleNameLikeThisOneIs ()
import TestJustShortEnoughModuleNameLikeThisOne ()

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

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

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

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

#test import-with-comments
-- Test
import Data.List (nub) -- Test
{- Test -}
import qualified Data.List as L (foldl') {- 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 Test (test)

#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
    ( With
    -- Comments
    , and
    -- also
    , items
    -- !
    )
  )
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
  ) where

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

-- Test
import Test (test)

###############################################################################
###############################################################################
###############################################################################
#group context-free/regression
###############################################################################
###############################################################################
###############################################################################

#test newlines-comment
func = do
  abc <- foo

--abc
return ()

#test parenthesis-around-unit
func = (())

#test let-defs indentation
func = do
  let
    foo True = True
    foo _ = False
  return ()

#test let-defs no indent
func = do
  let
    foo True = True
    foo _ = False
  return ()

#test let-defs no indent
func = do
  let
    foo = True
    b = False
  return ()

#test let-defs no indent
func =
  let
    foo = True
    b = False
  in return ()

#test record update indentation 1
func = do
  s <- mGet
  mSet $ s { _lstate_indent = _lstate_indent state }

#test record update indentation 2
func = do
  s <- mGet
  mSet $ s
    { _lstate_indent = _lstate_indent state
    , _lstate_foo = _lstate_foo state
    }

#test record update indentation 3
func = do
  s <- mGet
  mSet $ s
    { _lstate_indent = _lstate_indent lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
    , _lstate_foo = _lstate_foo kasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
    }

#test record construction 1
func = Foo { _lstate_indent = _lstate_indent state }

#test record construction 2
func = Foo
  { _lstate_indent = _lstate_indent lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
  , _lstate_foo = _lstate_foo lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
  }

#test record construction 3
func = do
  Foo
    { _lstate_indent = _lstate_indent lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
    , _lstate_foo = _lstate_foo lkasdlkjalsdjlakjsdlkjasldkjalskdjlkajsd
    }

#test post-indent comment
func = do
-- abc
  -- def
  return ()

#test post-unindent comment
func = do
  do
    return ()
    -- abc
  -- def
  return ()

#test CPP empty comment case
#pending CPP parsing needs fixing for roundTripEqual
{-# LANGUAGE CPP #-}
module Test where
func = do
#if FOO
  let x = 13
#endif
  stmt x

## really, the following should be handled by forcing the Alt to multiline
## because there are comments. as long as this is not implemented though,
## we should ensure the trivial solution works.
#test comment inline placement (temporary)
func
  :: Int -- basic indentation amount
  -> Int -- currently used width in current line (after indent)
         -- used to accurately calc placing of the current-line
  -> LayoutDesc
  -> Int

#test some indentation thingy
func =
  ( lkjadljasldjalskdjaldjalsdjkalsdjlaksdjlasjdlajsaldskj
  $ abc
  $ def
  $ ghi
  $ jkl
  )

#test parenthesized operator
buildG bounds0 edges0 = accumArray (flip (:)) [] bounds0 (map reassoc edges0)
  where reassoc (v, e, w) = (v, (e, w))

#test record pattern matching stuff
downloadRepoPackage = case repo of
  RepoLocal {..} -> return ()
  RepoLocal { abc } -> return ()
  RepoLocal{} -> return ()

#test do let comment indentation level problem
func = do
  let
    (primaryPkg, otherPkgs) = selectPrimaryLocalPackage pwd pkgs'
    (bproblems, x) = resolveBuildTargets primaryPkg otherPkgs utargets''
    -- default local dir target if there's no given target
    utargets'' = "foo"
  return ()

#test list comprehension comment placement
func =
  [ (thing, take 10 alts) --TODO: select best ones
  | (thing, _got, alts@(_ : _)) <- nosuchFooThing
  , gast <- award
  ]

#test if-then-else comment placement
func = if x
  then if y -- y is important
    then foo
    else bar
  else Nothing

#test qualified infix pattern
wrapPatPrepend pat prepElem = do
  patDocs <- layoutPat pat
  case Seq.viewl patDocs of
    Seq.EmptyL -> return $ Seq.empty
    x1 Seq.:< xR -> do
      x1' <- docSeq [prepElem, return x1]
      return $ x1' Seq.<| xR

#test type signature multiline forcing issue
layoutWriteNewlineBlock
  :: ( MonadMultiWriter Text.Builder.Builder m
     , MonadMultiState LayoutState m
     , MonadMultiWriter (Seq String) m
     )
  => m ()

#test multiwayif proper indentation
{-# LANGUAGE MultiWayIf #-}
readMergePersConfig path shouldCreate conf = do
  exists <- liftIO $ System.Directory.doesFileExist path
  if
    | exists -> do
      contents <- liftIO $ ByteString.readFile path -- no lazy IO, tyvm.
      fileConf <- case Data.Yaml.decodeEither contents of
        Left e -> do
          liftIO
            $ putStrErrLn
            $ "error reading in brittany config from " ++ path ++ ":"
          liftIO $ putStrErrLn e
          mzero
        Right x -> return x
      return $ fileConf Semigroup.<> conf
    | shouldCreate -> do
      liftIO
        $ ByteString.writeFile path
        $ Data.Yaml.encode
        $ cMap (Option . Just . runIdentity) staticDefaultConfig
      return $ conf
    | otherwise -> do
      return conf

#test nested pattern alignment issue"
func = BuildReport
 where
  convertInstallOutcome = case result of
    Left BR.PlanningFailed -> PlanningFailed
    Left (BR.DependentFailed p) -> DependencyFailed p
    Left (BR.DownloadFailed _) -> DownloadFailed
    Left (BR.UnpackFailed _) -> UnpackFailed
    Left (BR.ConfigureFailed _) -> ConfigureFailed
    Left (BR.BuildFailed _) -> BuildFailed
    Left (BR.TestsFailed _) -> TestsFailed
    Left (BR.InstallFailed _) -> InstallFailed
    Right (BR.BuildOk _ _ _) -> InstallOk

#test nested pattern alignment issue"
func = BuildReport
 where
  convertInstallOutcome = case result of
    Left BR.PlanningFailed -> PlanningFailed
    Left (BR.DependentFailed p) -> DependencyFailed p
    Left (BR.DownloadFailed _) -> DownloadFailed
    Left (BR.UnpackFailed _) -> UnpackFailed
    Left (BR.ConfigureFailed _) -> ConfigureFailed
    Left (BR.BuildFailed _) -> BuildFailed
    Left (BR.TestsFailed _) -> TestsFailed
    Left (BR.InstallFailed _) -> InstallFailed
    Right (BR.BuildOk _ _ _) -> InstallOk

#test partially overflowing alignment issue"
showPackageDetailedInfo pkginfo =
  renderStyle (style { lineLength = 80, ribbonsPerLine = 1 })
    $ char '*'
    $+$ something
          [ entry "Synopsis" synopsis hideIfNull reflowParagraphs
          , entry
              "Versions available"
              sourceVersions
              (altText null "[ Not available from server ]")
              (dispTopVersions 9 (preferredVersions pkginfo))
          , entry
              "Versions installed"
              installedVersions
              (altText
                null
                (if hasLib pkginfo then "[ Not installed ]" else "[ Unknown ]")
              )
              (dispTopVersions 4 (preferredVersions pkginfo))
          , entry "Homepage" homepage orNotSpecified text
          , entry "Bug reports" bugReports orNotSpecified text
          , entry "Description" description hideIfNull reflowParagraphs
          , entry "Category" category hideIfNull text
          , entry "License" license alwaysShow disp
          , entry "Author" author hideIfNull reflowLines
          , entry "Maintainer" maintainer hideIfNull reflowLines
          , entry "Source repo" sourceRepo orNotSpecified text
          , entry "Executables" executables hideIfNull (commaSep text)
          , entry "Flags" flags hideIfNull (commaSep dispFlag)
          , entry "Dependencies" dependencies hideIfNull (commaSep dispExtDep)
          , entry "Documentation" haddockHtml showIfInstalled text
          , entry "Cached" haveTarball alwaysShow dispYesNo
          , if not (hasLib pkginfo)
              then empty
              else
                text "Modules:"
                $+$ nest 4 (vcat (map disp . sort . modules $ pkginfo))
          ]

#test issue 7a
isValidPosition position
  | validX && validY = Just position
  | otherwise = Nothing

#test issue-6-pattern-linebreak-validity
## this is ugly, but at least syntactically valid.
foo = Reflex.runSpiderHost $ ReflexHost.hostApp $ do
  (inputEvent :: Reflex.Event Reflex.Spider String, inputFire :: String
    -> IO Bool) <-
    ReflexHost.newExternalEvent
  liftIO . forkIO . forever $ getLine >>= inputFire
  ReflexHost.performEvent_ $ fmap (liftIO . putStrLn) inputEvent

#test issue 15
-- Test.hs
module Test where

data X = X

#test issue 16
foldrDesc f z = unSwitchQueue $ \q ->
  switch (Min.foldrDesc (f unTaggedF) z q) (Min.foldrAsc (f unTaggedF) z q)

#test issue 18
autocheckCases =
  [ ("Never Deadlocks", representative deadlocksNever)
  , ("No Exceptions", representative exceptionsNever)
  , ("Consistent Result", alwaysSame) -- already representative
  ]

#test issue 18b
autocheckCases =
  [ ("Never Deadlocks", representative deadlocksNever)
  , ("No Exceptions", representative exceptionsNever)
  , ( "Consistent Result"
    , alwaysSame -- already representative
    )
  ]

#test issue 18c
func =
  [ (abc, (1111, 1111))
  , (def, (2, 2))
  , foo -- comment
  ]

#test issue 26
foo a b = g a b -- fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
  where g a b = b + b * a

#test issue 26b
foo a b = g a b where g a b = b + b * a -- fooooooooooooooooooooooooooooooooooo

#test aggressive alignment 1
func = do
  abc <- expr
  abcccccccccccccccccc <- expr
  abcccccccccccccccccccccccccccccccccccccccccc <- expr
  abccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc <- expr

#test example alignment 1
func (MyLongFoo abc def) = 1
func (Bar a d) = 2
func _ = 3

#test listcomprehension-case-of
parserCompactLocation =
  [ try
    $ [ ParseRelAbs (Text.Read.read digits) _ _
      | digits <- many1 digit
      , rel1 :: Maybe (Either Int (Ratio Int)) <- optionMaybe
        [ case divPart of
            Nothing -> Left $ Text.Read.read digits
            Just ddigits ->
              Right $ Text.Read.read digits % Text.Read.read ddigits
        | digits <- many1 digit
        , divPart <- optionMaybe (string "/" *> many1 digit)
        ]
      ]
  ]

#test opapp-specialcasing-1
func =
  fooooooooooooooooooooooooooooooooo
    $ foooooooooooooooooooooooooooooooo
        foooooooooooooooooooooooooooooooo
        foooooooooooooooooooooooooooooooo

#test opapp-specialcasing-2
func =
  fooooooooooooooooooooooooooooooooo
    + foooooooooooooooooooooooooooooooo
        foooooooooooooooooooooooooooooooo
        foooooooooooooooooooooooooooooooo

#test opapp-specialcasing-3
func =
  fooooooooooooooooooooooooooooooooo
    + foooooooooooooooooooooooooooooooo
        [ foooooooooooooooooooooooooooooooo
        , foooooooooooooooooooooooooooooooo
        , foooooooooooooooooooooooooooooooo
        ]

#test opapp-indenting
parserPrim =
  [ r
  | r <-
    [ SGPPrimFloat
      $ bool id (0 -) minus
      $ readGnok "parserPrim" (d1 ++ d2 ++ d3 ++ d4)
    | d2 <- string "."
    , d3 <- many1 (oneOf "0123456789")
    , _ <- string "f"
    ]
    <|> [ SGPPrimFloat $ bool id (0 -) minus $ fromIntegral
            (readGnok "parserPrim" d1 :: Integer)
        | _ <- string "f"
        ]
    <|> [ SGPPrimInt $ bool id (0 -) minus $ fromIntegral
            (readGnok "parserPrim" d1 :: Integer)
        | _ <- string "i"
        ]
  ]

#test another-parspacing-testcase

samples = (SV.unpackaaaaadat) <&> \f ->
  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

#test recordupd-singleline-bug

runBrittany tabSize text = do
  let
    config' = staticDefaultConfig
    config = config'
      { _conf_layout = (_conf_layout config')
        { _lconfig_indentAmount = coerce tabSize
        }
      , _conf_forward = forwardOptionsSyntaxExtsEnabled
      }
  parsePrintModule config text

#test issue 38

{-# LANGUAGE TypeApplications #-}
foo = bar @Baz

#test comment-before-BDCols
{-# LANGUAGE TypeApplications #-}
layoutPatternBindFinal alignmentToken binderDoc mPatDoc clauseDocs = do
  docAlt
    $  -- one-line solution
      [ docCols
          (ColBindingLine alignmentToken)
          [ docSeq (patPartInline ++ [guardPart])
          , docSeq
              [ appSep $ return binderDoc
              , docForceSingleline $ return body
              , wherePart
              ]
          ]
      | not hasComments
      , [(guards, body, _bodyRaw)] <- [clauseDocs]
      , let guardPart = singleLineGuardsDoc guards
      , wherePart <- case mWhereDocs of
        Nothing -> return @[] $ docEmpty
        Just [w] -> return @[] $ docSeq
          [ docSeparator
          , appSep $ docLit $ Text.pack "where"
          , docSetIndentLevel $ docForceSingleline $ return w
          ]
        _ -> []
      ]
    ++ -- one-line solution + where in next line(s)
       [ docLines
         $ [ docCols
               (ColBindingLine alignmentToken)
               [ docSeq (patPartInline ++ [guardPart])
               , docSeq
                   [appSep $ return binderDoc, docForceParSpacing $ return body]
               ]
           ]
         ++ wherePartMultiLine
       | [(guards, body, _bodyRaw)] <- [clauseDocs]
       , let guardPart = singleLineGuardsDoc guards
       , Data.Maybe.isJust mWhereDocs
       ]
    ++ -- two-line solution + where in next line(s)
       [ docLines
         $ [ docForceSingleline $ docSeq
               (patPartInline ++ [guardPart, return binderDoc])
           , docEnsureIndent BrIndentRegular
             $ docForceSingleline
             $ return body
           ]
         ++ wherePartMultiLine
       | [(guards, body, _bodyRaw)] <- [clauseDocs]
       , let guardPart = singleLineGuardsDoc guards
       ]

#test comment-testcase-17
{-# LANGUAGE MultiWayIf #-}
func = do
  let
    foo = if
      | Constuctoooooooooooooooooooooooooooooooooooor `elem` artics -- TODO
      -> max (defLen - 0.2) -- TODO
                            (defLen * 0.8)
      | otherwise
      -> max (defLen - 0.05) (defLen * 0.95) -- TODO
  return True

#test issue 49

foo n = case n of
  1 -> True
  -1 -> False

bar n = case n of
  (-2, -2) -> (-2, -2)

#test issue 48 b

{-# LANGUAGE TypeApplications #-}
foo =
  let
    a = b @1
    cccc = ()
  in foo

#test issue 176

-- brittany { lconfig_unknownFixityHandling: UFHSafeIgnore }
record :: Record
record = Record
  { rProperties =
    [ "foo" .= "bar"
    , "foo" .= "bar"
    , "foo" .= "bar"
    , "foo" .= "bar"
    , "foo" .= "bar"
    , "foo" .= "bar"
    , "foo" .= "bar"
    , "foo" .= "bar"
    ]
  }


###############################################################################
###############################################################################
###############################################################################
#group context-free/pending
###############################################################################
###############################################################################
###############################################################################



## this testcase is not about idempotency, but about _how_ the output differs
## from the input; i cannot really express this yet with the current
## test-suite.
## #test ayaz
##
## myManageHook =
##   composeOne [isFullscreen -?> doFullFloat, isDialog -?> doFloat, transience]
##     <+> composeAll
##           [ className =? "Pidgin" --> doFloat
##           , className =? "XCalc" --> doFloat
##           -- plan9port's acme
##           , className =? "acme" --> doFloat
##           -- Acme with Vi bindings editor
##           , title =? "ED" --> doFloat
##           , title =? "wlc-x11" --> doFloat
##           , className =? "Skype" --> doFloat
##           , className =? "ffplay" --> doFloat
##           , className =? "mpv" --> doFloat
##           , className =? "Plugin-container" --> doFloat -- Firefox flash, etc.
##           -- Firefox works well tiled, but it has dialog windows we want to float.
##           , appName =? "Browser" --> doFloat
##           ]
##  where
##   role = stringProperty "WM_WINDOW_ROLE"
