{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ViewPatterns #-} module Ide.Plugin.CallHierarchy.Query ( incomingCalls , outgoingCalls , getSymbolPosition ) where import qualified Data.Text as T import Database.SQLite.Simple import Development.IDE.GHC.Compat import HieDb (HieDb (getConn), Symbol (..), toNsChar) import Ide.Plugin.CallHierarchy.Types incomingCalls :: HieDb -> Symbol -> IO [Vertex] incomingCalls (getConn -> conn) symbol = do let (o, m, u) = parseSymbol symbol query conn (Query $ T.pack $ concat [ "SELECT mods.mod, decls.occ, mods.hs_src, decls.sl, decls.sc, " , "decls.el, decls.ec, refs.sl, refs.sc, refs.el, refs.ec " , "FROM refs " , "JOIN decls ON decls.hieFile = refs.hieFile " , "JOIN mods ON mods.hieFile = decls.hieFile " , "where " , "(refs.occ = ? AND refs.mod = ? AND refs.unit = ?) " , "AND " , "(decls.occ != ? OR mods.mod != ? OR mods.unit != ?) " , "AND " , "((refs.sl = decls.sl AND refs.sc > decls.sc) OR (refs.sl > decls.sl)) " , "AND " ,"((refs.el = decls.el AND refs.ec <= decls.ec) OR (refs.el < decls.el))" ] ) (o, m, u, o, m, u) outgoingCalls :: HieDb -> Symbol -> IO [Vertex] outgoingCalls (getConn -> conn) symbol = do let (o, m, u) = parseSymbol symbol query conn (Query $ T.pack $ concat [ "SELECT rm.mod, defs.occ, rm.hs_src, defs.sl, defs.sc, defs.el, defs.ec, " , "refs.sl, refs.sc, refs.el, refs.ec " , "from refs " , "JOIN defs ON defs.occ = refs.occ " , "JOIN decls rd ON rd.hieFile = defs.hieFile AND rd.occ = defs.occ " , "JOIN mods rm ON rm.mod = refs.mod AND rm.unit = refs.unit AND rm.hieFile = defs.hieFile " , "JOIN decls ON decls.hieFile = refs.hieFile " , "JOIN mods ON mods.hieFile = decls.hieFile " , "where " , "(decls.occ = ? AND mods.mod = ? AND mods.unit = ?) " , "AND " , "(defs.occ != ? OR rm.mod != ? OR rm.unit != ?) " , "AND " , "((refs.sl = decls.sl AND refs.sc > decls.sc) OR (refs.sl > decls.sl)) " , "AND " , "((refs.el = decls.el AND refs.ec <= decls.ec) OR (refs.el < decls.el))" ] ) (o, m, u, o, m, u) getSymbolPosition :: HieDb -> Vertex -> IO [SymbolPosition] getSymbolPosition (getConn -> conn) Vertex{..} = do query conn (Query $ T.pack $ concat [ "SELECT refs.sl, refs.sc from refs where " , "(occ = ?) " , "AND " , "((refs.sl = ? AND refs.sc > ?) OR (refs.sl > ?)) " , "AND " , "((refs.el = ? AND refs.ec <= ?) OR (refs.el < ?))" ] ) (occ, sl, sc, sl, el, ec, el) parseSymbol :: Symbol -> (String, String, String) parseSymbol Symbol{..} = let o = toNsChar (occNameSpace symName) : occNameString symName m = moduleNameString $ moduleName symModule u = unitString $ moduleUnit symModule in (o, m, u)