{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleInstances    #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiWayIf           #-}
{-# LANGUAGE NamedFieldPuns       #-}
{-# LANGUAGE RankNTypes           #-}
{-# LANGUAGE StandaloneDeriving   #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE ViewPatterns         #-}

module Language.Haskell.GHC.ExactPrint.Types
  where

import GHC hiding (EpaComment)
import GHC.Utils.Outputable hiding ( (<>) )

-- ---------------------------------------------------------------------

type Pos = (Int,Int)

-- ---------------------------------------------------------------------

data Rigidity = NormalLayout | RigidLayout deriving (Rigidity -> Rigidity -> Bool
(Rigidity -> Rigidity -> Bool)
-> (Rigidity -> Rigidity -> Bool) -> Eq Rigidity
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Rigidity -> Rigidity -> Bool
$c/= :: Rigidity -> Rigidity -> Bool
== :: Rigidity -> Rigidity -> Bool
$c== :: Rigidity -> Rigidity -> Bool
Eq, Eq Rigidity
Eq Rigidity
-> (Rigidity -> Rigidity -> Ordering)
-> (Rigidity -> Rigidity -> Bool)
-> (Rigidity -> Rigidity -> Bool)
-> (Rigidity -> Rigidity -> Bool)
-> (Rigidity -> Rigidity -> Bool)
-> (Rigidity -> Rigidity -> Rigidity)
-> (Rigidity -> Rigidity -> Rigidity)
-> Ord Rigidity
Rigidity -> Rigidity -> Bool
Rigidity -> Rigidity -> Ordering
Rigidity -> Rigidity -> Rigidity
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Rigidity -> Rigidity -> Rigidity
$cmin :: Rigidity -> Rigidity -> Rigidity
max :: Rigidity -> Rigidity -> Rigidity
$cmax :: Rigidity -> Rigidity -> Rigidity
>= :: Rigidity -> Rigidity -> Bool
$c>= :: Rigidity -> Rigidity -> Bool
> :: Rigidity -> Rigidity -> Bool
$c> :: Rigidity -> Rigidity -> Bool
<= :: Rigidity -> Rigidity -> Bool
$c<= :: Rigidity -> Rigidity -> Bool
< :: Rigidity -> Rigidity -> Bool
$c< :: Rigidity -> Rigidity -> Bool
compare :: Rigidity -> Rigidity -> Ordering
$ccompare :: Rigidity -> Rigidity -> Ordering
Ord, Int -> Rigidity -> ShowS
[Rigidity] -> ShowS
Rigidity -> String
(Int -> Rigidity -> ShowS)
-> (Rigidity -> String) -> ([Rigidity] -> ShowS) -> Show Rigidity
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Rigidity] -> ShowS
$cshowList :: [Rigidity] -> ShowS
show :: Rigidity -> String
$cshow :: Rigidity -> String
showsPrec :: Int -> Rigidity -> ShowS
$cshowsPrec :: Int -> Rigidity -> ShowS
Show)

-- ---------------------------------------------------------------------

-- | A Haskell comment. The @AnnKeywordId@ is present if it has been converted
-- from an @AnnKeywordId@ because the annotation must be interleaved into the
-- stream and does not have a well-defined position
data Comment = Comment
    {
      Comment -> String
commentContents   :: !String -- ^ The contents of the comment including separators

    -- AZ:TODO: commentIdentifier is a misnomer, should be commentSrcSpan, it is
    -- the thing we use to decide where in the output stream the comment should
    -- go.
    , Comment -> Anchor
commentAnchor :: !Anchor
    , Comment -> Maybe AnnKeywordId
commentOrigin :: !(Maybe AnnKeywordId) -- ^ We sometimes turn syntax into comments in order to process them properly.
    }
  deriving Comment -> Comment -> Bool
(Comment -> Comment -> Bool)
-> (Comment -> Comment -> Bool) -> Eq Comment
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Comment -> Comment -> Bool
$c/= :: Comment -> Comment -> Bool
== :: Comment -> Comment -> Bool
$c== :: Comment -> Comment -> Bool
Eq

instance Show Comment where
  show :: Comment -> String
show (Comment String
cs Anchor
ss Maybe AnnKeywordId
o) = String
"(Comment " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ShowS
forall a. Show a => a -> String
show String
cs String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Anchor -> String
forall a. Outputable a => a -> String
showPprUnsafe Anchor
ss String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Maybe AnnKeywordId -> String
forall a. Show a => a -> String
show Maybe AnnKeywordId
o String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"

instance Ord Comment where
  -- When we have CPP injected comments with a fake filename, or LINE
  -- pragma, the file name changes, so we need to compare the
  -- locations only, with out the filename.
  compare :: Comment -> Comment -> Ordering
compare (Comment String
_ Anchor
ss1 Maybe AnnKeywordId
_) (Comment String
_ Anchor
ss2 Maybe AnnKeywordId
_) = (Int, Int) -> (Int, Int) -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (RealSrcSpan -> (Int, Int)
ss2pos (RealSrcSpan -> (Int, Int)) -> RealSrcSpan -> (Int, Int)
forall a b. (a -> b) -> a -> b
$ Anchor -> RealSrcSpan
anchor Anchor
ss1) (RealSrcSpan -> (Int, Int)
ss2pos (RealSrcSpan -> (Int, Int)) -> RealSrcSpan -> (Int, Int)
forall a b. (a -> b) -> a -> b
$ Anchor -> RealSrcSpan
anchor Anchor
ss2)
    where
      ss2pos :: RealSrcSpan -> (Int, Int)
ss2pos RealSrcSpan
ss = (RealSrcSpan -> Int
srcSpanStartLine RealSrcSpan
ss,RealSrcSpan -> Int
srcSpanStartCol RealSrcSpan
ss)

instance Outputable Comment where
  ppr :: Comment -> SDoc
ppr Comment
x = String -> SDoc
text (Comment -> String
forall a. Show a => a -> String
show Comment
x)

-- | The different syntactic elements which are not represented in the
-- AST.
data KeywordId = G AnnKeywordId  -- ^ A normal keyword
               | AnnSemiSep          -- ^ A separating comma
               | AnnTypeApp          -- ^ Visible type application annotation
               | AnnComment Comment
               | AnnString String    -- ^ Used to pass information from
                                     -- Delta to Print when we have to work
                                     -- out details from the original
                                     -- SrcSpan.
               deriving (KeywordId -> KeywordId -> Bool
(KeywordId -> KeywordId -> Bool)
-> (KeywordId -> KeywordId -> Bool) -> Eq KeywordId
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: KeywordId -> KeywordId -> Bool
$c/= :: KeywordId -> KeywordId -> Bool
== :: KeywordId -> KeywordId -> Bool
$c== :: KeywordId -> KeywordId -> Bool
Eq)

instance Show KeywordId where
  show :: KeywordId -> String
show (G AnnKeywordId
gc)          = String
"(G " String -> ShowS
forall a. [a] -> [a] -> [a]
++ AnnKeywordId -> String
forall a. Show a => a -> String
show AnnKeywordId
gc String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
  show KeywordId
AnnSemiSep      = String
"AnnSemiSep"
  show KeywordId
AnnTypeApp      = String
"AnnTypeApp"
  show (AnnComment Comment
dc) = String
"(AnnComment " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Comment -> String
forall a. Show a => a -> String
show Comment
dc String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
  show (AnnString String
s)   = String
"(AnnString " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
s String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"

-- | Marks the start column of a layout block.
newtype LayoutStartCol = LayoutStartCol { LayoutStartCol -> Int
getLayoutStartCol :: Int }
  deriving (LayoutStartCol -> LayoutStartCol -> Bool
(LayoutStartCol -> LayoutStartCol -> Bool)
-> (LayoutStartCol -> LayoutStartCol -> Bool) -> Eq LayoutStartCol
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LayoutStartCol -> LayoutStartCol -> Bool
$c/= :: LayoutStartCol -> LayoutStartCol -> Bool
== :: LayoutStartCol -> LayoutStartCol -> Bool
$c== :: LayoutStartCol -> LayoutStartCol -> Bool
Eq, Integer -> LayoutStartCol
LayoutStartCol -> LayoutStartCol
LayoutStartCol -> LayoutStartCol -> LayoutStartCol
(LayoutStartCol -> LayoutStartCol -> LayoutStartCol)
-> (LayoutStartCol -> LayoutStartCol -> LayoutStartCol)
-> (LayoutStartCol -> LayoutStartCol -> LayoutStartCol)
-> (LayoutStartCol -> LayoutStartCol)
-> (LayoutStartCol -> LayoutStartCol)
-> (LayoutStartCol -> LayoutStartCol)
-> (Integer -> LayoutStartCol)
-> Num LayoutStartCol
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> LayoutStartCol
$cfromInteger :: Integer -> LayoutStartCol
signum :: LayoutStartCol -> LayoutStartCol
$csignum :: LayoutStartCol -> LayoutStartCol
abs :: LayoutStartCol -> LayoutStartCol
$cabs :: LayoutStartCol -> LayoutStartCol
negate :: LayoutStartCol -> LayoutStartCol
$cnegate :: LayoutStartCol -> LayoutStartCol
* :: LayoutStartCol -> LayoutStartCol -> LayoutStartCol
$c* :: LayoutStartCol -> LayoutStartCol -> LayoutStartCol
- :: LayoutStartCol -> LayoutStartCol -> LayoutStartCol
$c- :: LayoutStartCol -> LayoutStartCol -> LayoutStartCol
+ :: LayoutStartCol -> LayoutStartCol -> LayoutStartCol
$c+ :: LayoutStartCol -> LayoutStartCol -> LayoutStartCol
Num)

instance Show LayoutStartCol where
  show :: LayoutStartCol -> String
show (LayoutStartCol Int
sc) = String
"(LayoutStartCol " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
sc String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"

-- ---------------------------------------------------------------------

-- Duplicated here so it can be used in show instances
showGhc :: (Outputable a) => a -> String
showGhc :: forall a. Outputable a => a -> String
showGhc = a -> String
forall a. Outputable a => a -> String
showPprUnsafe