ghc-exactprint-1.7.1.0: ExactPrint for GHC

Safe Haskell | Safe-Inferred
Language | Haskell2010

Language.Haskell.GHC.ExactPrint.Transform

Contents

- The Transform Monad
- Transform monad operations
  - Managing declarations, in Transform monad
    - Utility, does not manage layout
  - New gen functions
  - Managing lists, Transform monad
    - Low level operations used in `HasDecls`
  - Managing lists, pure functions
- Operations
- Pure functions

Description

This module is currently under heavy development, and no promises are made about API stability. Use with care.

We welcome any feedback / contributions on this, as it is the main point of the library.

Synopsis

- type Transform = TransformT Identity
- newtype TransformT m a = TransformT {
  - unTransformT :: RWST () [String] Int m a
  }
- hoistTransform :: (forall x. m x -> n x) -> TransformT m a -> TransformT n a
- runTransform :: Transform a -> (a, Int, [String])
- runTransformT :: TransformT m a -> m (a, Int, [String])
- runTransformFrom :: Int -> Transform a -> (a, Int, [String])
- runTransformFromT :: Int -> TransformT m a -> m (a, Int, [String])
- logTr :: Monad m => String -> TransformT m ()
- logDataWithAnnsTr :: Monad m => Data a => String -> a -> TransformT m ()
- uniqueSrcSpanT :: Monad m => TransformT m SrcSpan
- class Monad m => HasTransform m where
  - liftT :: Transform a -> m a
- class Data t => HasDecls t where
  - hsDecls :: Monad m => t -> TransformT m [LHsDecl GhcPs]
  - replaceDecls :: Monad m => t -> [LHsDecl GhcPs] -> TransformT m t
- hsDeclsPatBind :: Monad m => LHsBind GhcPs -> TransformT m [LHsDecl GhcPs]
- hsDeclsPatBindD :: Monad m => LHsDecl GhcPs -> TransformT m [LHsDecl GhcPs]
- replaceDeclsPatBind :: Monad m => LHsBind GhcPs -> [LHsDecl GhcPs] -> TransformT m (LHsBind GhcPs)
- replaceDeclsPatBindD :: Monad m => LHsDecl GhcPs -> [LHsDecl GhcPs] -> TransformT m (LHsDecl GhcPs)
- modifyDeclsT :: (HasDecls t, HasTransform m) => ([LHsDecl GhcPs] -> m [LHsDecl GhcPs]) -> t -> m t
- modifyValD :: forall m t. HasTransform m => SrcSpan -> Decl -> (PMatch -> [Decl] -> m ([Decl], Maybe t)) -> m (Decl, Maybe t)
- hsDeclsValBinds :: Monad m => HsLocalBinds GhcPs -> TransformT m [LHsDecl GhcPs]
- replaceDeclsValbinds :: Monad m => WithWhere -> HsLocalBinds GhcPs -> [LHsDecl GhcPs] -> TransformT m (HsLocalBinds GhcPs)
- data WithWhere
  - = WithWhere
  - | WithoutWhere
