###############################################################################
###############################################################################
###############################################################################
#group extensions
###############################################################################
###############################################################################
###############################################################################

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

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


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



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

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


###############################################################################
## RecursiveDo
#test recursivedo 1
{-# LANGUAGE RecursiveDo #-}
foo = do
  rec a <- f b
      b <- g a
  return (a, b)

#test recursivedo 2
{-# LANGUAGE RecursiveDo #-}
foo = do
  rec -- comment
      a <- f b
      b <- g a
  return (a, b)

###############################################################################
## ExplicitNamespaces + PatternSynonyms
#test explicitnamespaces_patternsynonyms export
{-# LANGUAGE ExplicitNamespaces #-}
{-# LANGUAGE PatternSynonyms #-}
module Test (type (++), (++), pattern Foo) where

#test explicitnamespaces_patternsynonyms import
{-# LANGUAGE ExplicitNamespaces #-}
{-# LANGUAGE PatternSynonyms #-}
import           Test                                     ( type (++)
                                                          , (++)
                                                          , pattern Foo
                                                          , pattern (:.)
                                                          )

###############################################################################
## PatternSynonyms
#test bidirectional pattern
{-# LANGUAGE PatternSynonyms #-}
pattern J x = Just x

#test unidirection pattern
{-# LANGUAGE PatternSynonyms #-}
pattern F x <- (x, _)

#test explicitly bidirectional pattern
{-# LANGUAGE PatternSynonyms #-}
pattern HeadC x <- x : xs where
  HeadC x = [x]

#test Multiple arguments
{-# LANGUAGE PatternSynonyms #-}
pattern Head2 x y <- x : y : xs where
  Head2 x y = [x, y]

#test Infix argument
{-# LANGUAGE PatternSynonyms #-}
pattern x :> y = [x, y]

#test Record argument
{-# LANGUAGE PatternSynonyms #-}
pattern MyData { a, b, c } = [a, b, c]

#test long pattern match
{-# LANGUAGE PatternSynonyms #-}
pattern myLongLeftVariableName `MyLongInfixPatternMatcher` myLongRightVariableName =
  [myLongLeftVariableName, myLongRightVariableName]

#test long explicitly bidirectional match
{-# LANGUAGE PatternSynonyms #-}
pattern myLeftVariableName `MyInfixPatternMatcher` myRightVariableName <-
  [myLongLeftVariableName, myLongRightVariableName] where
  MyInfixPatternMatcher x y = [x, x, y]

#test Pattern synonym types 
{-# LANGUAGE PatternSynonyms #-}
pattern J :: a -> Maybe a
pattern J x = Just x

#test pattern synonym bidirectional multiple cases
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ViewPatterns #-}
pattern Signed x <- (asSigned -> x) where
  Signed (Neg x) = -x
  Signed Zero    = 0
  Signed (Pos x) = x

#test pattern synonym bidirectional multiple cases long
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ViewPatterns #-}
pattern Signed xxxxxxxxxxxxxxxxxxxxxxxx <-
  (asSigned -> xxxxxxxxxxxxxxxxxxxxxxxx) where
  Signed (Neg x) = -x
  Signed Zero    = 0
  Signed (Pos x) = x

#test pattern synonym bidirectional multiple cases with comments
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ViewPatterns #-}
pattern Signed x <- (asSigned -> x) where
  Signed (Neg x) = -x -- negative comment
  Signed Zero    = 0  -- zero comment
  Signed (Pos x) = x  -- positive comment

#test Pattern synonym types multiple names
#min-ghc 8.2
{-# LANGUAGE PatternSynonyms #-}
pattern J, K :: a -> Maybe a

#test Pattern synonym type sig wrapped
{-# LANGUAGE PatternSynonyms #-}
pattern LongMatcher
  :: longlongtypevar
  -> longlongtypevar
  -> longlongtypevar
  -> Maybe [longlongtypevar]
pattern LongMatcher x y z = Just [x, y, z]


###############################################################################
## UnboxedTuples + MagicHash
#test unboxed-tuple and vanilla names
{-# LANGUAGE UnboxedTuples #-}
spanKey :: (# Int, Int #) -> (# Int, Int #)
spanKey = case foo of
  (# bar, baz #) -> (# baz, bar #)

#test unboxed-tuple and hashed name
{-# LANGUAGE MagicHash, UnboxedTuples #-}
spanKey :: (# Int#, Int# #) -> (# Int#, Int# #)
spanKey = case foo of
  (# bar#, baz# #) -> (# baz# +# bar#, bar# #)


###############################################################################
## QuasiQuotes
#test quasi-quotes simple 1
{-# LANGUAGE QuasiQuotes #-}
func = [blub|
  asd
  qwe
  |]

#test quasi-quotes simple 2
{-# LANGUAGE QuasiQuotes #-}
func = [blub|
        asd
  qwe|]

#test quasi-quotes ignoring layouting
{-# LANGUAGE QuasiQuotes #-}
func = do
  let body = [json|
  hello
  |]
  pure True

#test quasi-quotes ignoring layouting, strict mode
-- brittany { lconfig_allowHangingQuasiQuotes: False }
{-# LANGUAGE QuasiQuotes #-}
func = do
  let
    body =
      [json|
  hello
  |]
  pure True

###############################################################################
## OverloadedLabels
#test bare label
{-# LANGUAGE OverloadedLabels #-}
foo = #bar

#test applied and composed label
{-# LANGUAGE OverloadedLabels #-}
foo = #bar . #baz $ fmap #foo xs

###############################################################################
## ImplicitParams

#test IP usage
{-# LANGUAGE ImplicitParams #-}
foo = ?bar

#test IP binding
{-# LANGUAGE ImplicitParams #-}
foo = let ?bar = Foo in value

#test IP type signature
{-# LANGUAGE ImplicitParams #-}
foo :: (?bar::Bool) => ()
foo = ()