ghc-exactprint-1.9.0.0: ExactPrint for GHC

Safe Haskell | None
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 :: Type -> Type) 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 :: forall (m :: Type -> Type). Monad m => String -> TransformT m ()
- logDataWithAnnsTr :: forall (m :: Type -> Type) a. (Monad m, Data a) => String -> a -> TransformT m ()
- uniqueSrcSpanT :: forall (m :: Type -> Type). Monad m => TransformT m SrcSpan
- class Monad m => HasTransform (m :: Type -> Type) where
  - liftT :: Transform a -> m a
- class Data t => HasDecls t where
  - hsDecls :: forall (m :: Type -> Type). Monad m => t -> TransformT m [LHsDecl GhcPs]
  - replaceDecls :: forall (m :: Type -> Type). Monad m => t -> [LHsDecl GhcPs] -> TransformT m t
- hsDeclsPatBind :: LHsBind GhcPs -> [LHsDecl GhcPs]
- hsDeclsPatBindD :: LHsDecl GhcPs -> [LHsDecl GhcPs]
- replaceDeclsPatBind :: forall (m :: Type -> Type). Monad m => LHsBind GhcPs -> [LHsDecl GhcPs] -> TransformT m (LHsBind GhcPs)
- replaceDeclsPatBindD :: forall (m :: Type -> Type). Monad m => LHsDecl GhcPs -> [LHsDecl GhcPs] -> TransformT m (LHsDecl GhcPs)
- modifyDeclsT :: (HasDecls t, HasTransform m) => ([LHsDecl GhcPs] -> m [LHsDecl GhcPs]) -> t -> m t
- modifyValD :: HasTransform m => SrcSpan -> Decl -> (PMatch -> [Decl] -> m ([Decl], Maybe t)) -> m (Decl, Maybe t)
- hsDeclsValBinds :: HsValBindsLR GhcPs GhcPs -> [LHsDecl GhcPs]
- replaceDeclsValbinds :: forall (m :: Type -> Type). Monad m => WithWhere -> HsLocalBinds GhcPs -> [LHsDecl GhcPs] -> TransformT m (HsLocalBinds GhcPs)
- data WithWhere
  - = WithWhere
  - | WithoutWhere
- noAnnSrcSpanDP :: NoAnn ann => DeltaPos -> EpAnn ann
- noAnnSrcSpanDP0 :: NoAnn ann => EpAnn ann
- noAnnSrcSpanDP1 :: NoAnn ann => EpAnn ann
- noAnnSrcSpanDPn :: NoAnn ann => Int -> EpAnn ann
- d0 :: EpaLocation
- d1 :: EpaLocation
- dn :: Int -> EpaLocation
- 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 :: forall (m :: Type -> Type). Monad m => LHsDecl GhcPs -> LHsDecl GhcPs -> TransformT m (LHsDecl GhcPs, LHsDecl GhcPs)
- balanceCommentsList :: forall (m :: Type -> Type). Monad m => [LHsDecl GhcPs] -> TransformT m [LHsDecl GhcPs]
- balanceCommentsListA :: forall (m :: Type -> Type) a. Monad m => [LocatedA a] -> TransformT m [LocatedA a]
- anchorEof :: ParsedSource -> ParsedSource
- captureOrderBinds :: [LHsDecl GhcPs] -> AnnSortKey BindTag
- captureLineSpacing :: [LocatedA e] -> [LocatedA e]
- captureMatchLineSpacing :: LHsDecl GhcPs -> LHsDecl GhcPs
- captureTypeSigSpacing :: LHsDecl GhcPs -> LHsDecl GhcPs
- isUniqueSrcSpan :: SrcSpan -> Bool
- setEntryDP :: LocatedAn t a -> DeltaPos -> LocatedAn t a
- setEntryDPDecl :: LHsDecl GhcPs -> DeltaPos -> LHsDecl GhcPs
- getEntryDP :: LocatedAn t a -> DeltaPos
- transferEntryDP :: forall (m :: Type -> Type) t1 t2 a b. (Monad m, Typeable t1, Typeable t2) => LocatedAn t1 a -> LocatedAn t2 b -> TransformT m (LocatedAn t2 b)
- transferEntryDP' :: forall (m :: Type -> Type). 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 #

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 :: Type -> Type) a #

Monad transformer version of `Transform` monad

Constructors

TransformT |

Fields

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

#### Instances

Instances details

MonadTrans TransformT # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods lift :: Monad m => m a -> TransformT m a #
Monad m => MonadReader () (TransformT m) # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods ask :: TransformT m () # local :: (() -> ()) -> TransformT m a -> TransformT m a # reader :: (() -> a) -> TransformT m a #
Monad m => MonadState Int (TransformT m) # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods get :: TransformT m Int # put :: Int -> TransformT m () # state :: (Int -> (a, Int)) -> TransformT m a #
Monad m => HasTransform (TransformT m) # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods liftT :: Transform a -> TransformT m a #
Monad m => Applicative (TransformT m) # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods pure :: a -> TransformT m a # (<*>) :: TransformT m (a -> b) -> TransformT m a -> TransformT m b # liftA2 :: (a -> b -> c) -> TransformT m a -> TransformT m b -> TransformT m c # (*>) :: TransformT m a -> TransformT m b -> TransformT m b # (<*) :: TransformT m a -> TransformT m b -> TransformT m a #
Functor m => Functor (TransformT m) # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods fmap :: (a -> b) -> TransformT m a -> TransformT m b # (<$) :: a -> TransformT m b -> TransformT m a #
Monad m => Monad (TransformT m) # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods (>>=) :: TransformT m a -> (a -> TransformT m b) -> TransformT m b # (>>) :: TransformT m a -> TransformT m b -> TransformT m b # return :: a -> TransformT m a #
MonadFail m => MonadFail (TransformT m) # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods fail :: String -> TransformT m a #
Monad m => MonadWriter [String] (TransformT m) # |
Instance details Defined in Language.Haskell.GHC.ExactPrint.Transform Methods writer :: (a, [String]) -> TransformT m a # tell :: [String] -> TransformT m () # listen :: TransformT m a -> TransformT m (a, [String]) # pass :: TransformT m (a, [String] -> [String]) -> TransformT m a #

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

