-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | the Haskell Refactorer. -- -- A Haskell 2010 refactoring tool. HaRe supports the full Haskell 2010 -- standard, through making use of the GHC API. -- -- It is tested against GHC 7.4.x and 7.6.x (via travis-ci.org) -- -- It currently only has emacs integration built in, community input -- welcome for others. -- -- Warning: This is alpha code. Always commit code to your version -- control system before refactoring. The developers make no warranties, -- use at your own risk. -- -- Despite the disclaimer, HaRe attempts to operate in a safe way, by -- first writing new files with proposed changes, and only swapping these -- with the originals when the change is accepted. In the process the -- original file is renamed to have the current date/time as a suffix. -- Thus it should be possible to (manually) undo changes. -- -- The renaming refactoring seems reasonably reliable, as does lifting -- and demoting -- -- At the moment parsing of any file with FFI exports will fail. @package HaRe @version 0.7.2.3 module Paths_HaRe version :: Version getBinDir :: IO FilePath getLibDir :: IO FilePath getDataDir :: IO FilePath getLibexecDir :: IO FilePath getDataFileName :: FilePath -> IO FilePath getSysconfDir :: IO FilePath module Language.Haskell.Refact.Utils.GhcModuleGraph getModulesAsGraph :: Bool -> [ModSummary] -> Maybe ModuleName -> Graph SummaryNode summaryNodeSummary :: SummaryNode -> ModSummary -- | This is a legacy module from the pre-GHC HaRe, and will disappear -- eventually. module Language.Haskell.Refact.Utils.TypeSyn type HsExpP = HsExpr RdrName type HsPatP = Pat RdrName type HsDeclP = LHsDecl RdrName type HsDeclsP = HsGroup Name type InScopes = [Name] type SimpPos = (Int, Int) type PosToken = (Located Token, String) type Export = LIE RdrName -- | HsName is a name as it is found in the source This seems to be quite a -- close correlation type HsName = RdrName -- | The PN is the name as it occurs to the parser, and corresponds with -- the GHC.RdrName type PN = GHC.RdrName newtype PName PN :: HsName -> PName type HsModuleP = Located (HsModule RdrName) ghead :: String -> [a] -> a glast :: String -> [a] -> a gtail :: String -> [a] -> [a] gfromJust :: [Char] -> Maybe a -> a instance Eq PName instance Outputable (ConDeclField Name) instance Outputable (HsTupArg Name) instance Outputable (GRHS Name) instance Outputable (GRHSs Name) instance Outputable (Match Name) instance Outputable (MatchGroup Name) instance Outputable NameSpace instance Show NameSpace -- | This module contains types shared between TokenUtils and Monad, and -- exists to break import cycles module Language.Haskell.Refact.Utils.TokenUtilsTypes data TokenCache TK :: !(Map TreeId (Tree Entry)) -> !TreeId -> TokenCache tkCache :: TokenCache -> !(Map TreeId (Tree Entry)) tkLastTreeId :: TokenCache -> !TreeId data TreeId TId :: !Int -> TreeId -- | Identifies the tree carrying the main tokens, not any work in progress -- or deleted ones mainTid :: TreeId -- | An entry in the data structure for a particular srcspan. data Entry -- | The tokens for the SrcSpan if subtree is empty Entry :: !ForestSpan -> !Layout -> ![PosToken] -> Entry -- | The gap between this span end and the start of the next in the fringe -- of the tree. deriving (Show) Deleted :: !ForestSpan -> RowOffset -> SimpPos -> Entry data Layout -- | Initial offset from token before the stacked list of items, the (r,c) -- of the first non-comment token, the (r,c) of the end of the last -- non-comment token in the stacked list to be able to calculate the -- (RowOffset,ColOffset) between the last token and the start of the next -- item. Above :: EndOffset -> (Row, Col) -> (Row, Col) -> EndOffset -> Layout NoChange :: Layout data EndOffset None :: EndOffset SameLine :: ColOffset -> EndOffset FromAlignCol :: (RowOffset, ColOffset) -> EndOffset type RowOffset = Int type ColOffset = Int type Row = Int type Col = Int data ForestLine ForestLine :: !Bool -> !Int -> !Int -> !Int -> ForestLine -- | The length of the span may have changed due to updated tokens. flSpanLengthChanged :: ForestLine -> !Bool flTreeSelector :: ForestLine -> !Int flInsertVersion :: ForestLine -> !Int flLine :: ForestLine -> !Int type ForestPos = (ForestLine, Int) -- | Match a SrcSpan, using a ForestLine as the marker type ForestSpan = (ForestPos, ForestPos) data PprOrigin -- | Original tokens Original :: PprOrigin -- | Added tokens Added :: PprOrigin -- | A data structure to make the ppr process visible data Ppr -- | Original row and col of the tokens making up the string PprText :: Row -> Col -> PprOrigin -> String -> Ppr -- | Offset of start of embedded parts, coords of last token, offset to -- start of next part, relative to the column of the start PprAbove :: EndOffset -> (Row, Col) -> EndOffset -> [Ppr] -> Ppr -- | Marks lines that have been deleted together with the original gap -- before, how many lines were originally included, and gap after. And a -- note field for debugging PprDeleted :: Row -> Col -> RowOffset -> RowOffset -> RowOffset -> Ppr instance Show EndOffset instance Eq EndOffset instance Show Layout instance Eq Layout instance Eq TreeId instance Ord TreeId instance Show TreeId instance Eq PprOrigin instance Show PprOrigin instance Eq Ppr instance Show Ppr instance Outputable ForestLine instance Show ForestLine instance Eq ForestLine module Language.Haskell.Refact.Utils.LayoutTypes data TokenLayout TL :: (Tree Entry) -> TokenLayout type LayoutTree = Tree Entry data Label Label :: SrcSpan -> Layout -> [PosToken] -> Label -- | Provide workarounds for bugs detected in GHC, until they are fixed in -- a later version module Language.Haskell.Refact.Utils.GhcBugWorkArounds bypassGHCBug7351 :: [PosToken] -> [PosToken] -- | Replacement for original getRichTokenStream which will return -- the tokens for a file processed by CPP. See bug -- http://ghc.haskell.org/trac/ghc/ticket/8265 getRichTokenStreamWA :: GhcMonad m => Module -> m [(Located Token, String)] module Language.Haskell.Refact.Utils.Monad -- | Result of parsing a Haskell source file. It is simply the -- TypeCheckedModule produced by GHC. type ParseResult = TypecheckedModule data VerboseLevel Debug :: VerboseLevel Normal :: VerboseLevel Off :: VerboseLevel data RefactSettings RefSet :: ![String] -> ![FilePath] -> Bool -> LineSeparator -> Maybe [FilePath] -> !Bool -> !VerboseLevel -> (Bool, Bool, Bool, Bool) -> RefactSettings rsetGhcOpts :: RefactSettings -> ![String] rsetImportPaths :: RefactSettings -> ![FilePath] rsetExpandSplice :: RefactSettings -> Bool rsetLineSeparator :: RefactSettings -> LineSeparator rsetMainFile :: RefactSettings -> Maybe [FilePath] rsetCheckTokenUtilsInvariant :: RefactSettings -> !Bool rsetVerboseLevel :: RefactSettings -> !VerboseLevel rsetEnabledTargets :: RefactSettings -> (Bool, Bool, Bool, Bool) -- | State for refactoring a single file. Holds/hides the token stream, -- which gets updated transparently at key points. data RefactState RefSt :: !RefactSettings -> !Int -> !RefactFlags -> !StateStorage -> [TargetGraph] -> [([FilePath], ModuleGraph)] -> Maybe [FilePath] -> !(Maybe RefactModule) -> RefactState -- | Session level settings rsSettings :: RefactState -> !RefactSettings -- | Current Unique creator value, incremented every time it is used rsUniqState :: RefactState -> !Int -- | Flags for controlling generic traversals rsFlags :: RefactState -> !RefactFlags -- | Temporary storage of values while refactoring takes place rsStorage :: RefactState -> !StateStorage rsGraph :: RefactState -> [TargetGraph] rsModuleGraph :: RefactState -> [([FilePath], ModuleGraph)] rsCurrentTarget :: RefactState -> Maybe [FilePath] -- | The current module being refactored rsModule :: RefactState -> !(Maybe RefactModule) data RefactModule RefMod :: !TypecheckedModule -> ![PosToken] -> !TokenCache -> !Bool -> RefactModule rsTypecheckedMod :: RefactModule -> !TypecheckedModule -- | Original Token stream for the current module rsOrigTokenStream :: RefactModule -> ![PosToken] -- | Token stream for the current module, maybe modified, in SrcSpan tree -- form rsTokenCache :: RefactModule -> !TokenCache -- | current module has updated the token stream rsStreamModified :: RefactModule -> !Bool type TargetModule = ([FilePath], ModSummary) data RefactStashId Stash :: !String -> RefactStashId data RefactFlags RefFlags :: !Bool -> RefactFlags -- | Current traversal has already made a change rsDone :: RefactFlags -> !Bool -- | Provide some temporary storage while the refactoring is taking place data StateStorage StorageNone :: StateStorage StorageBind :: (LHsBind Name) -> StateStorage StorageSig :: (LSig Name) -> StateStorage type RefactGhc a = GhcT (StateT RefactState IO) a runRefactGhc :: RefactGhc a -> RefactState -> IO (a, RefactState) getRefacSettings :: RefactGhc RefactSettings defaultSettings :: RefactSettings logSettings :: RefactSettings -- | Initialise the GHC session, when starting a refactoring. This should -- never be called directly. initGhcSession :: Cradle -> [FilePath] -> RefactGhc () -- | Load a module graph into the GHC session, starting from main loadModuleGraphGhc :: Maybe [FilePath] -> RefactGhc () -- | Make sure the given file is the currently loaded target, and load it -- if not. Assumes that all the module graphs had been generated before, -- so these are not updated. ensureTargetLoaded :: TargetModule -> RefactGhc ModSummary canonicalizeGraph :: [ModSummary] -> IO [(Maybe (FilePath), ModSummary)] logm :: String -> RefactGhc () instance Show LineSeparator instance Eq VerboseLevel instance Show VerboseLevel instance Show RefactSettings instance Show RefactStashId instance Eq RefactStashId instance Ord RefactStashId instance Show Module instance Show ModSummary instance (MonadPlus m, Functor m, MonadIO m, ExceptionMonad m) => MonadPlus (GhcT m) instance MonadTrans GhcT instance MonadState RefactState (GhcT (StateT RefactState IO)) instance ExceptionMonad m => ExceptionMonad (StateT s m) instance MonadIO (StateT RefactState IO) instance MonadIO (GhcT (StateT RefactState IO)) instance Show StateStorage -- | This module contains all the code that depends on a specific version -- of GHC, and should be the only one requiring CPP module Language.Haskell.Refact.Utils.GhcVersionSpecific -- | Show a GHC API structure showGhc :: Outputable a => a -> String prettyprint :: Outputable a => a -> String prettyprint2 :: Outputable a => a -> String ppType :: Type -> String lexStringToRichTokens :: RealSrcLoc -> String -> IO [PosToken] getDataConstructors :: LHsDecl n -> [LConDecl n] setGhcContext :: GhcMonad m => ModSummary -> m () -- | This module contains routines used to perform generic traversals of -- the GHC AST, avoiding the traps resulting from certain fields being -- populated with values defined to trigger an error if ever evaluated. -- -- This is a useful feature for tracking down bugs in GHC, but makes use -- of the GHC library problematic. module Language.Haskell.Refact.Utils.GhcUtils everythingButStaged :: Stage -> (r -> r -> r) -> r -> GenericQ (r, Bool) -> GenericQ r -- | Look up a subterm by means of a maybe-typed filter somethingStaged :: Stage -> (Maybe u) -> GenericQ (Maybe u) -> GenericQ (Maybe u) -- | Staged variation of SYB.everything The stage must be provided to avoid -- trying to modify elements which may not be present at all stages of -- AST processing. Note: Top-down order everythingStaged :: Stage -> (r -> r -> r) -> r -> GenericQ r -> GenericQ r -- | Apply a monadic transformation at least somewhere somewhereMStaged :: MonadPlus m => Stage -> GenericM m -> GenericM m -- | Apply a monadic transformation at least somewhere, in bottom up order somewhereMStagedBu :: MonadPlus m => Stage -> GenericM m -> GenericM m -- | Monadic variation on everywhere everywhereMStaged :: Monad m => Stage -> GenericM m -> GenericM m -- | Monadic variation on everywhere' everywhereMStaged' :: Monad m => Stage -> GenericM m -> GenericM m -- | Bottom-up transformation everywhereStaged :: Stage -> (forall a. Data a => a -> a) -> forall a. Data a => a -> a -- | Top-down version of everywhereStaged everywhereStaged' :: Stage -> (forall a. Data a => a -> a) -> forall a. Data a => a -> a -- | Perform a query on the immediate subterms only, avoiding holes onelayerStaged :: Stage -> r -> GenericQ r -> GenericQ [r] -- | Staged variation of SYB.listify The stage must be provided to avoid -- trying to modify elements which may not be present at all stages of -- AST processing. listifyStaged :: (Data a, Typeable a1) => Stage -> (a1 -> Bool) -> a -> [a1] checkItemRenamer :: (Data a, Typeable a) => a -> Bool -- | Full type-unifying traversal in top-down order. full_tdTUGhc :: (MonadPlus m, Monoid a) => TU a m -> TU a m -- | Top-down type-unifying traversal that is cut of below nodes where the -- argument strategy succeeds. stop_tdTUGhc :: (MonadPlus m, Monoid a) => TU a m -> TU a m -- | Top-down type-preserving traversal that is cut of below nodes where -- the argument strategy succeeds. stop_tdTPGhc :: MonadPlus m => TP m -> TP m allTUGhc' :: (MonadPlus m, Monoid a) => TU a m -> TU a m -- | Top-down type-preserving traversal that performs its argument strategy -- at most once. once_tdTPGhc :: MonadPlus m => TP m -> TP m -- | Bottom-up type-preserving traversal that performs its argument -- strategy at most once. once_buTPGhc :: MonadPlus m => TP m -> TP m oneTPGhc :: MonadPlus m => TP m -> TP m allTUGhc :: MonadPlus m => (a -> a -> a) -> a -> TU a m -> TU a m checkItemStage' :: MonadPlus m => Stage -> TU () m checkItemRenamer' :: MonadPlus m => TU () m -- | Apply a generic transformation everywhere in a bottom-up manner. zeverywhereStaged :: Typeable a => Stage -> GenericT -> Zipper a -> Zipper a -- | Open a zipper to the point where the Geneneric query passes. returns -- the original zipper if the query does not pass (check this) zopenStaged :: Typeable a => Stage -> GenericQ Bool -> Zipper a -> [Zipper a] -- | Apply a generic monadic transformation once at the topmost leftmost -- successful location, avoiding holes in the GHC structures zsomewhereStaged :: MonadPlus m => Stage -> GenericM m -> Zipper a -> m (Zipper a) -- | Transform a zipper opened with a given generic query transZ :: Stage -> GenericQ Bool -> (Stage -> Zipper a -> Zipper a) -> Zipper a -> Zipper a -- | Monadic transform of a zipper opened with a given generic query transZM :: Monad m => Stage -> GenericQ Bool -> (Stage -> Zipper a -> m (Zipper a)) -> Zipper a -> m (Zipper a) -- | Open a zipper to the point where the Generic query passes, returning -- the zipper and a value from the specific part of the GenericQ that -- matched. This allows the components of the query to return a specific -- transformation routine, to apply to the returned zipper zopenStaged' :: Typeable a => Stage -> GenericQ (Maybe b) -> Zipper a -> [(Zipper a, b)] -- | Open a zipper to the point where the Generic query passes, and apply -- the transformation returned from the specific part of the GenericQ -- that matched. ztransformStagedM :: (Typeable a, Monad m) => Stage -> GenericQ (Maybe (Stage -> Zipper a -> m (Zipper a))) -> Zipper a -> m (Zipper a) checkZipperStaged :: Stage -> Zipper a -> Bool -- | Climb the tree until a predicate holds upUntil :: GenericQ Bool -> Zipper a -> Maybe (Zipper a) -- | Up the zipper until a predicate holds, and then return the zipper hole findAbove :: Data a => (a -> Bool) -> Zipper a -> Maybe a module Language.Haskell.Refact.Utils.LocUtils type SimpPos = (Int, Int) unmodified :: Bool modified :: Bool simpPos0 :: (Int, Int) nullSrcSpan :: SrcSpan showToks :: [PosToken] -> String whiteSpaceTokens :: (Int, Int) -> Int -> [PosToken] realSrcLocFromTok :: PosToken -> RealSrcLoc isWhite :: PosToken -> Bool notWhite :: PosToken -> Bool isWhiteSpace :: PosToken -> Bool isWhiteSpaceOrIgnored :: PosToken -> Bool isIgnored :: PosToken -> Bool -- | Tokens that are ignored when determining the first non-comment token -- in a span isIgnoredNonComment :: PosToken -> Bool isComment :: PosToken -> Bool isMultiLineComment :: PosToken -> Bool isOpenSquareBracket :: PosToken -> Bool isCloseSquareBracket :: PosToken -> Bool isIn :: PosToken -> Bool isComma :: PosToken -> Bool isOpenParen :: PosToken -> Bool isBar :: PosToken -> Bool -- | Returns True if the token ends with '\n' ++AZ++: is this meaningful? endsWithNewLn :: PosToken -> Bool -- | Returns True if the token starts with `\n`. ++AZ++: is this -- meaningful? startsWithNewLn :: PosToken -> Bool hasNewLn :: PosToken -> Bool -- | Remove the extra preceding empty lines. compressPreNewLns :: [PosToken] -> [PosToken] -- | Remove the following extra empty lines. compressEndNewLns :: [PosToken] -> [PosToken] -- | Given a token stream covering multi-lines, calculate the length of the -- last line AZ: should be the last token start col, plus length of -- token. lengthOfLastLine :: [PosToken] -> Int -- | get a token stream specified by the start and end position. getToks :: (SimpPos, SimpPos) -> [PosToken] -> [PosToken] -- | Replace a single token in the token stream by a new token, without -- adjusting the layout. Note1: does not re-align, else other later -- replacements may fail. Note2: must keep original end col, to know what -- the inter-token gap was when re-aligning replaceTokNoReAlign :: [PosToken] -> SimpPos -> PosToken -> [PosToken] -- | Delete a sequence of tokens specified by the start position and end -- position from the token stream, then adjust the remaining token stream -- to preserve layout deleteToks :: [PosToken] -> SimpPos -> SimpPos -> [PosToken] -- | remove at most n white space tokens from the beginning of ts doRmWhites :: Int -> [PosToken] -> [PosToken] -- | get all the source locations (use locations) in an AST phrase t -- according the the occurrence order of identifiers. srcLocs :: Data t => t -> [SimpPos] -- | Get the first SrcSpan found, in top down traversal getSrcSpan :: Data t => t -> Maybe SrcSpan -- | Get all the source locations in a given syntax fragment getAllSrcLocs :: Data t => t -> [(SimpPos, SimpPos)] getBiggestStartEndLoc :: Data t => t -> (SimpPos, SimpPos) -- | Extend the given position forwards to the end of the file while the -- supplied condition holds extendForwards :: [PosToken] -> (SimpPos, SimpPos) -> (PosToken -> Bool) -> (SimpPos, SimpPos) -- | Extend the given position backwards to the front of the file while the -- supplied condition holds extendBackwards :: [PosToken] -> (SimpPos, SimpPos) -> (PosToken -> Bool) -> (SimpPos, SimpPos) -- | Get the start&end location of syntax phrase t, then extend the end -- location to cover the comment/white spaces or new line which starts in -- the same line as the end location TODO: deprecate this in favour of -- startEndLocIncComments startEndLocIncFowComment :: Data t => [PosToken] -> t -> (SimpPos, SimpPos) -- | Get the start&end location of t in the token stream, then extend -- the start and end location to cover the preceding and following -- comments. -- -- In this routine, 'then','else','do' and 'in' are treated as comments. startEndLocIncComments :: Data t => [PosToken] -> t -> (SimpPos, SimpPos) startEndLocIncComments' :: [PosToken] -> (SimpPos, SimpPos) -> (SimpPos, SimpPos) -- | Convert a string into a set of Haskell tokens, following the given -- position, with each line indented by a given column offset if required -- TODO: replace 'colOffset withFirstLineIndent' with a Maybe Int ++AZ++ tokenise :: RealSrcLoc -> Int -> Bool -> String -> IO [PosToken] -- | Convert a string into a set of Haskell tokens. It has default position -- and offset, since it will be stitched into place in TokenUtils basicTokenise :: String -> IO [PosToken] prettyprintPatList :: (t -> String) -> Bool -> [t] -> String groupTokensByLine :: [PosToken] -> [[PosToken]] toksOnSameLine :: PosToken -> PosToken -> Bool addLocInfo :: (LHsBind Name, [PosToken]) -> RefactGhc (LHsBind Name, [PosToken]) -- | Get the start of the line before the pos, getLineOffset :: [PosToken] -> SimpPos -> Int tokenCol :: PosToken -> Int tokenColEnd :: PosToken -> Int tokenRow :: PosToken -> Int tokenPos :: (GenLocated SrcSpan t1, t) -> SimpPos tokenPosEnd :: (GenLocated SrcSpan t1, t) -> SimpPos tokenSrcSpan :: (Located t1, t) -> SrcSpan tokenCon :: PosToken -> String increaseSrcSpan :: SimpPos -> PosToken -> PosToken -- | gets the (row,col) of the start of the GHC.SrcSpan, or -- (-1,-1) if there is an GHC.UnhelpfulSpan getGhcLoc :: SrcSpan -> (Int, Int) -- | gets the (row,col) of the end of the GHC.SrcSpan, or (-1,-1) -- if there is an GHC.UnhelpfulSpan getGhcLocEnd :: SrcSpan -> (Int, Int) getLocatedStart :: GenLocated SrcSpan t -> (Int, Int) getLocatedEnd :: GenLocated SrcSpan t -> (Int, Int) getStartEndLoc :: Data t => t -> (SimpPos, SimpPos) startEndLocGhc :: Located b -> (SimpPos, SimpPos) realSrcLocEndTok :: PosToken -> RealSrcLoc fileNameFromTok :: PosToken -> FastString -- | Split the token stream into three parts: the tokens before the -- startPos, the tokens between startPos and endPos, and the tokens after -- endPos. Note: The startPos and endPos refer to the startPos of a token -- only. So a single token will have the same startPos and endPos NO^^^^ splitToks :: (SimpPos, SimpPos) -> [PosToken] -> ([PosToken], [PosToken], [PosToken]) -- | Get around lack of instance Eq when simply testing for empty list emptyList :: [t] -> Bool nonEmptyList :: [t] -> Bool -- | Split a set of comment tokens into the ones that belong with the -- startLine and those that belong with the endLine divideComments :: Int -> Int -> [PosToken] -> ([PosToken], [PosToken]) notWhiteSpace :: PosToken -> Bool isDoubleColon :: PosToken -> Bool isEmpty :: PosToken -> Bool isWhereOrLet :: PosToken -> Bool isWhere :: PosToken -> Bool isLet :: PosToken -> Bool isElse :: PosToken -> Bool isThen :: PosToken -> Bool isOf :: PosToken -> Bool isDo :: PosToken -> Bool -- | Get the indent of the line before, taking into account in-line -- 'where', 'let', 'in' and 'do' tokens getIndentOffset :: [PosToken] -> SimpPos -> Int splitOnNewLn :: [PosToken] -> ([PosToken], [PosToken]) tokenLen :: PosToken -> Int newLnToken :: PosToken -> PosToken newLinesToken :: Int -> PosToken -> PosToken -- | sort out line numbering so that they are always monotonically -- increasing. monotonicLineToks :: [PosToken] -> [PosToken] -- | Adjust token stream to cater for changes in token length due to token -- renaming reSequenceToks :: [PosToken] -> [PosToken] -- | Compose a new token using the given arguments. mkToken :: Token -> SimpPos -> String -> PosToken mkZeroToken :: PosToken -- | Mark a token so that it can be use to trigger layout checking later -- when the toks are retrieved markToken :: PosToken -> PosToken -- | Does a token have the file mark in it isMarked :: PosToken -> Bool -- | Add a constant line and column offset to a span of tokens addOffsetToToks :: SimpPos -> [PosToken] -> [PosToken] -- | Transfer the location information from the first param to the second matchTokenPos :: PosToken -> PosToken -> PosToken rmOffsetFromToks :: [PosToken] -> [PosToken] instance Show (GenLocated SrcSpan Token) -- | This module contains an API to manage a token stream. -- -- This API is used internally by MonadFunctions and the other utility -- modules, it should probably never be used directly in a refactoring. module Language.Haskell.Refact.Utils.TokenUtils initTokenCache :: [PosToken] -> TokenCache initTokenCacheLayout :: Tree Entry -> TokenCache -- | Make a tree representing a particular set of tokens mkTreeFromTokens :: [PosToken] -> Tree Entry -- | Make a tree representing a particular set of tokens mkTreeFromSpanTokens :: ForestSpan -> [PosToken] -> Tree Entry putToksInCache :: TokenCache -> SrcSpan -> [PosToken] -> (TokenCache, SrcSpan) putDeclToksInCache :: Data t => TokenCache -> SrcSpan -> [PosToken] -> Located t -> (TokenCache, SrcSpan, Located t) replaceTokenInCache :: TokenCache -> SrcSpan -> PosToken -> TokenCache removeToksFromCache :: TokenCache -> SrcSpan -> TokenCache getTreeFromCache :: SrcSpan -> TokenCache -> Tree Entry replaceTreeInCache :: SrcSpan -> Tree Entry -> TokenCache -> TokenCache -- | Assuming most recent operation has stashed the old tokens, sync the -- given AST to the most recent stash entry syncAstToLatestCache :: Data t => TokenCache -> Located t -> Located t -- | Get the (possible cached) tokens for a given source span, and cache -- their being fetched. NOTE: The SrcSpan may be one introduced by HaRe, -- rather than GHC. getTokensFor :: Bool -> Tree Entry -> SrcSpan -> (Tree Entry, [PosToken]) -- | Get the (possible cached) tokens for a given source span, and cache -- their being fetched. NOTE: The SrcSpan may be one introduced by HaRe, -- rather than GHC. getTokensForNoIntros :: Bool -> Tree Entry -> SrcSpan -> (Tree Entry, [PosToken]) -- | Get the tokens preceding a given SrcSpan getTokensBefore :: Tree Entry -> SrcSpan -> (Tree Entry, ReversedToks) -- | Replace a single token in a token tree, without changing the structure -- of the tree NOTE: the GHC.SrcSpan may have been used to select the -- appropriate forest in the first place, and is required to select the -- correct span in the tree, due to the ForestLine annotations that may -- be present replaceTokenForSrcSpan :: Tree Entry -> SrcSpan -> PosToken -> Tree Entry -- | Replace the tokens for a given SrcSpan with new ones. The SrcSpan will -- be inserted into the tree if it is not already there. If the SrcSpan -- changes size, replace the SrcSpan with a new one (marked), and return -- it, as well as the old one TODO: What about trailing comments? -- Preserve or replace? updateTokensForSrcSpan :: Tree Entry -> SrcSpan -> [PosToken] -> (Tree Entry, SrcSpan, Tree Entry) -- | Insert a ForestSpan into the forest, if it is not there already. -- Assumes the forest was populated with the tokens containing the -- ForestSpan already insertSrcSpan :: Tree Entry -> ForestSpan -> Tree Entry -- | Removes a ForestSpan and its tokens from the forest. removeSrcSpan :: Tree Entry -> ForestSpan -> (Tree Entry, Tree Entry) -- | Retrieve a path to the tree containing a ForestSpan from the forest, -- inserting it if not already present getSrcSpanFor :: Tree Entry -> ForestSpan -> (Tree Entry, Tree Entry) -- | Retrieve a path to the tree containing a ForestSpan from the forest, -- inserting it if not already present. In the case where there is a -- nested series of spans as in an Above layout, return the -- deepest one getSrcSpanForDeep :: Tree Entry -> ForestSpan -> (Tree Entry, Tree Entry) -- | Add a new SrcSpan and Tokens after a given one in the token stream and -- forest. This will be given a unique SrcSpan in return, which -- specifically indexes into the forest. addNewSrcSpanAndToksAfter :: Tree Entry -> SrcSpan -> SrcSpan -> Positioning -> [PosToken] -> (Tree Entry, SrcSpan) -- | Add new tokens after the given SrcSpan, constructing a new SrcSpan in -- the process addToksAfterSrcSpan :: Tree Entry -> SrcSpan -> Positioning -> [PosToken] -> (Tree Entry, SrcSpan) -- | Add new tokens belonging to an AST fragment after a given SrcSpan, and -- re-sync the AST fragment to match the new location addDeclToksAfterSrcSpan :: Data t => Tree Entry -> SrcSpan -> Positioning -> [PosToken] -> Located t -> (Tree Entry, SrcSpan, Located t) -- | Synchronise a located AST fragment to use a newly created SrcSpan in -- the token tree. TODO: Should this indent the tokens as well? syncAST :: Data t => Located t -> SrcSpan -> Tree Entry -> (Located t, Tree Entry) -- | indent the tree and tokens by the given offset, and sync the AST to -- the tree too. indentDeclToks :: Data t => Located t -> Tree Entry -> Int -> (Located t, Tree Entry) -- | How new SrcSpans should be inserted in the Token tree, relative to the -- prior span data Positioning -- | Only a single space between the end of the prior span and the new one PlaceAdjacent :: Positioning -- | Start at the specified line and col PlaceAbsolute :: !Int -> !Int -> Positioning -- | Line offset and absolute Col. Mainly for forcing start at left margin, -- number of lines to add at the end PlaceAbsCol :: !Int -> !Int -> !Int -> Positioning -- | Line and Col offset for start, num lines to add at the end relative to -- the indent level of the prior span PlaceOffset :: !Int -> !Int -> !Int -> Positioning -- | Line and Col offset for start, num lines to add at the end relative to -- the indent level of the prior line PlaceIndent :: !Int -> !Int -> !Int -> Positioning -- | Retrieve all the tokens at the leaves of the tree, in order. Marked -- tokens are re-aligned, and gaps are closed. retrieveTokensFinal :: Tree Entry -> [PosToken] adjustLinesForDeleted :: Tree Entry -> Tree Entry -- | Retrieve all the tokens at the leaves of the tree, in order. No -- adjustments are made to address gaps or re-alignment of the tokens retrieveTokensInterim :: Tree Entry -> [PosToken] retrieveTokens' :: Tree Entry -> [Entry] treeIdFromForestSpan :: ForestSpan -> TreeId reAlignMarked :: [PosToken] -> [PosToken] -- | Convert a simple (start,end) position to a SrcSpan belonging to the -- file in the tree posToSrcSpan :: Tree Entry -> (SimpPos, SimpPos) -> SrcSpan -- | Convert a simple (start,end) position to a SrcSpan belonging to the -- file in the given token posToSrcSpanTok :: PosToken -> (SimpPos, SimpPos) -> SrcSpan fileNameFromTok :: PosToken -> FastString -- | Get the start and end position of a Tree treeStartEnd :: Tree Entry -- -> (SimpPos,SimpPos) treeStartEnd (Node (Entry sspan _) _) = -- (getGhcLoc sspan,getGhcLocEnd sspan) treeStartEnd :: Tree Entry -> ForestSpan -- | Get the start and end position of a SrcSpan spanStartEnd :: -- GHC.SrcSpan -> (SimpPos,SimpPos) spanStartEnd sspan = (getGhcLoc -- sspan,getGhcLocEnd sspan) spanStartEnd :: SrcSpan -> ForestSpan sf :: SrcSpan -> ForestSpan fs :: ForestSpan -> SrcSpan forestSpanFromEntry :: Entry -> ForestSpan -- | ForestSpan version of GHC combineSrcSpans combineSpans :: ForestSpan -> ForestSpan -> ForestSpan -- | Keep track of when tokens are reversed, to avoid confusion data ReversedToks RT :: [PosToken] -> ReversedToks reverseToks :: [PosToken] -> ReversedToks unReverseToks :: ReversedToks -> [PosToken] reversedToks :: ReversedToks -> [PosToken] placeToksForSpan :: Tree Entry -> SrcSpan -> Tree Entry -> Positioning -> [PosToken] -> [PosToken] limitPrevToks :: ReversedToks -> SrcSpan -> ReversedToks reIndentToks :: Positioning -> [PosToken] -> [PosToken] -> [PosToken] -- | Some tokens are marked if they belong to identifiers which have been -- renamed. When the renaming takes place, no layout adjustment is done. -- This function adjusts the spacing for the rest of the line to match as -- far as possible the original spacing, except for the name change. reAlignOneLine :: [PosToken] -> [PosToken] reAlignToks :: [PosToken] -> [PosToken] -- | Split a forest of trees into a (begin,middle,end) according to a -- ForestSpan, such that no tokens are included in begin or end belonging -- to the ForestSpan, and all of middle has some part of the ForestSpan splitForestOnSpan :: Forest Entry -> ForestSpan -> ([Tree Entry], [Tree Entry], [Tree Entry]) -- | Does the first span contain the second? Takes cognisance of the -- various flags a ForestSpan can have. NOTE: This function relies on the -- Eq instance for ForestLine spanContains :: ForestSpan -> ForestSpan -> Bool -- | True if the start of the second param lies in the span of the first containsStart :: ForestSpan -> ForestSpan -> Bool -- | True if the start of the second param lies before the first, and ends -- after or on the second containsMiddle :: ForestSpan -> ForestSpan -> Bool -- | True if the end of the second param lies in the span of the first containsEnd :: ForestSpan -> ForestSpan -> Bool doSplitTree :: Tree Entry -> ForestSpan -> ([Tree Entry], [Tree Entry], [Tree Entry]) -- | Split a given tree into a possibly empty part that lies before the -- srcspan, the part that is wholly included in the srcspan and the part -- the lies outside of it at the end. splitSubtree :: Tree Entry -> ForestSpan -> ([Tree Entry], [Tree Entry], [Tree Entry]) splitSubToks :: Tree Entry -> (ForestPos, ForestPos) -> ([Tree Entry], [Tree Entry], [Tree Entry]) -- | Extract the start and end position of a span, without any leading or -- trailing comments nonCommentSpan :: [PosToken] -> (SimpPos, SimpPos) -- | Utility function to either return True or throw an error to report the -- problem invariantOk :: Tree Entry -> Bool -- | Check the invariant for the token cache. Returns list of any errors -- found. Invariants: 1. For each tree, either the rootLabel has a -- SrcSpan only, or the subForest /= []. 2a. The trees making up the -- subForest of a given node fully include the parent SrcSpan. i.e. the -- leaves contain all the tokens for a given SrcSpan. 2b. The subForest -- is in SrcSpan order 3. A given SrcSpan can only appear (or be -- included) in a single tree of the forest. 4. The parent link for all -- sub-trees does exist, and actually points to the parent. 5. There are -- no nullSpan entries in the tree NOTE: the tokens may extend before or -- after the SrcSpan, due to comments only NOTE2: this will have to be -- revisited when edits to the tokens are made invariant :: Tree Entry -> [String] showForest :: [Tree Entry] -> [String] showTree :: Tree Entry -> String showSrcSpan :: SrcSpan -> String showSrcSpanF :: SrcSpan -> String ghcSpanStartEnd :: SrcSpan -> ((Int, Int), (Int, Int)) -- | Insert a new node after the designated one in the tree insertNodeAfter :: Tree Entry -> Tree Entry -> Tree Entry -> Tree Entry -- | Starting from a point in the zipper, retrieve all tokens backwards -- until the line changes for a non-comment/non-empty token or beginning -- of file. retrievePrevLineToks :: TreePos Full Entry -> ReversedToks getTreeSpansAsList :: Tree Entry -> [(Int, ForestSpan)] -- | Open a zipper so that its focus is the given node NOTE: the node must -- already be in the tree openZipperToNode :: Tree Entry -> TreePos Full Entry -> TreePos Full Entry -- | Open a zipper so that its focus is the given node NOTE: the node must -- already be in the tree openZipperToNodeDeep :: Tree Entry -> TreePos Full Entry -> TreePos Full Entry -- | Open a zipper so that its focus has the given SrcSpan in its subtree, -- or the location where the SrcSpan should go, if it is not in the tree openZipperToSpan :: ForestSpan -> TreePos Full Entry -> TreePos Full Entry -- | Open a zipper so that its focus has the given SrcSpan in its subtree, -- or the location where the SrcSpan should go, if it is not in the tree. -- In the case of an Above layout with the same SrcSpan below, -- return that instead openZipperToSpanDeep :: ForestSpan -> TreePos Full Entry -> TreePos Full Entry -- | Open a zipper to a SrcSpan that has been added in the tree, and thus -- does not necessarily fall in the logical hierarchy of the tree openZipperToSpanAdded :: ForestSpan -> TreePos Full Entry -> TreePos Full Entry -- | Open a zipper so that its focus has the given SrcSpan in its subtree, -- or the location where the SrcSpan should go, if it is not in the tree openZipperToSpanOrig :: ForestSpan -> TreePos Full Entry -> TreePos Full Entry -- | Strip out the version markers forestSpanToSimpPos :: ForestSpan -> (SimpPos, SimpPos) -- | Strip out the version markers forestSpanToGhcPos :: ForestSpan -> (SimpPos, SimpPos) -- | Extract an encoded ForestLine from a GHC line ghcLineToForestLine :: Int -> ForestLine stripForestLineFromGhc :: SrcSpan -> SrcSpan forestLineToGhcLine :: ForestLine -> Int forestSpanToSrcSpan :: ForestSpan -> SrcSpan -- | Checks if the version is non-zero forestPosVersionSet :: ForestPos -> Bool -- | Checks if the version is zero forestPosVersionNotSet :: ForestPos -> Bool forestSpanLenChanged :: ForestSpan -> Bool -- | Gets the version numbers forestSpanVersions :: ForestSpan -> (Int, Int) -- | Checks if the version is non-zero in either position forestSpanVersionSet :: ForestSpan -> Bool -- | Checks if the version is zero in both positions forestSpanVersionNotSet :: ForestSpan -> Bool -- | Replace any ForestLine flags already in a SrcSpan with the given ones insertForestLineInSrcSpan :: ForestLine -> SrcSpan -> SrcSpan insertLenChangedInSrcSpan :: Bool -> Bool -> SrcSpan -> SrcSpan insertVersionsInSrcSpan :: Int -> Int -> SrcSpan -> SrcSpan srcSpanToForestSpan :: SrcSpan -> ForestSpan nullSpan :: ForestSpan nullPos :: ForestPos simpPosToForestSpan :: (SimpPos, SimpPos) -> ForestSpan srcPosToSimpPos :: (Int, Int) -> (Int, Int) showForestSpan :: ForestSpan -> String -- | Process the leaf nodes of a tree to remove all deleted spans deleteGapsToks :: [Entry] -> [PosToken] -- | For a span about to be deleted, calculate the gap between the end of -- the span being deleted and the start of the next one, at a token -- level. calcEndGap :: Tree Entry -> ForestSpan -> SimpPos stripForestLines :: [PosToken] -> [PosToken] -- | Neat 2-dimensional drawing of a tree. drawTreeEntry :: Tree Entry -> String -- | Call drawTreeEntry on the entire token cache drawTokenCache :: TokenCache -> String -- | Call drawTreeEntry on the entire token cache drawTokenCacheDetailed :: TokenCache -> String -- | Neat 2-dimensional drawing of a forest. drawForestEntry :: Forest Entry -> String drawEntry :: Tree Entry -> [String] drawTreeCompact :: Tree Entry -> String instance Show Entry instance Show ReversedToks instance Show Positioning instance Ord ForestLine instance Eq Entry instance Ord LayoutTree module Language.Haskell.Refact.Utils.DualTree layoutTreeToSourceTree :: LayoutTree -> SourceTree retrieveLinesFromLayoutTree :: LayoutTree -> [Line] retrieveLines :: SourceTree -> [Line] renderLines :: [Line] -> String renderSourceTree :: SourceTree -> String -- | The main data structure for this module type SourceTree = DUALTree Transformation Up Annot Prim data Line Line :: Row -> Col -> RowOffset -> Source -> LineOpt -> [PosToken] -> Line data Source SOriginal :: Source SAdded :: Source SWasAdded :: Source renderLinesFromLayoutTree :: LayoutTree -> String instance Show Transformation instance Show Span instance Eq Span instance Show DeletedSpan instance Eq DeletedSpan instance Show Alignment instance Eq Alignment instance Show Source instance Eq Source instance Show LineOpt instance Eq LineOpt instance Show Up instance Show Annot instance Show Prim instance Outputable LineOpt instance Outputable Source instance Outputable Line instance Outputable a => Outputable (NonEmpty a) instance Outputable Span instance Outputable DeletedSpan instance Outputable Alignment instance Outputable Up instance Outputable Annot instance Outputable EndOffset instance Outputable Transformation instance Outputable Prim instance Outputable (DUALTreeNE Transformation Up Annot Prim) instance Outputable (DUALTreeU Transformation Up Annot Prim) instance Outputable SourceTree instance Action Transformation Up instance Semigroup Transformation instance Semigroup Up instance Semigroup Span instance Show Line module Language.Haskell.Refact.Utils.Layout initTokenLayout :: ParsedSource -> [PosToken] -> LayoutTree nullTokenLayout :: TokenLayout allocTokens :: ParsedSource -> [PosToken] -> LayoutTree retrieveTokens :: LayoutTree -> [PosToken] getLoc :: LayoutTree -> ForestSpan addEndOffsets :: LayoutTree -> [PosToken] -> LayoutTree instance Show Label instance Outputable EndOffset instance Outputable Ppr instance Outputable PprOrigin instance Outputable Layout instance Outputable Entry instance Outputable (Tree Entry) module Language.Haskell.Refact.Utils.MonadFunctions -- | fetch the final tokens fetchToksFinal :: RefactGhc [PosToken] -- | fetch the final tokens in Ppr format fetchLinesFinal :: RefactGhc [Line] -- | fetch the pristine token stream fetchOrigToks :: RefactGhc [PosToken] -- | fetch the possibly modified tokens. Deprecated fetchToks :: RefactGhc [PosToken] getTypecheckedModule :: RefactGhc TypecheckedModule getRefactStreamModified :: RefactGhc Bool getRefactInscopes :: RefactGhc InScopes getRefactRenamed :: RefactGhc RenamedSource putRefactRenamed :: RenamedSource -> RefactGhc () getRefactParsed :: RefactGhc ParsedSource putParsedModule :: TypecheckedModule -> [PosToken] -> RefactGhc () clearParsedModule :: RefactGhc () getRefactFileName :: RefactGhc (Maybe FilePath) -- | Replace a token occurring in a given GHC.SrcSpan replaceToken :: SrcSpan -> PosToken -> RefactGhc () -- | Replace the tokens for a given GHC.SrcSpan, return new GHC.SrcSpan -- delimiting new tokens putToksForSpan :: SrcSpan -> [PosToken] -> RefactGhc SrcSpan -- | Replace the tokens for a given GHC.SrcSpan, return new GHC.SrcSpan -- delimiting new tokens, and update the AST fragment to reflect it putDeclToksForSpan :: Data t => SrcSpan -> Located t -> [PosToken] -> RefactGhc (SrcSpan, Located t) -- | Get the current tokens for a given GHC.SrcSpan. getToksForSpan :: SrcSpan -> RefactGhc [PosToken] -- | Get the current tokens for a given GHC.SrcSpan, without checking the -- invariant. TODO: this should not be necessary getToksForSpanNoInv :: SrcSpan -> RefactGhc [PosToken] -- | Get the current tokens for a given GHC.SrcSpan, leaving out any -- leading 'then', 'else', 'of', 'do' or 'in' tokens getToksForSpanWithIntros :: SrcSpan -> RefactGhc [PosToken] -- | Get the current tokens preceding a given GHC.SrcSpan. getToksBeforeSpan :: SrcSpan -> RefactGhc ReversedToks -- | Replace the tokens for a given GHC.SrcSpan, return GHC.SrcSpan they -- are placed in putToksForPos :: (SimpPos, SimpPos) -> [PosToken] -> RefactGhc SrcSpan -- | Add tokens after a designated GHC.SrcSpan putToksAfterSpan :: SrcSpan -> Positioning -> [PosToken] -> RefactGhc SrcSpan -- | Add tokens after a designated position putToksAfterPos :: (SimpPos, SimpPos) -> Positioning -> [PosToken] -> RefactGhc SrcSpan -- | Add tokens after a designated GHC.SrcSpan, and update the AST fragment -- to reflect it putDeclToksAfterSpan :: Data t => SrcSpan -> Located t -> Positioning -> [PosToken] -> RefactGhc (Located t) -- | Remove a GHC.SrcSpan and its associated tokens removeToksForSpan :: SrcSpan -> RefactGhc () -- | Remove a GHC.SrcSpan and its associated tokens removeToksForPos :: (SimpPos, SimpPos) -> RefactGhc () syncDeclToLatestStash :: Data t => (Located t) -> RefactGhc (Located t) -- | Indent an AST fragment and its associated tokens by a set amount indentDeclAndToks :: Data t => (Located t) -> Int -> RefactGhc (Located t) -- | Print the Token Tree for debug purposes drawTokenTree :: String -> RefactGhc () -- | Print detailed Token Tree for debug purposes drawTokenTreeDetailed :: String -> RefactGhc () -- | Get the Token Tree for debug purposes getTokenTree :: RefactGhc (Tree Entry) showLinesDebug :: String -> RefactGhc () getRefactDone :: RefactGhc Bool setRefactDone :: RefactGhc () clearRefactDone :: RefactGhc () setStateStorage :: StateStorage -> RefactGhc () getStateStorage :: RefactGhc StateStorage updateToks :: Data t => Located t -> Located t -> (Located t -> [Char]) -> Bool -> RefactGhc () updateToksWithPos :: Data t => (SimpPos, SimpPos) -> t -> (t -> [Char]) -> Bool -> RefactGhc () initRefactModule :: TypecheckedModule -> [PosToken] -> Maybe RefactModule -- | This module contains a collection of program analysis and -- transformation functions (the API) that work over the Type Decorated -- AST. Most of the functions defined in the module are taken directly -- from the API, but in some cases are modified to work with the type -- decorated AST. -- -- In particular some new functions have been added to make type -- decorated AST traversals easier. -- -- In HaRe, in order to preserve the comments and layout of refactored -- programs, a refactoring modifies not only the AST but also the token -- stream, and the program source after the refactoring is extracted from -- the token stream rather than the AST, for the comments and layout -- information is kept in the token steam instead of the AST. As a -- consequence, a program transformation function from this API modifies -- both the AST and the token stream (unless explicitly stated). So when -- you build your own program transformations, try to use the API to do -- the transformation, as this can liberate you from caring about the -- token stream. -- -- This type decorated API is still in development. Any suggestions and -- comments are very much welcome. module Language.Haskell.Refact.Utils.TypeUtils -- | Process the inscope relation returned from the parsing and module -- analysis pass, and return a list of four-element tuples. Each tuple -- contains an identifier name, the identifier's namespace info, the -- identifier's defining module name and its qualifier name. -- -- The same identifier may have multiple entries in the result because it -- may have different qualifiers. This makes it easier to decide whether -- the identifier can be used unqualifiedly by just checking whether -- there is an entry for it with the qualifier field being Nothing. inScopeInfo :: InScopes -> [(String, NameSpace, ModuleName, Maybe ModuleName)] -- | Return True if the identifier is inscope and can be used without a -- qualifier. isInScopeAndUnqualified :: String -> InScopes -> Bool -- | Return True if the identifier is inscope and can be used without a -- qualifier. The identifier name string may have a qualifier already -- NOTE: may require qualification based on name clash with an existing -- identifier. isInScopeAndUnqualifiedGhc :: String -> (Maybe Name) -> RefactGhc Bool inScopeNames :: String -> RefactGhc [Name] -- | Return True if an identifier is exported by the module currently being -- refactored. isExported :: Name -> RefactGhc Bool -- | Return True if an identifier is explicitly exported by the module. isExplicitlyExported :: Name -> RenamedSource -> Bool -- | Return True if the current module is exported either by default or by -- specifying the module name in the export. modIsExported :: ModuleName -> RenamedSource -> Bool -- | True if the name is a field name isFieldName :: Name -> Bool -- | True if the name is a field name isClassName :: Name -> Bool -- | True if the name is a class instance isInstanceName :: Name -> Bool -- | Collect the identifiers (in PName format) in a given syntax phrase. hsPNs :: Data t => t -> [PName] hsBinds :: HsValBinds t => t -> [LHsBind Name] replaceBinds :: HsValBinds t => t -> [LHsBind Name] -> t class Data t => HsValBinds t hsValBinds :: HsValBinds t => t -> HsValBinds Name replaceValBinds :: HsValBinds t => t -> HsValBinds Name -> t hsTyDecls :: HsValBinds t => t -> [[LTyClDecl Name]] isDeclaredIn :: HsValBinds t => Name -> t -> Bool -- | Collect the free and declared variables (in the GHC.Name format) in a -- given syntax phrase t. In the result, the first list contains the free -- variables, and the second list contains the declared variables. -- Expects RenamedSource hsFreeAndDeclaredPNsOld :: Data t => t -> ([Name], [Name]) -- | The same as hsFreeAndDeclaredPNs except that the returned -- variables are in the String format. hsFreeAndDeclaredNameStrings :: (Data t, Outputable t) => t -> RefactGhc ([String], [String]) hsFreeAndDeclaredPNs :: (Data t, Outputable t) => t -> RefactGhc ([Name], [Name]) -- | Collect the free and declared variables (in the GHC.Name format) in a -- given syntax phrase t. In the result, the first list contains the free -- variables, and the second list contains the declared variables. TODO: -- use GHC.NameSet instead of lists for FreeNames/DeclaredNames NOTE: The -- GHC fvs fields only carry non-GHC values, as they are used in the -- renaming process hsFreeAndDeclaredGhc :: (Data t, Outputable t) => t -> RefactGhc (FreeNames, DeclaredNames) getDeclaredTypes :: LTyClDecl Name -> [Name] -- | Experiment with GHC fvs stuff getFvs :: [LHsBind Name] -> [([Name], NameSet)] getFreeVars :: [LHsBind Name] -> [Name] getDeclaredVars :: [LHsBind Name] -> [Name] -- | Given syntax phrases e and t, if e occurs in t, then return those -- variables which are declared in t and accessible to e, otherwise -- return []. hsVisiblePNs :: (FindEntity e, Data e, Data t, HsValBinds t, Outputable e) => e -> t -> RefactGhc [Name] -- | Same as hsVisiblePNs except that the returned identifiers are -- in String format. hsVisibleNames :: (FindEntity t1, Data t1, Data t2, HsValBinds t2, Outputable t1) => t1 -> t2 -> RefactGhc [String] -- | hsFDsFromInside is different from hsFreeAndDeclaredPNs -- in that: given an syntax phrase t, hsFDsFromInside returns not -- only the declared variables that are visible from outside of t, but -- also those declared variables that are visible to the main expression -- inside t. NOTE: Expects to be given RenamedSource hsFDsFromInside :: Data t => t -> RefactGhc ([Name], [Name]) -- | The same as hsFDsFromInside except that the returned variables -- are in the String format hsFDNamesFromInside :: Data t => t -> RefactGhc ([String], [String]) -- | Given syntax phrases e and t, if e occurs in t, then return those -- variables which are declared in t and accessible to e, otherwise -- return []. hsVisibleDs :: (FindEntity e, Data e, Data t, HsValBinds t, Outputable e) => e -> t -> RefactGhc DeclaredNames -- | Return True if a string is a lexically valid variable name. isVarId :: String -> Bool -- | Return True if a string is a lexically valid constructor name. isConId :: String -> Bool -- | Return True if a string is a lexically valid operator name. isOperator :: String -> Bool -- | Return True if a PName is a toplevel PName. isTopLevelPN :: Name -> RefactGhc Bool -- | Return True if a PName is a local PName. isLocalPN :: Name -> Bool -- | Return True if the name has a GHC.SrcSpan, i.e. is declared -- in source we care about isNonLibraryName :: Name -> Bool -- | Return True if a PName is a qualified PName. AZ:NOTE: this tests the -- use instance, the underlying name may be qualified. e.g. used name is -- zip, GHC.List.zip NOTE2: not sure if this gives a meaningful result -- for a GHC.Name isQualifiedPN :: Name -> RefactGhc Bool -- | Return True if a PName is a function/pattern name defined in t. isFunOrPatName :: Data t => Name -> t -> Bool -- | Return True if a declaration is a type signature declaration. isTypeSig :: Located (Sig a) -> Bool -- | Return True if a declaration is a function definition. isFunBindP :: HsDeclP -> Bool isFunBindR :: LHsBind t -> Bool -- | Returns True if a declaration is a pattern binding. isPatBindP :: HsDeclP -> Bool isPatBindR :: LHsBind t -> Bool -- | Return True if a declaration is a pattern binding which only defines a -- variable value. isSimplePatBind :: Data t => LHsBind t -> Bool -- | Return True if a declaration is a pattern binding but not a simple -- one. isComplexPatBind :: LHsBind Name -> Bool -- | Return True if a declaration is a function/pattern definition. isFunOrPatBindP :: HsDeclP -> Bool -- | Return True if a declaration is a function/pattern definition. isFunOrPatBindR :: LHsBind t -> Bool -- | Return True if the identifier is unqualifiedly used in the given -- syntax phrase. usedWithoutQualR :: GHC.Name -> GHC.ParsedSource -- -> Bool usedWithoutQualR :: Data t => Name -> t -> Bool -- | Return True if the identifier is used in the RHS if a function/pattern -- binding. isUsedInRhs :: Data t => (Located Name) -> t -> Bool -- | Return True if the identifier occurs in the given syntax phrase. findPNT :: Data t => Located Name -> t -> Bool -- | Return True if the identifier occurs in the given syntax phrase. findPN :: Data t => Name -> t -> Bool -- | Find all occurrences with location of the given name findAllNameOccurences :: Data t => Name -> t -> [(Located Name)] -- | Return True if any of the specified PNames ocuur in the given syntax -- phrase. findPNs :: Data t => [Name] -> t -> Bool -- | Returns True is a syntax phrase, say a, is part of another syntax -- phrase, say b. NOTE: very important: only do a shallow check findEntity :: (FindEntity a, Data b, Typeable b) => a -> b -> Bool findEntity' :: (Data a, Data b) => a -> b -> Maybe (SimpPos, SimpPos) -- | Return the type checked Id corresponding to the given -- Name findIdForName :: Name -> RefactGhc (Maybe Id) getTypeForName :: Name -> RefactGhc (Maybe Type) -- | Return True if syntax phrases t1 and t2 refer to the same one. sameOccurrence :: (Located t) -> (Located t) -> Bool -- | Return True if the function/pattern binding defines the specified -- identifier. defines :: Name -> LHsBind Name -> Bool definesP :: PName -> HsDeclP -> Bool -- | Return True if the declaration defines the type signature of the -- specified identifier. definesTypeSig :: Name -> LSig Name -> Bool sameBind :: LHsBind Name -> LHsBind Name -> Bool class Data t => UsedByRhs t usedByRhs :: UsedByRhs t => t -> [Name] -> Bool isMainModule :: Module -> Bool getModule :: RefactGhc Module -- | Return the identifier's defining location. defineLoc::PNT->SrcLoc defineLoc :: Located Name -> SrcLoc -- | Return the identifier's source location. useLoc::PNT->SrcLoc useLoc :: (Located Name) -> SrcLoc -- | Given the syntax phrase, find the largest-leftmost expression -- contained in the region specified by the start and end position, if -- found. locToExp :: (Data t, Typeable n) => SimpPos -> SimpPos -> t -> Maybe (Located (HsExpr n)) -- | Find the identifier(in GHC.Name format) whose start position is -- (row,col) in the file specified by the fileName, and returns -- Nothing if such an identifier does not exist. locToName :: Data t => SimpPos -> t -> Maybe (Located Name) -- | Find the identifier(in GHC.RdrName format) whose start position is -- (row,col) in the file specified by the fileName, and returns -- Nothing if such an identifier does not exist. locToRdrName :: Data t => SimpPos -> t -> Maybe (Located RdrName) -- | Find the identifier with the given name. This looks through the given -- syntax phrase for the first GHC.Name which matches. Because it is -- Renamed source, the GHC.Name will include its defining location. -- Returns Nothing if the name is not found. getName :: Data t => String -> t -> Maybe Name -- | Adding a declaration to the declaration list of the given syntax -- phrase. If the second argument is Nothing, then the declaration will -- be added to the beginning of the declaration list, but after the data -- type declarations is there is any. addDecl :: (Data t, HsValBinds t) => t -> Maybe Name -> (LHsBind Name, [LSig Name], Maybe [PosToken]) -> Bool -> RefactGhc t -- | Add identifiers (given by the third argument) to the explicit entity -- list in the declaration importing the specified module name. This -- function does nothing if the import declaration does not have an -- explicit entity list. addItemsToImport :: ModuleName -> RenamedSource -> [Name] -> RefactGhc RenamedSource -- | add items to the hiding list of an import declaration which imports -- the specified module. addHiding :: ModuleName -> RenamedSource -> [Name] -> RefactGhc RenamedSource addParamsToDecls :: [LHsBind Name] -> Name -> [Name] -> Bool -> RefactGhc [LHsBind Name] addActualParamsToRhs :: (Typeable t, Data t) => Bool -> Name -> [Name] -> t -> RefactGhc t -- | Add identifiers to the export list of a module. If the second argument -- is like: Just p, then do the adding only if p occurs in the export -- list, and the new identifiers are added right after p in the export -- list. Otherwise the new identifiers are add to the beginning of the -- export list. In the case that the export list is emport, then if the -- third argument is True, then create an explict export list to contain -- only the new identifiers, otherwise do nothing. addImportDecl :: RenamedSource -> ModuleName -> Maybe FastString -> Bool -> Bool -> Bool -> Maybe String -> Bool -> [Name] -> RefactGhc RenamedSource -- | Remove those specified items from the entity list in the import -- declaration. -- -- Remove the specified entities from the module's exports. The entities -- can be specified in either of two formats: i.e. either specify the -- module names and identifier names to be removed, so just given the -- exact AST for these entities. -- -- Duplicate a function/pattern binding declaration under a new name -- right after the original one. Also updates the token stream. duplicateDecl :: Data t => [LHsBind Name] -> t -> Name -> Name -> RefactGhc [LHsBind Name] -- | Remove the declaration (and the type signature is the second parameter -- is True) that defines the given identifier from the declaration list. rmDecl :: Data t => Name -> Bool -> t -> RefactGhc (t, LHsBind Name, Maybe (LSig Name)) -- | Remove the type signature that defines the given identifier's type -- from the declaration list. rmTypeSig :: Data t => Name -> t -> RefactGhc (t, Maybe (LSig Name)) -- | Remove multiple type signatures rmTypeSigs :: Data t => [Name] -> t -> RefactGhc (t, [LSig Name]) -- | Remove the qualifier from the given identifiers in the given syntax -- phrase. rmQualifier :: Data t => [Name] -> t -> RefactGhc t -- | Replace all occurences of a top level GHC.Name with a qualified -- version. qualifyToplevelName :: Name -> RefactGhc () -- | Rename each occurrences of the identifier in the given syntax phrase -- with the new name. If the Bool parameter is True, then modify both the -- AST and the token stream, otherwise only modify the AST. TODO: the -- syntax phrase is required to be GHC.Located, not sure how to specify -- this without breaking the everywhereMStaged call renamePN :: Data t => Name -> Name -> Bool -> Bool -> t -> RefactGhc t -- | Check whether the specified identifier is declared in the given syntax -- phrase t, if so, rename the identifier by creating a new name -- automatically. If the Bool parameter is True, the token stream will be -- modified, otherwise only the AST is modified. autoRenameLocalVar :: HsValBinds t => Bool -> Name -> t -> RefactGhc t -- | Show a list of entities, the parameter f is a function that specifies -- how to format an entity. showEntities :: (t -> String) -> [t] -> String -- | Show a PName in a format like: pn(at row:r, col: c). showPNwithLoc :: Located Name -> String defaultPN :: PName defaultName :: Name -- | Default expression. defaultExp :: HsExpP ghcToPN :: RdrName -> PName lghcToPN :: Located RdrName -> PName -- | If an expression consists of only one identifier then return this -- identifier in the GHC.Name format, otherwise return the default Name expToName :: Located (HsExpr Name) -> Name nameToString :: Name -> String -- | If a pattern consists of only one identifier then return this -- identifier, otherwise return Nothing patToPNT :: LPat Name -> Maybe Name -- | Compose a pattern from a pName. pNtoPat :: Name -> Pat Name -- | Return the list of identifiers (in PName format) defined by a -- function/pattern binding. definedPNs :: LHsBind Name -> [Name] -- | Find those declarations(function/pattern binding) which define the -- specified GHC.Names. incTypeSig indicates whether the corresponding -- type signature will be included. definingDeclsNames :: [Name] -> [LHsBind Name] -> Bool -> Bool -> [LHsBind Name] -- | Find those declarations(function/pattern binding) which define the -- specified GHC.Names. incTypeSig indicates whether the corresponding -- type signature will be included. definingDeclsNames' :: Data t => [Name] -> t -> [LHsBind Name] -- | Find those type signatures for the specified GHC.Names. definingSigsNames :: Data t => [Name] -> t -> [LSig Name] -- | Find those declarations which define the specified GHC.Names. definingTyClDeclsNames :: Data t => [Name] -> t -> [LTyClDecl Name] -- | Find all Located Names in the given Syntax phrase. allNames :: Data t => t -> [Located Name] mkRdrName :: String -> RdrName -- | Make a new GHC.Name, using the Unique Int sequence stored in the -- RefactState. mkNewGhcName :: Maybe Module -> String -> RefactGhc Name -- | Create a new name base on the old name. Suppose the old name is -- f, then the new name would be like f_i where -- i is an integer. mkNewName :: String -> [String] -> Int -> String mkNewToplevelName :: Module -> String -> SrcSpan -> RefactGhc Name -- | Check if the proposed new name will conflict with an existing export causeNameClashInExports :: Name -> Name -> ModuleName -> RenamedSource -> Bool -- | Remove at most offset whitespaces from each line in the -- tokens removeOffset :: Int -> [PosToken] -> [PosToken] getDeclAndToks :: HsValBinds t => Name -> Bool -> [PosToken] -> t -> ([LHsBind Name], [PosToken]) -- | Get the signature and tokens for a declaration getSigAndToks :: Data t => Name -> t -> [PosToken] -> Maybe (LSig Name, [PosToken]) getToksForDecl :: Data t => t -> [PosToken] -> [PosToken] -- | Normalise a set of tokens to start at the offset of the first one removeToksOffset :: [PosToken] -> [PosToken] -- | Given a RenamedSource LPAT, return the equivalent ParsedSource part. -- NOTE: returns pristine ParsedSource, since HaRe does not change it getParsedForRenamedLPat :: ParsedSource -> LPat Name -> LPat RdrName -- | Given a RenamedSource Located name, return the equivalent ParsedSource -- part. NOTE: returns pristine ParsedSource, since HaRe does not change -- it getParsedForRenamedName :: ParsedSource -> Located Name -> Located RdrName -- | Given a RenamedSource Located name, return the equivalent ParsedSource -- part. NOTE: returns pristine ParsedSource, since HaRe does not change -- it getParsedForRenamedLocated :: Typeable b => Located a -> RefactGhc (Located b) -- | Create a new name token. If useQual then use the qualified -- name, if it exists. The end position is not changed, so the eventual -- realignment can know what the difference in length in the token is newNameTok :: Bool -> SrcSpan -> Name -> PosToken -- | Take a list of strings and return a list with the longest prefix of -- spaces removed stripLeadingSpaces :: [String] -> [String] instance UsedByRhs (Stmt Name) instance UsedByRhs (HsExpr Name) instance UsedByRhs (LHsExpr Name) instance UsedByRhs (LHsBind Name) instance UsedByRhs (HsBind Name) instance UsedByRhs [LHsBind Name] instance UsedByRhs (Match Name) instance UsedByRhs (HsValBinds Name) instance UsedByRhs (LHsBinds Name) instance UsedByRhs RenamedSource instance FindEntity (Located (HsDecl Name)) instance FindEntity (Located (HsBindLR Name Name)) instance FindEntity (Located (HsExpr Name)) instance FindEntity (Located Name) instance FindEntity Name instance HsValBinds (HsIPBinds Name) instance HsValBinds (LFamInstDecl Name) instance HsValBinds [LFamInstDecl Name] instance HsValBinds (LSig Name) instance HsValBinds [LSig Name] instance HsValBinds (LHsType Name) instance HsValBinds (LInstDecl Name) instance HsValBinds [LInstDecl Name] instance HsValBinds (LTyClDecl Name) instance HsValBinds [LTyClDecl Name] instance HsValBinds [[LTyClDecl Name]] instance HsValBinds [SyntaxExpr Name] instance HsValBinds Name instance HsValBinds (LPat Name) instance HsValBinds [LPat Name] instance HsValBinds (LStmt Name) instance HsValBinds [LStmt Name] instance HsValBinds (LGRHS Name) instance HsValBinds [LGRHS Name] instance HsValBinds (LHsExpr Name) instance HsValBinds [LHsBind Name] instance HsValBinds (LHsBind Name) instance HsValBinds (LHsBinds Name) instance HsValBinds (Stmt Name) instance HsValBinds (HsExpr Name) instance HsValBinds (HsBind Name) instance HsValBinds (Match Name) instance HsValBinds (LMatch Name) instance HsValBinds [LMatch Name] instance HsValBinds (MatchGroup Name) instance HsValBinds (GRHSs Name) instance HsValBinds (HsLocalBinds Name) instance HsValBinds (HsGroup Name) instance HsValBinds (HsValBinds Name) instance HsValBinds RenamedSource instance Monoid DeclaredNames instance Monoid FreeNames instance Show DeclaredNames instance Show FreeNames module Language.Haskell.Refact.Utils.Utils -- | Once the module graph has been loaded, load the given module into the -- RefactGhc monad TODO: relax the equality test, if the file is loaded -- via cabal it may have a full filesystem path. getModuleGhc :: FilePath -> RefactGhc () -- | Parse a single source file into a GHC session parseSourceFileGhc :: FilePath -> RefactGhc () -- | In the existing GHC session, put the requested TypeCheckedModule into -- the RefactGhc Monad, after ensuring that its originating target is the -- currently loaded one activateModule :: TargetModule -> RefactGhc ModSummary -- | In the existing GHC session, put the requested TypeCheckedModule into -- the RefactGhc monad getModuleDetails :: ModSummary -> RefactGhc () -- | Manage a whole refactor session. Initialise the monad, load the whole -- project if required, and then apply the individual refactorings, and -- write out the resulting files. -- -- It is intended that this forms the umbrella function, in which -- applyRefac is called runRefacSession :: RefactSettings -> Cradle -> RefactGhc [ApplyRefacResult] -> IO [FilePath] -- | Apply a refactoring (or part of a refactoring) to a single module applyRefac :: RefactGhc a -> RefacSource -> RefactGhc (ApplyRefacResult, a) -- | Returns True if any of the results has its modified flag set refactDone :: [ApplyRefacResult] -> Bool -- | The result of a refactoring is the file, a flag as to whether it was -- modified, the updated token stream, and the updated AST type -- ApplyRefacResult = ((FilePath, Bool), ([Ppr],[PosToken], -- GHC.RenamedSource)) type ApplyRefacResult = ((FilePath, Bool), ([Line], [PosToken], RenamedSource)) data RefacSource RSFile :: FilePath -> RefacSource RSMod :: ModSummary -> RefacSource RSAlreadyLoaded :: RefacSource -- | Update the occurrence of one syntax phrase in a given scope by another -- syntax phrase of the same type update :: Update t t1 => t -> t -> t1 -> RefactGhc t1 -- | From file name to module name. fileNameToModName :: FilePath -> RefactGhc ModuleName fileNameFromModSummary :: ModSummary -> FilePath -- | Extract the module name from the parsed source, if there is one getModuleName :: ParsedSource -> Maybe (ModuleName, String) -- | Return the client modules and file names. The client modules of -- module, say m, are those modules which directly or indirectly import -- module m. clientModsAndFiles :: ModuleName -> RefactGhc [([FilePath], ModSummary)] -- | Return the server module and file names. The server modules of module, -- say m, are those modules which are directly or indirectly imported by -- module m. This can only be called in a live GHC session TODO: make -- sure this works with multiple targets. Is that needed? No? serverModsAndFiles :: GhcMonad m => ModuleName -> m [ModSummary] instance Show ModuleName instance (Data t, OutputableBndr n1, OutputableBndr n2, Data n1, Data n2) => Update (LHsBindLR n1 n2) t instance (Data t, OutputableBndr n, Data n) => Update (LHsType n) t instance (Data t, OutputableBndr n, Data n) => Update (LPat n) t instance (Data t, OutputableBndr n, Data n) => Update (Located (HsExpr n)) t -- | This module should provide all that is required to write further -- refactorings. NOTE: it is currently unstable, and may change without -- notice on minor version number bumps module Language.Haskell.Refact.API -- | Result of parsing a Haskell source file. It is simply the -- TypeCheckedModule produced by GHC. type ParseResult = TypecheckedModule data VerboseLevel Debug :: VerboseLevel Normal :: VerboseLevel Off :: VerboseLevel data RefactSettings RefSet :: ![String] -> ![FilePath] -> Bool -> LineSeparator -> Maybe [FilePath] -> !Bool -> !VerboseLevel -> (Bool, Bool, Bool, Bool) -> RefactSettings rsetGhcOpts :: RefactSettings -> ![String] rsetImportPaths :: RefactSettings -> ![FilePath] rsetExpandSplice :: RefactSettings -> Bool rsetLineSeparator :: RefactSettings -> LineSeparator rsetMainFile :: RefactSettings -> Maybe [FilePath] rsetCheckTokenUtilsInvariant :: RefactSettings -> !Bool rsetVerboseLevel :: RefactSettings -> !VerboseLevel rsetEnabledTargets :: RefactSettings -> (Bool, Bool, Bool, Bool) type TargetModule = ([FilePath], ModSummary) data RefactFlags RefFlags :: !Bool -> RefactFlags -- | Current traversal has already made a change rsDone :: RefactFlags -> !Bool -- | Provide some temporary storage while the refactoring is taking place data StateStorage StorageNone :: StateStorage StorageBind :: (LHsBind Name) -> StateStorage StorageSig :: (LSig Name) -> StateStorage type RefactGhc a = GhcT (StateT RefactState IO) a runRefactGhc :: RefactGhc a -> RefactState -> IO (a, RefactState) getRefacSettings :: RefactGhc RefactSettings defaultSettings :: RefactSettings logSettings :: RefactSettings -- | Initialise the GHC session, when starting a refactoring. This should -- never be called directly. initGhcSession :: Cradle -> [FilePath] -> RefactGhc () -- | Load a module graph into the GHC session, starting from main loadModuleGraphGhc :: Maybe [FilePath] -> RefactGhc () -- | Make sure the given file is the currently loaded target, and load it -- if not. Assumes that all the module graphs had been generated before, -- so these are not updated. ensureTargetLoaded :: TargetModule -> RefactGhc ModSummary canonicalizeGraph :: [ModSummary] -> IO [(Maybe (FilePath), ModSummary)] logm :: String -> RefactGhc () -- | Once the module graph has been loaded, load the given module into the -- RefactGhc monad TODO: relax the equality test, if the file is loaded -- via cabal it may have a full filesystem path. getModuleGhc :: FilePath -> RefactGhc () -- | Parse a single source file into a GHC session parseSourceFileGhc :: FilePath -> RefactGhc () -- | In the existing GHC session, put the requested TypeCheckedModule into -- the RefactGhc Monad, after ensuring that its originating target is the -- currently loaded one activateModule :: TargetModule -> RefactGhc ModSummary -- | In the existing GHC session, put the requested TypeCheckedModule into -- the RefactGhc monad getModuleDetails :: ModSummary -> RefactGhc () -- | Manage a whole refactor session. Initialise the monad, load the whole -- project if required, and then apply the individual refactorings, and -- write out the resulting files. -- -- It is intended that this forms the umbrella function, in which -- applyRefac is called runRefacSession :: RefactSettings -> Cradle -> RefactGhc [ApplyRefacResult] -> IO [FilePath] -- | Apply a refactoring (or part of a refactoring) to a single module applyRefac :: RefactGhc a -> RefacSource -> RefactGhc (ApplyRefacResult, a) -- | Returns True if any of the results has its modified flag set refactDone :: [ApplyRefacResult] -> Bool -- | The result of a refactoring is the file, a flag as to whether it was -- modified, the updated token stream, and the updated AST type -- ApplyRefacResult = ((FilePath, Bool), ([Ppr],[PosToken], -- GHC.RenamedSource)) type ApplyRefacResult = ((FilePath, Bool), ([Line], [PosToken], RenamedSource)) data RefacSource RSFile :: FilePath -> RefacSource RSMod :: ModSummary -> RefacSource RSAlreadyLoaded :: RefacSource -- | Update the occurrence of one syntax phrase in a given scope by another -- syntax phrase of the same type update :: Update t t1 => t -> t -> t1 -> RefactGhc t1 -- | From file name to module name. fileNameToModName :: FilePath -> RefactGhc ModuleName fileNameFromModSummary :: ModSummary -> FilePath -- | Extract the module name from the parsed source, if there is one getModuleName :: ParsedSource -> Maybe (ModuleName, String) -- | Return the client modules and file names. The client modules of -- module, say m, are those modules which directly or indirectly import -- module m. clientModsAndFiles :: ModuleName -> RefactGhc [([FilePath], ModSummary)] -- | Return the server module and file names. The server modules of module, -- say m, are those modules which are directly or indirectly imported by -- module m. This can only be called in a live GHC session TODO: make -- sure this works with multiple targets. Is that needed? No? serverModsAndFiles :: GhcMonad m => ModuleName -> m [ModSummary] -- | fetch the final tokens fetchToksFinal :: RefactGhc [PosToken] -- | fetch the final tokens in Ppr format fetchLinesFinal :: RefactGhc [Line] -- | fetch the pristine token stream fetchOrigToks :: RefactGhc [PosToken] -- | fetch the possibly modified tokens. Deprecated fetchToks :: RefactGhc [PosToken] getTypecheckedModule :: RefactGhc TypecheckedModule getRefactStreamModified :: RefactGhc Bool getRefactInscopes :: RefactGhc InScopes getRefactRenamed :: RefactGhc RenamedSource putRefactRenamed :: RenamedSource -> RefactGhc () getRefactParsed :: RefactGhc ParsedSource putParsedModule :: TypecheckedModule -> [PosToken] -> RefactGhc () clearParsedModule :: RefactGhc () getRefactFileName :: RefactGhc (Maybe FilePath) -- | Replace a token occurring in a given GHC.SrcSpan replaceToken :: SrcSpan -> PosToken -> RefactGhc () -- | Replace the tokens for a given GHC.SrcSpan, return new GHC.SrcSpan -- delimiting new tokens putToksForSpan :: SrcSpan -> [PosToken] -> RefactGhc SrcSpan -- | Replace the tokens for a given GHC.SrcSpan, return new GHC.SrcSpan -- delimiting new tokens, and update the AST fragment to reflect it putDeclToksForSpan :: Data t => SrcSpan -> Located t -> [PosToken] -> RefactGhc (SrcSpan, Located t) -- | Get the current tokens for a given GHC.SrcSpan. getToksForSpan :: SrcSpan -> RefactGhc [PosToken] -- | Get the current tokens for a given GHC.SrcSpan, without checking the -- invariant. TODO: this should not be necessary getToksForSpanNoInv :: SrcSpan -> RefactGhc [PosToken] -- | Get the current tokens for a given GHC.SrcSpan, leaving out any -- leading 'then', 'else', 'of', 'do' or 'in' tokens getToksForSpanWithIntros :: SrcSpan -> RefactGhc [PosToken] -- | Get the current tokens preceding a given GHC.SrcSpan. getToksBeforeSpan :: SrcSpan -> RefactGhc ReversedToks -- | Replace the tokens for a given GHC.SrcSpan, return GHC.SrcSpan they -- are placed in putToksForPos :: (SimpPos, SimpPos) -> [PosToken] -> RefactGhc SrcSpan -- | Add tokens after a designated GHC.SrcSpan putToksAfterSpan :: SrcSpan -> Positioning -> [PosToken] -> RefactGhc SrcSpan -- | Add tokens after a designated position putToksAfterPos :: (SimpPos, SimpPos) -> Positioning -> [PosToken] -> RefactGhc SrcSpan -- | Add tokens after a designated GHC.SrcSpan, and update the AST fragment -- to reflect it putDeclToksAfterSpan :: Data t => SrcSpan -> Located t -> Positioning -> [PosToken] -> RefactGhc (Located t) -- | Remove a GHC.SrcSpan and its associated tokens removeToksForSpan :: SrcSpan -> RefactGhc () -- | Remove a GHC.SrcSpan and its associated tokens removeToksForPos :: (SimpPos, SimpPos) -> RefactGhc () syncDeclToLatestStash :: Data t => (Located t) -> RefactGhc (Located t) -- | Indent an AST fragment and its associated tokens by a set amount indentDeclAndToks :: Data t => (Located t) -> Int -> RefactGhc (Located t) -- | Print the Token Tree for debug purposes drawTokenTree :: String -> RefactGhc () -- | Print detailed Token Tree for debug purposes drawTokenTreeDetailed :: String -> RefactGhc () -- | Get the Token Tree for debug purposes getTokenTree :: RefactGhc (Tree Entry) showLinesDebug :: String -> RefactGhc () getRefactDone :: RefactGhc Bool setRefactDone :: RefactGhc () clearRefactDone :: RefactGhc () setStateStorage :: StateStorage -> RefactGhc () getStateStorage :: RefactGhc StateStorage updateToks :: Data t => Located t -> Located t -> (Located t -> [Char]) -> Bool -> RefactGhc () updateToksWithPos :: Data t => (SimpPos, SimpPos) -> t -> (t -> [Char]) -> Bool -> RefactGhc () type SimpPos = (Int, Int) unmodified :: Bool modified :: Bool simpPos0 :: (Int, Int) nullSrcSpan :: SrcSpan showToks :: [PosToken] -> String whiteSpaceTokens :: (Int, Int) -> Int -> [PosToken] realSrcLocFromTok :: PosToken -> RealSrcLoc isWhite :: PosToken -> Bool notWhite :: PosToken -> Bool isWhiteSpace :: PosToken -> Bool isWhiteSpaceOrIgnored :: PosToken -> Bool isIgnored :: PosToken -> Bool -- | Tokens that are ignored when determining the first non-comment token -- in a span isIgnoredNonComment :: PosToken -> Bool isComment :: PosToken -> Bool isMultiLineComment :: PosToken -> Bool isOpenSquareBracket :: PosToken -> Bool isCloseSquareBracket :: PosToken -> Bool isIn :: PosToken -> Bool isComma :: PosToken -> Bool isBar :: PosToken -> Bool -- | Returns True if the token ends with '\n' ++AZ++: is this meaningful? endsWithNewLn :: PosToken -> Bool -- | Returns True if the token starts with `\n`. ++AZ++: is this -- meaningful? startsWithNewLn :: PosToken -> Bool hasNewLn :: PosToken -> Bool -- | Remove the extra preceding empty lines. compressPreNewLns :: [PosToken] -> [PosToken] -- | Remove the following extra empty lines. compressEndNewLns :: [PosToken] -> [PosToken] -- | Given a token stream covering multi-lines, calculate the length of the -- last line AZ: should be the last token start col, plus length of -- token. lengthOfLastLine :: [PosToken] -> Int -- | get a token stream specified by the start and end position. getToks :: (SimpPos, SimpPos) -> [PosToken] -> [PosToken] -- | Replace a single token in the token stream by a new token, without -- adjusting the layout. Note1: does not re-align, else other later -- replacements may fail. Note2: must keep original end col, to know what -- the inter-token gap was when re-aligning replaceTokNoReAlign :: [PosToken] -> SimpPos -> PosToken -> [PosToken] -- | Delete a sequence of tokens specified by the start position and end -- position from the token stream, then adjust the remaining token stream -- to preserve layout deleteToks :: [PosToken] -> SimpPos -> SimpPos -> [PosToken] -- | remove at most n white space tokens from the beginning of ts doRmWhites :: Int -> [PosToken] -> [PosToken] -- | get all the source locations (use locations) in an AST phrase t -- according the the occurrence order of identifiers. srcLocs :: Data t => t -> [SimpPos] -- | Get the first SrcSpan found, in top down traversal getSrcSpan :: Data t => t -> Maybe SrcSpan -- | Get all the source locations in a given syntax fragment getAllSrcLocs :: Data t => t -> [(SimpPos, SimpPos)] getBiggestStartEndLoc :: Data t => t -> (SimpPos, SimpPos) -- | Extend the given position forwards to the end of the file while the -- supplied condition holds extendForwards :: [PosToken] -> (SimpPos, SimpPos) -> (PosToken -> Bool) -> (SimpPos, SimpPos) -- | Extend the given position backwards to the front of the file while the -- supplied condition holds extendBackwards :: [PosToken] -> (SimpPos, SimpPos) -> (PosToken -> Bool) -> (SimpPos, SimpPos) -- | Get the start&end location of syntax phrase t, then extend the end -- location to cover the comment/white spaces or new line which starts in -- the same line as the end location TODO: deprecate this in favour of -- startEndLocIncComments startEndLocIncFowComment :: Data t => [PosToken] -> t -> (SimpPos, SimpPos) -- | Get the start&end location of t in the token stream, then extend -- the start and end location to cover the preceding and following -- comments. -- -- In this routine, 'then','else','do' and 'in' are treated as comments. startEndLocIncComments :: Data t => [PosToken] -> t -> (SimpPos, SimpPos) startEndLocIncComments' :: [PosToken] -> (SimpPos, SimpPos) -> (SimpPos, SimpPos) -- | Convert a string into a set of Haskell tokens, following the given -- position, with each line indented by a given column offset if required -- TODO: replace 'colOffset withFirstLineIndent' with a Maybe Int ++AZ++ tokenise :: RealSrcLoc -> Int -> Bool -> String -> IO [PosToken] -- | Convert a string into a set of Haskell tokens. It has default position -- and offset, since it will be stitched into place in TokenUtils basicTokenise :: String -> IO [PosToken] prettyprintPatList :: (t -> String) -> Bool -> [t] -> String groupTokensByLine :: [PosToken] -> [[PosToken]] toksOnSameLine :: PosToken -> PosToken -> Bool addLocInfo :: (LHsBind Name, [PosToken]) -> RefactGhc (LHsBind Name, [PosToken]) -- | Get the start of the line before the pos, getLineOffset :: [PosToken] -> SimpPos -> Int tokenCol :: PosToken -> Int tokenColEnd :: PosToken -> Int tokenRow :: PosToken -> Int tokenPos :: (GenLocated SrcSpan t1, t) -> SimpPos tokenPosEnd :: (GenLocated SrcSpan t1, t) -> SimpPos tokenSrcSpan :: (Located t1, t) -> SrcSpan tokenCon :: PosToken -> String increaseSrcSpan :: SimpPos -> PosToken -> PosToken -- | gets the (row,col) of the start of the GHC.SrcSpan, or -- (-1,-1) if there is an GHC.UnhelpfulSpan getGhcLoc :: SrcSpan -> (Int, Int) -- | gets the (row,col) of the end of the GHC.SrcSpan, or (-1,-1) -- if there is an GHC.UnhelpfulSpan getGhcLocEnd :: SrcSpan -> (Int, Int) getLocatedStart :: GenLocated SrcSpan t -> (Int, Int) getLocatedEnd :: GenLocated SrcSpan t -> (Int, Int) getStartEndLoc :: Data t => t -> (SimpPos, SimpPos) startEndLocGhc :: Located b -> (SimpPos, SimpPos) realSrcLocEndTok :: PosToken -> RealSrcLoc fileNameFromTok :: PosToken -> FastString -- | Split the token stream into three parts: the tokens before the -- startPos, the tokens between startPos and endPos, and the tokens after -- endPos. Note: The startPos and endPos refer to the startPos of a token -- only. So a single token will have the same startPos and endPos NO^^^^ splitToks :: (SimpPos, SimpPos) -> [PosToken] -> ([PosToken], [PosToken], [PosToken]) -- | Get around lack of instance Eq when simply testing for empty list emptyList :: [t] -> Bool nonEmptyList :: [t] -> Bool -- | Split a set of comment tokens into the ones that belong with the -- startLine and those that belong with the endLine divideComments :: Int -> Int -> [PosToken] -> ([PosToken], [PosToken]) notWhiteSpace :: PosToken -> Bool isDoubleColon :: PosToken -> Bool isEmpty :: PosToken -> Bool isWhereOrLet :: PosToken -> Bool isWhere :: PosToken -> Bool isLet :: PosToken -> Bool isElse :: PosToken -> Bool isThen :: PosToken -> Bool isOf :: PosToken -> Bool isDo :: PosToken -> Bool -- | Get the indent of the line before, taking into account in-line -- 'where', 'let', 'in' and 'do' tokens getIndentOffset :: [PosToken] -> SimpPos -> Int splitOnNewLn :: [PosToken] -> ([PosToken], [PosToken]) tokenLen :: PosToken -> Int newLnToken :: PosToken -> PosToken newLinesToken :: Int -> PosToken -> PosToken -- | sort out line numbering so that they are always monotonically -- increasing. monotonicLineToks :: [PosToken] -> [PosToken] -- | Adjust token stream to cater for changes in token length due to token -- renaming reSequenceToks :: [PosToken] -> [PosToken] -- | Compose a new token using the given arguments. mkToken :: Token -> SimpPos -> String -> PosToken mkZeroToken :: PosToken -- | Mark a token so that it can be use to trigger layout checking later -- when the toks are retrieved markToken :: PosToken -> PosToken -- | Does a token have the file mark in it isMarked :: PosToken -> Bool -- | Add a constant line and column offset to a span of tokens addOffsetToToks :: SimpPos -> [PosToken] -> [PosToken] -- | Transfer the location information from the first param to the second matchTokenPos :: PosToken -> PosToken -> PosToken rmOffsetFromToks :: [PosToken] -> [PosToken] type InScopes = [Name] type PosToken = (Located Token, String) ghead :: String -> [a] -> a glast :: String -> [a] -> a gtail :: String -> [a] -> [a] gfromJust :: [Char] -> Maybe a -> a -- | Process the inscope relation returned from the parsing and module -- analysis pass, and return a list of four-element tuples. Each tuple -- contains an identifier name, the identifier's namespace info, the -- identifier's defining module name and its qualifier name. -- -- The same identifier may have multiple entries in the result because it -- may have different qualifiers. This makes it easier to decide whether -- the identifier can be used unqualifiedly by just checking whether -- there is an entry for it with the qualifier field being Nothing. inScopeInfo :: InScopes -> [(String, NameSpace, ModuleName, Maybe ModuleName)] -- | Return True if the identifier is inscope and can be used without a -- qualifier. isInScopeAndUnqualified :: String -> InScopes -> Bool -- | Return True if the identifier is inscope and can be used without a -- qualifier. The identifier name string may have a qualifier already -- NOTE: may require qualification based on name clash with an existing -- identifier. isInScopeAndUnqualifiedGhc :: String -> (Maybe Name) -> RefactGhc Bool inScopeNames :: String -> RefactGhc [Name] -- | Return True if an identifier is exported by the module currently being -- refactored. isExported :: Name -> RefactGhc Bool -- | Return True if an identifier is explicitly exported by the module. isExplicitlyExported :: Name -> RenamedSource -> Bool -- | Return True if the current module is exported either by default or by -- specifying the module name in the export. modIsExported :: ModuleName -> RenamedSource -> Bool -- | True if the name is a field name isFieldName :: Name -> Bool -- | True if the name is a field name isClassName :: Name -> Bool -- | True if the name is a class instance isInstanceName :: Name -> Bool -- | Collect the identifiers (in PName format) in a given syntax phrase. hsPNs :: Data t => t -> [PName] hsBinds :: HsValBinds t => t -> [LHsBind Name] replaceBinds :: HsValBinds t => t -> [LHsBind Name] -> t class Data t => HsValBinds t hsValBinds :: HsValBinds t => t -> HsValBinds Name replaceValBinds :: HsValBinds t => t -> HsValBinds Name -> t hsTyDecls :: HsValBinds t => t -> [[LTyClDecl Name]] isDeclaredIn :: HsValBinds t => Name -> t -> Bool -- | Collect the free and declared variables (in the GHC.Name format) in a -- given syntax phrase t. In the result, the first list contains the free -- variables, and the second list contains the declared variables. -- Expects RenamedSource hsFreeAndDeclaredPNsOld :: Data t => t -> ([Name], [Name]) -- | The same as hsFreeAndDeclaredPNs except that the returned -- variables are in the String format. hsFreeAndDeclaredNameStrings :: (Data t, Outputable t) => t -> RefactGhc ([String], [String]) hsFreeAndDeclaredPNs :: (Data t, Outputable t) => t -> RefactGhc ([Name], [Name]) -- | Collect the free and declared variables (in the GHC.Name format) in a -- given syntax phrase t. In the result, the first list contains the free -- variables, and the second list contains the declared variables. TODO: -- use GHC.NameSet instead of lists for FreeNames/DeclaredNames NOTE: The -- GHC fvs fields only carry non-GHC values, as they are used in the -- renaming process hsFreeAndDeclaredGhc :: (Data t, Outputable t) => t -> RefactGhc (FreeNames, DeclaredNames) getDeclaredTypes :: LTyClDecl Name -> [Name] -- | Experiment with GHC fvs stuff getFvs :: [LHsBind Name] -> [([Name], NameSet)] getFreeVars :: [LHsBind Name] -> [Name] getDeclaredVars :: [LHsBind Name] -> [Name] -- | Given syntax phrases e and t, if e occurs in t, then return those -- variables which are declared in t and accessible to e, otherwise -- return []. hsVisiblePNs :: (FindEntity e, Data e, Data t, HsValBinds t, Outputable e) => e -> t -> RefactGhc [Name] -- | Same as hsVisiblePNs except that the returned identifiers are -- in String format. hsVisibleNames :: (FindEntity t1, Data t1, Data t2, HsValBinds t2, Outputable t1) => t1 -> t2 -> RefactGhc [String] -- | hsFDsFromInside is different from hsFreeAndDeclaredPNs -- in that: given an syntax phrase t, hsFDsFromInside returns not -- only the declared variables that are visible from outside of t, but -- also those declared variables that are visible to the main expression -- inside t. NOTE: Expects to be given RenamedSource hsFDsFromInside :: Data t => t -> RefactGhc ([Name], [Name]) -- | The same as hsFDsFromInside except that the returned variables -- are in the String format hsFDNamesFromInside :: Data t => t -> RefactGhc ([String], [String]) -- | Given syntax phrases e and t, if e occurs in t, then return those -- variables which are declared in t and accessible to e, otherwise -- return []. hsVisibleDs :: (FindEntity e, Data e, Data t, HsValBinds t, Outputable e) => e -> t -> RefactGhc DeclaredNames -- | Return True if a string is a lexically valid variable name. isVarId :: String -> Bool -- | Return True if a string is a lexically valid constructor name. isConId :: String -> Bool -- | Return True if a string is a lexically valid operator name. isOperator :: String -> Bool -- | Return True if a PName is a toplevel PName. isTopLevelPN :: Name -> RefactGhc Bool -- | Return True if a PName is a local PName. isLocalPN :: Name -> Bool -- | Return True if the name has a GHC.SrcSpan, i.e. is declared -- in source we care about isNonLibraryName :: Name -> Bool -- | Return True if a PName is a qualified PName. AZ:NOTE: this tests the -- use instance, the underlying name may be qualified. e.g. used name is -- zip, GHC.List.zip NOTE2: not sure if this gives a meaningful result -- for a GHC.Name isQualifiedPN :: Name -> RefactGhc Bool -- | Return True if a PName is a function/pattern name defined in t. isFunOrPatName :: Data t => Name -> t -> Bool -- | Return True if a declaration is a type signature declaration. isTypeSig :: Located (Sig a) -> Bool -- | Return True if a declaration is a function definition. isFunBindP :: HsDeclP -> Bool isFunBindR :: LHsBind t -> Bool -- | Returns True if a declaration is a pattern binding. isPatBindP :: HsDeclP -> Bool isPatBindR :: LHsBind t -> Bool -- | Return True if a declaration is a pattern binding which only defines a -- variable value. isSimplePatBind :: Data t => LHsBind t -> Bool -- | Return True if a declaration is a pattern binding but not a simple -- one. isComplexPatBind :: LHsBind Name -> Bool -- | Return True if a declaration is a function/pattern definition. isFunOrPatBindP :: HsDeclP -> Bool -- | Return True if a declaration is a function/pattern definition. isFunOrPatBindR :: LHsBind t -> Bool -- | Return True if the identifier is unqualifiedly used in the given -- syntax phrase. usedWithoutQualR :: GHC.Name -> GHC.ParsedSource -- -> Bool usedWithoutQualR :: Data t => Name -> t -> Bool -- | Return True if the identifier is used in the RHS if a function/pattern -- binding. isUsedInRhs :: Data t => (Located Name) -> t -> Bool -- | Return True if the identifier occurs in the given syntax phrase. findPNT :: Data t => Located Name -> t -> Bool -- | Return True if the identifier occurs in the given syntax phrase. findPN :: Data t => Name -> t -> Bool -- | Find all occurrences with location of the given name findAllNameOccurences :: Data t => Name -> t -> [(Located Name)] -- | Return True if any of the specified PNames ocuur in the given syntax -- phrase. findPNs :: Data t => [Name] -> t -> Bool -- | Returns True is a syntax phrase, say a, is part of another syntax -- phrase, say b. NOTE: very important: only do a shallow check findEntity :: (FindEntity a, Data b, Typeable b) => a -> b -> Bool findEntity' :: (Data a, Data b) => a -> b -> Maybe (SimpPos, SimpPos) -- | Return True if syntax phrases t1 and t2 refer to the same one. sameOccurrence :: (Located t) -> (Located t) -> Bool -- | Return the type checked Id corresponding to the given -- Name findIdForName :: Name -> RefactGhc (Maybe Id) getTypeForName :: Name -> RefactGhc (Maybe Type) -- | Return True if the function/pattern binding defines the specified -- identifier. defines :: Name -> LHsBind Name -> Bool definesP :: PName -> HsDeclP -> Bool -- | Return True if the declaration defines the type signature of the -- specified identifier. definesTypeSig :: Name -> LSig Name -> Bool sameBind :: LHsBind Name -> LHsBind Name -> Bool class Data t => UsedByRhs t usedByRhs :: UsedByRhs t => t -> [Name] -> Bool isMainModule :: Module -> Bool getModule :: RefactGhc Module -- | Return the identifier's defining location. defineLoc::PNT->SrcLoc defineLoc :: Located Name -> SrcLoc -- | Return the identifier's source location. useLoc::PNT->SrcLoc useLoc :: (Located Name) -> SrcLoc -- | Given the syntax phrase, find the largest-leftmost expression -- contained in the region specified by the start and end position, if -- found. locToExp :: (Data t, Typeable n) => SimpPos -> SimpPos -> t -> Maybe (Located (HsExpr n)) -- | Find the identifier(in GHC.Name format) whose start position is -- (row,col) in the file specified by the fileName, and returns -- Nothing if such an identifier does not exist. locToName :: Data t => SimpPos -> t -> Maybe (Located Name) -- | Find the identifier(in GHC.RdrName format) whose start position is -- (row,col) in the file specified by the fileName, and returns -- Nothing if such an identifier does not exist. locToRdrName :: Data t => SimpPos -> t -> Maybe (Located RdrName) -- | Find the identifier with the given name. This looks through the given -- syntax phrase for the first GHC.Name which matches. Because it is -- Renamed source, the GHC.Name will include its defining location. -- Returns Nothing if the name is not found. getName :: Data t => String -> t -> Maybe Name -- | Adding a declaration to the declaration list of the given syntax -- phrase. If the second argument is Nothing, then the declaration will -- be added to the beginning of the declaration list, but after the data -- type declarations is there is any. addDecl :: (Data t, HsValBinds t) => t -> Maybe Name -> (LHsBind Name, [LSig Name], Maybe [PosToken]) -> Bool -> RefactGhc t -- | Add identifiers (given by the third argument) to the explicit entity -- list in the declaration importing the specified module name. This -- function does nothing if the import declaration does not have an -- explicit entity list. addItemsToImport :: ModuleName -> RenamedSource -> [Name] -> RefactGhc RenamedSource -- | add items to the hiding list of an import declaration which imports -- the specified module. addHiding :: ModuleName -> RenamedSource -> [Name] -> RefactGhc RenamedSource addParamsToDecls :: [LHsBind Name] -> Name -> [Name] -> Bool -> RefactGhc [LHsBind Name] addActualParamsToRhs :: (Typeable t, Data t) => Bool -> Name -> [Name] -> t -> RefactGhc t -- | Add identifiers to the export list of a module. If the second argument -- is like: Just p, then do the adding only if p occurs in the export -- list, and the new identifiers are added right after p in the export -- list. Otherwise the new identifiers are add to the beginning of the -- export list. In the case that the export list is emport, then if the -- third argument is True, then create an explict export list to contain -- only the new identifiers, otherwise do nothing. addImportDecl :: RenamedSource -> ModuleName -> Maybe FastString -> Bool -> Bool -> Bool -> Maybe String -> Bool -> [Name] -> RefactGhc RenamedSource -- | Remove those specified items from the entity list in the import -- declaration. -- -- Remove the specified entities from the module's exports. The entities -- can be specified in either of two formats: i.e. either specify the -- module names and identifier names to be removed, so just given the -- exact AST for these entities. -- -- Duplicate a function/pattern binding declaration under a new name -- right after the original one. Also updates the token stream. duplicateDecl :: Data t => [LHsBind Name] -> t -> Name -> Name -> RefactGhc [LHsBind Name] -- | Remove the declaration (and the type signature is the second parameter -- is True) that defines the given identifier from the declaration list. rmDecl :: Data t => Name -> Bool -> t -> RefactGhc (t, LHsBind Name, Maybe (LSig Name)) -- | Remove the type signature that defines the given identifier's type -- from the declaration list. rmTypeSig :: Data t => Name -> t -> RefactGhc (t, Maybe (LSig Name)) -- | Remove multiple type signatures rmTypeSigs :: Data t => [Name] -> t -> RefactGhc (t, [LSig Name]) -- | Remove the qualifier from the given identifiers in the given syntax -- phrase. rmQualifier :: Data t => [Name] -> t -> RefactGhc t -- | Replace all occurences of a top level GHC.Name with a qualified -- version. qualifyToplevelName :: Name -> RefactGhc () -- | Rename each occurrences of the identifier in the given syntax phrase -- with the new name. If the Bool parameter is True, then modify both the -- AST and the token stream, otherwise only modify the AST. TODO: the -- syntax phrase is required to be GHC.Located, not sure how to specify -- this without breaking the everywhereMStaged call renamePN :: Data t => Name -> Name -> Bool -> Bool -> t -> RefactGhc t -- | Check whether the specified identifier is declared in the given syntax -- phrase t, if so, rename the identifier by creating a new name -- automatically. If the Bool parameter is True, the token stream will be -- modified, otherwise only the AST is modified. autoRenameLocalVar :: HsValBinds t => Bool -> Name -> t -> RefactGhc t -- | Show a list of entities, the parameter f is a function that specifies -- how to format an entity. showEntities :: (t -> String) -> [t] -> String -- | Show a PName in a format like: pn(at row:r, col: c). showPNwithLoc :: Located Name -> String defaultPN :: PName defaultName :: Name -- | Default expression. defaultExp :: HsExpP ghcToPN :: RdrName -> PName lghcToPN :: Located RdrName -> PName -- | If an expression consists of only one identifier then return this -- identifier in the GHC.Name format, otherwise return the default Name expToName :: Located (HsExpr Name) -> Name nameToString :: Name -> String -- | If a pattern consists of only one identifier then return this -- identifier, otherwise return Nothing patToPNT :: LPat Name -> Maybe Name -- | Compose a pattern from a pName. pNtoPat :: Name -> Pat Name -- | Return the list of identifiers (in PName format) defined by a -- function/pattern binding. definedPNs :: LHsBind Name -> [Name] -- | Find those declarations(function/pattern binding) which define the -- specified GHC.Names. incTypeSig indicates whether the corresponding -- type signature will be included. definingDeclsNames :: [Name] -> [LHsBind Name] -> Bool -> Bool -> [LHsBind Name] -- | Find those declarations(function/pattern binding) which define the -- specified GHC.Names. incTypeSig indicates whether the corresponding -- type signature will be included. definingDeclsNames' :: Data t => [Name] -> t -> [LHsBind Name] -- | Find those type signatures for the specified GHC.Names. definingSigsNames :: Data t => [Name] -> t -> [LSig Name] -- | Find those declarations which define the specified GHC.Names. definingTyClDeclsNames :: Data t => [Name] -> t -> [LTyClDecl Name] -- | Find all Located Names in the given Syntax phrase. allNames :: Data t => t -> [Located Name] mkRdrName :: String -> RdrName -- | Make a new GHC.Name, using the Unique Int sequence stored in the -- RefactState. mkNewGhcName :: Maybe Module -> String -> RefactGhc Name -- | Create a new name base on the old name. Suppose the old name is -- f, then the new name would be like f_i where -- i is an integer. mkNewName :: String -> [String] -> Int -> String mkNewToplevelName :: Module -> String -> SrcSpan -> RefactGhc Name -- | Check if the proposed new name will conflict with an existing export causeNameClashInExports :: Name -> Name -> ModuleName -> RenamedSource -> Bool -- | Remove at most offset whitespaces from each line in the -- tokens removeOffset :: Int -> [PosToken] -> [PosToken] getDeclAndToks :: HsValBinds t => Name -> Bool -> [PosToken] -> t -> ([LHsBind Name], [PosToken]) -- | Get the signature and tokens for a declaration getSigAndToks :: Data t => Name -> t -> [PosToken] -> Maybe (LSig Name, [PosToken]) getToksForDecl :: Data t => t -> [PosToken] -> [PosToken] -- | Normalise a set of tokens to start at the offset of the first one removeToksOffset :: [PosToken] -> [PosToken] -- | Given a RenamedSource LPAT, return the equivalent ParsedSource part. -- NOTE: returns pristine ParsedSource, since HaRe does not change it getParsedForRenamedLPat :: ParsedSource -> LPat Name -> LPat RdrName -- | Given a RenamedSource Located name, return the equivalent ParsedSource -- part. NOTE: returns pristine ParsedSource, since HaRe does not change -- it getParsedForRenamedName :: ParsedSource -> Located Name -> Located RdrName -- | Given a RenamedSource Located name, return the equivalent ParsedSource -- part. NOTE: returns pristine ParsedSource, since HaRe does not change -- it getParsedForRenamedLocated :: Typeable b => Located a -> RefactGhc (Located b) -- | Create a new name token. If useQual then use the qualified -- name, if it exists. The end position is not changed, so the eventual -- realignment can know what the difference in length in the token is newNameTok :: Bool -> SrcSpan -> Name -> PosToken -- | Take a list of strings and return a list with the longest prefix of -- spaces removed stripLeadingSpaces :: [String] -> [String] everythingButStaged :: Stage -> (r -> r -> r) -> r -> GenericQ (r, Bool) -> GenericQ r -- | Look up a subterm by means of a maybe-typed filter somethingStaged :: Stage -> (Maybe u) -> GenericQ (Maybe u) -> GenericQ (Maybe u) -- | Staged variation of SYB.everything The stage must be provided to avoid -- trying to modify elements which may not be present at all stages of -- AST processing. Note: Top-down order everythingStaged :: Stage -> (r -> r -> r) -> r -> GenericQ r -> GenericQ r -- | Apply a monadic transformation at least somewhere somewhereMStaged :: MonadPlus m => Stage -> GenericM m -> GenericM m -- | Apply a monadic transformation at least somewhere, in bottom up order somewhereMStagedBu :: MonadPlus m => Stage -> GenericM m -> GenericM m -- | Monadic variation on everywhere everywhereMStaged :: Monad m => Stage -> GenericM m -> GenericM m -- | Monadic variation on everywhere' everywhereMStaged' :: Monad m => Stage -> GenericM m -> GenericM m -- | Bottom-up transformation everywhereStaged :: Stage -> (forall a. Data a => a -> a) -> forall a. Data a => a -> a -- | Top-down version of everywhereStaged everywhereStaged' :: Stage -> (forall a. Data a => a -> a) -> forall a. Data a => a -> a -- | Perform a query on the immediate subterms only, avoiding holes onelayerStaged :: Stage -> r -> GenericQ r -> GenericQ [r] -- | Staged variation of SYB.listify The stage must be provided to avoid -- trying to modify elements which may not be present at all stages of -- AST processing. listifyStaged :: (Data a, Typeable a1) => Stage -> (a1 -> Bool) -> a -> [a1] checkItemRenamer :: (Data a, Typeable a) => a -> Bool -- | Full type-unifying traversal in top-down order. full_tdTUGhc :: (MonadPlus m, Monoid a) => TU a m -> TU a m -- | Top-down type-unifying traversal that is cut of below nodes where the -- argument strategy succeeds. stop_tdTUGhc :: (MonadPlus m, Monoid a) => TU a m -> TU a m -- | Top-down type-preserving traversal that is cut of below nodes where -- the argument strategy succeeds. stop_tdTPGhc :: MonadPlus m => TP m -> TP m allTUGhc' :: (MonadPlus m, Monoid a) => TU a m -> TU a m -- | Top-down type-preserving traversal that performs its argument strategy -- at most once. once_tdTPGhc :: MonadPlus m => TP m -> TP m -- | Bottom-up type-preserving traversal that performs its argument -- strategy at most once. once_buTPGhc :: MonadPlus m => TP m -> TP m oneTPGhc :: MonadPlus m => TP m -> TP m allTUGhc :: MonadPlus m => (a -> a -> a) -> a -> TU a m -> TU a m checkItemStage' :: MonadPlus m => Stage -> TU () m checkItemRenamer' :: MonadPlus m => TU () m -- | Apply a generic transformation everywhere in a bottom-up manner. zeverywhereStaged :: Typeable a => Stage -> GenericT -> Zipper a -> Zipper a -- | Open a zipper to the point where the Geneneric query passes. returns -- the original zipper if the query does not pass (check this) zopenStaged :: Typeable a => Stage -> GenericQ Bool -> Zipper a -> [Zipper a] -- | Apply a generic monadic transformation once at the topmost leftmost -- successful location, avoiding holes in the GHC structures zsomewhereStaged :: MonadPlus m => Stage -> GenericM m -> Zipper a -> m (Zipper a) -- | Transform a zipper opened with a given generic query transZ :: Stage -> GenericQ Bool -> (Stage -> Zipper a -> Zipper a) -> Zipper a -> Zipper a -- | Monadic transform of a zipper opened with a given generic query transZM :: Monad m => Stage -> GenericQ Bool -> (Stage -> Zipper a -> m (Zipper a)) -> Zipper a -> m (Zipper a) -- | Open a zipper to the point where the Generic query passes, returning -- the zipper and a value from the specific part of the GenericQ that -- matched. This allows the components of the query to return a specific -- transformation routine, to apply to the returned zipper zopenStaged' :: Typeable a => Stage -> GenericQ (Maybe b) -> Zipper a -> [(Zipper a, b)] -- | Open a zipper to the point where the Generic query passes, and apply -- the transformation returned from the specific part of the GenericQ -- that matched. ztransformStagedM :: (Typeable a, Monad m) => Stage -> GenericQ (Maybe (Stage -> Zipper a -> m (Zipper a))) -> Zipper a -> m (Zipper a) checkZipperStaged :: Stage -> Zipper a -> Bool -- | Climb the tree until a predicate holds upUntil :: GenericQ Bool -> Zipper a -> Maybe (Zipper a) -- | Up the zipper until a predicate holds, and then return the zipper hole findAbove :: Data a => (a -> Bool) -> Zipper a -> Maybe a -- | Show a GHC API structure showGhc :: Outputable a => a -> String prettyprint :: Outputable a => a -> String prettyprint2 :: Outputable a => a -> String ppType :: Type -> String lexStringToRichTokens :: RealSrcLoc -> String -> IO [PosToken] getDataConstructors :: LHsDecl n -> [LConDecl n] setGhcContext :: GhcMonad m => ModSummary -> m () -- | How new SrcSpans should be inserted in the Token tree, relative to the -- prior span data Positioning -- | Only a single space between the end of the prior span and the new one PlaceAdjacent :: Positioning -- | Start at the specified line and col PlaceAbsolute :: !Int -> !Int -> Positioning -- | Line offset and absolute Col. Mainly for forcing start at left margin, -- number of lines to add at the end PlaceAbsCol :: !Int -> !Int -> !Int -> Positioning -- | Line and Col offset for start, num lines to add at the end relative to -- the indent level of the prior span PlaceOffset :: !Int -> !Int -> !Int -> Positioning -- | Line and Col offset for start, num lines to add at the end relative to -- the indent level of the prior line PlaceIndent :: !Int -> !Int -> !Int -> Positioning reIndentToks :: Positioning -> [PosToken] -> [PosToken] -> [PosToken] srcSpanToForestSpan :: SrcSpan -> ForestSpan module Language.Haskell.Refact.Refactoring.Case -- | Convert an if expression to a case expression ifToCase :: RefactSettings -> Cradle -> FilePath -> SimpPos -> SimpPos -> IO [FilePath] module Language.Haskell.Refact.Refactoring.DupDef -- | This refactoring duplicates a definition (function binding or simple -- pattern binding) at the same level with a new name provided by the -- user. The new name should not cause name clash/capture. duplicateDef :: RefactSettings -> Cradle -> FilePath -> String -> SimpPos -> IO [FilePath] module Language.Haskell.Refact.Refactoring.MoveDef -- | Lift a definition to the top level liftToTopLevel :: RefactSettings -> Cradle -> FilePath -> SimpPos -> IO [FilePath] -- | Move a definition one level up from where it is now liftOneLevel :: RefactSettings -> Cradle -> FilePath -> SimpPos -> IO [FilePath] -- | Move a definition one level down demote :: RefactSettings -> Cradle -> FilePath -> SimpPos -> IO [FilePath] module Language.Haskell.Refact.Refactoring.Renaming -- | Rename the given identifier. rename :: RefactSettings -> Cradle -> FilePath -> String -> SimpPos -> IO [FilePath] module Language.Haskell.Refact.Refactoring.SwapArgs swapArgs :: RefactSettings -> Cradle -> [String] -> IO [FilePath] module Language.Haskell.Refact.HaRe data RefactSettings RefSet :: ![String] -> ![FilePath] -> Bool -> LineSeparator -> Maybe [FilePath] -> !Bool -> !VerboseLevel -> (Bool, Bool, Bool, Bool) -> RefactSettings rsetGhcOpts :: RefactSettings -> ![String] rsetImportPaths :: RefactSettings -> ![FilePath] rsetExpandSplice :: RefactSettings -> Bool rsetLineSeparator :: RefactSettings -> LineSeparator rsetMainFile :: RefactSettings -> Maybe [FilePath] rsetCheckTokenUtilsInvariant :: RefactSettings -> !Bool rsetVerboseLevel :: RefactSettings -> !VerboseLevel rsetEnabledTargets :: RefactSettings -> (Bool, Bool, Bool, Bool) data VerboseLevel Debug :: VerboseLevel Normal :: VerboseLevel Off :: VerboseLevel defaultSettings :: RefactSettings type SimpPos = (Int, Int) -- | Convert an if expression to a case expression ifToCase :: RefactSettings -> Cradle -> FilePath -> SimpPos -> SimpPos -> IO [FilePath] -- | This refactoring duplicates a definition (function binding or simple -- pattern binding) at the same level with a new name provided by the -- user. The new name should not cause name clash/capture. duplicateDef :: RefactSettings -> Cradle -> FilePath -> String -> SimpPos -> IO [FilePath] -- | Lift a definition to the top level liftToTopLevel :: RefactSettings -> Cradle -> FilePath -> SimpPos -> IO [FilePath] -- | Move a definition one level up from where it is now liftOneLevel :: RefactSettings -> Cradle -> FilePath -> SimpPos -> IO [FilePath] -- | Move a definition one level down demote :: RefactSettings -> Cradle -> FilePath -> SimpPos -> IO [FilePath] -- | Rename the given identifier. rename :: RefactSettings -> Cradle -> FilePath -> String -> SimpPos -> IO [FilePath] swapArgs :: RefactSettings -> Cradle -> [String] -> IO [FilePath]