- noAnnSrcSpanDP :: Monoid ann => SrcSpan -> DeltaPos -> SrcSpanAnn' (EpAnn ann)
- noAnnSrcSpanDP0 :: Monoid ann => SrcSpan -> SrcSpanAnn' (EpAnn ann)
- noAnnSrcSpanDP1 :: Monoid ann => SrcSpan -> SrcSpanAnn' (EpAnn ann)
- noAnnSrcSpanDPn :: Monoid ann => SrcSpan -> Int -> SrcSpanAnn' (EpAnn ann)
- d0 :: EpaLocation
- d1 :: EpaLocation
- dn :: Int -> EpaLocation
- m0 :: AnchorOperation
- m1 :: AnchorOperation
- mn :: Int -> AnchorOperation
- addComma :: SrcSpanAnnA -> SrcSpanAnnA
- insertAt :: HasDecls ast => (LHsDecl GhcPs -> [LHsDecl GhcPs] -> [LHsDecl GhcPs]) -> ast -> LHsDecl GhcPs -> Transform ast
- insertAtStart :: HasDecls ast => ast -> LHsDecl GhcPs -> Transform ast
- insertAtEnd :: HasDecls ast => ast -> LHsDecl GhcPs -> Transform ast
- insertAfter :: HasDecls (LocatedA ast) => LocatedA old -> LocatedA ast -> LHsDecl GhcPs -> Transform (LocatedA ast)
- insertBefore :: HasDecls (LocatedA ast) => LocatedA old -> LocatedA ast -> LHsDecl GhcPs -> Transform (LocatedA ast)
- balanceComments :: Monad m => LHsDecl GhcPs -> LHsDecl GhcPs -> TransformT m (LHsDecl GhcPs, LHsDecl GhcPs)
- balanceCommentsList :: Monad m => [LHsDecl GhcPs] -> TransformT m [LHsDecl GhcPs]
- balanceCommentsList' :: Monad m => [LocatedA a] -> TransformT m [LocatedA a]
- anchorEof :: ParsedSource -> ParsedSource
- captureOrder :: [LocatedA b] -> AnnSortKey
- captureLineSpacing :: Default t => [LocatedAn t e] -> [LocatedAn t e]
- captureMatchLineSpacing :: LHsDecl GhcPs -> LHsDecl GhcPs
- captureTypeSigSpacing :: LHsDecl GhcPs -> LHsDecl GhcPs
- isUniqueSrcSpan :: SrcSpan -> Bool
- setEntryDP :: Default t => LocatedAn t a -> DeltaPos -> LocatedAn t a
- getEntryDP :: LocatedAn t a -> DeltaPos
- transferEntryDP :: (Monad m, Monoid t2, Typeable t1, Typeable t2) => LocatedAn t1 a -> LocatedAn t2 b -> TransformT m (LocatedAn t2 b)
- transferEntryDP' :: Monad m => LHsDecl GhcPs -> LHsDecl GhcPs -> TransformT m (LHsDecl GhcPs)
- wrapSig :: LSig GhcPs -> LHsDecl GhcPs
- wrapDecl :: LHsBind GhcPs -> LHsDecl GhcPs
- decl2Sig :: LHsDecl GhcPs -> [LSig GhcPs]
- decl2Bind :: LHsDecl GhcPs -> [LHsBind GhcPs]

# The Transform Monad

type Transform = TransformT Identity Source #

Monad type for updating the AST and managing the annotations at the same time. The W state is used to generate logging information if required.

newtype TransformT m a Source #

Monad transformer version of `Transform` monad

Constructors

TransformT |

Fields

- unTransformT :: RWST () [String] Int m a

#### Instances

Instances details

MonadTrans TransformT Source # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods lift :: Monad m => m a -> TransformT m a Source #
Monad m => MonadReader () (TransformT m) Source # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods ask :: TransformT m () Source # local :: (() -> ()) -> TransformT m a -> TransformT m a Source # reader :: (() -> a) -> TransformT m a Source #
Monad m => MonadState Int (TransformT m) Source # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods get :: TransformT m Int Source # put :: Int -> TransformT m () Source # state :: (Int -> (a, Int)) -> TransformT m a Source #
MonadFail m => MonadFail (TransformT m) Source # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods fail :: String -> TransformT m a Source #
Monad m => Applicative (TransformT m) Source # |

Instance details

Defined in Language.Haskell.GHC.ExactPrint.Transform

Methods

pure :: a -> TransformT m a Source #

(<*>) :: TransformT m (a -> b) -> TransformT m a -> TransformT m b Source #

liftA2 :: (a -> b -> c) -> TransformT m a -> TransformT m b -> TransformT m c Source #

(*>) :: TransformT m a -> TransformT m b -> TransformT m b Source #

(<*) :: TransformT m a -> TransformT m b -> TransformT m a Source #

Functor m => Functor (TransformT m) Source # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods fmap :: (a -> b) -> TransformT m a -> TransformT m b Source # (<$) :: a -> TransformT m b -> TransformT m a Source #
Monad m => Monad (TransformT m) Source # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods (>>=) :: TransformT m a -> (a -> TransformT m b) -> TransformT m b Source # (>>) :: TransformT m a -> TransformT m b -> TransformT m b Source # return :: a -> TransformT m a Source #
Monad m => HasTransform (TransformT m) Source # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods liftT :: Transform a -> TransformT m a Source #
Monad m => MonadWriter [String] (TransformT m) Source # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods writer :: (a, [String]) -> TransformT m a Source # tell :: [String] -> TransformT m () Source # listen :: TransformT m a -> TransformT m (a, [String]) Source # pass :: TransformT m (a, [String] -> [String]) -> TransformT m a Source #

hoistTransform :: (forall x. m x -> n x) -> TransformT m a -> TransformT n a Source #

