<commit_before>{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PatternSynonyms #-}
module Language.Haskell.GHC.ExactPrint.Annotate
       (
         annotate
       , AnnotationF(..)
       , Annotated
       , Annotate(..)) where

import Data.Data (Data)
import Data.List (sort, sortBy)
import Data.Maybe (fromMaybe)

import Language.Haskell.GHC.ExactPrint.Types
import Language.Haskell.GHC.ExactPrint.Utils (rdrName2String, isListComp, debug, span2ss, ss2span, spanLength)

import qualified Bag            as GHC
import qualified BasicTypes     as GHC
import qualified BooleanFormula as GHC
import qualified Class          as GHC
import qualified CoAxiom        as GHC
import qualified FastString     as GHC
import qualified ForeignCall    as GHC
import qualified GHC            as GHC
import qualified Outputable     as GHC
import qualified SrcLoc         as GHC

import Control.Monad.Trans.Free
import Control.Monad.Free.TH (makeFreeCon)
import Control.Monad.Reader

import Debug.Trace


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


data AnnotationF next where
  MarkEOF        ::                                                         next -> AnnotationF next
  MarkPrim       :: GHC.AnnKeywordId -> Maybe String                     -> next -> AnnotationF next
  MarkExternal   :: GHC.SrcSpan -> GHC.AnnKeywordId -> String            -> next -> AnnotationF next
  MarkOutside    :: GHC.AnnKeywordId -> KeywordId                        -> next -> AnnotationF next
  MarkInside     :: GHC.AnnKeywordId                                     -> next -> AnnotationF next
  MarkMany       :: GHC.AnnKeywordId                                     -> next -> AnnotationF next
  MarkOffsetPrim :: GHC.AnnKeywordId -> Int -> Maybe String              -> next -> AnnotationF next
  MarkAfter      :: GHC.AnnKeywordId                                     -> next -> AnnotationF next
  WithAST        :: Data a => GHC.Located a -> LayoutFlag -> Annotated b -> next -> AnnotationF next
  CountAnns      ::  GHC.AnnKeywordId                           -> (Int -> next) -> AnnotationF next
  -- | Abstraction breakers
  SetLayoutFlag  ::  Annotated ()                    -> next -> AnnotationF next

  -- | Required to work around deficiencies in the GHC AST
  StoreOriginalSrcSpan :: GHC.SrcSpan                   -> (GHC.SrcSpan -> next) -> AnnotationF next
  GetSrcSpanForKw :: GHC.AnnKeywordId                   -> (GHC.SrcSpan -> next) -> AnnotationF next
  StoreString :: String -> GHC.SrcSpan                  -> next -> AnnotationF next

deriving instance Functor (AnnotationF)

type Annotated = Free AnnotationF

type IAnnotated = ReaderT [Context] Annotated

data Context = None | Case | Where | Lam | MultiIf
             | HsSpliceE  -- Used for marking when an explicit template haskell
                          -- splice has been used. $(foo) for example.
             deriving (Eq, Ord, Show)

addContext :: Context -> IAnnotated () -> IAnnotated ()
addContext c = local (c:)

check :: Context -> IAnnotated () -> IAnnotated ()
check c = checkMany [c]

checkMany :: [Context] -> IAnnotated () -> IAnnotated ()
checkMany cs action = do
  ctx <- ask
  when (any (`elem` ctx) cs) action



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

makeFreeCon  'MarkEOF
makeFreeCon  'MarkPrim
makeFreeCon  'MarkOutside
makeFreeCon  'MarkInside
makeFreeCon  'MarkExternal
makeFreeCon  'MarkMany
makeFreeCon  'MarkOffsetPrim
makeFreeCon  'MarkAfter
makeFreeCon  'CountAnns
makeFreeCon  'StoreOriginalSrcSpan
makeFreeCon  'GetSrcSpanForKw
makeFreeCon  'StoreString

setLayoutFlag :: IAnnotated () -> IAnnotated ()
setLayoutFlag prog = do
  finalProg <- runReaderT prog <$> ask
  liftF (SetLayoutFlag finalProg ())

workOutString :: GHC.AnnKeywordId -> (GHC.SrcSpan -> String) -> IAnnotated ()
workOutString kw f = do
  ss <- getSrcSpanForKw kw
  storeString (f ss) ss

annotate :: (Annotate ast) => GHC.Located ast -> Annotated ()
annotate ast = runReaderT (markLocated ast) []

-- ---------------------------------------------------------------------
-- |Main driver point for annotations.
withAST :: Data a => GHC.Located a -> LayoutFlag -> IAnnotated () -> IAnnotated ()
withAST lss layout action = do
  finalProg <- runReaderT prog <$> ask
  liftF (WithAST lss layout finalProg ())
  where
    prog = do
      action
      -- Automatically add any trailing comma or semi
      markAfter GHC.AnnComma
      markOutside GHC.AnnSemi AnnSemiSep

-- ---------------------------------------------------------------------
-- Additional smart constructors

mark :: GHC.AnnKeywordId -> IAnnotated ()
mark kwid = markPrim kwid Nothing

markWithString :: GHC.AnnKeywordId -> String -> IAnnotated ()
markWithString kwid s = markPrim kwid (Just s)

markOffsetWithString :: GHC.AnnKeywordId -> Int -> String -> IAnnotated ()
markOffsetWithString kwid n s = markOffsetPrim kwid n (Just s)

markOffset :: GHC.AnnKeywordId -> Int -> IAnnotated ()
markOffset kwid n = markOffsetPrim kwid n Nothing

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

-- | Constructs a syntax tree which contains information about which
-- annotations are required by each element.
markLocated :: (Annotate ast) => GHC.Located ast -> IAnnotated ()
markLocated a = withLocated a NoLayoutRules markAST

-- | Constructs a syntax tree which contains information about which
-- annotations are required by each element, flagging the item to be IAnnotated
-- as requiring layout according to the haskell layout rules.
markWithLayout :: Annotate ast => GHC.Located ast -> IAnnotated ()
markWithLayout a = withLocated a LayoutRules markAST

withLocated :: Data a
            => GHC.Located a
            -> LayoutFlag
            -> (GHC.SrcSpan -> a -> IAnnotated ())
            -> IAnnotated ()
withLocated a@(GHC.L l ast) layoutFlag action =
  withAST a layoutFlag (action l ast)

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

markListWithLayout :: Annotate [GHC.Located ast] => [GHC.Located ast] -> IAnnotated ()
markListWithLayout ls = do
  let ss = getListSrcSpan ls
  ss' <- storeOriginalSrcSpan ss
  markWithLayout (GHC.L ss' ls)

markLocalBindsWithLayout :: (GHC.DataId name,GHC.OutputableBndr name,Annotate name)
  => GHC.HsLocalBinds name -> IAnnotated ()
markLocalBindsWithLayout binds = do
  let ss = getLocalBindsSrcSpan binds
  ss' <- storeOriginalSrcSpan ss
  markWithLayout (GHC.L ss' binds)

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

-- |This function is used to get around shortcomings in the GHC AST for 7.10.1
markLocatedFromKw :: (Annotate ast) => GHC.AnnKeywordId -> ast -> IAnnotated ()
markLocatedFromKw kw a = do
  -- ++AZ++ TODO: We always use GHC.AnnEofPos here, maybe use it as a constant
  -- here rather than a param. And rename the fn appropriately.
  ss <- getSrcSpanForKw kw
  ss' <- storeOriginalSrcSpan ss
  markLocated (GHC.L ss' a)

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

markMaybe :: (Annotate ast) => Maybe (GHC.Located ast) -> IAnnotated ()
markMaybe Nothing    = return ()
markMaybe (Just ast) = markLocated ast

markList :: (Annotate ast) => [GHC.Located ast] -> IAnnotated ()
markList xs = mapM_ markLocated xs

-- ---------------------------------------------------------------------
-- Managing lists which have been separated, e.g. Sigs and Binds

prepareListAnnotation :: Annotate a => [GHC.Located a] -> [(GHC.SrcSpan,IAnnotated ())]
prepareListAnnotation ls = map (\b@(GHC.L l _) -> (l,markLocated b)) ls

applyListAnnotations :: [(GHC.SrcSpan, IAnnotated ())] -> IAnnotated ()
applyListAnnotations ls
  = mapM_ snd $ sortBy (\(a,_) (b,_) -> compare a b) ls

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

class Data ast => Annotate ast where
  markAST :: GHC.SrcSpan -> ast -> IAnnotated ()

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

instance Annotate (GHC.HsModule GHC.RdrName) where
  markAST _ (GHC.HsModule mmn mexp imps decs mdepr _haddock) = do


    case mmn of
      Nothing -> return ()
      Just (GHC.L ln mn) -> do
        mark GHC.AnnModule
        markExternal ln GHC.AnnVal (GHC.moduleNameString mn)

    case mdepr of
      Nothing -> return ()
      Just depr -> markLocated depr

    case mexp of
      Nothing   -> return ()
      Just expr -> markLocated expr

    mark GHC.AnnWhere
    mark GHC.AnnOpenC -- Possible '{'
    markMany GHC.AnnSemi -- possible leading semis
    mapM_ markLocated imps

    markList decs

    mark GHC.AnnCloseC -- Possible '}'

    markEOF

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

instance Annotate GHC.WarningTxt where
  markAST _ (GHC.WarningTxt (GHC.L ls txt) lss) = do
    markExternal ls GHC.AnnOpen txt
    mark GHC.AnnOpenS
    mapM_ markLocated lss
    mark GHC.AnnCloseS
    markWithString GHC.AnnClose "#-}"

  markAST _ (GHC.DeprecatedTxt (GHC.L ls txt) lss) = do
    markExternal ls GHC.AnnOpen txt
    mark GHC.AnnOpenS
    mapM_ markLocated lss
    mark GHC.AnnCloseS
    markWithString GHC.AnnClose "#-}"

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

instance (GHC.DataId name,Annotate name)
  => Annotate [GHC.LIE name] where
   markAST _ ls = do
     mark GHC.AnnHiding -- in an import decl
     mark GHC.AnnOpenP -- '('
     mapM_ markLocated ls
     mark GHC.AnnCloseP -- ')'

instance (GHC.DataId name,Annotate name)
  => Annotate (GHC.IE name) where
  markAST _ ie = do

    case ie of
        (GHC.IEVar ln) -> do
          mark GHC.AnnPattern
          mark GHC.AnnType
          markLocated ln

        (GHC.IEThingAbs ln) -> do
          mark GHC.AnnType
          markLocated ln

        (GHC.IEThingWith ln ns) -> do
          markLocated ln
          mark GHC.AnnOpenP
          mapM_ markLocated ns
          mark GHC.AnnCloseP

        (GHC.IEThingAll ln) -> do
          markLocated ln
          mark GHC.AnnOpenP
          mark GHC.AnnDotdot
          mark GHC.AnnCloseP

        (GHC.IEModuleContents (GHC.L lm mn)) -> do
          mark GHC.AnnModule
          markExternal lm GHC.AnnVal (GHC.moduleNameString mn)

        -- Only used in Haddock mode so we can ignore them.
        (GHC.IEGroup _ _) -> return ()

        (GHC.IEDoc _)     -> return ()

        (GHC.IEDocNamed _)    -> return ()

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

instance Annotate GHC.RdrName where
  markAST l n = do
    case rdrName2String n of
      "[]" -> do
        mark GHC.AnnOpenS  -- '['
        mark GHC.AnnCloseS -- ']'
      "()" -> do
        mark GHC.AnnOpenP  -- '('
        mark GHC.AnnCloseP -- ')'
      "(##)" -> do
        markWithString GHC.AnnOpen  "(#" -- '(#'
        markWithString GHC.AnnClose  "#)"-- '#)'
      "[::]" -> do
        markWithString GHC.AnnOpen  "[:" -- '[:'
        markWithString GHC.AnnClose ":]" -- ':]'
      str ->  do
        mark GHC.AnnType
        mark GHC.AnnOpenP -- '('
        markOffset GHC.AnnBackquote 0
        markMany GHC.AnnCommaTuple -- For '(,,,)'
        cnt <- countAnns GHC.AnnVal
        cntT <- countAnns GHC.AnnCommaTuple
        cntR <- countAnns GHC.AnnRarrow
        case cnt of
          0 -> if cntT >0 || cntR >0
                 then return ()
                 else markExternal l GHC.AnnVal str
          1 -> markWithString GHC.AnnVal str
          _ -> return ()
        mark GHC.AnnTildehsh
        mark GHC.AnnTilde
        mark GHC.AnnRarrow
        markOffset GHC.AnnBackquote 1
        mark GHC.AnnCloseP -- ')'

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

-- TODO: What is this used for? Not in ExactPrint
instance Annotate GHC.Name where
  markAST l n = do
    markExternal l GHC.AnnVal (showGhc n)

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

instance (GHC.DataId name,Annotate name)<commit_msg>Improve handling of RdrNames<commit_after>{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PatternSynonyms #-}
module Language.Haskell.GHC.ExactPrint.Annotate
       (
         annotate
       , AnnotationF(..)
       , Annotated
       , Annotate(..)) where

import Data.Data (Data)
import Data.List (sort, sortBy)
import Data.Maybe (fromMaybe)

import Language.Haskell.GHC.ExactPrint.Types
import Language.Haskell.GHC.ExactPrint.Utils (rdrName2String, isListComp, debug, span2ss, ss2span, spanLength)

import qualified Bag            as GHC
import qualified BasicTypes     as GHC
import qualified BooleanFormula as GHC
import qualified Class          as GHC
import qualified CoAxiom        as GHC
import qualified FastString     as GHC
import qualified ForeignCall    as GHC
import qualified GHC            as GHC
import qualified Outputable     as GHC
import qualified SrcLoc         as GHC

import Control.Monad.Trans.Free
import Control.Monad.Free.TH (makeFreeCon)
import Control.Monad.Reader

import Debug.Trace


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


data AnnotationF next where
  MarkEOF        ::                                                         next -> AnnotationF next
  MarkPrim       :: GHC.AnnKeywordId -> Maybe String                     -> next -> AnnotationF next
  MarkExternal   :: GHC.SrcSpan -> GHC.AnnKeywordId -> String            -> next -> AnnotationF next
  MarkOutside    :: GHC.AnnKeywordId -> KeywordId                        -> next -> AnnotationF next
  MarkInside     :: GHC.AnnKeywordId                                     -> next -> AnnotationF next
  MarkMany       :: GHC.AnnKeywordId                                     -> next -> AnnotationF next
  MarkOffsetPrim :: GHC.AnnKeywordId -> Int -> Maybe String              -> next -> AnnotationF next
  MarkAfter      :: GHC.AnnKeywordId                                     -> next -> AnnotationF next
  WithAST        :: Data a => GHC.Located a -> LayoutFlag -> Annotated b -> next -> AnnotationF next
  CountAnns      ::  GHC.AnnKeywordId                           -> (Int -> next) -> AnnotationF next
  -- | Abstraction breakers
  SetLayoutFlag  ::  Annotated ()                    -> next -> AnnotationF next

  -- | Required to work around deficiencies in the GHC AST
  StoreOriginalSrcSpan :: GHC.SrcSpan                   -> (GHC.SrcSpan -> next) -> AnnotationF next
  GetSrcSpanForKw :: GHC.AnnKeywordId                   -> (GHC.SrcSpan -> next) -> AnnotationF next
  StoreString :: String -> GHC.SrcSpan                  -> next -> AnnotationF next

deriving instance Functor (AnnotationF)

type Annotated = Free AnnotationF

type IAnnotated = ReaderT [Context] Annotated

data Context = None | Case | Where | Lam | MultiIf
             | HsSpliceE  -- Used for marking when an explicit template haskell
                          -- splice has been used. $(foo) for example.
             deriving (Eq, Ord, Show)

addContext :: Context -> IAnnotated () -> IAnnotated ()
addContext c = local (c:)

check :: Context -> IAnnotated () -> IAnnotated ()
check c = checkMany [c]

checkMany :: [Context] -> IAnnotated () -> IAnnotated ()
checkMany cs action = do
  ctx <- ask
  when (any (`elem` ctx) cs) action



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

makeFreeCon  'MarkEOF
makeFreeCon  'MarkPrim
makeFreeCon  'MarkOutside
makeFreeCon  'MarkInside
makeFreeCon  'MarkExternal
makeFreeCon  'MarkMany
makeFreeCon  'MarkOffsetPrim
makeFreeCon  'MarkAfter
makeFreeCon  'CountAnns
makeFreeCon  'StoreOriginalSrcSpan
makeFreeCon  'GetSrcSpanForKw
makeFreeCon  'StoreString

setLayoutFlag :: IAnnotated () -> IAnnotated ()
setLayoutFlag prog = do
  finalProg <- runReaderT prog <$> ask
  liftF (SetLayoutFlag finalProg ())

workOutString :: GHC.AnnKeywordId -> (GHC.SrcSpan -> String) -> IAnnotated ()
workOutString kw f = do
  ss <- getSrcSpanForKw kw
  storeString (f ss) ss

annotate :: (Annotate ast) => GHC.Located ast -> Annotated ()
annotate ast = runReaderT (markLocated ast) []

-- ---------------------------------------------------------------------
-- |Main driver point for annotations.
withAST :: Data a => GHC.Located a -> LayoutFlag -> IAnnotated () -> IAnnotated ()
withAST lss layout action = do
  finalProg <- runReaderT prog <$> ask
  liftF (WithAST lss layout finalProg ())
  where
    prog = do
      action
      -- Automatically add any trailing comma or semi
      markAfter GHC.AnnComma
      markOutside GHC.AnnSemi AnnSemiSep

-- ---------------------------------------------------------------------
-- Additional smart constructors

mark :: GHC.AnnKeywordId -> IAnnotated ()
mark kwid = markPrim kwid Nothing

markWithString :: GHC.AnnKeywordId -> String -> IAnnotated ()
markWithString kwid s = markPrim kwid (Just s)

markOffsetWithString :: GHC.AnnKeywordId -> Int -> String -> IAnnotated ()
markOffsetWithString kwid n s = markOffsetPrim kwid n (Just s)

markOffset :: GHC.AnnKeywordId -> Int -> IAnnotated ()
markOffset kwid n = markOffsetPrim kwid n Nothing

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

-- | Constructs a syntax tree which contains information about which
-- annotations are required by each element.
markLocated :: (Annotate ast) => GHC.Located ast -> IAnnotated ()
markLocated a = withLocated a NoLayoutRules markAST

-- | Constructs a syntax tree which contains information about which
-- annotations are required by each element, flagging the item to be IAnnotated
-- as requiring layout according to the haskell layout rules.
markWithLayout :: Annotate ast => GHC.Located ast -> IAnnotated ()
markWithLayout a = withLocated a LayoutRules markAST

withLocated :: Data a
            => GHC.Located a
            -> LayoutFlag
            -> (GHC.SrcSpan -> a -> IAnnotated ())
            -> IAnnotated ()
withLocated a@(GHC.L l ast) layoutFlag action =
  withAST a layoutFlag (action l ast)

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

markListWithLayout :: Annotate [GHC.Located ast] => [GHC.Located ast] -> IAnnotated ()
markListWithLayout ls = do
  let ss = getListSrcSpan ls
  ss' <- storeOriginalSrcSpan ss
  markWithLayout (GHC.L ss' ls)

markLocalBindsWithLayout :: (GHC.DataId name,GHC.OutputableBndr name,Annotate name)
  => GHC.HsLocalBinds name -> IAnnotated ()
markLocalBindsWithLayout binds = do
  let ss = getLocalBindsSrcSpan binds
  ss' <- storeOriginalSrcSpan ss
  markWithLayout (GHC.L ss' binds)

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

-- |This function is used to get around shortcomings in the GHC AST for 7.10.1
markLocatedFromKw :: (Annotate ast) => GHC.AnnKeywordId -> ast -> IAnnotated ()
markLocatedFromKw kw a = do
  -- ++AZ++ TODO: We always use GHC.AnnEofPos here, maybe use it as a constant
  -- here rather than a param. And rename the fn appropriately.
  ss <- getSrcSpanForKw kw
  ss' <- storeOriginalSrcSpan ss
  markLocated (GHC.L ss' a)

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

markMaybe :: (Annotate ast) => Maybe (GHC.Located ast) -> IAnnotated ()
markMaybe Nothing    = return ()
markMaybe (Just ast) = markLocated ast

markList :: (Annotate ast) => [GHC.Located ast] -> IAnnotated ()
markList xs = mapM_ markLocated xs

-- ---------------------------------------------------------------------
-- Managing lists which have been separated, e.g. Sigs and Binds

prepareListAnnotation :: Annotate a => [GHC.Located a] -> [(GHC.SrcSpan,IAnnotated ())]
prepareListAnnotation ls = map (\b@(GHC.L l _) -> (l,markLocated b)) ls

applyListAnnotations :: [(GHC.SrcSpan, IAnnotated ())] -> IAnnotated ()
applyListAnnotations ls
  = mapM_ snd $ sortBy (\(a,_) (b,_) -> compare a b) ls

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

class Data ast => Annotate ast where
  markAST :: GHC.SrcSpan -> ast -> IAnnotated ()

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

instance Annotate (GHC.HsModule GHC.RdrName) where
  markAST _ (GHC.HsModule mmn mexp imps decs mdepr _haddock) = do


    case mmn of
      Nothing -> return ()
      Just (GHC.L ln mn) -> do
        mark GHC.AnnModule
        markExternal ln GHC.AnnVal (GHC.moduleNameString mn)

    case mdepr of
      Nothing -> return ()
      Just depr -> markLocated depr

    case mexp of
      Nothing   -> return ()
      Just expr -> markLocated expr

    mark GHC.AnnWhere
    mark GHC.AnnOpenC -- Possible '{'
    markMany GHC.AnnSemi -- possible leading semis
    mapM_ markLocated imps

    markList decs

    mark GHC.AnnCloseC -- Possible '}'

    markEOF

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

instance Annotate GHC.WarningTxt where
  markAST _ (GHC.WarningTxt (GHC.L ls txt) lss) = do
    markExternal ls GHC.AnnOpen txt
    mark GHC.AnnOpenS
    mapM_ markLocated lss
    mark GHC.AnnCloseS
    markWithString GHC.AnnClose "#-}"

  markAST _ (GHC.DeprecatedTxt (GHC.L ls txt) lss) = do
    markExternal ls GHC.AnnOpen txt
    mark GHC.AnnOpenS
    mapM_ markLocated lss
    mark GHC.AnnCloseS
    markWithString GHC.AnnClose "#-}"

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

instance (GHC.DataId name,Annotate name)
  => Annotate [GHC.LIE name] where
   markAST _ ls = do
     mark GHC.AnnHiding -- in an import decl
     mark GHC.AnnOpenP -- '('
     mapM_ markLocated ls
     mark GHC.AnnCloseP -- ')'

instance (GHC.DataId name,Annotate name)
  => Annotate (GHC.IE name) where
  markAST _ ie = do

    case ie of
        (GHC.IEVar ln) -> do
          mark GHC.AnnPattern
          mark GHC.AnnType
          markLocated ln

        (GHC.IEThingAbs ln) -> do
          mark GHC.AnnType
          markLocated ln

        (GHC.IEThingWith ln ns) -> do
          markLocated ln
          mark GHC.AnnOpenP
          mapM_ markLocated ns
          mark GHC.AnnCloseP

        (GHC.IEThingAll ln) -> do
          markLocated ln
          mark GHC.AnnOpenP
          mark GHC.AnnDotdot
          mark GHC.AnnCloseP

        (GHC.IEModuleContents (GHC.L lm mn)) -> do
          mark GHC.AnnModule
          markExternal lm GHC.AnnVal (GHC.moduleNameString mn)

        -- Only used in Haddock mode so we can ignore them.
        (GHC.IEGroup _ _) -> return ()

        (GHC.IEDoc _)     -> return ()

        (GHC.IEDocNamed _)    -> return ()

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

instance Annotate GHC.RdrName where
  markAST l n = do
    case rdrName2String n of
      -- Special handling for atypical RdrNames.
      "[]" -> do
        mark GHC.AnnOpenS  -- '['
        mark GHC.AnnCloseS -- ']'
      "()" -> do
        mark GHC.AnnOpenP  -- '('
        mark GHC.AnnCloseP -- ')'
      "(##)" -> do
        markWithString GHC.AnnOpen  "(#" -- '(#'
        markWithString GHC.AnnClose  "#)"-- '#)'
      "[::]" -> do
        markWithString GHC.AnnOpen  "[:" -- '[:'
        markWithString GHC.AnnClose ":]" -- ':]'
      "(->)" -> do
        mark GHC.AnnOpenP -- '('
        mark GHC.AnnRarrow
        mark GHC.AnnCloseP -- ')'
      str ->  do
        mark GHC.AnnType
        mark GHC.AnnOpenP -- '('
        markOffset GHC.AnnBackquote 0
        markMany GHC.AnnCommaTuple -- For '(,,,)'
        cnt <- countAnns GHC.AnnVal
        cntT <- countAnns GHC.AnnCommaTuple
        case cnt of
          0 -> if cntT > 0
                 then traceM "Printing RdrName, no AnnVal, multiple AnnCommTuple"
                 else markExternal l GHC.AnnVal str
          1 -> markWithString GHC.AnnVal str
          _ -> traceM "Printing RdrName, more than 1 AnnVal"
        -- TODO: Add tests for these and move to seperate branches
        mark GHC.AnnTildehsh
        mark GHC.AnnTilde
        markOffset GHC.AnnBackquote 1
        mark GHC.AnnCloseP -- ')'

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

-- TODO: What is this used for? Not in ExactPrint
instance Annotate GHC.Name where
  markAST l n = do
    markExternal l GHC.AnnVal (showGhc n)

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

instance (GHC.DataId name,Annotate name)
{'fraction_non_alphanumeric': 0.18074935926121802, 'fraction_numerical': 0.0011390911679752655, 'mean_word_length': 1.7905551140878646, 'pattern_counts': {'":': 2, '<': 28, '<?xml version=': 0, '>': 246, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2486987', 'n_tokens_mistral': 7421, 'n_tokens_neox': 7199, 'n_words': 2085}