GHC API を使ってある型コンストラクタのデータコンストラクタを得る

neco-ghc などで,Haskell 用の補完候補をより正確に計算するときに活用できないかなーと思った.
GHC 7.0.3 で試した.


あるモジュールがエクスポートしている名前は modInfoExports でとれる.
そのモジュールで定義されていれば modInfoTyThings で TyThing をとれるけど,例えば aeson の Data.Aeson のように他のモジュールからインポートしたものをエクスポートしている場合,名前は modInfoExports には含まれているけど TyThing が modInfoTyThings に含まれていない,ということが発生する.
なので,modInfoExports で得た名前に関して lookupName で改めて問い合わせて TyThing を得ている.


コンパイルするときは

% ghc -package ghc Browse.hs

と明示的に -package ghc をつけてやる必要がある.

import GHC
import GHC.Paths (libdir)
import MonadUtils (liftIO)
import Name
import Data.Maybe (catMaybes)
import Control.Applicative ((<$>))
import System.Environment (getArgs)

main :: IO ()
main = do
  args <- getArgs
  runGhc (Just libdir) $ do
    getSessionDynFlags >>= setSessionDynFlags
    mapM_ browse args

browse :: GhcMonad m => String -> m ()
browse m = do
  xs <- maybe [] modInfoExports <$> lookupModuleInfo >>= collapseData
  liftIO $ mapM_ putStrLn xs
  where
    lookupModuleInfo = findModule (mkModuleName m) Nothing >>= getModuleInfo
    collapseData = fmap (map expand . catMaybes) . mapM lookupName . filter (not . isDataConName)
      where
        expand (ATyCon ty) = unwords $ (getOccString ty :) $ map getOccString $ tyConDataCons ty
        expand t = getOccString t


ghc-mod browse との違い

% ghc-mod browse -o Data.Aeson
(.:)
(.:?)
(.=)
Array
Array
Bool
DotNetTime
DotNetTime
Error
FromJSON
Null
Number
Object
Object
Result
String
Success
ToJSON
Value
encode
fromDotNetTime
fromJSON
json
object
parseJSON
toJSON
% ./Browse Data.Aeson
encode
json
.:
.:?
.=
Array
DotNetTime DotNetTime
fromDotNetTime
FromJSON
parseJSON
Object
Result Error Success
ToJSON
toJSON
Value Object Array String Number Bool Null
fromJSON
object