    {-# LANGUAGE LambdaCase          #-}
    {-# LANGUAGE RankNTypes          #-}
    {-# LANGUAGE OverloadedStrings   #-}
    {-# LANGUAGE ScopedTypeVariables #-}
    {-# LANGUAGE ViewPatterns        #-}

    {-# OPTIONS -fno-warn-name-shadowing #-}

    -- | Get information on modules, expressions, and identifiers
    module Clash.GHCi.UI.Info
        ( ModInfo(..)
        , SpanInfo(..)
        , spanInfoFromRealSrcSpan
        , collectInfo
        , findLoc
        , findNameUses
        , findType
        , getModInfo
        ) where

    import           Control.Exception
    import           Control.Monad
    import           Control.Monad.Catch as MC
    import           Control.Monad.Trans.Class
    import           Control.Monad.Trans.Except
    import           Control.Monad.Trans.Maybe
    import           Data.Data
    import           Data.Function
    import           Data.List (find, sortBy)
    import           Data.Map.Strict   (Map)
    import qualified Data.Map.Strict   as M
    import           Data.Maybe
    import           Data.Time
    import           Prelude           hiding (mod,(<>))
    import           System.Directory

    import           GHC.Hs.Syn.Type
    import           GHC.Driver.Session (HasDynFlags(..))
    import           GHC.Data.FastString
    import           GHC
    import           GHC.Driver.Monad
    import           GHC.Driver.Env
    import           GHC.Driver.Ppr
    import           GHC.Types.Name
    import           GHC.Types.Name.Reader
    import           GHC.Types.Name.Set
    import           GHC.Utils.Outputable
    import           GHC.Types.SrcLoc
    import           GHC.Types.Var
    import qualified GHC.Data.Strict as Strict

    -- | Info about a module. This information is generated every time a
    -- module is loaded.
    data ModInfo = ModInfo
        { ModInfo -> ModSummary
    modinfoSummary    :: !ModSummary
          -- ^ Summary generated by GHC. Can be used to access more
          -- information about the module.
        , ModInfo -> [SpanInfo]
    modinfoSpans      :: [SpanInfo]
          -- ^ Generated set of information about all spans in the
          -- module that correspond to some kind of identifier for
          -- which there will be type info and/or location info.
        , ModInfo -> Maybe IfGlobalRdrEnv
    modinfoRdrEnv     :: !(Strict.Maybe IfGlobalRdrEnv)
          -- ^ What's in scope in the module.
        , ModInfo -> UTCTime
    modinfoLastUpdate :: !UTCTime
          -- ^ The timestamp of the file used to generate this record.
        }

    -- | Type of some span of source code. Most of these fields are
    -- unboxed but Haddock doesn't show that.
    data SpanInfo = SpanInfo
        { SpanInfo -> RealSrcSpan
    spaninfoSrcSpan   :: {-# UNPACK #-} !RealSrcSpan
          -- ^ The span we associate information with
        , SpanInfo -> Maybe Type
    spaninfoType      :: !(Maybe Type)
          -- ^ The 'Type' associated with the span
        , SpanInfo -> Maybe Id
    spaninfoVar       :: !(Maybe Id)
          -- ^ The actual 'Var' associated with the span, if
          -- any. This can be useful for accessing a variety of
          -- information about the identifier such as module,
          -- locality, definition location, etc.
        }

    instance Outputable SpanInfo where
      ppr :: SpanInfo -> SDoc
    ppr (SpanInfo RealSrcSpan
    s Maybe Type
    t Maybe Id
    i) = RealSrcSpan -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr RealSrcSpan
    s SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Maybe Type -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Maybe Type
    t SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Maybe Id -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Maybe Id
    i

    -- | Test whether second span is contained in (or equal to) first span.
    -- This is basically 'containsSpan' for 'SpanInfo'
    containsSpanInfo :: SpanInfo -> SpanInfo -> Bool
    containsSpanInfo :: SpanInfo -> SpanInfo -> Bool
    containsSpanInfo = RealSrcSpan -> RealSrcSpan -> Bool
    containsSpan (RealSrcSpan -> RealSrcSpan -> Bool)
    -> (SpanInfo -> RealSrcSpan) -> SpanInfo -> SpanInfo -> Bool
    forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
    `on` SpanInfo -> RealSrcSpan
    spaninfoSrcSpan

    -- | Filter all 'SpanInfo' which are contained in 'SpanInfo'
    spaninfosWithin :: [SpanInfo] -> SpanInfo -> [SpanInfo]
    spaninfosWithin :: [SpanInfo] -> SpanInfo -> [SpanInfo]
    spaninfosWithin [SpanInfo]
    spans' SpanInfo
    si = (SpanInfo -> Bool) -> [SpanInfo] -> [SpanInfo]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (SpanInfo
    si SpanInfo -> SpanInfo -> Bool
    `containsSpanInfo`) [SpanInfo]
    spans'

    -- | Construct a 'SpanInfo' from a 'RealSrcSpan' and optionally a
    -- 'Type' and an 'Id' (for 'spaninfoType' and 'spaninfoVar'
    -- respectively)
    spanInfoFromRealSrcSpan :: RealSrcSpan -> Maybe Type -> Maybe Id -> SpanInfo
    spanInfoFromRealSrcSpan :: RealSrcSpan -> Maybe Type -> Maybe Id -> SpanInfo
    spanInfoFromRealSrcSpan RealSrcSpan
    spn Maybe Type
    mty Maybe Id
    mvar =
        RealSrcSpan -> Maybe Type -> Maybe Id -> SpanInfo
    SpanInfo RealSrcSpan
    spn Maybe Type
    mty Maybe Id
    mvar

    -- | Convenience wrapper around 'spanInfoFromRealSrcSpan' which needs
    -- only a 'RealSrcSpan'
    spanInfoFromRealSrcSpan' :: RealSrcSpan -> SpanInfo
    spanInfoFromRealSrcSpan' :: RealSrcSpan -> SpanInfo
    spanInfoFromRealSrcSpan' RealSrcSpan
    s = RealSrcSpan -> Maybe Type -> Maybe Id -> SpanInfo
    spanInfoFromRealSrcSpan RealSrcSpan
    s Maybe Type
    forall a. Maybe a
    Nothing Maybe Id
    forall a. Maybe a
    Nothing

    -- | Convenience wrapper around 'srcSpanFile' which results in a 'FilePath'
    srcSpanFilePath :: RealSrcSpan -> FilePath
    srcSpanFilePath :: RealSrcSpan -> FilePath
    srcSpanFilePath = FastString -> FilePath
    unpackFS (FastString -> FilePath)
    -> (RealSrcSpan -> FastString) -> RealSrcSpan -> FilePath
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . RealSrcSpan -> FastString
    srcSpanFile

    -- | Try to find the location of the given identifier at the given
    -- position in the module.
    findLoc :: GhcMonad m
            => Map ModuleName ModInfo
            -> RealSrcSpan
            -> String
            -> ExceptT SDoc m (ModInfo,Name,SrcSpan)
    findLoc :: forall (m :: Type -> Type).
    GhcMonad m =>
    Map ModuleName ModInfo
    -> RealSrcSpan
    -> FilePath
    -> ExceptT SDoc m (ModInfo, Name, SrcSpan)
    findLoc Map ModuleName ModInfo
    infos RealSrcSpan
    span0 FilePath
    string = do
        name  <- SDoc -> MaybeT m ModuleName -> ExceptT SDoc m ModuleName
    forall (m :: Type -> Type) e a.
    Functor m =>
    e -> MaybeT m a -> ExceptT e m a
    maybeToExceptT SDoc
    "Couldn't guess that module name. Does it exist?" (MaybeT m ModuleName -> ExceptT SDoc m ModuleName)
    -> MaybeT m ModuleName -> ExceptT SDoc m ModuleName
    forall a b. (a -> b) -> a -> b
    $
                 Map ModuleName ModInfo -> FilePath -> MaybeT m ModuleName
    forall (m :: Type -> Type).
    GhcMonad m =>
    Map ModuleName ModInfo -> FilePath -> MaybeT m ModuleName
    guessModule Map ModuleName ModInfo
    infos (RealSrcSpan -> FilePath
    srcSpanFilePath RealSrcSpan
    span0)

        info  <- maybeToExceptT "No module info for current file! Try loading it?" $
                 MaybeT $ pure $ M.lookup name infos

        name' <- findName infos span0 info string

        case getSrcSpan name' of
            UnhelpfulSpan{} -> do
                SDoc -> ExceptT SDoc m (ModInfo, Name, SrcSpan)
    forall (m :: Type -> Type) e a. Monad m => e -> ExceptT e m a
    throwE (SDoc
    "Found a name, but no location information." SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+>
                        SDoc
    "The module is:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+>
                        SDoc -> (GenModule Unit -> SDoc) -> Maybe (GenModule Unit) -> SDoc
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe SDoc
    "<unknown>" (ModuleName -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModuleName -> SDoc)
    -> (GenModule Unit -> ModuleName) -> GenModule Unit -> SDoc
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GenModule Unit -> ModuleName
    forall unit. GenModule unit -> ModuleName
    moduleName)
                              (Name -> Maybe (GenModule Unit)
    nameModule_maybe Name
    name'))

            SrcSpan
    span' -> (ModInfo, Name, SrcSpan) -> ExceptT SDoc m (ModInfo, Name, SrcSpan)
    forall a. a -> ExceptT SDoc m a
    forall (m :: Type -> Type) a. Monad m => a -> m a
    return (ModInfo
    info,Name
    name',SrcSpan
    span')

    -- | Find any uses of the given identifier in the codebase.
    findNameUses :: (GhcMonad m)
                 => Map ModuleName ModInfo
                 -> RealSrcSpan
                 -> String
                 -> ExceptT SDoc m [SrcSpan]
    findNameUses :: forall (m :: Type -> Type).
    GhcMonad m =>
    Map ModuleName ModInfo
    -> RealSrcSpan -> FilePath -> ExceptT SDoc m [SrcSpan]
    findNameUses Map ModuleName ModInfo
    infos RealSrcSpan
    span0 FilePath
    string =
        (ModInfo, Name, SrcSpan) -> [SrcSpan]
    locToSpans ((ModInfo, Name, SrcSpan) -> [SrcSpan])
    -> ExceptT SDoc m (ModInfo, Name, SrcSpan)
    -> ExceptT SDoc m [SrcSpan]
    forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
    <$> Map ModuleName ModInfo
    -> RealSrcSpan
    -> FilePath
    -> ExceptT SDoc m (ModInfo, Name, SrcSpan)
    forall (m :: Type -> Type).
    GhcMonad m =>
    Map ModuleName ModInfo
    -> RealSrcSpan
    -> FilePath
    -> ExceptT SDoc m (ModInfo, Name, SrcSpan)
    findLoc Map ModuleName ModInfo
    infos RealSrcSpan
    span0 FilePath
    string
      where
        locToSpans :: (ModInfo, Name, SrcSpan) -> [SrcSpan]
    locToSpans (ModInfo
    modinfo,Name
    name',SrcSpan
    span') =
            [SrcSpan] -> [SrcSpan]
    stripSurrounding (SrcSpan
    span' SrcSpan -> [SrcSpan] -> [SrcSpan]
    forall a. a -> [a] -> [a]
    : (SpanInfo -> SrcSpan) -> [SpanInfo] -> [SrcSpan]
    forall a b. (a -> b) -> [a] -> [b]
    map SpanInfo -> SrcSpan
    toSrcSpan [SpanInfo]
    spans)
          where
            toSrcSpan :: SpanInfo -> SrcSpan
    toSrcSpan SpanInfo
    s = RealSrcSpan -> Maybe BufSpan -> SrcSpan
    RealSrcSpan (SpanInfo -> RealSrcSpan
    spaninfoSrcSpan SpanInfo
    s) Maybe BufSpan
    forall a. Maybe a
    Strict.Nothing
            spans :: [SpanInfo]
    spans = (SpanInfo -> Bool) -> [SpanInfo] -> [SpanInfo]
    forall a. (a -> Bool) -> [a] -> [a]
    filter ((Maybe Name -> Maybe Name -> Bool
    forall a. Eq a => a -> a -> Bool
    == Name -> Maybe Name
    forall a. a -> Maybe a
    Just Name
    name') (Maybe Name -> Bool)
    -> (SpanInfo -> Maybe Name) -> SpanInfo -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Id -> Name) -> Maybe Id -> Maybe Name
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
    fmap Id -> Name
    forall a. NamedThing a => a -> Name
    getName (Maybe Id -> Maybe Name)
    -> (SpanInfo -> Maybe Id) -> SpanInfo -> Maybe Name
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . SpanInfo -> Maybe Id
    spaninfoVar)
                           (ModInfo -> [SpanInfo]
    modinfoSpans ModInfo
    modinfo)

    -- | Filter out redundant spans which surround/contain other spans.
    stripSurrounding :: [SrcSpan] -> [SrcSpan]
    stripSurrounding :: [SrcSpan] -> [SrcSpan]
    stripSurrounding [SrcSpan]
    xs = (SrcSpan -> Bool) -> [SrcSpan] -> [SrcSpan]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (Bool -> Bool
    not (Bool -> Bool) -> (SrcSpan -> Bool) -> SrcSpan -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . SrcSpan -> Bool
    isRedundant) [SrcSpan]
    xs
      where
        isRedundant :: SrcSpan -> Bool
    isRedundant SrcSpan
    x = (SrcSpan -> Bool) -> [SrcSpan] -> Bool
    forall (t :: Type -> Type) a.
    Foldable t =>
    (a -> Bool) -> t a -> Bool
    any (SrcSpan
    x SrcSpan -> SrcSpan -> Bool
    `strictlyContains`) [SrcSpan]
    xs

        (RealSrcSpan RealSrcSpan
    s1 Maybe BufSpan
    _) strictlyContains :: SrcSpan -> SrcSpan -> Bool
    `strictlyContains` (RealSrcSpan RealSrcSpan
    s2 Maybe BufSpan
    _)
             = RealSrcSpan
    s1 RealSrcSpan -> RealSrcSpan -> Bool
    forall a. Eq a => a -> a -> Bool
    /= RealSrcSpan
    s2 Bool -> Bool -> Bool
    && RealSrcSpan
    s1 RealSrcSpan -> RealSrcSpan -> Bool
    `containsSpan` RealSrcSpan
    s2
        SrcSpan
    _                `strictlyContains` SrcSpan
    _ = Bool
    False

    -- | Try to resolve the name located at the given position, or
    -- otherwise resolve based on the current module's scope.
    findName :: GhcMonad m
             => Map ModuleName ModInfo
             -> RealSrcSpan
             -> ModInfo
             -> String
             -> ExceptT SDoc m Name
    findName :: forall (m :: Type -> Type).
    GhcMonad m =>
    Map ModuleName ModInfo
    -> RealSrcSpan -> ModInfo -> FilePath -> ExceptT SDoc m Name
    findName Map ModuleName ModInfo
    infos RealSrcSpan
    span0 ModInfo
    mi FilePath
    string =
        case [SpanInfo] -> SpanInfo -> Maybe Id
    resolveName (ModInfo -> [SpanInfo]
    modinfoSpans ModInfo
    mi) (RealSrcSpan -> SpanInfo
    spanInfoFromRealSrcSpan' RealSrcSpan
    span0) of
          Maybe Id
    Nothing -> ExceptT SDoc m Name
    tryExternalModuleResolution
          Just Id
    name ->
            case Id -> SrcSpan
    forall a. NamedThing a => a -> SrcSpan
    getSrcSpan Id
    name of
              UnhelpfulSpan {} -> ExceptT SDoc m Name
    tryExternalModuleResolution
              RealSrcSpan   {} -> Name -> ExceptT SDoc m Name
    forall a. a -> ExceptT SDoc m a
    forall (m :: Type -> Type) a. Monad m => a -> m a
    return (Id -> Name
    forall a. NamedThing a => a -> Name
    getName Id
    name)
      where
        rdrs :: [Name]
    rdrs = ModInfo -> [Name]
    modInfo_rdrs ModInfo
    mi
        tryExternalModuleResolution :: ExceptT SDoc m Name
    tryExternalModuleResolution =
          case (Name -> Bool) -> [Name] -> Maybe Name
    forall (t :: Type -> Type) a.
    Foldable t =>
    (a -> Bool) -> t a -> Maybe a
    find (FastString -> Name -> Bool
    matchName (FastString -> Name -> Bool) -> FastString -> Name -> Bool
    forall a b. (a -> b) -> a -> b
    $ FilePath -> FastString
    mkFastString FilePath
    string) [Name]
    rdrs of
            Maybe Name
    Nothing -> SDoc -> ExceptT SDoc m Name
    forall (m :: Type -> Type) e a. Monad m => e -> ExceptT e m a
    throwE SDoc
    "Couldn't resolve to any modules."
            Just Name
    imported -> Map ModuleName ModInfo -> Name -> ExceptT SDoc m Name
    forall (m :: Type -> Type).
    GhcMonad m =>
    Map ModuleName ModInfo -> Name -> ExceptT SDoc m Name
    resolveNameFromModule Map ModuleName ModInfo
    infos Name
    imported

        matchName :: FastString -> Name -> Bool
        matchName :: FastString -> Name -> Bool
    matchName FastString
    str Name
    name =
          FastString
    str FastString -> FastString -> Bool
    forall a. Eq a => a -> a -> Bool
    ==
          OccName -> FastString
    occNameFS (Name -> OccName
    forall a. NamedThing a => a -> OccName
    getOccName Name
    name)

    -- | Try to resolve the name from another (loaded) module's exports.
    resolveNameFromModule :: GhcMonad m
                          => Map ModuleName ModInfo
                          -> Name
                          -> ExceptT SDoc m Name
    resolveNameFromModule :: forall (m :: Type -> Type).
    GhcMonad m =>
    Map ModuleName ModInfo -> Name -> ExceptT SDoc m Name
    resolveNameFromModule Map ModuleName ModInfo
    infos Name
    name = do
         modL <- ExceptT SDoc m (GenModule Unit)
    -> (GenModule Unit -> ExceptT SDoc m (GenModule Unit))
    -> Maybe (GenModule Unit)
    -> ExceptT SDoc m (GenModule Unit)
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe (SDoc -> ExceptT SDoc m (GenModule Unit)
    forall (m :: Type -> Type) e a. Monad m => e -> ExceptT e m a
    throwE (SDoc -> ExceptT SDoc m (GenModule Unit))
    -> SDoc -> ExceptT SDoc m (GenModule Unit)
    forall a b. (a -> b) -> a -> b
    $ SDoc
    "No module for" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Name -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Name
    name) GenModule Unit -> ExceptT SDoc m (GenModule Unit)
    forall a. a -> ExceptT SDoc m a
    forall (m :: Type -> Type) a. Monad m => a -> m a
    return (Maybe (GenModule Unit) -> ExceptT SDoc m (GenModule Unit))
    -> Maybe (GenModule Unit) -> ExceptT SDoc m (GenModule Unit)
    forall a b. (a -> b) -> a -> b
    $
                 Name -> Maybe (GenModule Unit)
    nameModule_maybe Name
    name

         info <- maybe (throwE (ppr (moduleUnit modL) <> ":" <>
                                ppr modL)) return $
                 M.lookup (moduleName modL) infos

         let all_names = ModInfo -> [Name]
    modInfo_rdrs ModInfo
    info

         maybe (throwE "No matching export in any local modules.") return $
             find (matchName name) all_names
      where
        matchName :: Name -> Name -> Bool
        matchName :: Name -> Name -> Bool
    matchName Name
    x Name
    y = OccName -> FastString
    occNameFS (Name -> OccName
    forall a. NamedThing a => a -> OccName
    getOccName Name
    x) FastString -> FastString -> Bool
    forall a. Eq a => a -> a -> Bool
    ==
                        OccName -> FastString
    occNameFS (Name -> OccName
    forall a. NamedThing a => a -> OccName
    getOccName Name
    y)

    -- | Try to resolve the type display from the given span.
    resolveName :: [SpanInfo] -> SpanInfo -> Maybe Var
    resolveName :: [SpanInfo] -> SpanInfo -> Maybe Id
    resolveName [SpanInfo]
    spans' SpanInfo
    si = [Id] -> Maybe Id
    forall a. [a] -> Maybe a
    listToMaybe ([Id] -> Maybe Id) -> [Id] -> Maybe Id
    forall a b. (a -> b) -> a -> b
    $ (SpanInfo -> Maybe Id) -> [SpanInfo] -> [Id]
    forall a b. (a -> Maybe b) -> [a] -> [b]
    mapMaybe SpanInfo -> Maybe Id
    spaninfoVar ([SpanInfo] -> [Id]) -> [SpanInfo] -> [Id]
    forall a b. (a -> b) -> a -> b
    $
                            [SpanInfo] -> [SpanInfo]
    forall a. [a] -> [a]
    reverse [SpanInfo]
    spans' [SpanInfo] -> SpanInfo -> [SpanInfo]
    `spaninfosWithin` SpanInfo
    si

    -- | Try to find the type of the given span.
    findType :: GhcMonad m
             => Map ModuleName ModInfo
             -> RealSrcSpan
             -> String
             -> ExceptT SDoc m (ModInfo, Type)
    findType :: forall (m :: Type -> Type).
    GhcMonad m =>
    Map ModuleName ModInfo
    -> RealSrcSpan -> FilePath -> ExceptT SDoc m (ModInfo, Type)
    findType Map ModuleName ModInfo
    infos RealSrcSpan
    span0 FilePath
    string = do
        name  <- SDoc -> MaybeT m ModuleName -> ExceptT SDoc m ModuleName
    forall (m :: Type -> Type) e a.
    Functor m =>
    e -> MaybeT m a -> ExceptT e m a
    maybeToExceptT SDoc
    "Couldn't guess that module name. Does it exist?" (MaybeT m ModuleName -> ExceptT SDoc m ModuleName)
    -> MaybeT m ModuleName -> ExceptT SDoc m ModuleName
    forall a b. (a -> b) -> a -> b
    $
                 Map ModuleName ModInfo -> FilePath -> MaybeT m ModuleName
    forall (m :: Type -> Type).
    GhcMonad m =>
    Map ModuleName ModInfo -> FilePath -> MaybeT m ModuleName
    guessModule Map ModuleName ModInfo
    infos (RealSrcSpan -> FilePath
    srcSpanFilePath RealSrcSpan
    span0)

        info  <- maybeToExceptT "No module info for current file! Try loading it?" $
                 MaybeT $ pure $ M.lookup name infos

        case resolveType (modinfoSpans info) (spanInfoFromRealSrcSpan' span0) of
            Maybe Type
    Nothing -> (,) ModInfo
    info (Type -> (ModInfo, Type))
    -> ExceptT SDoc m Type -> ExceptT SDoc m (ModInfo, Type)
    forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
    <$> m Type -> ExceptT SDoc m Type
    forall (m :: Type -> Type) a. Monad m => m a -> ExceptT SDoc m a
    forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (TcRnExprMode -> FilePath -> m Type
    forall (m :: Type -> Type).
    GhcMonad m =>
    TcRnExprMode -> FilePath -> m Type
    exprType TcRnExprMode
    TM_Inst FilePath
    string)
            Just Type
    ty -> (ModInfo, Type) -> ExceptT SDoc m (ModInfo, Type)
    forall a. a -> ExceptT SDoc m a
    forall (m :: Type -> Type) a. Monad m => a -> m a
    return (ModInfo
    info, Type
    ty)
      where
        -- | Try to resolve the type display from the given span.
        resolveType :: [SpanInfo] -> SpanInfo -> Maybe Type
        resolveType :: [SpanInfo] -> SpanInfo -> Maybe Type
    resolveType [SpanInfo]
    spans' SpanInfo
    si = [Type] -> Maybe Type
    forall a. [a] -> Maybe a
    listToMaybe ([Type] -> Maybe Type) -> [Type] -> Maybe Type
    forall a b. (a -> b) -> a -> b
    $ (SpanInfo -> Maybe Type) -> [SpanInfo] -> [Type]
    forall a b. (a -> Maybe b) -> [a] -> [b]
    mapMaybe SpanInfo -> Maybe Type
    spaninfoType ([SpanInfo] -> [Type]) -> [SpanInfo] -> [Type]
    forall a b. (a -> b) -> a -> b
    $
                                [SpanInfo] -> [SpanInfo]
    forall a. [a] -> [a]
    reverse [SpanInfo]
    spans' [SpanInfo] -> SpanInfo -> [SpanInfo]
    `spaninfosWithin` SpanInfo
    si

    -- | Guess a module name from a file path.
    guessModule :: GhcMonad m
                => Map ModuleName ModInfo -> FilePath -> MaybeT m ModuleName
    guessModule :: forall (m :: Type -> Type).
    GhcMonad m =>
    Map ModuleName ModInfo -> FilePath -> MaybeT m ModuleName
    guessModule Map ModuleName ModInfo
    infos FilePath
    fp = do
        target <- m Target -> MaybeT m Target
    forall (m :: Type -> Type) a. Monad m => m a -> MaybeT m a
    forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (m Target -> MaybeT m Target) -> m Target -> MaybeT m Target
    forall a b. (a -> b) -> a -> b
    $ FilePath -> Maybe UnitId -> Maybe Phase -> m Target
    forall (m :: Type -> Type).
    GhcMonad m =>
    FilePath -> Maybe UnitId -> Maybe Phase -> m Target
    guessTarget FilePath
    fp Maybe UnitId
    forall a. Maybe a
    Nothing Maybe Phase
    forall a. Maybe a
    Nothing
        case targetId target of
            TargetModule ModuleName
    mn  -> ModuleName -> MaybeT m ModuleName
    forall a. a -> MaybeT m a
    forall (m :: Type -> Type) a. Monad m => a -> m a
    return ModuleName
    mn
            TargetFile FilePath
    fp' Maybe Phase
    _ -> FilePath -> MaybeT m ModuleName
    forall (m :: Type -> Type).
    GhcMonad m =>
    FilePath -> MaybeT m ModuleName
    guessModule' FilePath
    fp'
      where
        guessModule' :: GhcMonad m => FilePath -> MaybeT m ModuleName
        guessModule' :: forall (m :: Type -> Type).
    GhcMonad m =>
    FilePath -> MaybeT m ModuleName
    guessModule' FilePath
    fp' = case FilePath -> Maybe ModuleName
    findModByFp FilePath
    fp' of
            Just ModuleName
    mn -> ModuleName -> MaybeT m ModuleName
    forall a. a -> MaybeT m a
    forall (m :: Type -> Type) a. Monad m => a -> m a
    return ModuleName
    mn
            Maybe ModuleName
    Nothing -> do
                fp'' <- IO FilePath -> MaybeT m FilePath
    forall a. IO a -> MaybeT m a
    forall (m :: Type -> Type) a. MonadIO m => IO a -> m a
    liftIO (FilePath -> IO FilePath
    makeRelativeToCurrentDirectory FilePath
    fp')

                target' <- lift $ guessTarget fp'' Nothing Nothing
                case targetId target' of
                    TargetModule ModuleName
    mn -> ModuleName -> MaybeT m ModuleName
    forall a. a -> MaybeT m a
    forall (m :: Type -> Type) a. Monad m => a -> m a
    return ModuleName
    mn
                    TargetId
    _               -> m (Maybe ModuleName) -> MaybeT m ModuleName
    forall (m :: Type -> Type) a. m (Maybe a) -> MaybeT m a
    MaybeT (m (Maybe ModuleName) -> MaybeT m ModuleName)
    -> (Maybe ModuleName -> m (Maybe ModuleName))
    -> Maybe ModuleName
    -> MaybeT m ModuleName
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Maybe ModuleName -> m (Maybe ModuleName)
    forall a. a -> m a
    forall (f :: Type -> Type) a. Applicative f => a -> f a
    pure (Maybe ModuleName -> MaybeT m ModuleName)
    -> Maybe ModuleName -> MaybeT m ModuleName
    forall a b. (a -> b) -> a -> b
    $ FilePath -> Maybe ModuleName
    findModByFp FilePath
    fp''

        findModByFp :: FilePath -> Maybe ModuleName
        findModByFp :: FilePath -> Maybe ModuleName
    findModByFp FilePath
    fp' = (ModuleName, ModInfo) -> ModuleName
    forall a b. (a, b) -> a
    fst ((ModuleName, ModInfo) -> ModuleName)
    -> Maybe (ModuleName, ModInfo) -> Maybe ModuleName
    forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
    <$> ((ModuleName, ModInfo) -> Bool)
    -> [(ModuleName, ModInfo)] -> Maybe (ModuleName, ModInfo)
    forall (t :: Type -> Type) a.
    Foldable t =>
    (a -> Bool) -> t a -> Maybe a
    find ((FilePath -> Maybe FilePath
    forall a. a -> Maybe a
    Just FilePath
    fp' Maybe FilePath -> Maybe FilePath -> Bool
    forall a. Eq a => a -> a -> Bool
    ==) (Maybe FilePath -> Bool)
    -> ((ModuleName, ModInfo) -> Maybe FilePath)
    -> (ModuleName, ModInfo)
    -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ModuleName, ModInfo) -> Maybe FilePath
    mifp) (Map ModuleName ModInfo -> [(ModuleName, ModInfo)]
    forall k a. Map k a -> [(k, a)]
    M.toList Map ModuleName ModInfo
    infos)
          where
            mifp :: (ModuleName, ModInfo) -> Maybe FilePath
            mifp :: (ModuleName, ModInfo) -> Maybe FilePath
    mifp = ModLocation -> Maybe FilePath
    ml_hs_file (ModLocation -> Maybe FilePath)
    -> ((ModuleName, ModInfo) -> ModLocation)
    -> (ModuleName, ModInfo)
    -> Maybe FilePath
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ModSummary -> ModLocation
    ms_location (ModSummary -> ModLocation)
    -> ((ModuleName, ModInfo) -> ModSummary)
    -> (ModuleName, ModInfo)
    -> ModLocation
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ModInfo -> ModSummary
    modinfoSummary (ModInfo -> ModSummary)
    -> ((ModuleName, ModInfo) -> ModInfo)
    -> (ModuleName, ModInfo)
    -> ModSummary
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ModuleName, ModInfo) -> ModInfo
    forall a b. (a, b) -> b
    snd

    -- | Collect type info data for the loaded modules.
    collectInfo :: (GhcMonad m) => Map ModuleName ModInfo -> [ModuleName]
                   -> m (Map ModuleName ModInfo)
    collectInfo :: forall (m :: Type -> Type).
    GhcMonad m =>
    Map ModuleName ModInfo
    -> [ModuleName] -> m (Map ModuleName ModInfo)
    collectInfo Map ModuleName ModInfo
    ms [ModuleName]
    loaded = do
        df <- m DynFlags
    forall (m :: Type -> Type). HasDynFlags m => m DynFlags
    getDynFlags
        unit_state <- hsc_units <$> getSession
        liftIO (filterM cacheInvalid loaded) >>= \case
            [] -> Map ModuleName ModInfo -> m (Map ModuleName ModInfo)
    forall a. a -> m a
    forall (m :: Type -> Type) a. Monad m => a -> m a
    return Map ModuleName ModInfo
    ms
            [ModuleName]
    invalidated -> do
                IO () -> m ()
    forall a. IO a -> m a
    forall (m :: Type -> Type) a. MonadIO m => IO a -> m a
    liftIO (FilePath -> IO ()
    putStrLn (FilePath
    "Collecting type info for " FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++
                                  Int -> FilePath
    forall a. Show a => a -> FilePath
    show ([ModuleName] -> Int
    forall a. [a] -> Int
    forall (t :: Type -> Type) a. Foldable t => t a -> Int
    length [ModuleName]
    invalidated) FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++
                                  FilePath
    " module(s) ... "))

                (Map ModuleName ModInfo
     -> ModuleName -> m (Map ModuleName ModInfo))
    -> Map ModuleName ModInfo
    -> [ModuleName]
    -> m (Map ModuleName ModInfo)
    forall (t :: Type -> Type) (m :: Type -> Type) b a.
    (Foldable t, Monad m) =>
    (b -> a -> m b) -> b -> t a -> m b
    foldM (DynFlags
    -> UnitState
    -> Map ModuleName ModInfo
    -> ModuleName
    -> m (Map ModuleName ModInfo)
    forall {m :: Type -> Type}.
    GhcMonad m =>
    DynFlags
    -> UnitState
    -> Map ModuleName ModInfo
    -> ModuleName
    -> m (Map ModuleName ModInfo)
    go DynFlags
    df UnitState
    unit_state) Map ModuleName ModInfo
    ms [ModuleName]
    invalidated
      where
        go :: DynFlags
    -> UnitState
    -> Map ModuleName ModInfo
    -> ModuleName
    -> m (Map ModuleName ModInfo)
    go DynFlags
    df UnitState
    unit_state Map ModuleName ModInfo
    m ModuleName
    name = do { info <- ModuleName -> m ModInfo
    forall (m :: Type -> Type). GhcMonad m => ModuleName -> m ModInfo
    getModInfo ModuleName
    name; return (M.insert name info m) }
                       m (Map ModuleName ModInfo)
    -> (SomeException -> m (Map ModuleName ModInfo))
    -> m (Map ModuleName ModInfo)
    forall e a. (HasCallStack, Exception e) => m a -> (e -> m a) -> m a
    forall (m :: Type -> Type) e a.
    (MonadCatch m, HasCallStack, Exception e) =>
    m a -> (e -> m a) -> m a
    `MC.catch`
                       (\(SomeException
    e :: SomeException) -> do
                             IO () -> m ()
    forall a. IO a -> m a
    forall (m :: Type -> Type) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ FilePath -> IO ()
    putStrLn
                                    (FilePath -> IO ()) -> FilePath -> IO ()
    forall a b. (a -> b) -> a -> b
    $ DynFlags -> UnitState -> NamePprCtx -> SDoc -> FilePath
    showSDocForUser DynFlags
    df UnitState
    unit_state NamePprCtx
    alwaysQualify
                                    (SDoc -> FilePath) -> SDoc -> FilePath
    forall a b. (a -> b) -> a -> b
    $ SDoc
    "Error while getting type info from" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+>
                                      ModuleName -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr ModuleName
    name SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> SDoc
    ":" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> FilePath -> SDoc
    forall doc. IsLine doc => FilePath -> doc
    text (SomeException -> FilePath
    forall a. Show a => a -> FilePath
    show SomeException
    e)
                             Map ModuleName ModInfo -> m (Map ModuleName ModInfo)
    forall a. a -> m a
    forall (m :: Type -> Type) a. Monad m => a -> m a
    return Map ModuleName ModInfo
    m)

        cacheInvalid :: ModuleName -> IO Bool
    cacheInvalid ModuleName
    name = case ModuleName -> Map ModuleName ModInfo -> Maybe ModInfo
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup ModuleName
    name Map ModuleName ModInfo
    ms of
            Maybe ModInfo
    Nothing -> Bool -> IO Bool
    forall a. a -> IO a
    forall (m :: Type -> Type) a. Monad m => a -> m a
    return Bool
    True
            Just ModInfo
    mi -> do
                let fp :: FilePath
    fp = ModSummary -> FilePath
    srcFilePath (ModInfo -> ModSummary
    modinfoSummary ModInfo
    mi)
                    last' :: UTCTime
    last' = ModInfo -> UTCTime
    modinfoLastUpdate ModInfo
    mi
                current <- FilePath -> IO UTCTime
    getModificationTime FilePath
    fp
                exists <- doesFileExist fp
                if exists
                    then return $ current /= last'
                    else return True

    -- | Get the source file path from a ModSummary.
    -- If the .hs file is missing, and the .o file exists,
    -- we return the .o file path.
    srcFilePath :: ModSummary -> FilePath
    srcFilePath :: ModSummary -> FilePath
    srcFilePath ModSummary
    modSum = FilePath -> Maybe FilePath -> FilePath
    forall a. a -> Maybe a -> a
    fromMaybe FilePath
    obj_fp Maybe FilePath
    src_fp
        where
            src_fp :: Maybe FilePath
    src_fp = ModLocation -> Maybe FilePath
    ml_hs_file ModLocation
    ms_loc
            obj_fp :: FilePath
    obj_fp = ModLocation -> FilePath
    ml_obj_file ModLocation
    ms_loc
            ms_loc :: ModLocation
    ms_loc = ModSummary -> ModLocation
    ms_location ModSummary
    modSum

    -- | Get info about the module: summary, types, etc.
    getModInfo :: (GhcMonad m) => ModuleName -> m ModInfo
    getModInfo :: forall (m :: Type -> Type). GhcMonad m => ModuleName -> m ModInfo
    getModInfo ModuleName
    name = do
        m <- ModuleName -> m ModSummary
    forall (m :: Type -> Type).
    GhcMonad m =>
    ModuleName -> m ModSummary
    getModSummary ModuleName
    name
        p <- parseModule m
        typechecked <- typecheckModule p
        let allTypes = TypecheckedModule -> [SpanInfo]
    processAllTypeCheckedModule TypecheckedModule
    typechecked
            module_info = TypecheckedModule -> ModuleInfo
    tm_checked_module_info TypecheckedModule
    typechecked
            !rdr_env = case ModuleInfo -> Maybe IfGlobalRdrEnv
    modInfoRdrEnv ModuleInfo
    module_info of
              Just IfGlobalRdrEnv
    rdrs -> IfGlobalRdrEnv -> Maybe IfGlobalRdrEnv
    forall a. a -> Maybe a
    Strict.Just IfGlobalRdrEnv
    rdrs
                -- NB: this has already been deeply forced; no need to do that again.
                -- See test case T15369 and Note [Forcing GREInfo] in GHC.Types.GREInfo.
              Maybe IfGlobalRdrEnv
    Nothing   -> Maybe IfGlobalRdrEnv
    forall a. Maybe a
    Strict.Nothing
        ts <- liftIO $ getModificationTime $ srcFilePath m
        return $
          ModInfo
            { modinfoSummary    = m
            , modinfoSpans      = allTypes
            , modinfoRdrEnv     = rdr_env
            , modinfoLastUpdate = ts
            }

    -- | Get the 'Name's from the 'GlobalRdrEnv' of the 'ModInfo', if any.
    modInfo_rdrs :: ModInfo -> [Name]
    modInfo_rdrs :: ModInfo -> [Name]
    modInfo_rdrs ModInfo
    mi =
      case ModInfo -> Maybe IfGlobalRdrEnv
    modinfoRdrEnv ModInfo
    mi of
        Maybe IfGlobalRdrEnv
    Strict.Nothing  -> []
        Strict.Just IfGlobalRdrEnv
    env -> (GlobalRdrEltX () -> Name) -> [GlobalRdrEltX ()] -> [Name]
    forall a b. (a -> b) -> [a] -> [b]
    map GlobalRdrEltX () -> Name
    forall info. GlobalRdrEltX info -> Name
    greName ([GlobalRdrEltX ()] -> [Name]) -> [GlobalRdrEltX ()] -> [Name]
    forall a b. (a -> b) -> a -> b
    $ IfGlobalRdrEnv -> [GlobalRdrEltX ()]
    forall info. GlobalRdrEnvX info -> [GlobalRdrEltX info]
    globalRdrEnvElts IfGlobalRdrEnv
    env

    -- | Get ALL source spans in the module.
    processAllTypeCheckedModule :: TypecheckedModule -> [SpanInfo]
    processAllTypeCheckedModule :: TypecheckedModule -> [SpanInfo]
    processAllTypeCheckedModule TypecheckedModule
    tcm
      = ((Maybe Id, SrcSpan, Type) -> Maybe SpanInfo)
    -> [(Maybe Id, SrcSpan, Type)] -> [SpanInfo]
    forall a b. (a -> Maybe b) -> [a] -> [b]
    mapMaybe (Maybe Id, SrcSpan, Type) -> Maybe SpanInfo
    toSpanInfo
      ([(Maybe Id, SrcSpan, Type)] -> [SpanInfo])
    -> [(Maybe Id, SrcSpan, Type)] -> [SpanInfo]
    forall a b. (a -> b) -> a -> b
    $ ((Maybe Id, SrcSpan, Type)
     -> (Maybe Id, SrcSpan, Type) -> Ordering)
    -> [(Maybe Id, SrcSpan, Type)] -> [(Maybe Id, SrcSpan, Type)]
    forall a. (a -> a -> Ordering) -> [a] -> [a]
    sortBy (Maybe Id, SrcSpan, Type) -> (Maybe Id, SrcSpan, Type) -> Ordering
    forall {a} {c} {a} {c}.
    (a, SrcSpan, c) -> (a, SrcSpan, c) -> Ordering
    cmpSpan
      ([(Maybe Id, SrcSpan, Type)] -> [(Maybe Id, SrcSpan, Type)])
    -> [(Maybe Id, SrcSpan, Type)] -> [(Maybe Id, SrcSpan, Type)]
    forall a b. (a -> b) -> a -> b
    $ [Maybe (Maybe Id, SrcSpan, Type)] -> [(Maybe Id, SrcSpan, Type)]
    forall a. [Maybe a] -> [a]
    catMaybes ([Maybe (Maybe Id, SrcSpan, Type)]
    bts [Maybe (Maybe Id, SrcSpan, Type)]
    -> [Maybe (Maybe Id, SrcSpan, Type)]
    -> [Maybe (Maybe Id, SrcSpan, Type)]
    forall a. [a] -> [a] -> [a]
    ++ [Maybe (Maybe Id, SrcSpan, Type)]
    ets [Maybe (Maybe Id, SrcSpan, Type)]
    -> [Maybe (Maybe Id, SrcSpan, Type)]
    -> [Maybe (Maybe Id, SrcSpan, Type)]
    forall a. [a] -> [a] -> [a]
    ++ [Maybe (Maybe Id, SrcSpan, Type)]
    pts)
      where
        bts :: [Maybe (Maybe Id, SrcSpan, Type)]
    bts = (LocatedA (HsBindLR GhcTc GhcTc)
     -> Maybe (Maybe Id, SrcSpan, Type))
    -> [LocatedA (HsBindLR GhcTc GhcTc)]
    -> [Maybe (Maybe Id, SrcSpan, Type)]
    forall a b. (a -> b) -> [a] -> [b]
    map LHsBind GhcTc -> Maybe (Maybe Id, SrcSpan, Type)
    LocatedA (HsBindLR GhcTc GhcTc) -> Maybe (Maybe Id, SrcSpan, Type)
    getTypeLHsBind ([LocatedA (HsBindLR GhcTc GhcTc)]
     -> [Maybe (Maybe Id, SrcSpan, Type)])
    -> [LocatedA (HsBindLR GhcTc GhcTc)]
    -> [Maybe (Maybe Id, SrcSpan, Type)]
    forall a b. (a -> b) -> a -> b
    $ TypecheckedSource -> [LocatedA (HsBindLR GhcTc GhcTc)]
    forall a. Typeable a => TypecheckedSource -> [LocatedA a]
    listifyAllSpans TypecheckedSource
    Bag (LocatedA (HsBindLR GhcTc GhcTc))
    tcs
        ets :: [Maybe (Maybe Id, SrcSpan, Type)]
    ets = (LocatedA (HsExpr GhcTc) -> Maybe (Maybe Id, SrcSpan, Type))
    -> [LocatedA (HsExpr GhcTc)] -> [Maybe (Maybe Id, SrcSpan, Type)]
    forall a b. (a -> b) -> [a] -> [b]
    map LHsExpr GhcTc -> Maybe (Maybe Id, SrcSpan, Type)
    LocatedA (HsExpr GhcTc) -> Maybe (Maybe Id, SrcSpan, Type)
    getTypeLHsExpr ([LocatedA (HsExpr GhcTc)] -> [Maybe (Maybe Id, SrcSpan, Type)])
    -> [LocatedA (HsExpr GhcTc)] -> [Maybe (Maybe Id, SrcSpan, Type)]
    forall a b. (a -> b) -> a -> b
    $ TypecheckedSource -> [LocatedA (HsExpr GhcTc)]
    forall a. Typeable a => TypecheckedSource -> [LocatedA a]
    listifyAllSpans TypecheckedSource
    Bag (LocatedA (HsBindLR GhcTc GhcTc))
    tcs
        pts :: [Maybe (Maybe Id, SrcSpan, Type)]
    pts = (LocatedA (Pat GhcTc) -> Maybe (Maybe Id, SrcSpan, Type))
    -> [LocatedA (Pat GhcTc)] -> [Maybe (Maybe Id, SrcSpan, Type)]
    forall a b. (a -> b) -> [a] -> [b]
    map LPat GhcTc -> Maybe (Maybe Id, SrcSpan, Type)
    LocatedA (Pat GhcTc) -> Maybe (Maybe Id, SrcSpan, Type)
    getTypeLPat    ([LocatedA (Pat GhcTc)] -> [Maybe (Maybe Id, SrcSpan, Type)])
    -> [LocatedA (Pat GhcTc)] -> [Maybe (Maybe Id, SrcSpan, Type)]
    forall a b. (a -> b) -> a -> b
    $ TypecheckedSource -> [LocatedA (Pat GhcTc)]
    forall a. Typeable a => TypecheckedSource -> [LocatedA a]
    listifyAllSpans TypecheckedSource
    Bag (LocatedA (HsBindLR GhcTc GhcTc))
    tcs

        tcs :: TypecheckedSource
    tcs = TypecheckedModule -> TypecheckedSource
    tm_typechecked_source TypecheckedModule
    tcm

        -- | Extract 'Id', 'SrcSpan', and 'Type' for 'LHsBind's
        getTypeLHsBind :: LHsBind GhcTc -> Maybe (Maybe Id,SrcSpan,Type)
        getTypeLHsBind :: LHsBind GhcTc -> Maybe (Maybe Id, SrcSpan, Type)
    getTypeLHsBind (L SrcSpanAnnA
    _spn FunBind{fun_id :: forall idL idR. HsBindLR idL idR -> LIdP idL
    fun_id = LIdP GhcTc
    pid,fun_matches :: forall idL idR. HsBindLR idL idR -> MatchGroup idR (LHsExpr idR)
    fun_matches = MG XMG GhcTc (LHsExpr GhcTc)
    _ XRec GhcTc [LMatch GhcTc (LHsExpr GhcTc)]
    _})
            = (Maybe Id, SrcSpan, Type) -> Maybe (Maybe Id, SrcSpan, Type)
    forall a. a -> Maybe a
    Just (Id -> Maybe Id
    forall a. a -> Maybe a
    Just (GenLocated SrcSpanAnnN Id -> Id
    forall l e. GenLocated l e -> e
    unLoc LIdP GhcTc
    GenLocated SrcSpanAnnN Id
    pid), GenLocated SrcSpanAnnN Id -> SrcSpan
    forall a e. HasLoc a => GenLocated a e -> SrcSpan
    getLocA LIdP GhcTc
    GenLocated SrcSpanAnnN Id
    pid,Id -> Type
    varType (GenLocated SrcSpanAnnN Id -> Id
    forall l e. GenLocated l e -> e
    unLoc LIdP GhcTc
    GenLocated SrcSpanAnnN Id
    pid))
        getTypeLHsBind LHsBind GhcTc
    _ = Maybe (Maybe Id, SrcSpan, Type)
    forall a. Maybe a
    Nothing

        -- | Extract 'Id', 'SrcSpan', and 'Type' for 'LHsExpr's
        getTypeLHsExpr :: LHsExpr GhcTc -> Maybe (Maybe Id,SrcSpan,Type)
        getTypeLHsExpr :: LHsExpr GhcTc -> Maybe (Maybe Id, SrcSpan, Type)
    getTypeLHsExpr LHsExpr GhcTc
    e = (Maybe Id, SrcSpan, Type) -> Maybe (Maybe Id, SrcSpan, Type)
    forall a. a -> Maybe a
    Just (Maybe Id
    mid, LocatedA (HsExpr GhcTc) -> SrcSpan
    forall a e. HasLoc a => GenLocated a e -> SrcSpan
    getLocA LHsExpr GhcTc
    LocatedA (HsExpr GhcTc)
    e, LHsExpr GhcTc -> Type
    lhsExprType LHsExpr GhcTc
    e)
          where
            mid :: Maybe Id
            mid :: Maybe Id
    mid | HsVar XVar GhcTc
    _ (L SrcSpanAnnN
    _ Id
    i) <- HsExpr GhcTc -> HsExpr GhcTc
    unwrapVar (LocatedA (HsExpr GhcTc) -> HsExpr GhcTc
    forall l e. GenLocated l e -> e
    unLoc LHsExpr GhcTc
    LocatedA (HsExpr GhcTc)
    e) = Id -> Maybe Id
    forall a. a -> Maybe a
    Just Id
    i
                | Bool
    otherwise                              = Maybe Id
    forall a. Maybe a
    Nothing

            unwrapVar :: HsExpr GhcTc -> HsExpr GhcTc
    unwrapVar (XExpr (WrapExpr (HsWrap HsWrapper
    _ HsExpr GhcTc
    var))) = HsExpr GhcTc
    var
            unwrapVar HsExpr GhcTc
    e'                                = HsExpr GhcTc
    e'

        -- | Extract 'Id', 'SrcSpan', and 'Type' for 'LPats's
        getTypeLPat :: LPat GhcTc -> Maybe (Maybe Id,SrcSpan,Type)
        getTypeLPat :: LPat GhcTc -> Maybe (Maybe Id, SrcSpan, Type)
    getTypeLPat (L SrcSpanAnnA
    spn Pat GhcTc
    pat) = (Maybe Id, SrcSpan, Type) -> Maybe (Maybe Id, SrcSpan, Type)
    forall a. a -> Maybe a
    Just (Pat GhcTc -> Maybe Id
    getMaybeId Pat GhcTc
    pat,SrcSpanAnnA -> SrcSpan
    forall a. HasLoc a => a -> SrcSpan
    locA SrcSpanAnnA
    spn,Pat GhcTc -> Type
    hsPatType Pat GhcTc
    pat)
          where
            getMaybeId :: Pat GhcTc -> Maybe Id
            getMaybeId :: Pat GhcTc -> Maybe Id
    getMaybeId (VarPat XVarPat GhcTc
    _ (L SrcSpanAnnN
    _ Id
    vid)) = Id -> Maybe Id
    forall a. a -> Maybe a
    Just Id
    vid
            getMaybeId Pat GhcTc
    _                        = Maybe Id
    forall a. Maybe a
    Nothing

        -- | Get ALL source spans in the source.
        listifyAllSpans :: Typeable a => TypecheckedSource -> [LocatedA a]
        listifyAllSpans :: forall a. Typeable a => TypecheckedSource -> [LocatedA a]
    listifyAllSpans = ([LocatedA a] -> [LocatedA a] -> [LocatedA a])
    -> [LocatedA a] -> GenericQ [LocatedA a] -> GenericQ [LocatedA a]
    forall r. (r -> r -> r) -> r -> GenericQ r -> GenericQ r
    everythingAllSpans [LocatedA a] -> [LocatedA a] -> [LocatedA a]
    forall a. [a] -> [a] -> [a]
    (++) [] ([] [LocatedA a] -> (LocatedA a -> [LocatedA a]) -> a -> [LocatedA a]
    forall a b r. (Typeable a, Typeable b) => r -> (b -> r) -> a -> r
    `mkQ` (\LocatedA a
    x -> [LocatedA a
    x | LocatedA a -> Bool
    forall {a} {e}. HasLoc a => GenLocated a e -> Bool
    p LocatedA a
    x]))
          where
            p :: GenLocated a e -> Bool
    p (L a
    spn e
    _) = SrcSpan -> Bool
    isGoodSrcSpan (a -> SrcSpan
    forall a. HasLoc a => a -> SrcSpan
    locA a
    spn)

        -- | Variant of @syb@'s @everything@ (which summarises all nodes
        -- in top-down, left-to-right order) with a stop-condition on 'NameSet's
        -- and 'OverLitTc'
        everythingAllSpans :: (r -> r -> r) -> r -> GenericQ r -> GenericQ r
        everythingAllSpans :: forall r. (r -> r -> r) -> r -> GenericQ r -> GenericQ r
    everythingAllSpans r -> r -> r
    k r
    z GenericQ r
    f a
    x
          | (Bool
    False Bool -> (NameSet -> Bool) -> a -> Bool
    forall a b r. (Typeable a, Typeable b) => r -> (b -> r) -> a -> r
    `mkQ` (Bool -> NameSet -> Bool
    forall a b. a -> b -> a
    const Bool
    True :: NameSet -> Bool)) a
    x = r
    z
          -- Exception for OverLitTc: we have SrcSpans in the ol_witness field,
          -- but it's there only for HIE file info (see Note [Source locations for implicit function calls]).
          -- T16804 fails without this.
          | (Bool
    False Bool -> (OverLitTc -> Bool) -> a -> Bool
    forall a b r. (Typeable a, Typeable b) => r -> (b -> r) -> a -> r
    `mkQ` (Bool -> OverLitTc -> Bool
    forall a b. a -> b -> a
    const Bool
    True :: OverLitTc -> Bool)) a
    x = r
    z
          | Bool
    otherwise = (r -> r -> r) -> r -> [r] -> r
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: Type -> Type) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl r -> r -> r
    k (a -> r
    GenericQ r
    f a
    x) (GenericQ r -> a -> [r]
    forall a u. Data a => (forall d. Data d => d -> u) -> a -> [u]
    forall u. (forall d. Data d => d -> u) -> a -> [u]
    gmapQ ((r -> r -> r) -> r -> GenericQ r -> GenericQ r
    forall r. (r -> r -> r) -> r -> GenericQ r -> GenericQ r
    everythingAllSpans r -> r -> r
    k r
    z a -> r
    GenericQ r
    f) a
    x)

        cmpSpan :: (a, SrcSpan, c) -> (a, SrcSpan, c) -> Ordering
    cmpSpan (a
    _,SrcSpan
    a,c
    _) (a
    _,SrcSpan
    b,c
    _)
          | SrcSpan
    a SrcSpan -> SrcSpan -> Bool
    `isSubspanOf` SrcSpan
    b = Ordering
    LT
          | SrcSpan
    b SrcSpan -> SrcSpan -> Bool
    `isSubspanOf` SrcSpan
    a = Ordering
    GT
          | Bool
    otherwise         = Ordering
    EQ

        -- | Pretty print the types into a 'SpanInfo'.
        toSpanInfo :: (Maybe Id,SrcSpan,Type) -> Maybe SpanInfo
        toSpanInfo :: (Maybe Id, SrcSpan, Type) -> Maybe SpanInfo
    toSpanInfo (Maybe Id
    n,RealSrcSpan RealSrcSpan
    spn Maybe BufSpan
    _,Type
    typ)
            = SpanInfo -> Maybe SpanInfo
    forall a. a -> Maybe a
    Just (SpanInfo -> Maybe SpanInfo) -> SpanInfo -> Maybe SpanInfo
    forall a b. (a -> b) -> a -> b
    $ RealSrcSpan -> Maybe Type -> Maybe Id -> SpanInfo
    spanInfoFromRealSrcSpan RealSrcSpan
    spn (Type -> Maybe Type
    forall a. a -> Maybe a
    Just Type
    typ) Maybe Id
    n
        toSpanInfo (Maybe Id, SrcSpan, Type)
    _ = Maybe SpanInfo
    forall a. Maybe a
    Nothing

    -- helper stolen from @syb@ package
    type GenericQ r = forall a. Data a => a -> r

    mkQ :: (Typeable a, Typeable b) => r -> (b -> r) -> a -> r
    (r
    r mkQ :: forall a b r. (Typeable a, Typeable b) => r -> (b -> r) -> a -> r
    `mkQ` b -> r
    br) a
    a = r -> (b -> r) -> Maybe b -> r
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe r
    r b -> r
    br (a -> Maybe b
    forall a b. (Typeable a, Typeable b) => a -> Maybe b
    cast a
    a)