Change inner monad of `TransformT`.

runTransform :: Transform a -> (a, Int, [String]) Source #

Run a transformation in the `Transform` monad, returning the updated annotations and any logging generated via `logTr`

runTransformT :: TransformT m a -> m (a, Int, [String]) Source #

runTransformFrom :: Int -> Transform a -> (a, Int, [String]) Source #

Run a transformation in the `Transform` monad, returning the updated annotations and any logging generated via `logTr`, allocating any new SrcSpans from the provided initial value.

runTransformFromT :: Int -> TransformT m a -> m (a, Int, [String]) Source #

Run a monad transformer stack for the `TransformT` monad transformer

# Transform monad operations

logTr :: Monad m => String -> TransformT m () Source #

Log a string to the output of the Monad

logDataWithAnnsTr :: Monad m => Data a => String -> a -> TransformT m () Source #

Log a representation of the given AST with annotations to the output of the Monad

uniqueSrcSpanT :: Monad m => TransformT m SrcSpan Source #

If we need to add new elements to the AST, they need their own `SrcSpan` for this.

## Managing declarations, in Transform monad

class Monad m => HasTransform m where Source #

Used to integrate a `Transform` into other Monad stacks

Methods

liftT :: Transform a -> m a Source #

#### Instances

Instances details

Monad m => HasTransform (TransformT m) Source # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods liftT :: Transform a -> TransformT m a Source #

class Data t => HasDecls t where Source #

Provide a means to get and process the immediate child declartions of a given AST element.

Methods

hsDecls :: Monad m => t -> TransformT m [LHsDecl GhcPs] Source #

Return the `HsDecl`s that are directly enclosed in the given syntax phrase. They are always returned in the wrapped `HsDecl` form, even if orginating in local decls. This is safe, as annotations never attach to the wrapper, only to the wrapped item.

replaceDecls :: Monad m => t -> [LHsDecl GhcPs] -> TransformT m t Source #

Replace the directly enclosed decl list by the given decl list. Runs in the `Transform` monad to be able to update list order annotations, and rebalance comments and other layout changes as needed.

For example, a call on replaceDecls for a wrapped `FunBind` having no where clause will convert

    -- |This is a function
    foo = x -- comment1

in to

    -- |This is a function
    foo = x -- comment1
      where
        nn = 2

#### Instances

Instances details

HasDecls ParsedSource Source # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods hsDecls :: forall (m :: Type -> Type). Monad m => ParsedSource -> TransformT m [LHsDecl GhcPs] Source # replaceDecls :: forall (m :: Type -> Type). Monad m => ParsedSource -> [LHsDecl GhcPs] -> TransformT m ParsedSource Source #
HasDecls (LocatedA (HsExpr GhcPs)) Source # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods hsDecls :: forall (m :: Type -> Type). Monad m => LocatedA (HsExpr GhcPs) -> TransformT m [LHsDecl GhcPs] Source # replaceDecls :: forall (m :: Type -> Type). Monad m => LocatedA (HsExpr GhcPs) -> [LHsDecl GhcPs] -> TransformT m (LocatedA (HsExpr GhcPs)) Source #
HasDecls (LocatedA (Match GhcPs (LocatedA (HsExpr GhcPs)))) Source # |

Instance details

Defined in Language.Haskell.GHC.ExactPrint.Transform

Methods

hsDecls :: forall (m :: Type -> Type). Monad m => LocatedA (Match GhcPs (LocatedA (HsExpr GhcPs))) -> TransformT m [LHsDecl GhcPs] Source #

replaceDecls :: forall (m :: Type -> Type). Monad m => LocatedA (Match GhcPs (LocatedA (HsExpr GhcPs))) -> [LHsDecl GhcPs] -> TransformT m (LocatedA (Match GhcPs (LocatedA (HsExpr GhcPs)))) Source #

HasDecls (LocatedA (Stmt GhcPs (LocatedA (HsExpr GhcPs)))) Source # |

Instance details

Defined in Language.Haskell.GHC.ExactPrint.Transform

Methods

hsDecls :: forall (m :: Type -> Type). Monad m => LocatedA (Stmt GhcPs (LocatedA (HsExpr GhcPs))) -> TransformT m [LHsDecl GhcPs] Source #

replaceDecls :: forall (m :: Type -> Type). Monad m => LocatedA (Stmt GhcPs (LocatedA (HsExpr GhcPs))) -> [LHsDecl GhcPs] -> TransformT m (LocatedA (Stmt GhcPs (LocatedA (HsExpr GhcPs)))) Source #

