large-anon-0.2: src/Data/Record/Anon/Internal/Plugin/Source/GhcShim.hs
{-# LANGUAGE CPP #-}
-- | Thin shim around the GHC API
--
-- For the typechecker part we have the excellent @ghc-tcplugin-api@ library;
-- unfortunately, we have no such library for source plugins. We could reuse a
-- small part of @ghc-tcplugin-api@ here, but there isn't too much point: source
-- plugins need quite a different subset of the GHC API than typechecker plugins
-- do.
module Data.Record.Anon.Internal.Plugin.Source.GhcShim (
-- * Extensions
HasDefaultExt(..)
#if __GLASGOW_HASKELL__ < 902
-- * Exact-print annotations
, reLoc, reLocA
#endif
-- * Names
, lookupName
-- * NameCache
, NameCacheIO
, hscNameCacheIO
, takeUniqFromNameCacheIO
-- * Miscellaneous
, importDecl
, issueWarning
, mkLabel
#if __GLASGOW_HASKELL__ < 900
, mkHsApps
#endif
-- * Re-exports
#if __GLASGOW_HASKELL__ < 900
, module BasicTypes
, module FastString
, module GHC
, module HscMain
, module HscTypes
, module Name
, module OccName
, module Outputable
, module RdrName
, module UniqSupply
#else
, module GHC
, module GHC.Data.FastString
, module GHC.Driver.Main
, module GHC.Types.Name
, module GHC.Types.Name.Occurrence
, module GHC.Types.Name.Reader
, module GHC.Types.Unique.Supply
, module GHC.Utils.Outputable
#if __GLASGOW_HASKELL__ < 902
, module GHC.Driver.Types
#else
, module GHC.Driver.Errors
, module GHC.Driver.Env.Types
, module GHC.Types.SourceText
#endif
#endif
) where
import GHC.Stack
#if __GLASGOW_HASKELL__ < 900
import Data.IORef
import Data.List (foldl')
import GHC hiding (lookupName)
import Bag (Bag, listToBag)
import BasicTypes (Origin(Generated), PromotionFlag(NotPromoted), SourceText(NoSourceText))
import DynFlags (getDynFlags)
import ErrUtils (mkWarnMsg)
import FastString (FastString)
import Finder (findImportedModule)
import HscMain (getHscEnv)
import HscTypes
import IfaceEnv (lookupOrigIO)
import MonadUtils
import Name (mkInternalName)
import NameCache (NameCache(nsUniqs))
import OccName
import Outputable
import RdrName (RdrName(Exact), rdrNameOcc, mkRdrQual, mkRdrUnqual)
import UniqSupply (takeUniqFromSupply)
import Unique (Unique)
#else
import GHC hiding (lookupName)
import GHC.Data.Bag (listToBag, Bag)
import GHC.Data.FastString (FastString)
import GHC.Driver.Main (getHscEnv)
import GHC.Driver.Session (getDynFlags)
import GHC.Types.Name (mkInternalName)
import GHC.Types.Name.Occurrence
import GHC.Types.Name.Reader (RdrName(Exact), rdrNameOcc, mkRdrQual, mkRdrUnqual)
import GHC.Types.SrcLoc (LayoutInfo(NoLayoutInfo))
import GHC.Types.Unique (Unique)
import GHC.Types.Unique.Supply (takeUniqFromSupply)
import GHC.Utils.Monad
import GHC.Utils.Outputable
#if __GLASGOW_HASKELL__ >= 902
import GHC.Driver.Env.Types
import GHC.Driver.Errors
import GHC.Types.SourceText (SourceText(NoSourceText))
import GHC.Unit.Finder (findImportedModule, FindResult(Found))
import GHC.Unit.Types (IsBootInterface(NotBoot))
#else
import GHC.Driver.Finder (findImportedModule)
import GHC.Driver.Types
import GHC.Types.Basic (SourceText(NoSourceText))
#endif
#if __GLASGOW_HASKELL__ < 904
import Data.IORef
import GHC.Iface.Env (lookupOrigIO)
import GHC.Types.Name.Cache (NameCache(nsUniqs))
import GHC.Utils.Error (mkWarnMsg)
#else
import GHC.Driver.Config.Diagnostic (initDiagOpts)
import GHC.Driver.Errors.Types (GhcMessage(..))
import GHC.Iface.Env (lookupNameCache)
import GHC.Rename.Names (renamePkgQual)
import GHC.Types.Error (MsgEnvelope(..), mkMessages)
import GHC.Types.Name.Cache (NameCache, takeUniqFromNameCache)
import GHC.Types.PkgQual (RawPkgQual(NoRawPkgQual))
import GHC.Utils.Error (mkPlainError)
#endif
#endif
{-------------------------------------------------------------------------------
Names
-------------------------------------------------------------------------------}
lookupName ::
HasCallStack
=> ModuleName
-> Maybe FastString -- ^ Optional package name
-> String -> Hsc Name
lookupName modl pkg = lookupOccName modl pkg . mkVarOcc
lookupOccName ::
HasCallStack
=> ModuleName
-> Maybe FastString -- ^ Optional package name
-> OccName -> Hsc Name
lookupOccName modlName mPkgName name = do
env <- getHscEnv
#if __GLASGOW_HASKELL__ >= 904
let pkgq :: PkgQual
pkgq = renamePkgQual (hsc_unit_env env) modlName mPkgName
#else
let pkgq :: Maybe FastString
pkgq = mPkgName
#endif
mModl <- liftIO $ findImportedModule env modlName pkgq
case mModl of
Found _ modl -> liftIO $ lookupOrigIO env modl name
_otherwise -> error $ "lookupName: name not found"
#if __GLASGOW_HASKELL__ >= 904
lookupOrigIO :: HscEnv -> Module -> OccName -> IO Name
lookupOrigIO env modl occ = lookupNameCache (hsc_NC env) modl occ
#endif
{-------------------------------------------------------------------------------
NameCache
-------------------------------------------------------------------------------}
#if __GLASGOW_HASKELL__ < 904
type NameCacheIO = IORef NameCache
takeUniqFromNameCacheIO :: NameCacheIO -> IO Unique
takeUniqFromNameCacheIO = flip atomicModifyIORef aux
where
aux :: NameCache -> (NameCache, Unique)
aux nc = let (newUniq, us) = takeUniqFromSupply (nsUniqs nc)
in (nc { nsUniqs = us }, newUniq)
#else
type NameCacheIO = NameCache
takeUniqFromNameCacheIO :: NameCacheIO -> IO Unique
takeUniqFromNameCacheIO = takeUniqFromNameCache
#endif
hscNameCacheIO :: HscEnv -> NameCacheIO
hscNameCacheIO = hsc_NC
{-------------------------------------------------------------------------------
Miscellaneous
-------------------------------------------------------------------------------}
-- | Optionally @qualified@ import declaration
importDecl :: Bool -> ModuleName -> LImportDecl GhcPs
importDecl qualified name = reLocA $ noLoc $ ImportDecl {
ideclExt = defExt
, ideclSourceSrc = NoSourceText
, ideclName = reLocA $ noLoc name
#if __GLASGOW_HASKELL__ >= 904
, ideclPkgQual = NoRawPkgQual
#else
, ideclPkgQual = Nothing
#endif
, ideclSafe = False
, ideclImplicit = False
, ideclAs = Nothing
, ideclHiding = Nothing
#if __GLASGOW_HASKELL__ < 810
, ideclQualified = qualified
#else
, ideclQualified = if qualified then QualifiedPre else NotQualified
#endif
#if __GLASGOW_HASKELL__ < 900
, ideclSource = False
#else
, ideclSource = NotBoot
#endif
}
issueWarning :: SrcSpan -> SDoc -> Hsc ()
issueWarning l errMsg = do
dynFlags <- getDynFlags
#if __GLASGOW_HASKELL__ == 902
logger <- getLogger
liftIO $ printOrThrowWarnings logger dynFlags . bag $
mkWarnMsg l neverQualify errMsg
#elif __GLASGOW_HASKELL__ >= 904
logger <- getLogger
liftIO $ printOrThrowDiagnostics logger (initDiagOpts dynFlags) . mkMessages . bag $
MsgEnvelope {
errMsgSpan = l
, errMsgContext = neverQualify
, errMsgDiagnostic = GhcUnknownMessage $ mkPlainError [] errMsg
, errMsgSeverity = SevWarning
}
#else
liftIO $ printOrThrowWarnings dynFlags . bag $
mkWarnMsg dynFlags l neverQualify errMsg
#endif
where
bag :: a -> Bag a
bag = listToBag . (:[])
#if __GLASGOW_HASKELL__ < 900
mkHsApps ::
LHsExpr (GhcPass id)
-> [LHsExpr (GhcPass id)]
-> LHsExpr (GhcPass id)
mkHsApps = foldl' mkHsApp
#endif
{-------------------------------------------------------------------------------
Extensions
-------------------------------------------------------------------------------}
class HasDefaultExt a where
defExt :: a
#if __GLASGOW_HASKELL__ < 810
instance HasDefaultExt NoExt where
defExt = noExt
#else
instance HasDefaultExt NoExtField where
defExt = noExtField
#endif
#if __GLASGOW_HASKELL__ >= 900
instance HasDefaultExt LayoutInfo where
defExt = NoLayoutInfo
#endif
#if __GLASGOW_HASKELL__ >= 902
instance HasDefaultExt (EpAnn ann) where
defExt = noAnn
#endif
{-------------------------------------------------------------------------------
Exact-print annotations
-------------------------------------------------------------------------------}
#if __GLASGOW_HASKELL__ < 902
reLoc :: Located a -> Located a
reLoc = id
reLocA :: Located a -> Located a
reLocA = id
#endif
{-------------------------------------------------------------------------------
mkLabel
-------------------------------------------------------------------------------}
mkLabel :: SrcSpan -> FastString -> LHsExpr GhcPs
mkLabel l n = reLocA $ L l
$ HsOverLabel defExt
#if __GLASGOW_HASKELL__ < 902
Nothing
#endif
n