-- 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.6 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 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 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 -- | 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 PosToken) -> !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 PosToken) -- | 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 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 unmodified :: Bool modified :: Bool simpPos0 :: (Int, Int) nullSrcSpan :: SrcSpan whiteSpaceTokens :: (Int, Int) -> Int -> [PosToken] realSrcLocFromTok :: PosToken -> RealSrcLoc isWhite :: PosToken -> Bool notWhite :: PosToken -> Bool isWhiteSpace :: PosToken -> Bool isWhiteSpaceOrIgnored :: IsToken a => a -> Bool isIgnored :: IsToken a => a -> Bool isMultiLineComment :: PosToken -> Bool isOpenSquareBracket :: PosToken -> Bool isCloseSquareBracket :: PosToken -> Bool isIn :: IsToken a => a -> 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] -- | 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) -- | 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. startEndLocIncComments' :: IsToken a => [a] -> (SimpPos, SimpPos) -> (SimpPos, SimpPos) prettyprintPatList :: (t -> String) -> Bool -> [t] -> String groupTokensByLine :: IsToken a => [a] -> [[a]] 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 tokenSrcSpan :: (Located t1, t) -> SrcSpan tokenCon :: PosToken -> String -- | Shift the whole token by the given offset increaseSrcSpan :: IsToken a => SimpPos -> a -> a -- | 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 :: IsToken a => (SimpPos, SimpPos) -> [a] -> ([a], [a], [a]) -- | Get around lack of instance Eq when simply testing for empty list -- TODO: get rid of this in favour of null built in fn emptyList :: [t] -> Bool nonEmptyList :: [t] -> Bool notWhiteSpace :: IsToken a => a -> Bool isDoubleColon :: PosToken -> Bool -- | Zero-length tokens, as appear in GHC as markers isEmpty :: IsToken a => a -> Bool isWhereOrLet :: IsToken a => a -> Bool isWhere :: IsToken a => a -> Bool isLet :: IsToken a => a -> Bool isElse :: IsToken a => a -> Bool isThen :: IsToken a => a -> Bool isOf :: IsToken a => a -> Bool isDo :: IsToken a => a -> Bool -- | Get the indent of the line before, taking into account in-line -- 'where', 'let', 'in' and 'do' tokens getIndentOffset :: IsToken a => [a] -> SimpPos -> Int splitOnNewLn :: IsToken a => [a] -> ([a], [a]) -- | tokenLen returns the length of the string representation of the token, -- not just the difference in the location, as the string may have -- changed without the position being updated, e.g. in a renaming tokenLen :: IsToken a => a -> Int newLnToken :: IsToken a => a -> a -- | 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 -> GhcPosToken mkZeroToken :: IsToken a => a -- | Mark a token so that it can be use to trigger layout checking later -- when the toks are retrieved markToken :: IsToken a => a -> a isMarked :: IsToken a => a -> Bool rmOffsetFromToks :: [PosToken] -> [PosToken] -- | 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 putDeclToksInCache :: Data t => TokenCache PosToken -> SrcSpan -> [PosToken] -> Located t -> (TokenCache PosToken, SrcSpan, Located t) -- | Assuming most recent operation has stashed the old tokens, sync the -- given AST to the most recent stash entry syncAstToLatestCache :: Data t => TokenCache PosToken -> Located t -> Located t -- | 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 PosToken) -> SrcSpan -> Positioning -> [PosToken] -> Located t -> (Tree (Entry PosToken), 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 -> ForestSpan -> (Located t) -- | Convert a simple (start,end) position to a SrcSpan belonging to the -- file in the tree posToSrcSpan :: Tree (Entry PosToken) -> (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 -- | Extract the start and end position of a span, without any leading or -- trailing comments nonCommentSpan :: IsToken a => [a] -> (SimpPos, SimpPos) showSrcSpan :: SrcSpan -> String showSrcSpanF :: SrcSpan -> String ghcSpanStartEnd :: SrcSpan -> ((Int, Int), (Int, Int)) stripForestLineFromGhc :: SrcSpan -> SrcSpan ghcSrcSpanToForestSpan :: SrcSpan -> ForestSpan -- | Process the leaf nodes of a tree to remove all deleted spans deleteGapsToks :: [Entry PosToken] -> [PosToken] module Language.Haskell.Refact.Utils.MonadFunctions -- | fetch the final tokens in Ppr format fetchLinesFinal :: RefactGhc [Line PosToken] -- | 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 preceding a given GHC.SrcSpan. getToksBeforeSpan :: SrcSpan -> RefactGhc (ReversedToks PosToken) -- | 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 addToksAfterSpan :: SrcSpan -> Positioning -> [PosToken] -> RefactGhc SrcSpan -- | Add tokens after a designated position addToksAfterPos :: (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 PosToken)) 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.Binds hsBinds :: HsValBinds t => t -> [LHsBind Name] replaceBinds :: HsValBinds t => t -> [LHsBind Name] -> t getValBindSigs :: HsValBinds Name -> [LSig Name] emptyValBinds :: HsValBinds Name class Data t => HsValBinds t hsValBinds :: HsValBinds t => t -> HsValBinds Name replaceValBinds :: HsValBinds t => t -> HsValBinds Name -> t hsTyDecls :: HsValBinds t => t -> [[LTyClDecl 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 -- | 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] 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 -- | Returns True is a syntax phrase, say a, is part of another syntax -- phrase, say b. Expects to be at least Parser output 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 -- | 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) -- | 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 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], [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], [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 in Ppr format fetchLinesFinal :: RefactGhc [Line PosToken] -- | 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 preceding a given GHC.SrcSpan. getToksBeforeSpan :: SrcSpan -> RefactGhc (ReversedToks PosToken) -- | 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 addToksAfterSpan :: SrcSpan -> Positioning -> [PosToken] -> RefactGhc SrcSpan -- | Add tokens after a designated position addToksAfterPos :: (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 PosToken)) 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 whiteSpaceTokens :: (Int, Int) -> Int -> [PosToken] realSrcLocFromTok :: PosToken -> RealSrcLoc isWhite :: PosToken -> Bool notWhite :: PosToken -> Bool isWhiteSpace :: PosToken -> Bool isWhiteSpaceOrIgnored :: IsToken a => a -> Bool isIgnored :: IsToken a => a -> Bool -- | Tokens that are ignored when determining the first non-comment token -- in a span isIgnoredNonComment :: IsToken a => a -> Bool isComment :: IsToken a => a -> Bool isMultiLineComment :: PosToken -> Bool isOpenSquareBracket :: PosToken -> Bool isCloseSquareBracket :: PosToken -> Bool isIn :: IsToken a => a -> 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 :: IsToken a => [a] -> SimpPos -> a -> [a] -- | 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) -- | 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. startEndLocIncComments' :: IsToken a => [a] -> (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 :: IsToken a => SimpSpan -> Int -> Bool -> String -> [a] -- | 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 :: IsToken a => String -> [a] prettyprintPatList :: (t -> String) -> Bool -> [t] -> String groupTokensByLine :: IsToken a => [a] -> [[a]] 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 :: IsToken a => a -> Int tokenColEnd :: IsToken a => a -> Int tokenRow :: IsToken a => a -> Int tokenPos :: IsToken a => a -> SimpPos tokenPosEnd :: IsToken a => a -> SimpPos tokenSrcSpan :: (Located t1, t) -> SrcSpan tokenCon :: PosToken -> String -- | Shift the whole token by the given offset increaseSrcSpan :: IsToken a => SimpPos -> a -> a -- | 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 :: IsToken a => (SimpPos, SimpPos) -> [a] -> ([a], [a], [a]) -- | Get around lack of instance Eq when simply testing for empty list -- TODO: get rid of this in favour of null built in fn emptyList :: [t] -> Bool nonEmptyList :: [t] -> Bool notWhiteSpace :: IsToken a => a -> Bool isDoubleColon :: PosToken -> Bool -- | Zero-length tokens, as appear in GHC as markers isEmpty :: IsToken a => a -> Bool isWhereOrLet :: IsToken a => a -> Bool isWhere :: IsToken a => a -> Bool isLet :: IsToken a => a -> Bool isElse :: IsToken a => a -> Bool isThen :: IsToken a => a -> Bool isOf :: IsToken a => a -> Bool isDo :: IsToken a => a -> Bool -- | Get the indent of the line before, taking into account in-line -- 'where', 'let', 'in' and 'do' tokens getIndentOffset :: IsToken a => [a] -> SimpPos -> Int splitOnNewLn :: IsToken a => [a] -> ([a], [a]) -- | tokenLen returns the length of the string representation of the token, -- not just the difference in the location, as the string may have -- changed without the position being updated, e.g. in a renaming tokenLen :: IsToken a => a -> Int newLnToken :: IsToken a => a -> a -- | 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 -> GhcPosToken mkZeroToken :: IsToken a => a -- | Mark a token so that it can be use to trigger layout checking later -- when the toks are retrieved markToken :: IsToken a => a -> a isMarked :: IsToken a => a -> Bool -- | Add a constant line and column offset to a span of tokens addOffsetToToks :: IsToken a => SimpPos -> [a] -> [a] -- | Transfer the location information from the first param to the second matchTokenPos :: IsToken a => a -> a -> a 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 -- | Returns True is a syntax phrase, say a, is part of another syntax -- phrase, say b. Expects to be at least Parser output 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 -- | 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) -- | 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 -- | Create a stream of tokens from source, with first token start at given -- location lexStringToTokens :: IsToken a => SimpSpan -> String -> [a] 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 -- | Place the new tokens so that they are positioned correctly relative to -- the previous tokens reIndentToks :: IsToken a => Positioning -> [a] -> [a] -> [a] ghcSrcSpanToForestSpan :: SrcSpan -> ForestSpan gs2f :: SrcSpan -> ForestSpan f2gs :: ForestSpan -> SrcSpan gs2ss :: SrcSpan -> SimpSpan ss2gs :: SimpSpan -> SrcSpan 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]