Finds (badly) unused imports based on Agda HTML output
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

67 lines
2.1 KiB

2 years ago
  1. #!/usr/bin/env stack
  2. {- stack --resolver lts-18.14 script
  3. --package text
  4. --package unordered-containers
  5. --package tagsoup
  6. --package filepath
  7. --package hashable
  8. -}
  9. {-# LANGUAGE OverloadedStrings #-}
  10. module Main where
  11. import qualified Data.Text.Lazy.IO as Text
  12. import qualified Data.HashSet as HashSet
  13. import qualified Data.Text.Lazy as Text
  14. import Data.HashSet (HashSet)
  15. import Data.Text.Lazy (Text)
  16. import Data.Hashable
  17. import System.Environment
  18. import Text.HTML.TagSoup
  19. import Data.Function
  20. import Data.Int
  21. import Data.Foldable
  22. import System.FilePath
  23. import Control.Monad
  24. main :: IO ()
  25. main = do
  26. args <- getArgs
  27. for_ args $ \mod -> do
  28. contents <- Text.readFile mod
  29. let unused = findUnusedImports mempty (parseTags contents)
  30. unless (null unused) $ do
  31. putStrLn $ "Potentially unused imports for: \x1b[1m" <> dropExtension (takeFileName mod) <> "\x1b[0m"
  32. Text.putStrLn $ " * " <> Text.intercalate ", " (toList unused)
  33. findUnusedImports :: HashSet Text -> [Tag Text] -> HashSet Text
  34. findUnusedImports unused (TagOpen "pre" attrs:ts)
  35. | Just "Agda" <- lookup "class" attrs
  36. = goAgda 0 unused ts
  37. findUnusedImports unused (_:ts) = findUnusedImports unused ts
  38. findUnusedImports unused [] = unused
  39. goAgda :: Int64 -> HashSet Text -> [Tag Text] -> HashSet Text
  40. goAgda line unused (TagOpen "a" attrs:TagText text:TagClose "a":ts)
  41. | Just "Module" <- lookup "class" attrs
  42. , Just href <- lookup "href" attrs
  43. , ".html" `Text.isSuffixOf` href
  44. = let
  45. imp = Text.take (Text.length href - 5) href
  46. in goAgda line (HashSet.insert imp unused) ts
  47. | Just href <- lookup "href" attrs
  48. , let (mod, ident) = Text.break (== '#') href
  49. , not (Text.null mod), not (Text.null (Text.drop 1 ident))
  50. = let
  51. imp = Text.take (Text.length mod - 5) mod
  52. in goAgda line (HashSet.delete imp unused) ts
  53. goAgda line unused (TagClose "pre":ts) = findUnusedImports unused ts
  54. goAgda line unused (TagText text:ts)
  55. | newlines <- Text.filter (== '\n') text = goAgda (line + Text.length newlines) unused ts
  56. goAgda line unused (t:ts) = goAgda line unused ts
  57. goAgda line unused [] = error "Unclosed <pre class=Agda> tag"