{-+ Chase source files through imports, assuming module names and file names agree. -} module PfeChase where import Prelude hiding (putStrLn) import List(nub,partition,(\\)) import Monad(unless,filterM) import HsName(moduleName,ModuleName(..),isHierarchical) --import Pfe0Cmds import PFE0 import PfeParse import AbstractIO import PathUtils import DirUtils(expand) import PrettyPrint import MUtils pfeChaseCmds = [("chase",(fileArgs findMissing,"look for imported modules in given files/directories"))] findMissing args = do checkProject fg <- getCurrentModuleGraph dirs <- filterM doesDirectoryExist args allfiles <- map normf # expand args let (ignored,newfiles) = partition (null.path2moduleName) (allfiles \\ map fst fg) missing = nub [i|(_,(_,is))<-fg,i<-is] \\ map (fst.snd) fg new = [(path,moduleName path (path2moduleName path))|path<-newfiles] unless (null ignored) $ pput $ "Ignoring:"<+>fsep ignored files <- map fst # chase dirs fg missing new --when (length files/=length (nub files)) $ pput "duplicates in file list" saveSrcList (nub files) projectStatus -- will report modules that are still missing where chase dirs fg missing new = case missing of [] -> return fg m:ms -> do (fms,new') <- find m case fms of [] -> chase dirs fg ms new' --didn't find m, skip & report later ((f,_):fms) -> do unless (null fms) $ pput $ "Using the first file for"<+>m<>":"<+> fsep (f:map fst fms) use f ms new' where find m = if isHierarchical m then findHierarchical m else return $ partition ((==m).snd) new findHierarchical m = do let paths = [dir++[pathSep]++path|dir<-dirs,path<-moduleName2Paths m] fs <- filterM doesFileExist paths return ([(f,m)|f<-fs],new) use f ms new' = do n@(m,is) <- moduleNode # preparseSourceFile f let fg' = ((f,n):fg) missing' = filter (isNew fg') is++ms pput $ "Adding"<+>m<+>"from"<+>f chase dirs fg' missing' new' isNew fg m = null . filter ((m==).fst.snd) $ fg -- from a path like foo/bar/M.hs, extract M path2moduleName = reverse . takeWhile (/=pathSep) . drop 1 . dropWhile (/='.') . reverse moduleName2Paths m = case m of MainModule path -> [path] PlainModule s -> [base++".lhs",base++".hs"] where base = map sep s sep '.' = pathSep sep c = c