1 module HpcDraft (draft_plugin) where
10 import qualified HpcSet as Set
11 import qualified HpcMap as Map
15 ------------------------------------------------------------------------------
16 draft_options :: FlagOptSeq
24 draft_plugin :: Plugin
25 draft_plugin = Plugin { name = "draft"
26 , usage = "[OPTION] .. <TIX_FILE>"
27 , options = draft_options
28 , summary = "Generate draft overlay that provides 100% coverage"
29 , implementation = draft_main
30 , init_flags = default_flags
31 , final_flags = default_final_flags
34 ------------------------------------------------------------------------------
36 draft_main :: Flags -> [String] -> IO ()
37 draft_main _ [] = error "draft_main: unhandled case: []"
38 draft_main hpcflags (progName:mods) = do
39 let hpcflags1 = hpcflags
40 { includeMods = Set.fromList mods
42 includeMods hpcflags }
43 let prog = getTixFileName $ progName
46 Just (Tix tickCounts) -> do
48 [ makeDraft hpcflags1 tixModule
49 | tixModule@(TixModule m _ _ _) <- tickCounts
50 , allowModule hpcflags1 m
52 case outputFile hpcflags1 of
53 "-" -> putStrLn (unlines outs)
54 out -> writeFile out (unlines outs)
55 Nothing -> hpcError draft_plugin $ "unable to find tix file for:" ++ progName
58 makeDraft :: Flags -> TixModule -> IO String
59 makeDraft hpcflags tix = do
60 let modu = tixModuleName tix
61 tixs = tixModuleTixs tix
63 (Mix filepath _ _ _ entries) <- readMixWithFlags hpcflags (Right tix)
65 let forest = createMixEntryDom
66 [ (srcspan,(box,v > 0))
67 | ((srcspan,box),v) <- zip entries tixs
70 -- let show' (span,stuff) = show (span,stuff,grabHpcPos hsMap span)
71 -- putStrLn $ drawForest $ map (fmap show) $ forest
73 let non_ticked = findNotTickedFromList forest
75 hs <- readFileFromPath (hpcError draft_plugin) filepath (srcDirs hpcflags)
77 let hsMap :: Map.Map Int String
78 hsMap = Map.fromList (zip [1..] $ lines hs)
80 let quoteString = show
82 let firstLine pos = case fromHpcPos pos of
86 let showPleaseTick :: Int -> PleaseTick -> String
87 showPleaseTick d (TickFun str pos) =
88 spaces d ++ "tick function \"" ++ last str ++ "\" "
89 ++ "on line " ++ show (firstLine pos) ++ ";"
90 showPleaseTick d (TickExp pos) =
93 then "at position " ++ show pos ++ ";"
94 else quoteString txt ++ " " ++ "on line " ++ show (firstLine pos) ++ ";"
97 txt = grabHpcPos hsMap pos
99 showPleaseTick d (TickInside [str] _ pleases) =
100 spaces d ++ "inside \"" ++ str ++ "\" {\n" ++
101 showPleaseTicks (d + 2) pleases ++
104 showPleaseTick _ (TickInside _ _ _)
105 = error "showPleaseTick: Unhandled case TickInside"
107 showPleaseTicks d pleases = unlines (map (showPleaseTick d) pleases)
109 spaces d = take d (repeat ' ')
111 return $ "module " ++ show (fixPackageSuffix modu) ++ " {\n" ++
112 showPleaseTicks 2 non_ticked ++ "}"
114 fixPackageSuffix :: String -> String
115 fixPackageSuffix modu = case span (/= '/') modu of
116 (before,'/':after) -> before ++ ":" ++ after
120 = TickFun [String] HpcPos
122 | TickInside [String] HpcPos [PleaseTick]
125 mkTickInside :: [String] -> HpcPos -> [PleaseTick]
126 -> [PleaseTick] -> [PleaseTick]
127 mkTickInside _ _ [] = id
128 mkTickInside nm pos inside = (TickInside nm pos inside :)
130 findNotTickedFromTree :: MixEntryDom [(BoxLabel,Bool)] -> [PleaseTick]
131 findNotTickedFromTree (Node (pos,(ExpBox {},False):_) _) = [TickExp pos]
132 findNotTickedFromTree (Node (pos,(TopLevelBox nm,False):_) _)
134 findNotTickedFromTree (Node (pos,(LocalBox nm,False):_) _)
136 findNotTickedFromTree (Node (pos,(TopLevelBox nm,True):_) children)
137 = mkTickInside nm pos (findNotTickedFromList children) []
138 findNotTickedFromTree (Node (pos,_:others) children) =
139 findNotTickedFromTree (Node (pos,others) children)
140 findNotTickedFromTree (Node (_, []) children) = findNotTickedFromList children
142 findNotTickedFromList :: [MixEntryDom [(BoxLabel,Bool)]] -> [PleaseTick]
143 findNotTickedFromList = concatMap findNotTickedFromTree