hsDeclsPatBind :: Monad m => LHsBind GhcPs -> TransformT m [LHsDecl GhcPs] Source #

Extract the immediate declarations for a `PatBind`. This cannot be a member of `HasDecls` because a `FunBind` is not idempotent for `hsDecls` / `replaceDecls`. `hsDeclsPatBind` / `replaceDeclsPatBind` is idempotent.

hsDeclsPatBindD :: Monad m => LHsDecl GhcPs -> TransformT m [LHsDecl GhcPs] Source #

Extract the immediate declarations for a `PatBind` wrapped in a `ValD`. This cannot be a member of `HasDecls` because a `FunBind` is not idempotent for `hsDecls` / `replaceDecls`. `hsDeclsPatBindD` / `replaceDeclsPatBindD` is idempotent.

replaceDeclsPatBind :: Monad m => LHsBind GhcPs -> [LHsDecl GhcPs] -> TransformT m (LHsBind GhcPs) Source #

Replace the immediate declarations for a `PatBind`. This cannot be a member of `HasDecls` because a `FunBind` is not idempotent for `hsDecls` / `replaceDecls`. `hsDeclsPatBind` / `replaceDeclsPatBind` is idempotent.

replaceDeclsPatBindD :: Monad m => LHsDecl GhcPs -> [LHsDecl GhcPs] -> TransformT m (LHsDecl GhcPs) Source #

Replace the immediate declarations for a `PatBind` wrapped in a `ValD`. This cannot be a member of `HasDecls` because a `FunBind` is not idempotent for `hsDecls` / `replaceDecls`. `hsDeclsPatBindD` / `replaceDeclsPatBindD` is idempotent.

modifyDeclsT :: (HasDecls t, HasTransform m) => ([LHsDecl GhcPs] -> m [LHsDecl GhcPs]) -> t -> m t Source #

Apply a transformation to the decls contained in `t`

modifyValD :: forall m t. HasTransform m => SrcSpan -> Decl -> (PMatch -> [Decl] -> m ([Decl], Maybe t)) -> m (Decl, Maybe t) Source #

Modify a `LHsBind` wrapped in a `ValD`. For a `PatBind` the declarations are extracted and returned after modification. For a `FunBind` the supplied `SrcSpan` is used to identify the specific `Match` to be transformed, for when there are multiple of them.

### Utility, does not manage layout

hsDeclsValBinds :: Monad m => HsLocalBinds GhcPs -> TransformT m [LHsDecl GhcPs] Source #

replaceDeclsValbinds :: Monad m => WithWhere -> HsLocalBinds GhcPs -> [LHsDecl GhcPs] -> TransformT m (HsLocalBinds GhcPs) Source #

Utility function for returning decls to `HsLocalBinds`. Use with care, as this does not manage the declaration order, the ordering should be done by the calling function from the `HsLocalBinds` context in the AST.

data WithWhere Source #

Constructors

WithWhere |
WithoutWhere |

#### Instances

Instances details

Show WithWhere Source # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods showsPrec :: Int -> WithWhere -> ShowS Source # show :: WithWhere -> String Source # showList :: [WithWhere] -> ShowS Source #
Eq WithWhere Source # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods (==) :: WithWhere -> WithWhere -> Bool Source # (/=) :: WithWhere -> WithWhere -> Bool Source #

## New gen functions

noAnnSrcSpanDP :: Monoid ann => SrcSpan -> DeltaPos -> SrcSpanAnn' (EpAnn ann) Source #

Create a `SrcSpanAnn` with a `MovedAnchor` operation using the given `DeltaPos`.

noAnnSrcSpanDP0 :: Monoid ann => SrcSpan -> SrcSpanAnn' (EpAnn ann) Source #

noAnnSrcSpanDP1 :: Monoid ann => SrcSpan -> SrcSpanAnn' (EpAnn ann) Source #

noAnnSrcSpanDPn :: Monoid ann => SrcSpan -> Int -> SrcSpanAnn' (EpAnn ann) Source #

d0 :: EpaLocation Source #

d1 :: EpaLocation Source #

dn :: Int -> EpaLocation Source #

m0 :: AnchorOperation Source #

m1 :: AnchorOperation Source #

mn :: Int -> AnchorOperation Source #

