{-# LANGUAGE OverloadedStrings #-} module StackTrace.Plugin (plugin) where import GhcPlugins import TcRnTypes (IfM, TcM, TcGblEnv, tcg_binds, tcg_rn_decls) import HsExtension (GhcTc, GhcRn) import HsDecls (HsGroup) import HsExpr (LHsExpr) import HsSyn import Data.Maybe plugin :: Plugin plugin = defaultPlugin { parsedResultAction = parsedPlugin } parsedPlugin :: [CommandLineOption] -> ModSummary -> HsParsedModule -> Hsc HsParsedModule parsedPlugin _ _ pm = do dflags <- getDynFlags let extract = hsmodImports . unLoc addGHCStackMod = noLoc $ simpleImportDecl $ mkModuleName "GHC.Stack" m = updateHsModule addGHCStackMod updateHsmodDecl <$> hpm_module pm pm' = pm { hpm_module = m } return pm' updateHsModule :: LImportDecl GhcPs -> (LHsDecl GhcPs -> LHsDecl GhcPs) -> HsModule GhcPs -> HsModule GhcPs updateHsModule importDecl update hsm = hsm { hsmodImports = importDecl:decls , hsmodDecls = map update lhss } where decls = hsmodImports hsm lhss = hsmodDecls hsm -------------- updateHsmodDecl :: LHsDecl GhcPs -> LHsDecl GhcPs updateHsmodDecl = fmap updateHsDecl updateHsDecl :: HsDecl GhcPs -> HsDecl GhcPs updateHsDecl (SigD xSig s) = SigD xSig (updateSig s) updateHsDecl decl = decl updateSig :: Sig GhcPs -> Sig GhcPs updateSig (TypeSig xSig ls t) = TypeSig xSig ls (updateLHsSigWcType t) updateSig sig = sig updateLHsSigWcType :: LHsSigWcType GhcPs -> LHsSigWcType GhcPs updateLHsSigWcType lhs@HsWC{} = lhs { hswc_body = updateLHsSigType (hswc_body lhs) } updateLHsSigWcType lhs@XHsWildCardBndrs{} = lhs updateLHsSigType :: LHsSigType GhcPs -> LHsSigType GhcPs updateLHsSigType lhs@HsIB{} = lhs { hsib_body = updateLHsType (hsib_body lhs )} updateLHsSigType lhs@XHsImplicitBndrs{} = lhs updateLHsType :: LHsType GhcPs -> LHsType GhcPs updateLHsType = fmap updateHsType -- Main process updateHsType :: HsType GhcPs -> HsType GhcPs updateHsType ty@(HsQualTy xty ctxt body) = HsQualTy xty (fmap appendHSC ctxt) body updateHsType ty@HsTyVar{} = HsQualTy noExt (noLoc $ appendHSC []) (noLoc ty) updateHsType ty@HsAppTy{} = HsQualTy noExt (noLoc $ appendHSC []) (noLoc ty) updateHsType ty@HsFunTy{} = HsQualTy noExt (noLoc $ appendHSC []) (noLoc ty) updateHsType ty@HsListTy{} = HsQualTy noExt (noLoc $ appendHSC []) (noLoc ty) updateHsType ty@HsTupleTy{} = HsQualTy noExt (noLoc $ appendHSC []) (noLoc ty) updateHsType ty = ty appendHSC :: HsContext GhcPs -> HsContext GhcPs appendHSC cs = mkHSC : cs -- make HasCallStack => constraint mkHSC :: LHsType GhcPs mkHSC = noLoc $ HsTyVar noExt NotPromoted lId lId :: Located (IdP GhcPs) lId = noLoc $ mkRdrUnqual $ mkClsOcc "HasCallStack"