1 module HpcDraft (draft_plugin) where
10 import qualified HpcSet as Set
11 import qualified HpcMap as Map
12 import System.Environment
16 ------------------------------------------------------------------------------
24 draft_plugin = Plugin { name = "draft"
25 , usage = "[OPTION] .. <TIX_FILE>"
26 , options = draft_options
27 , summary = "Generate draft overlay that provides 100% coverage"
28 , implementation = draft_main
29 , init_flags = default_flags
30 , final_flags = default_final_flags
33 ------------------------------------------------------------------------------
35 draft_main :: Flags -> [String] -> IO ()
36 draft_main hpcflags (progName:mods) = do
37 let hpcflags1 = hpcflags
38 { includeMods = Set.fromList mods
40 includeMods hpcflags }
41 let prog = getTixFileName $ progName
44 Just (Tix tickCounts) -> do
46 [ makeDraft hpcflags1 tixModule
47 | tixModule@(TixModule m _ _ _) <- tickCounts
48 , allowModule hpcflags1 m
50 case outputFile hpcflags1 of
51 "-" -> putStrLn (unlines outs)
52 out -> writeFile out (unlines outs)
53 Nothing -> hpcError draft_plugin $ "unable to find tix file for:" ++ progName
56 makeDraft :: Flags -> TixModule -> IO String
57 makeDraft hpcflags tix = do
58 let mod = tixModuleName tix
59 hash = tixModuleHash tix
60 tixs = tixModuleTixs tix
62 mix@(Mix filepath timestamp hash tabstop entries) <- readMixWithFlags hpcflags (Right tix)
64 let forest = createMixEntryDom
66 | ((span,box),v) <- zip entries tixs
69 -- let show' (span,stuff) = show (span,stuff,grabHpcPos hsMap span)
70 -- putStrLn $ drawForest $ map (fmap show) $ forest
72 let non_ticked = findNotTickedFromList forest
74 hs <- readFileFromPath (hpcError draft_plugin) filepath (srcDirs hpcflags)
76 let hsMap :: Map.Map Int String
77 hsMap = Map.fromList (zip [1..] $ lines hs)
79 let quoteString = show
81 let firstLine pos = case fromHpcPos pos of
85 let showPleaseTick :: Int -> PleaseTick -> String
86 showPleaseTick d (TickFun str pos) =
87 spaces d ++ "tick function \"" ++ last str ++ "\" "
88 ++ "on line " ++ show (firstLine pos) ++ ";"
89 showPleaseTick d (TickExp pos) =
92 then "at position " ++ show pos ++ ";"
93 else quoteString txt ++ " " ++ "on line " ++ show (firstLine pos) ++ ";"
96 txt = grabHpcPos hsMap pos
98 showPleaseTick d (TickInside [str] pos pleases) =
99 spaces d ++ "inside \"" ++ str ++ "\" {\n" ++
100 showPleaseTicks (d + 2) pleases ++
103 showPleaseTicks d pleases = unlines (map (showPleaseTick d) pleases)
105 spaces d = take d (repeat ' ')
107 return $ "module " ++ show (fixPackageSuffix mod) ++ " {\n" ++
108 showPleaseTicks 2 non_ticked ++ "}"
110 fixPackageSuffix :: String -> String
111 fixPackageSuffix mod = case span (/= '/') mod of
112 (before,'/':after) -> before ++ ":" ++ after
116 = TickFun [String] HpcPos
118 | TickInside [String] HpcPos [PleaseTick]
121 mkTickInside _ _ [] = id
122 mkTickInside nm pos inside = (TickInside nm pos inside :)
124 findNotTickedFromTree :: MixEntryDom [(BoxLabel,Bool)] -> [PleaseTick]
125 findNotTickedFromTree (Node (pos,(ExpBox {},False):_) _) = [TickExp pos]
126 findNotTickedFromTree (Node (pos,(TopLevelBox nm,False):_) _)
128 findNotTickedFromTree (Node (pos,(LocalBox nm,False):_) _)
130 findNotTickedFromTree (Node (pos,(TopLevelBox nm,True):others) children)
131 = mkTickInside nm pos (findNotTickedFromList children) []
132 findNotTickedFromTree (Node (pos,_:others) children) =
133 findNotTickedFromTree (Node (pos,others) children)
134 findNotTickedFromTree (Node (pos,[]) children) = findNotTickedFromList children
136 findNotTickedFromList :: [MixEntryDom [(BoxLabel,Bool)]] -> [PleaseTick]
137 findNotTickedFromList = concatMap findNotTickedFromTree