module Language.Haskell.Format.Types
  ( HaskellSource(..)
  , Reformatted(..)
  , Formatter(..)
  , Suggestion(..)
  ) where

import Control.Monad
import Data.Semigroup (Semigroup, (<>))

type ErrorString = String

data HaskellSource =
  HaskellSource FilePath String
  deriving (HaskellSource -> HaskellSource -> Bool
(HaskellSource -> HaskellSource -> Bool)
-> (HaskellSource -> HaskellSource -> Bool) -> Eq HaskellSource
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: HaskellSource -> HaskellSource -> Bool
$c/= :: HaskellSource -> HaskellSource -> Bool
== :: HaskellSource -> HaskellSource -> Bool
$c== :: HaskellSource -> HaskellSource -> Bool
Eq)

newtype Suggestion =
  Suggestion String

instance Show Suggestion where
  show :: Suggestion -> String
show (Suggestion String
text) = String
text

data Reformatted =
  Reformatted
    { Reformatted -> HaskellSource
reformattedSource :: HaskellSource
    , Reformatted -> [Suggestion]
suggestions       :: [Suggestion]
    }

instance Semigroup Reformatted where
  (Reformatted HaskellSource
_ [Suggestion]
suggestionsA) <> :: Reformatted -> Reformatted -> Reformatted
<> (Reformatted HaskellSource
sourceB [Suggestion]
suggestionsB) =
    HaskellSource -> [Suggestion] -> Reformatted
Reformatted HaskellSource
sourceB ([Suggestion]
suggestionsA [Suggestion] -> [Suggestion] -> [Suggestion]
forall a. Semigroup a => a -> a -> a
<> [Suggestion]
suggestionsB)

instance Monoid Reformatted where
  mempty :: Reformatted
mempty = HaskellSource -> [Suggestion] -> Reformatted
Reformatted HaskellSource
forall a. HasCallStack => a
undefined []
  mappend :: Reformatted -> Reformatted -> Reformatted
mappend = Reformatted -> Reformatted -> Reformatted
forall a. Semigroup a => a -> a -> a
(<>)

newtype Formatter =
  Formatter
    { Formatter -> HaskellSource -> Either String Reformatted
unFormatter :: HaskellSource -> Either ErrorString Reformatted
    }

instance Semigroup Formatter where
  (Formatter HaskellSource -> Either String Reformatted
f) <> :: Formatter -> Formatter -> Formatter
<> (Formatter HaskellSource -> Either String Reformatted
g) = (HaskellSource -> Either String Reformatted) -> Formatter
Formatter ((HaskellSource -> Either String Reformatted)
-> Reformatted -> Either String Reformatted
asReformatter HaskellSource -> Either String Reformatted
g (Reformatted -> Either String Reformatted)
-> (HaskellSource -> Either String Reformatted)
-> HaskellSource
-> Either String Reformatted
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< HaskellSource -> Either String Reformatted
f)

instance Monoid Formatter where
  mempty :: Formatter
mempty = (HaskellSource -> Either String Reformatted) -> Formatter
Formatter (\HaskellSource
source -> Reformatted -> Either String Reformatted
forall a b. b -> Either a b
Right (HaskellSource -> [Suggestion] -> Reformatted
Reformatted HaskellSource
source []))
  mappend :: Formatter -> Formatter -> Formatter
mappend = Formatter -> Formatter -> Formatter
forall a. Semigroup a => a -> a -> a
(<>)

asReformatter ::
     (HaskellSource -> Either ErrorString Reformatted)
  -> Reformatted
  -> Either ErrorString Reformatted
asReformatter :: (HaskellSource -> Either String Reformatted)
-> Reformatted -> Either String Reformatted
asReformatter HaskellSource -> Either String Reformatted
formatter Reformatted
r = (Reformatted
r Reformatted -> Reformatted -> Reformatted
forall a. Semigroup a => a -> a -> a
<>) (Reformatted -> Reformatted)
-> Either String Reformatted -> Either String Reformatted
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> HaskellSource -> Either String Reformatted
formatter (Reformatted -> HaskellSource
reformattedSource Reformatted
r)