forked from bitc/hdevtools
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request bitc#13 from dan-t/findsymbol_command
Findsymbol command :+1:
- Loading branch information
Showing
6 changed files
with
150 additions
and
3 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
{-# Language ScopedTypeVariables, CPP #-} | ||
|
||
module FindSymbol | ||
( findSymbol | ||
) where | ||
|
||
#if __GLASGOW_HASKELL__ < 710 | ||
import Control.Applicative ((<$>)) | ||
import qualified UniqFM | ||
#else | ||
import GHC.PackageDb (exposedName) | ||
import GhcMonad (liftIO) | ||
#endif | ||
|
||
import Control.Monad (filterM) | ||
import Control.Exception | ||
import Data.List (find, nub) | ||
import Data.Maybe (catMaybes, isJust) | ||
import qualified GHC | ||
import qualified Packages as PKG | ||
import qualified Name | ||
import Exception (ghandle) | ||
|
||
type SymbolName = String | ||
type ModuleName = String | ||
|
||
findSymbol :: SymbolName -> [FilePath] -> GHC.Ghc [ModuleName] | ||
findSymbol symbol files = do | ||
-- for the findsymbol command GHC shouldn't output any warnings | ||
-- or errors to stdout for the loaded source files, we're only | ||
-- interested in the module graph of the loaded targets | ||
dynFlags <- GHC.getSessionDynFlags | ||
_ <- GHC.setSessionDynFlags dynFlags { GHC.log_action = \_ _ _ _ _ -> return () } | ||
|
||
fileMods <- concat <$> mapM (findSymbolInFile symbol) files | ||
|
||
-- reset the old log_action | ||
_ <- GHC.setSessionDynFlags dynFlags | ||
|
||
pkgsMods <- findSymbolInPackages symbol | ||
return . nub . map (GHC.moduleNameString . GHC.moduleName) $ fileMods ++ pkgsMods | ||
|
||
|
||
findSymbolInFile :: SymbolName -> FilePath -> GHC.Ghc [GHC.Module] | ||
findSymbolInFile symbol file = do | ||
loadFile | ||
filterM (containsSymbol symbol) =<< fileModules | ||
where | ||
loadFile = do | ||
let noPhase = Nothing | ||
target <- GHC.guessTarget file noPhase | ||
GHC.setTargets [target] | ||
let handler err = GHC.printException err >> return GHC.Failed | ||
_ <- GHC.handleSourceError handler (GHC.load GHC.LoadAllTargets) | ||
return () | ||
|
||
fileModules = map GHC.ms_mod <$> GHC.getModuleGraph | ||
|
||
|
||
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__ < 710 | ||
exposedModuleNames = | ||
concatMap exposedModules | ||
. UniqFM.eltsUFM | ||
. PKG.pkgIdMap | ||
. GHC.pkgState | ||
<$> GHC.getSessionDynFlags | ||
#else | ||
exposedModuleNames = do | ||
dynFlags <- GHC.getSessionDynFlags | ||
pkgConfigs <- liftIO $ PKG.readPackageConfigs dynFlags | ||
return $ map exposedName (concatMap exposedModules pkgConfigs) | ||
#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) |
This file contains 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
This file contains 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