Change inner monad of `TransformT`.

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

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]) #

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

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]) #

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

# Transform monad operations

logTr :: forall (m :: Type -> Type). Monad m => String -> TransformT m () #

Log a string to the output of the Monad

logDataWithAnnsTr :: forall (m :: Type -> Type) a. (Monad m, Data a) => String -> a -> TransformT m () #

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

uniqueSrcSpanT :: forall (m :: Type -> Type). Monad m => TransformT m SrcSpan #

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 :: Type -> Type) where #

Used to integrate a `Transform` into other Monad stacks

Methods

liftT :: Transform a -> m a #

#### Instances

Instances details

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

class Data t => HasDecls t where #

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

Methods

hsDecls :: forall (m :: Type -> Type). Monad m => t -> TransformT m [LHsDecl GhcPs] #

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 :: forall (m :: Type -> Type). Monad m => t -> [LHsDecl GhcPs] -> TransformT m t #

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

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] #

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

HasDecls (LocatedA (Stmt GhcPs (LocatedA (HsExpr GhcPs)))) # |
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] # replaceDecls :: forall (m :: Type -> Type). Monad m => LocatedA (Stmt GhcPs (LocatedA (HsExpr GhcPs))) -> [LHsDecl GhcPs] -> TransformT m (LocatedA (Stmt GhcPs (LocatedA (HsExpr GhcPs)))) #

hsDeclsPatBind :: LHsBind GhcPs -> [LHsDecl GhcPs] #

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 :: LHsDecl GhcPs -> [LHsDecl GhcPs] #

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 :: forall (m :: Type -> Type). Monad m => LHsBind GhcPs -> [LHsDecl GhcPs] -> TransformT m (LHsBind GhcPs) #

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 :: forall (m :: Type -> Type). Monad m => LHsDecl GhcPs -> [LHsDecl GhcPs] -> TransformT m (LHsDecl GhcPs) #

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 #

Apply a transformation to the decls contained in `t`

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

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 :: HsValBindsLR GhcPs GhcPs -> [LHsDecl GhcPs] #

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

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 #

Constructors

WithWhere |
WithoutWhere |

#### Instances

Instances details

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

## New gen functions

noAnnSrcSpanDP :: NoAnn ann => DeltaPos -> EpAnn ann #

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

noAnnSrcSpanDP0 :: NoAnn ann => EpAnn ann #

noAnnSrcSpanDP1 :: NoAnn ann => EpAnn ann #

noAnnSrcSpanDPn :: NoAnn ann => Int -> EpAnn ann #

d0 :: EpaLocation #

d1 :: EpaLocation #

dn :: Int -> EpaLocation #

addComma :: SrcSpanAnnA -> SrcSpanAnnA #

## Managing lists, Transform monad

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

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 #

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

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

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) #

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) #

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

### Low level operations used in `HasDecls`

balanceComments :: forall (m :: Type -> Type). Monad m => LHsDecl GhcPs -> LHsDecl GhcPs -> TransformT m (LHsDecl GhcPs, LHsDecl GhcPs) #

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 :: forall (m :: Type -> Type). Monad m => [LHsDecl GhcPs] -> TransformT m [LHsDecl GhcPs] #

If we compile in haddock mode we get DocDecls, which we strip out while exact printing. Make sure we do not balance any comments on to them be stripping them out here already.

balanceCommentsListA :: forall (m :: Type -> Type) a. Monad m => [LocatedA a] -> TransformT m [LocatedA a] #

anchorEof :: ParsedSource -> ParsedSource #

## Managing lists, pure functions

captureOrderBinds :: [LHsDecl GhcPs] -> AnnSortKey BindTag #

captureLineSpacing :: [LocatedA e] -> [LocatedA e] #

captureMatchLineSpacing :: LHsDecl GhcPs -> LHsDecl GhcPs #

captureTypeSigSpacing :: LHsDecl GhcPs -> LHsDecl GhcPs #

# Operations

isUniqueSrcSpan :: SrcSpan -> Bool #

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

# Pure functions

setEntryDP :: LocatedAn t a -> DeltaPos -> LocatedAn t a #

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

setEntryDPDecl :: LHsDecl GhcPs -> DeltaPos -> LHsDecl GhcPs #

getEntryDP :: LocatedAn t a -> DeltaPos #

transferEntryDP :: forall (m :: Type -> Type) t1 t2 a b. (Monad m, Typeable t1, Typeable t2) => LocatedAn t1 a -> LocatedAn t2 b -> TransformT m (LocatedAn t2 b) #

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

transferEntryDP' :: forall (m :: Type -> Type). Monad m => LHsDecl GhcPs -> LHsDecl GhcPs -> TransformT m (LHsDecl GhcPs) #

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

wrapSig :: LSig GhcPs -> LHsDecl GhcPs #

Convert a `LSig` into a `LHsDecl`

wrapDecl :: LHsBind GhcPs -> LHsDecl GhcPs #

Convert a `LHsBind` into a `LHsDecl`

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

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] #

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`