    module Hint.Annotations (
        getModuleAnnotations,
        getValAnnotations
    ) where

    import Data.Data
    import GHC.Serialized

    import Hint.Base
    import qualified Hint.GHC as GHC

    #if MIN_VERSION_ghc(9,2,0)
    import GHC (ms_mod)
    import GHC.Driver.Env (hsc_mod_graph)
    #elif MIN_VERSION_ghc(9,0,0)
    import GHC.Driver.Types (hsc_mod_graph, ms_mod)
    #else
    import HscTypes (hsc_mod_graph, ms_mod)
    #endif

    #if MIN_VERSION_ghc(9,0,0)
    import GHC.Types.Annotations
    import GHC.Utils.Monad (concatMapM)
    #else
    import Annotations
    import MonadUtils (concatMapM)
    #endif

    -- Get the annotations associated with a particular module.
    getModuleAnnotations :: (Data a, MonadInterpreter m) => a -> String -> m [a]
    getModuleAnnotations :: forall a (m :: * -> *).
    (Data a, MonadInterpreter m) =>
    a -> String -> m [a]
    getModuleAnnotations a
    _ String
    x = do
        mods <- ModuleGraph -> [ModSummary]
    GHC.mgModSummaries (ModuleGraph -> [ModSummary])
    -> (HscEnv -> ModuleGraph) -> HscEnv -> [ModSummary]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . HscEnv -> ModuleGraph
    hsc_mod_graph (HscEnv -> [ModSummary]) -> m HscEnv -> m [ModSummary]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> RunGhc m HscEnv
    forall a. RunGhc m a
    forall (m :: * -> *) a. MonadInterpreter m => RunGhc m a
    runGhc GhcT n HscEnv
    forall {n :: * -> *}. (MonadIO n, MonadMask n) => GhcT n HscEnv
    forall (m :: * -> *). GhcMonad m => m HscEnv
    GHC.getSession
        let x' = (ModSummary -> Bool) -> [ModSummary] -> [ModSummary]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (String -> String -> Bool
    forall a. Eq a => a -> a -> Bool
    (==) String
    x (String -> Bool) -> (ModSummary -> String) -> ModSummary -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ModuleName -> String
    GHC.moduleNameString (ModuleName -> String)
    -> (ModSummary -> ModuleName) -> ModSummary -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GenModule Unit -> ModuleName
    forall unit. GenModule unit -> ModuleName
    GHC.moduleName (GenModule Unit -> ModuleName)
    -> (ModSummary -> GenModule Unit) -> ModSummary -> ModuleName
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ModSummary -> GenModule Unit
    ms_mod) [ModSummary]
    mods
        concatMapM (anns . ModuleTarget . ms_mod) x'

    -- Get the annotations associated with a particular function.
    getValAnnotations :: (Data a, MonadInterpreter m) => a -> String -> m [a]
    getValAnnotations :: forall a (m :: * -> *).
    (Data a, MonadInterpreter m) =>
    a -> String -> m [a]
    getValAnnotations a
    _ String
    s = do
        names <- RunGhc m (NonEmpty Name)
    forall a. RunGhc m a
    forall (m :: * -> *) a. MonadInterpreter m => RunGhc m a
    runGhc RunGhc m (NonEmpty Name) -> RunGhc m (NonEmpty Name)
    forall a b. (a -> b) -> a -> b
    $ String -> GhcT n (NonEmpty Name)
    forall (m :: * -> *). GhcMonad m => String -> m (NonEmpty Name)
    GHC.parseName String
    s
        concatMapM (anns . NamedTarget) names

    anns :: (MonadInterpreter m, Data a) => AnnTarget GHC.Name -> m [a]
    anns :: forall (m :: * -> *) a.
    (MonadInterpreter m, Data a) =>
    AnnTarget Name -> m [a]
    anns AnnTarget Name
    target = RunGhc m [a]
    forall a. RunGhc m a
    forall (m :: * -> *) a. MonadInterpreter m => RunGhc m a
    runGhc RunGhc m [a] -> RunGhc m [a]
    forall a b. (a -> b) -> a -> b
    $ ([Word8] -> a) -> AnnTarget Name -> GhcT n [a]
    forall (m :: * -> *) a.
    (GhcMonad m, Typeable a) =>
    ([Word8] -> a) -> AnnTarget Name -> m [a]
    GHC.findGlobalAnns [Word8] -> a
    forall a. Data a => [Word8] -> a
    deserializeWithData AnnTarget Name
    target