2014-04-24 08:02:50 +00:00
|
|
|
{-# LANGUAGE CPP, BangPatterns #-}
|
|
|
|
|
|
|
|
module Language.Haskell.GhcMod.Find where
|
|
|
|
|
|
|
|
import Data.Function (on)
|
|
|
|
import Data.List (groupBy, sort)
|
|
|
|
import Data.Maybe (fromMaybe)
|
|
|
|
import GHC (Ghc)
|
|
|
|
import qualified GHC as G
|
|
|
|
import Language.Haskell.GhcMod.Browse (browseAll)
|
2014-04-24 12:08:45 +00:00
|
|
|
import Language.Haskell.GhcMod.GHCApi
|
|
|
|
import Language.Haskell.GhcMod.Types
|
2014-04-24 08:02:50 +00:00
|
|
|
|
|
|
|
#ifndef MIN_VERSION_containers
|
|
|
|
#define MIN_VERSION_containers(x,y,z) 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if MIN_VERSION_containers(0,5,0)
|
|
|
|
import Control.DeepSeq (force)
|
|
|
|
import Data.Map.Strict (Map)
|
|
|
|
import qualified Data.Map.Strict as M
|
|
|
|
#else
|
|
|
|
import Data.Map (Map)
|
|
|
|
import qualified Data.Map as M
|
|
|
|
#endif
|
2014-04-24 12:08:45 +00:00
|
|
|
import Control.Applicative ((<$>))
|
2014-04-24 08:02:50 +00:00
|
|
|
|
|
|
|
-- | Type of key for `SymMdlDb`.
|
|
|
|
type Symbol = String
|
|
|
|
-- | Database from 'Symbol' to modules.
|
|
|
|
newtype SymMdlDb = SymMdlDb (Map Symbol [ModuleString])
|
|
|
|
|
2014-04-24 13:11:06 +00:00
|
|
|
-- | Find modules to which the symbol belong.
|
2014-04-24 12:08:45 +00:00
|
|
|
findSymbol :: Options -> Cradle -> Symbol -> IO String
|
|
|
|
findSymbol opt cradle sym = withGHC' $ do
|
2014-04-26 08:54:15 +00:00
|
|
|
initializeFlagsWithCradle opt cradle []
|
2014-04-24 12:08:45 +00:00
|
|
|
lookupSym opt sym <$> getSymMdlDb
|
|
|
|
|
2014-04-24 08:02:50 +00:00
|
|
|
-- | Creating 'SymMdlDb'.
|
|
|
|
getSymMdlDb :: Ghc SymMdlDb
|
|
|
|
getSymMdlDb = do
|
|
|
|
sm <- G.getSessionDynFlags >>= browseAll
|
|
|
|
#if MIN_VERSION_containers(0,5,0)
|
|
|
|
let !sms = force $ map tieup $ groupBy ((==) `on` fst) $ sort sm
|
|
|
|
!m = force $ M.fromList sms
|
|
|
|
#else
|
|
|
|
let !sms = map tieup $ groupBy ((==) `on` fst) $ sort sm
|
|
|
|
!m = M.fromList sms
|
|
|
|
#endif
|
|
|
|
return (SymMdlDb m)
|
|
|
|
where
|
|
|
|
tieup x = (head (map fst x), map snd x)
|
|
|
|
|
|
|
|
-- | Looking up 'SymMdlDb' with 'Symbol' to find modules.
|
|
|
|
lookupSym :: Options -> Symbol -> SymMdlDb -> String
|
|
|
|
lookupSym opt sym (SymMdlDb db) = convert opt $ fromMaybe [] (M.lookup sym db)
|