-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Clean up module imports, split and merge modules -- -- Clean up module imports, split and merge modules. @package module-management @version 0.11 module Language.Haskell.Modules.Util.Temp -- | Adapted from withTempDirectory to work in MonadCatchIO -- instances. withTempDirectory :: MonadCatchIO m => FilePath -> String -> (FilePath -> m a) -> m a module Language.Haskell.Modules.Util.DryIO class MonadIO m => MonadDryRun m dry :: MonadDryRun m => m Bool putDry :: MonadDryRun m => Bool -> m () dryIO :: MonadDryRun m => IO () -> m () dryIO' :: MonadDryRun m => IO a -> IO a -> m a tildeBackup :: FilePath -> Maybe FilePath noBackup :: FilePath -> Maybe FilePath readFileMaybe :: FilePath -> IO (Maybe String) -- | Replace the file at path with the given text, moving the original to -- the location returned by passing path to backup. If backup is the -- identity function you're going to have a bad time. replaceFile :: MonadDryRun m => (FilePath -> Maybe FilePath) -> FilePath -> String -> m () replaceFileIfDifferent :: MonadDryRun m => FilePath -> String -> m Bool removeFileIfPresent :: MonadDryRun m => FilePath -> m () createDirectoryIfMissing :: MonadDryRun m => Bool -> String -> m () writeFile :: MonadDryRun m => FilePath -> String -> m () module Language.Haskell.Modules.Common -- | Combine sortBy and groupBy groupBy' :: Ord a => (a -> a -> Ordering) -> [a] -> [[a]] mapNames :: Default a => [Name] -> [Name a] -- | Construct the base of a module path. modulePathBase :: ModuleName -> FilePath withCurrentDirectory :: FilePath -> IO a -> IO a module Language.Haskell.Modules.Util.SrcLoc class HasSpanInfo a spanInfo :: HasSpanInfo a => a -> SrcSpanInfo srcSpan :: HasSpanInfo x => x -> SrcSpan srcLoc :: HasSpanInfo x => x -> SrcLoc endLoc :: HasSpanInfo x => x -> SrcLoc textEndLoc :: String -> SrcLoc -- | Update a SrcLoc to move it from l past the string argument. increaseSrcLoc :: String -> SrcLoc -> SrcLoc textSpan :: String -> SrcSpanInfo srcPairText :: SrcLoc -> SrcLoc -> String -> (String, String) -- | Build a tree of SrcSpanInfo makeTree :: (HasSpanInfo a, Show a, Eq a, Ord a) => Set a -> Tree a tests :: Test instance Default SrcSpan instance Default SrcSpanInfo instance Default SrcLoc instance HasSpanInfo SrcSpanInfo instance HasSpanInfo Decl instance HasSpanInfo ImportDecl instance HasSpanInfo ExportSpec instance HasSpanInfo ExportSpecList instance HasSpanInfo WarningText instance HasSpanInfo ModulePragma instance HasSpanInfo ModuleName instance HasSpanInfo ModuleHead instance HasSpanInfo a => HasSpanInfo (Tree a) instance HasSpanInfo SrcSpan module Language.Haskell.Modules.Util.Symbols -- | Do a fold over the names that are declared in a declaration (not every -- name that appears, just the ones that the declaration is causing to -- exist - what's the word for that?. Reify!) class FoldDeclared a foldDeclared :: FoldDeclared a => (Maybe Name -> r -> r) -> r -> a -> r -- | Fold over the declared members - e.g. the method names of a class -- declaration, the constructors of a data declaration. class FoldMembers a foldMembers :: FoldMembers a => (Maybe Name -> r -> r) -> r -> a -> r symbols :: FoldDeclared a => a -> Set (Maybe Name) exports :: (FoldDeclared a, FoldMembers a) => a -> [ExportSpec] imports :: (FoldDeclared a, FoldMembers a) => a -> [ImportSpec] tests :: Test instance FoldDeclared (GadtDecl l) instance FoldDeclared (FieldDecl l) instance FoldDeclared (ConDecl l) instance FoldDeclared (QualConDecl l) instance FoldMembers (Decl a) instance FoldDeclared (ExportSpec l) instance FoldDeclared (ImportSpec l) instance FoldDeclared (Name l) instance FoldDeclared (RPat a) instance FoldDeclared (PatField a) instance FoldDeclared (Pat a) instance FoldDeclared (QName a) instance FoldDeclared (Match a) instance FoldDeclared (InstHead a) instance FoldDeclared (ClassDecl a) instance FoldDeclared (DeclHead a) instance FoldDeclared (Decl a) module Language.Haskell.Modules.Util.Test repoModules :: Set ModuleName logicModules :: Set ModuleName diff :: FilePath -> FilePath -> IO (ExitCode, String, String) -- | Like diff, but ignores extra files in b. diff' :: FilePath -> FilePath -> IO (ExitCode, String, String) rsync :: FilePath -> FilePath -> IO () -- | Convenience function for building the moduVerse, searches for modules -- in a directory hierarchy. FIXME: This should be in MonadClean and use -- the value of sourceDirs to remove prefixes from the module paths. And -- then it should look at the module text to see what the module name -- really is. findModules :: FilePath -> IO (Set ModuleName) -- | Find the paths of all the files below the directory top. findPaths :: FilePath -> IO (Set FilePath) -- | IO operations predicated on the verbosity value managed by the methods -- of MonadVerbosity. Noisily increases this value and quietly decreases -- it, and the q* operations only happen when the value is greater than -- zero. module Language.Haskell.Modules.Util.QIO class MonadIO m => MonadVerbosity m getVerbosity :: MonadVerbosity m => m Int putVerbosity :: MonadVerbosity m => Int -> m () modifyVerbosity :: MonadVerbosity m => (Int -> Int) -> m () quietly :: MonadVerbosity m => m a -> m a noisily :: MonadVerbosity m => m a -> m a qIO :: MonadVerbosity m => m () -> m () qPutStr :: MonadVerbosity m => String -> m () qLnPutStr :: MonadVerbosity m => String -> m () -- | foldModule is a utility function used to implement the clean, -- split, and merge operations. module Language.Haskell.Modules.Fold type ModuleInfo = (Module, String, [Comment]) type ModuleMap = Map ModuleName ModuleInfo -- | Given the result of parseModuleWithComments and the original module -- text, this does a fold over the parsed module contents, calling the -- seven argument functions in order. Each function is passed the AST -- value, the text of the space and comments leading up to the element, -- and the text for the element. Note that not everything passed to the -- pre argument of the functions will be comments and space - for -- example, the module keyword will be passed in the pre argument -- to the ModuleName function. foldModule :: Show r => (String -> r -> r) -> (ModulePragma -> String -> String -> String -> r -> r) -> (ModuleName -> String -> String -> String -> r -> r) -> (WarningText -> String -> String -> String -> r -> r) -> (String -> r -> r) -> (ExportSpec -> String -> String -> String -> r -> r) -> (String -> r -> r) -> (ImportDecl -> String -> String -> String -> r -> r) -> (Decl -> String -> String -> String -> r -> r) -> (String -> r -> r) -> ModuleInfo -> r -> r -- | Do just the header portion of foldModule. foldHeader :: Show r => (String -> r -> r) -> (ModulePragma -> String -> String -> String -> r -> r) -> (ModuleName -> String -> String -> String -> r -> r) -> (WarningText -> String -> String -> String -> r -> r) -> ModuleInfo -> r -> r -- | Do just the exports portion of foldModule. foldExports :: Show r => (String -> r -> r) -> (ExportSpec -> String -> String -> String -> r -> r) -> (String -> r -> r) -> ModuleInfo -> r -> r -- | Do just the imports portion of foldModule. foldImports :: Show r => (ImportDecl -> String -> String -> String -> r -> r) -> ModuleInfo -> r -> r -- | Do just the declarations portion of foldModule. foldDecls :: Show r => (Decl -> String -> String -> String -> r -> r) -> (String -> r -> r) -> ModuleInfo -> r -> r -- | This can be passed to foldModule to include the original text in the -- result echo :: Monoid m => t -> m -> m -> m -> Seq m -> Seq m -- | Similar to echo, but used for the two argument separator -- functions echo2 :: Monoid m => m -> Seq m -> Seq m -- | This can be passed to foldModule to omit the original text from the -- result. ignore :: t -> m -> m -> m -> r -> r -- | Similar to ignore, but used for the two argument separator -- functions ignore2 :: m -> r -> r instance Show St instance Spans (WarningText SrcSpanInfo) instance Spans (ModuleName SrcSpanInfo) instance Spans (Decl SrcSpanInfo) instance Spans (ImportDecl SrcSpanInfo) instance Spans (ModulePragma SrcSpanInfo) instance Spans (ExportSpec SrcSpanInfo) instance Spans (ExportSpecList SrcSpanInfo) instance Spans (ModuleHead SrcSpanInfo) instance Spans (Module SrcSpanInfo) module Language.Haskell.Modules.Imports -- | Clean up the imports of a source file. cleanImports :: MonadClean m => FilePath -> m ModuleResult module Language.Haskell.Modules.Merge -- | Merge the declarations from several modules into a single new one, -- updating the imports of the modules in the moduVerse to reflect the -- change. It *is* permissable to use one of the input modules as the -- output module. Note that circular imports can be created by this -- operation. mergeModules :: MonadClean m => [ModuleName] -> ModuleName -> m (Set ModuleResult) module Language.Haskell.Modules.Split data DeclName Exported :: Name -> DeclName Internal :: Name -> DeclName ReExported :: Name -> DeclName Instance :: DeclName -- | Do splitModuleBy with a custom symbol to module mapping splitModule :: MonadClean m => (DeclName -> ModuleName) -> ModuleName -> m () -- | Do splitModuleBy with the default symbol to module mapping (was -- splitModule) splitModuleDecls :: MonadClean m => ModuleName -> m () instance Eq DeclName instance Ord DeclName instance Show DeclName -- | Functions to control the state variables of MonadClean. module Language.Haskell.Modules.Params class (MonadIO m, MonadCatchIO m, Functor m) => MonadClean m -- | Create the environment required to do import cleaning and module -- splitting/merging. This environment, StateT Params m a, is an instance -- of MonadClean. runMonadClean :: MonadCatchIO m => StateT Params m a -> m a -- | Modify the set of modules whose imports will be updated when modules -- are split or merged. No default, it is an error to run splitModules or -- catModules without first setting this. modifyModuVerse :: MonadClean m => (Set ModuleName -> Set ModuleName) -> m () -- | If this flag is set, imports that become empty are removed. Sometimes -- this will lead to errors, specifically when an instance in the removed -- import that was required is no longer be available. (Note that this -- reflects a limitation of the -ddump-minimal-imports option of -- GHC.) If this happens this flag should be set. Note that an import -- that is already empty when cleanImports runs will never be -- removed, on the assumption that it was placed there only to import -- instances. Default is True. modifyRemoveEmptyImports :: MonadClean m => (Bool -> Bool) -> m () -- | Modify the list of directories that will be searched for source files, -- in a similar way to the Hs-Source-Dirs field in a cabal file. Default -- is ["."]. modifySourceDirs :: MonadClean m => ([FilePath] -> [FilePath]) -> m () -- | Modify the extra extensions passed to the compiler and the parser. -- Default value is the list in defaultParseMode. modifyExtensions :: MonadClean m => ([Extension] -> [Extension]) -> m () -- | Modify the list of extra flags passed to GHC. Default is []. modifyHsFlags :: MonadClean m => ([String] -> [String]) -> m () -- | Controls whether file updates will actually be performed. Default is -- False. (I recommend running in a directory controlled by a version -- control system so you don't have to worry about this.) modifyDryRun :: MonadClean m => (Bool -> Bool) -> m () -- | If TestMode is turned on no import cleaning will occur after a split -- or cat. Default is False. modifyTestMode :: MonadClean m => (Bool -> Bool) -> m () -- | This package provides three functions. The cleanImports -- function uses ghc's -ddump-minimal-imports flag to generate minimized -- and explicit imports and re-insert them into the module. -- -- The splitModuleDecls function moves each declaration of a -- module into a separate new module, and may also create three -- additional modules: ReExported (for identifiers that were re-exported -- from other imports), Instances (for declarations that don't result in -- an identifier to export), and OtherSymbols (for declarations that -- can't be turned into a module name.) -- -- In addition to creating new modules, splitModuleDecls also -- scans the a set of modules (known as the moduVerse) and updates their -- imports to account for the new locations of the symbols. The moduVerse -- is stored in MonadClean's state, and is updated as modules are created -- and destroyed by splitModule and catModules. -- -- The splitModule function is a version of -- splitModuleDecls that allows the caller to customize the -- mapping from symbols to new modules. -- -- The mergeModules function is the inverse operation of -- splitModule, it merges two or more modules into a new or -- existing module, updating imports of the moduVerse elements as -- necessary. -- -- There are several features worth noting. The Params type in -- the state of MonadClean has a removeEmptyImports -- field, which is True by default. This determines whether imports that -- turn into empty lists are preserved or not - if your program needs -- instances from a such an import, you will either want to set this flag -- to False or (better) add an empty import list to the import. -- -- These are the important entry points: -- -- -- -- Examples: -- -- -- --
--   findPaths "Language" >>= runMonadClean . mapM cleanImports . toList
--   
-- -- -- --
--   findModules "Language" >>= \ modules -> runMonadClean $
--         let mn = Language.Haskell.Exts.Syntax.ModuleName in
--         modifyModuVerse (const modules) >>
--         splitModule (mn "Language.Haskell.Modules.Common") >>
--         mergeModules (map mn ["Language.Haskell.Modules.Common.WithCurrentDirectory",
--                               "Language.Haskell.Modules.Common.ModulePathBase"])
--                      (mn "Language.Haskell.Modules.Common"))
--   
module Language.Haskell.Modules -- | Clean up the imports of a source file. cleanImports :: MonadClean m => FilePath -> m ModuleResult -- | Do splitModuleBy with a custom symbol to module mapping splitModule :: MonadClean m => (DeclName -> ModuleName) -> ModuleName -> m () -- | Do splitModuleBy with the default symbol to module mapping (was -- splitModule) splitModuleDecls :: MonadClean m => ModuleName -> m () -- | Merge the declarations from several modules into a single new one, -- updating the imports of the modules in the moduVerse to reflect the -- change. It *is* permissable to use one of the input modules as the -- output module. Note that circular imports can be created by this -- operation. mergeModules :: MonadClean m => [ModuleName] -> ModuleName -> m (Set ModuleResult) -- | Convenience function for building the moduVerse, searches for modules -- in a directory hierarchy. FIXME: This should be in MonadClean and use -- the value of sourceDirs to remove prefixes from the module paths. And -- then it should look at the module text to see what the module name -- really is. findModules :: FilePath -> IO (Set ModuleName) -- | Find the paths of all the files below the directory top. findPaths :: FilePath -> IO (Set FilePath)