Last active
June 9, 2021 18:02
-
-
Save guibou/711b3123b5cdb3c1745f12c85af97129 to your computer and use it in GitHub Desktop.
Check that module name inside an haskell file (e.g. "module Foo.Bar where") match the filename (e.g. `prefix/Foo/Bar.hs`)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import subprocess | |
| import re | |
| import string | |
| # Locate all haskell files in the repo | |
| all_hs = subprocess.run(["git", "ls-files", "**/*.hs"], capture_output=True, encoding='ascii').stdout.split() | |
| for path in all_hs: | |
| module_name = [] | |
| # Extract module name | |
| # foo/bar/Baz/Biz/Buz.hs leads to module name | |
| # Baz.Biz.Buz | |
| # -3 removes the trailing ".hs" | |
| # then split on the '/' and works from backward | |
| for path_component in path[:-3].split('/')[::-1]: | |
| # The name must start by a capitalized letter | |
| if not path_component[0] in string.ascii_uppercase: | |
| # rebuild module name | |
| module_name = '.'.join(module_name[::-1]) | |
| break | |
| else: | |
| module_name.append(path_component) | |
| # Now we open the module and check if the inner module name match the | |
| # filename. | |
| with open(path) as f: | |
| content = f.read() | |
| # match the module name | |
| m = re.search(r"^module +([^ (\n]+)", content, re.M) | |
| if m: | |
| true_module_name = m.group(1) | |
| # Ignore "Main", they are standalone module, never imported | |
| if true_module_name != "Main": | |
| # Print message in case of discrepancy | |
| if module_name != true_module_name: | |
| print(path) | |
| # Justify the string so module name is aligned with the filename | |
| print(f"{true_module_name}".rjust(len(path) - 3)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| {-# LANGUAGE OverloadedStrings #-} | |
| {-# LANGUAGE ViewPatterns #-} | |
| import System.Process | |
| import qualified Data.Text as Text | |
| import qualified Data.Text.IO as Text | |
| import Data.Foldable (for_) | |
| import Data.Char (isLower) | |
| import Control.Monad (when) | |
| import Control.Applicative ((<|>)) | |
| getTrueModuleName' (Text.split (\t -> t `elem` (" \n(" :: String)) -> l) = | |
| case l of | |
| "module":(dropWhile Text.null -> module_name:_) -> Just module_name | |
| _ -> Nothing | |
| getTrueModuleName xs | |
| = foldr ((<|>) . getTrueModuleName') Nothing xs | |
| main = do | |
| all_hs <- Text.lines . Text.pack <$> readProcess "git" ["ls-files", "**/*.hs"] "" | |
| for_ all_hs $ \path -> do | |
| let | |
| module_name = Text.intercalate "." $ dropWhile (isLower . Text.head) $ Text.splitOn "/" (Text.dropEnd 3 path) | |
| content <- Text.readFile (Text.unpack path) | |
| case getTrueModuleName (Text.lines content) of | |
| Nothing -> pure () | |
| Just true_module_name -> | |
| when (true_module_name /= "Main" && module_name /= true_module_name) $ do | |
| Text.putStrLn path | |
| Text.putStrLn (Text.justifyRight (Text.length path - 3) ' ' true_module_name) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment