/src/FindSymbol.hs
https://github.com/hdevtools/hdevtools · Haskell · 96 lines · 79 code · 16 blank · 1 comment · 3 complexity · 9b0c69640efedb3f7178dd5ea6655fec MD5 · raw file
- {-# Language ScopedTypeVariables, CPP #-}
- module FindSymbol
- ( findSymbol
- ) where
- #if __GLASGOW_HASKELL__ >= 802
- import GhcMonad (liftIO)
- #elif __GLASGOW_HASKELL__ >= 710
- import GHC.PackageDb (exposedName)
- import GhcMonad (liftIO)
- #else
- import Control.Applicative ((<$>))
- import qualified UniqFM
- #endif
- import Control.Exception
- import Control.Monad (filterM)
- import Data.List (find, nub)
- import Data.Maybe (catMaybes, isJust)
- import Exception (ghandle)
- import qualified GHC
- import qualified Packages as PKG
- import qualified Name
- import GhcTypes (getModSummaries)
- type SymbolName = String
- type ModuleName = String
- findSymbol :: SymbolName -> GHC.Ghc [ModuleName]
- findSymbol symbol = do
- fileMods <- findSymbolInFile symbol
- pkgsMods <- findSymbolInPackages symbol
- return . nub . map (GHC.moduleNameString . GHC.moduleName) $ fileMods ++ pkgsMods
- findSymbolInFile :: SymbolName -> GHC.Ghc [GHC.Module]
- findSymbolInFile symbol =
- filterM (containsSymbol symbol) =<< map GHC.ms_mod <$> getModSummaries
- findSymbolInPackages :: SymbolName -> GHC.Ghc [GHC.Module]
- findSymbolInPackages symbol =
- filterM (containsSymbol symbol) =<< allExposedModules
- where
- allExposedModules :: GHC.Ghc [GHC.Module]
- allExposedModules = do
- modNames <- exposedModuleNames
- catMaybes <$> mapM findModule modNames
- where
- exposedModuleNames :: GHC.Ghc [GHC.ModuleName]
- #if __GLASGOW_HASKELL__ >= 802
- exposedModuleNames = do
- dynFlags <- GHC.getSessionDynFlags
- pkgConfigs <- liftIO $ fmap concat
- . (fmap . fmap) snd . PKG.readPackageConfigs $ dynFlags
- return $ map fst (concatMap exposedModules pkgConfigs)
- #elif __GLASGOW_HASKELL__ >= 800
- exposedModuleNames = do
- dynFlags <- GHC.getSessionDynFlags
- pkgConfigs <- liftIO $ fmap concat
- . (fmap . fmap) snd . PKG.readPackageConfigs $ dynFlags
- return $ map exposedName (concatMap exposedModules pkgConfigs)
- #elif __GLASGOW_HASKELL__ >= 710
- exposedModuleNames = do
- dynFlags <- GHC.getSessionDynFlags
- pkgConfigs <- liftIO $ PKG.readPackageConfigs dynFlags
- return $ map exposedName (concatMap exposedModules pkgConfigs)
- #else
- exposedModuleNames =
- concatMap exposedModules
- . UniqFM.eltsUFM
- . PKG.pkgIdMap
- . GHC.pkgState
- <$> GHC.getSessionDynFlags
- #endif
- exposedModules pkg = if PKG.exposed pkg then PKG.exposedModules pkg else []
- findModule :: GHC.ModuleName -> GHC.Ghc (Maybe GHC.Module)
- findModule moduleName =
- ghandle (\(_ :: SomeException) -> return Nothing)
- (Just <$> GHC.findModule moduleName Nothing)
- containsSymbol :: SymbolName -> GHC.Module -> GHC.Ghc Bool
- containsSymbol symbol module_ =
- isJust . find (== symbol) <$> allExportedSymbols
- where
- allExportedSymbols =
- ghandle (\(_ :: SomeException) -> return [])
- (do info <- GHC.getModuleInfo module_
- return $ maybe [] (map Name.getOccString . GHC.modInfoExports) info)