packages feed

hdevtools 0.1.2.0 → 0.1.2.1

raw patch · 2 files changed

+101/−1 lines, 2 files

Files

hdevtools.cabal view
@@ -1,5 +1,5 @@ name:                hdevtools-version:             0.1.2.0+version:             0.1.2.1 synopsis:            Persistent GHC powered background server for FAST haskell development tools description:     'hdevtools' is a backend for text editor plugins, to allow for things such as@@ -52,6 +52,7 @@                        CommandArgs,                        CommandLoop,                        Daemonize,+                       FindSymbol,                        Info,                        Main,                        Server,
+ src/FindSymbol.hs view
@@ -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)