###############################################################################
###############################################################################
###############################################################################
#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 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 multiple types deriving
data Foo = Bar
  { foo  :: Baz
  , bars :: Bizzz
  }
  deriving (Show, Eq, Monad, Functor, Traversable, Foldable)

#test record multiple deriving strategies
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)
  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
  }


###############################################################################
###############################################################################
###############################################################################
#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)


###############################################################################
###############################################################################
###############################################################################
#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
    }


###############################################################################
###############################################################################
###############################################################################
#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