11{-# LANGUAGE RankNTypes #-}
22{-# LANGUAGE OverloadedStrings #-}
33{-# LANGUAGE CPP #-}
4+ {-# LANGUAGE FlexibleContexts #-}
45module StackTrace.Plugin (plugin ) where
56
67import Control.Arrow (first )
78import Data.Monoid (Any (Any , getAny ))
8- import GHC.Types.SrcLoc
9+
910#if __GLASGOW_HASKELL__ >= 900
1011import GHC.Plugins
1112#else
12-
1313import GhcPlugins
1414#endif
15+
1516#if __GLASGOW_HASKELL__ >= 810
1617import GHC.Hs
1718#endif
19+
1820#if __GLASGOW_HASKELL__ < 810
1921import HsSyn
2022#endif
2123
24+ -- srcSpan now requires strict maybe
25+ #if __GLASGOW_HASKELL__ >= 904
26+ import GHC.Data.Strict as Strict (Maybe (Nothing ))
27+ #endif
28+
2229type Traversal s t a b
2330 = forall f . Applicative f = >
2431 (a -> f b ) -> s -> f t
2532
2633type Traversal' s a = Traversal s s a a
2734
35+ #if __GLASGOW_HASKELL__ < 900
36+ emptyLoc :: e -> Located e
37+ emptyLoc = noLoc
38+ #elif __GLASGOW_HASKELL__ < 910
39+ emptyLoc :: a -> LocatedAn an a
40+ emptyLoc = noLocA
41+ #else
42+ emptyLoc :: (HasAnnotation b ) => e -> GenLocated b e
43+ emptyLoc = reLoc . noLoc
44+ #endif
45+
2846plugin :: Plugin
2947plugin = defaultPlugin {parsedResultAction = parsedPlugin, pluginRecompile = purePlugin}
3048
49+ #if __GLASGOW_HASKELL__ < 904
3150parsedPlugin ::
3251 [CommandLineOption ] -> ModSummary -> HsParsedModule -> Hsc HsParsedModule
3352parsedPlugin _ _ pm = do
3453 let m = updateHsModule <$> hpm_module pm
3554 pm' = pm {hpm_module = m}
3655 return pm'
56+ #else
57+ parsedPlugin ::
58+ [CommandLineOption ] -> ModSummary -> ParsedResult -> Hsc ParsedResult
59+ parsedPlugin _ _ pr = do
60+ let pm = parsedResultModule pr
61+ m = updateHsModule <$> hpm_module pm
62+ pm' = pm {hpm_module = m}
63+ return pr {parsedResultModule = pm'}
64+ #endif
65+
3766
3867-- Use qualified import for GHC.Stack as "AutoImported.GHC.Stack"
3968-- ...this should not interfere with other imports...
@@ -48,18 +77,42 @@ importDeclQualified :: ImportDeclQualifiedStyle
4877importDeclQualified = QualifiedPre
4978#endif
5079
51- ghcStackImport :: Located (ImportDecl (GhcPass p ))
80+
81+ #if __GLASGOW_HASKELL__ < 900
82+ ghcStackImport :: Located (ImportDecl GhcPs )
5283ghcStackImport =
5384 L srcSpan $
5485 (simpleImportDecl $ mkModuleName " GHC.Stack" )
55- { ideclQualified = importDeclQualified, ideclAs = Just $ noLoc ghcStackModuleName }
86+ { ideclQualified = importDeclQualified, ideclAs = ideclAs' }
5687 where
88+ ideclAs' = Just $ noLoc ghcStackModuleName
89+ srcSpan = RealSrcSpan (realSrcLocSpan $ mkRealSrcLoc " haskell-stack-trace-plugin:very-unique-file-name-to-avoid-collision" 1 1 )
90+ #else
91+ ghcStackImport :: LImportDecl GhcPs
92+ ghcStackImport =
93+ reLoc' $ L srcSpan $
94+ (simpleImportDecl $ mkModuleName " GHC.Stack" )
95+ { ideclQualified = importDeclQualified, ideclAs = ideclAs' }
96+ where
97+ ideclAs' = Just $ emptyLoc ghcStackModuleName
98+
99+ #if __GLASGOW_HASKELL__ >= 910
100+ reLoc' = reLoc
101+ #else
102+ reLoc' = reLocA
103+ #endif
104+
57105 -- This is for GHC-9 related problems. @noLoc@ causes GHC to throw warnings
58106 -- about unused imports. Even if the import is used
59107 -- See: https://github.com/waddlaw/haskell-stack-trace-plugin/issues/16
108+ #if __GLASGOW_HASKELL__ >= 904
109+ srcSpan = RealSrcSpan (realSrcLocSpan $ mkRealSrcLoc " haskell-stack-trace-plugin:very-unique-file-name-to-avoid-collision" 1 1 ) Strict. Nothing
110+ #else
60111 srcSpan = RealSrcSpan (realSrcLocSpan $ mkRealSrcLoc " haskell-stack-trace-plugin:very-unique-file-name-to-avoid-collision" 1 1 ) Nothing
112+ #endif
113+ #endif
61114
62- #if __GLASGOW_HASKELL__ >= 900
115+ #if __GLASGOW_HASKELL__ >= 900 && __GLASGOW_HASKELL__ < 906
63116updateHsModule :: HsModule -> HsModule
64117#else
65118updateHsModule :: HsModule GhcPs -> HsModule GhcPs
@@ -108,14 +161,25 @@ updateMatchGroup f mg@MG {} = (\x -> mg {mg_alts = x}) <$> updateLLMatch f (mg_a
108161updateMatchGroup _ mg = pure mg
109162#endif
110163
164+ #if __GLASGOW_HASKELL__ < 900
111165updateLocated :: Functor f => (a -> b -> f c ) -> a -> Located b -> f (Located c )
112166updateLocated f g (L l e) = L l <$> f g e
167+ #endif
113168
169+ #if __GLASGOW_HASKELL__ < 900
114170updateLLMatch :: Traversal' (Located [LMatch GhcPs (LHsExpr GhcPs )]) (LHsSigWcType GhcPs )
115171updateLLMatch = updateLocated updateLMatches
172+ #else
173+ updateLLMatch :: Traversal' (XRec GhcPs [LMatch GhcPs (LHsExpr GhcPs )]) (LHsSigWcType GhcPs )
174+ updateLLMatch = traverse . updateLMatches
175+ #endif
116176
117177updateLMatches :: Traversal' [LMatch GhcPs (LHsExpr GhcPs )] (LHsSigWcType GhcPs )
178+ #if __GLASGOW_HASKELL__ < 900
118179updateLMatches f = traverse (updateLocated updateMatch f)
180+ #else
181+ updateLMatches = traverse . traverse . updateMatch
182+ #endif
119183
120184updateMatch :: Traversal' (Match GhcPs (LHsExpr GhcPs )) (LHsSigWcType GhcPs )
121185updateMatch f m@ Match {} = (\ x -> m {m_grhss = x}) <$> updateGrhss f (m_grhss m)
@@ -124,13 +188,17 @@ updateMatch _ m = pure m
124188#endif
125189
126190updateGrhss :: Traversal' (GRHSs GhcPs (LHsExpr GhcPs )) (LHsSigWcType GhcPs )
127- updateGrhss f grhss@ GRHSs {} = (\ x -> grhss {grhssLocalBinds = x}) <$> updateLHsLocalBinds f (grhssLocalBinds grhss)
128191#if __GLASGOW_HASKELL__ < 900
192+ updateGrhss f grhss@ GRHSs {} = (\ x -> grhss {grhssLocalBinds = x}) <$> updateLHsLocalBinds f (grhssLocalBinds grhss)
129193updateGrhss _ grhss = pure grhss
194+ #else
195+ updateGrhss f grhss = (\ x -> grhss {grhssLocalBinds = x}) <$> updateLocalBinds f (grhssLocalBinds grhss)
130196#endif
131197
198+ #if __GLASGOW_HASKELL__ < 900
132199updateLHsLocalBinds :: Traversal' (LHsLocalBinds GhcPs ) (LHsSigWcType GhcPs )
133200updateLHsLocalBinds = updateLocated updateLocalBinds
201+ #endif
134202
135203updateLocalBinds :: Traversal' (HsLocalBinds GhcPs ) (LHsSigWcType GhcPs )
136204updateLocalBinds f (HsValBinds xHsValBinds hsValBindsLR) = HsValBinds xHsValBinds <$> updateHsValBindsLR f hsValBindsLR
@@ -141,7 +209,11 @@ updateHsValBindsLR f (ValBinds xValBinds lHsBindsLR lSigs) = ValBinds xValBinds
141209updateHsValBindsLR _ valBinds = pure valBinds
142210
143211updateLSigs :: Traversal' [LSig GhcPs ] (LHsSigWcType GhcPs )
212+ #if __GLASGOW_HASKELL__ < 900
144213updateLSigs f = traverse (updateLocated updateSig f)
214+ #else
215+ updateLSigs = traverse . traverse . updateSig
216+ #endif
145217
146218updateSig :: Traversal' (Sig GhcPs ) (LHsSigWcType GhcPs )
147219updateSig f (TypeSig xSig ls t) = TypeSig xSig ls <$> f t
@@ -155,31 +227,40 @@ updateLHsSigWsType _ lhs = pure lhs
155227#endif
156228
157229updateLHsSigType :: Traversal' (LHsSigType GhcPs ) (LHsType GhcPs )
230+ #if __GLASGOW_HASKELL__ >= 902
231+ updateLHsSigType = traverse . updateHsSigType
232+ #else
158233updateLHsSigType f lhs@ HsIB {} =
159234 (\ x -> lhs {hsib_body = x}) <$> f (hsib_body lhs)
235+ #endif
160236#if __GLASGOW_HASKELL__ < 900
161237updateLHsSigType _ lhs = pure lhs
162238#endif
163239
240+
241+ #if __GLASGOW_HASKELL__ >= 902
242+ updateHsSigType :: Traversal' (HsSigType GhcPs ) (LHsType GhcPs )
243+ updateHsSigType f hs@ HsSig {} = (\ x -> hs {sig_body = x}) <$> f (sig_body hs)
244+ #endif
164245updateLHsType :: Traversal' (LHsType GhcPs ) (HsType GhcPs )
165246updateLHsType = traverse
166247
248+ -- | Wraps an HsType with a HasStackCall qualifier
249+ wrapInQualTy :: HsType GhcPs -> (Any , HsType GhcPs )
250+ wrapInQualTy ty =
251+ flagASTModified $ HsQualTy xQualTy (emptyLoc $ appendHSC [] ) (emptyLoc ty)
252+
167253-- Main process
168254updateHsType :: HsType GhcPs -> (Any , HsType GhcPs )
169255updateHsType ty@ (HsQualTy xty ctxt body) =
170256 if hasHasCallStack (unLoc ctxt)
171257 then pure ty
172258 else flagASTModified $ HsQualTy xty (fmap appendHSC ctxt) body
173- updateHsType ty@ HsTyVar {} =
174- flagASTModified $ HsQualTy xQualTy (noLoc $ appendHSC [] ) (noLoc ty)
175- updateHsType ty@ HsAppTy {} =
176- flagASTModified $ HsQualTy xQualTy (noLoc $ appendHSC [] ) (noLoc ty)
177- updateHsType ty@ HsFunTy {} =
178- flagASTModified $ HsQualTy xQualTy (noLoc $ appendHSC [] ) (noLoc ty)
179- updateHsType ty@ HsListTy {} =
180- flagASTModified $ HsQualTy xQualTy (noLoc $ appendHSC [] ) (noLoc ty)
181- updateHsType ty@ HsTupleTy {} =
182- flagASTModified $ HsQualTy xQualTy (noLoc $ appendHSC [] ) (noLoc ty)
259+ updateHsType ty@ HsTyVar {} = wrapInQualTy ty
260+ updateHsType ty@ HsAppTy {} = wrapInQualTy ty
261+ updateHsType ty@ HsFunTy {} = wrapInQualTy ty
262+ updateHsType ty@ HsListTy {} = wrapInQualTy ty
263+ updateHsType ty@ HsTupleTy {} = wrapInQualTy ty
183264updateHsType ty = pure ty
184265
185266#if __GLASGOW_HASKELL__ < 810
@@ -203,9 +284,26 @@ hasHasCallStack = any (checkHsType . unLoc)
203284 checkHsType (HsTyVar _ _ lid) = unLoc lid == (mkRdrUnqual $ mkClsOcc " HasCallStack" )
204285 checkHsType _ = False
205286
287+ xTyVar :: XTyVar GhcPs
288+ #if __GLASGOW_HASKELL__ >= 912
289+ xTyVar = NoEpTok
290+ #elif __GLASGOW_HASKELL__ >= 910
291+ xTyVar = []
292+ #elif __GLASGOW_HASKELL__ >= 900
293+ xTyVar = noAnn
294+ #else
295+ xTyVar = xQualTy
296+ #endif
297+
206298-- make HasCallStack => constraint
207299mkHSC :: LHsType GhcPs
208- mkHSC = noLoc $ HsTyVar xQualTy NotPromoted lId
300+ mkHSC = emptyLoc $ HsTyVar xTyVar NotPromoted lId
301+
209302
303+ #if __GLASGOW_HASKELL__ < 900
210304lId :: Located (IdP GhcPs )
211305lId = noLoc $ mkRdrQual ghcStackModuleName $ mkClsOcc " HasCallStack"
306+ #else
307+ lId :: LIdP GhcPs
308+ lId = emptyLoc $ mkRdrQual ghcStackModuleName $ mkClsOcc " HasCallStack"
309+ #endif
0 commit comments