retrie-1.0.0.0: Retrie/GHC.hs
-- Copyright (c) Facebook, Inc. and its affiliates.
--
-- This source code is licensed under the MIT license found in the
-- LICENSE file in the root directory of this source tree.
--
{-# LANGUAGE CPP #-}
{-# LANGUAGE RecordWildCards #-}
module Retrie.GHC
( module Retrie.GHC
#if __GLASGOW_HASKELL__ < 900
, module ApiAnnotation
, module Bag
, module BasicTypes
, module FastString
, module FastStringEnv
#if __GLASGOW_HASKELL__ < 810
, module HsExpr
, module HsSyn
#else
, module ErrUtils
, module GHC.Hs.Expr
, module GHC.Hs
#endif
, module Module
, module Name
, module OccName
, module RdrName
, module SrcLoc
, module Unique
, module UniqFM
, module UniqSet
#else
-- GHC >= 9.0
, module GHC.Data.Bag
, module GHC.Data.FastString
, module GHC.Data.FastString.Env
, module GHC.Utils.Error
, module GHC.Hs
, module GHC.Parser.Annotation
, module GHC.Types.Basic
, module GHC.Types.Name
, module GHC.Types.Name.Reader
, module GHC.Types.SrcLoc
, module GHC.Types.Unique
, module GHC.Types.Unique.FM
, module GHC.Types.Unique.Set
, module GHC.Unit
#endif
) where
#if __GLASGOW_HASKELL__ < 900
import ApiAnnotation
import Bag
import BasicTypes
import FastString
import FastStringEnv
#if __GLASGOW_HASKELL__ < 810
import HsExpr
import HsSyn hiding (HsModule)
import qualified HsSyn as HS
#else
import ErrUtils
import GHC.Hs.Expr
import GHC.Hs hiding (HsModule)
import qualified GHC.Hs as HS
#endif
import Module
import Name
import OccName
import RdrName
import SrcLoc
import Unique
import UniqFM
import UniqSet
#else
-- GHC >= 9.0
import GHC.Data.Bag
import GHC.Data.FastString
import GHC.Data.FastString.Env
import GHC.Utils.Error
import GHC.Hs
import GHC.Parser.Annotation
import GHC.Types.Basic
import GHC.Types.Name
import GHC.Types.Name.Reader
import GHC.Types.SrcLoc
import GHC.Types.Unique
import GHC.Types.Unique.FM
import GHC.Types.Unique.Set
import GHC.Unit
#endif
import Data.Bifunctor (second)
import Data.Maybe
#if __GLASGOW_HASKELL__ < 900
type HsModule = HS.HsModule GhcPs
#endif
cLPat :: Located (Pat (GhcPass p)) -> LPat (GhcPass p)
#if __GLASGOW_HASKELL__ == 808
cLPat = composeSrcSpan
#else
cLPat = id
#endif
-- | Only returns located pat if there is a genuine location available.
dLPat :: LPat (GhcPass p) -> Maybe (Located (Pat (GhcPass p)))
#if __GLASGOW_HASKELL__ == 808
dLPat (XPat (L s p)) = Just $ L s $ stripSrcSpanPat p
dLPat _ = Nothing
#else
dLPat = Just
#endif
-- | Will always give a location, but it may be noSrcSpan.
dLPatUnsafe :: LPat (GhcPass p) -> Located (Pat (GhcPass p))
#if __GLASGOW_HASKELL__ == 808
dLPatUnsafe = dL
#else
dLPatUnsafe = id
#endif
#if __GLASGOW_HASKELL__ == 808
stripSrcSpanPat :: LPat (GhcPass p) -> Pat (GhcPass p)
stripSrcSpanPat (XPat (L _ p)) = stripSrcSpanPat p
stripSrcSpanPat p = p
#endif
rdrFS :: RdrName -> FastString
rdrFS (Qual m n) = mconcat [moduleNameFS m, fsDot, occNameFS n]
rdrFS rdr = occNameFS (occName rdr)
fsDot :: FastString
fsDot = mkFastString "."
varRdrName :: HsExpr p -> Maybe (Located (IdP p))
varRdrName (HsVar _ n) = Just n
varRdrName _ = Nothing
tyvarRdrName :: HsType p -> Maybe (Located (IdP p))
tyvarRdrName (HsTyVar _ _ n) = Just n
tyvarRdrName _ = Nothing
fixityDecls :: HsModule -> [(Located RdrName, Fixity)]
fixityDecls m =
[ (nm, fixity)
| L _ (SigD _ (FixSig _ (FixitySig _ nms fixity))) <- hsmodDecls m
, nm <- nms
]
ruleInfo :: RuleDecl GhcPs -> [RuleInfo]
ruleInfo (HsRule _ (L _ (_, riName)) _ tyBs valBs riLHS riRHS) =
let
riQuantifiers =
map unLoc (tyBindersToLocatedRdrNames (fromMaybe [] tyBs)) ++
ruleBindersToQs valBs
in [ RuleInfo{..} ]
#if __GLASGOW_HASKELL__ < 900
ruleInfo XRuleDecl{} = []
#endif
ruleBindersToQs :: [LRuleBndr GhcPs] -> [RdrName]
ruleBindersToQs bs = catMaybes
[ case b of
RuleBndr _ (L _ v) -> Just v
RuleBndrSig _ (L _ v) _ -> Just v
#if __GLASGOW_HASKELL__ < 900
XRuleBndr{} -> Nothing
#endif
| L _ b <- bs
]
#if __GLASGOW_HASKELL__ < 900
tyBindersToLocatedRdrNames :: [LHsTyVarBndr GhcPs] -> [Located RdrName]
#else
tyBindersToLocatedRdrNames :: [LHsTyVarBndr () GhcPs] -> [Located RdrName]
#endif
tyBindersToLocatedRdrNames vars = catMaybes
[ case var of
#if __GLASGOW_HASKELL__ < 900
UserTyVar _ v -> Just v
KindedTyVar _ v _ -> Just v
XTyVarBndr{} -> Nothing
#else
UserTyVar _ _ v -> Just v
KindedTyVar _ _ v _ -> Just v
#endif
| L _ var <- vars ]
data RuleInfo = RuleInfo
{ riName :: RuleName
, riQuantifiers :: [RdrName]
, riLHS :: LHsExpr GhcPs
, riRHS :: LHsExpr GhcPs
}
#if __GLASGOW_HASKELL__ < 810
noExtField :: NoExt
noExtField = noExt
#endif
overlaps :: SrcSpan -> SrcSpan -> Bool
overlaps ss1 ss2
| Just s1 <- getRealSpan ss1, Just s2 <- getRealSpan ss2 =
srcSpanFile s1 == srcSpanFile s2 &&
((srcSpanStartLine s1, srcSpanStartCol s1) `within` s2 ||
(srcSpanEndLine s1, srcSpanEndCol s1) `within` s2)
overlaps _ _ = False
within :: (Int, Int) -> RealSrcSpan -> Bool
within (l,p) s =
srcSpanStartLine s <= l &&
srcSpanStartCol s <= p &&
srcSpanEndLine s >= l &&
srcSpanEndCol s >= p
lineCount :: [SrcSpan] -> Int
lineCount ss = sum
[ srcSpanEndLine s - srcSpanStartLine s + 1
| Just s <- map getRealSpan ss
]
showRdrs :: [RdrName] -> String
showRdrs = show . map (occNameString . occName)
#if __GLASGOW_HASKELL__ < 900
uniqBag :: Uniquable a => [(a,b)] -> UniqFM [b]
#else
uniqBag :: Uniquable a => [(a,b)] -> UniqFM a [b]
#endif
uniqBag = listToUFM_C (++) . map (second pure)
getRealLoc :: SrcLoc -> Maybe RealSrcLoc
#if __GLASGOW_HASKELL__ < 900
getRealLoc (RealSrcLoc l) = Just l
#else
getRealLoc (RealSrcLoc l _) = Just l
#endif
getRealLoc _ = Nothing
getRealSpan :: SrcSpan -> Maybe RealSrcSpan
#if __GLASGOW_HASKELL__ < 900
getRealSpan (RealSrcSpan s) = Just s
#else
getRealSpan (RealSrcSpan s _) = Just s
#endif
getRealSpan _ = Nothing