addComma :: SrcSpanAnnA -> SrcSpanAnnA Source #

## Managing lists, Transform monad

insertAt :: HasDecls ast => (LHsDecl GhcPs -> [LHsDecl GhcPs] -> [LHsDecl GhcPs]) -> ast -> LHsDecl GhcPs -> Transform ast Source #

Insert a declaration into an AST element having sub-declarations (`HasDecls`) according to the given location function.

insertAtStart :: HasDecls ast => ast -> LHsDecl GhcPs -> Transform ast Source #

Insert a declaration at the beginning or end of the subdecls of the given AST item

insertAtEnd :: HasDecls ast => ast -> LHsDecl GhcPs -> Transform ast Source #

Insert a declaration at the beginning or end of the subdecls of the given AST item

insertAfter :: HasDecls (LocatedA ast) => LocatedA old -> LocatedA ast -> LHsDecl GhcPs -> Transform (LocatedA ast) Source #

Insert a declaration at a specific location in the subdecls of the given AST item

insertBefore :: HasDecls (LocatedA ast) => LocatedA old -> LocatedA ast -> LHsDecl GhcPs -> Transform (LocatedA ast) Source #

Insert a declaration at a specific location in the subdecls of the given AST item

### Low level operations used in `HasDecls`

balanceComments :: Monad m => LHsDecl GhcPs -> LHsDecl GhcPs -> TransformT m (LHsDecl GhcPs, LHsDecl GhcPs) Source #

The GHC parser puts all comments appearing between the end of one AST item and the beginning of the next as `annPriorComments` for the second one. This function takes two adjacent AST items and moves any `annPriorComments` from the second one to the `annFollowingComments` of the first if they belong to it instead. This is typically required before deleting or duplicating either of the AST elements.

balanceCommentsList :: Monad m => [LHsDecl GhcPs] -> TransformT m [LHsDecl GhcPs] Source #

balanceCommentsList' :: Monad m => [LocatedA a] -> TransformT m [LocatedA a] Source #

anchorEof :: ParsedSource -> ParsedSource Source #

## Managing lists, pure functions

captureOrder :: [LocatedA b] -> AnnSortKey Source #

If a list has been re-ordered or had items added, capture the new order in the appropriate `AnnSortKey` attached to the `Annotation` for the list.

captureLineSpacing :: Default t => [LocatedAn t e] -> [LocatedAn t e] Source #

captureMatchLineSpacing :: LHsDecl GhcPs -> LHsDecl GhcPs Source #

captureTypeSigSpacing :: LHsDecl GhcPs -> LHsDecl GhcPs Source #

# Operations

isUniqueSrcSpan :: SrcSpan -> Bool Source #

Test whether a given `SrcSpan` was generated by `uniqueSrcSpanT`

# Pure functions

setEntryDP :: Default t => LocatedAn t a -> DeltaPos -> LocatedAn t a Source #

Set the true entry `DeltaPos` from the annotation for a given AST element. This is the `DeltaPos` ignoring any comments.

getEntryDP :: LocatedAn t a -> DeltaPos Source #

transferEntryDP :: (Monad m, Monoid t2, Typeable t1, Typeable t2) => LocatedAn t1 a -> LocatedAn t2 b -> TransformT m (LocatedAn t2 b) Source #

Take the annEntryDelta associated with the first item and associate it with the second. Also transfer any comments occuring before it.

transferEntryDP' :: Monad m => LHsDecl GhcPs -> LHsDecl GhcPs -> TransformT m (LHsDecl GhcPs) Source #

Take the annEntryDelta associated with the first item and associate it with the second. Also transfer any comments occuring before it. TODO: call transferEntryDP, and use pushDeclDP

wrapSig :: LSig GhcPs -> LHsDecl GhcPs Source #

Convert a `LSig` into a `LHsDecl`

wrapDecl :: LHsBind GhcPs -> LHsDecl GhcPs Source #

Convert a `LHsBind` into a `LHsDecl`

decl2Sig :: LHsDecl GhcPs -> [LSig GhcPs] Source #

Pure function to convert a `LSig` to a `LHsBind`. This does nothing to any annotations that may be attached to either of the elements. It is used as a utility function in `replaceDecls`

decl2Bind :: LHsDecl GhcPs -> [LHsBind GhcPs] Source #

Pure function to convert a `LHsDecl` to a `LHsBind`. This does nothing to any annotations that may be attached to either of the elements. It is used as a utility function in `replaceDecls`