hlint-1.6: src/HSE/NameMatch.hs
module HSE.NameMatch(NameMatch, nameMatch) where
import Language.Haskell.Exts
import qualified Data.Map as Map
import Control.Arrow
import Data.List
import Data.Function
type NameMatch = QName -> QName -> Bool
-- Given a list of import statements, are the names equal
-- The import statements are only in scope on the second name
--
-- If the left is unqualified, then the right is dequalified and checked for match
-- If the left is qualified, then the right is wrapped and name resolved
nameMatch :: [ImportDecl] -> NameMatch
nameMatch imps = f
where
-- deal with "as" imports
resolve :: ModuleName -> ModuleName
resolve = \x -> Map.findWithDefault x x mp
where mp = Map.fromList [(as, importModule i) | i <- imps, Just as <- [importAs i]]
-- return True if x is potentially imported by B
importedFrom :: ModuleName -> Name -> Bool
importedFrom = \modu x -> any (g x) $ Map.findWithDefault [(True,[]) | modu == ModuleName "Prelude"] modu mp
where mp = Map.fromList $ map (fst . head &&& map snd) $
groupBy ((==) `on` fst) $ sortBy (compare `on` fst)
[(importModule i, importSpecNames i) | i <- imps, not $ importQualified i]
g x (hide,y) = hide /= (x `elem` y)
f (Qual xm x) (Qual ym y) = x == y && xm == resolve ym
f (Qual xm x) (UnQual y) = x == y && importedFrom xm x
f x y = x == y
importSpecNames :: ImportDecl -> (Bool, [Name])
importSpecNames x = case importSpecs x of
Nothing -> (True, [])
Just (b, x) -> (b, concatMap f x)
where
f (IVar x) = [x]
f (IAbs x) = [x]
f (IThingAll x) = [x]
f (IThingWith x ys) = x : map g ys
g (VarName x) = x
g (ConName x) = x