packages feed

scrod-0.2026.2.21: source/library/Scrod/Convert/FromGhc/ItemKind.hs

-- | Map GHC declaration types to Scrod's 'ItemKind.ItemKind'.
--
-- Pure functions that inspect GHC AST nodes and return the
-- corresponding 'ItemKind' value. No monadic state or internal
-- dependencies.
module Scrod.Convert.FromGhc.ItemKind where

import GHC.Hs ()
import qualified GHC.Hs.Extension as Ghc
import qualified GHC.Types.Name.Occurrence as Occurrence
import qualified GHC.Types.Name.Reader as Reader
import qualified GHC.Types.SrcLoc as SrcLoc
import qualified Language.Haskell.Syntax as Syntax
import qualified Scrod.Core.ItemKind as ItemKind

-- | Determine the ItemKind from a declaration.
itemKindFromDecl :: Syntax.HsDecl Ghc.GhcPs -> ItemKind.ItemKind
itemKindFromDecl decl = case decl of
  Syntax.TyClD _ tyClDecl -> itemKindFromTyClDecl tyClDecl
  Syntax.ValD _ bind -> itemKindFromBind bind
  Syntax.SigD _ sig -> itemKindFromSig sig
  Syntax.InstD _ inst -> itemKindFromInstDecl inst
  Syntax.KindSigD {} -> ItemKind.StandaloneKindSig
  Syntax.DefD {} -> ItemKind.Default
  Syntax.ForD _ foreignDecl -> itemKindFromForeignDecl foreignDecl
  Syntax.WarningD {} -> ItemKind.Warning
  Syntax.AnnD {} -> ItemKind.Annotation
  Syntax.RuleD {} -> ItemKind.Rule
  Syntax.SpliceD {} -> ItemKind.Splice
  Syntax.DocD {} -> ItemKind.Function -- Doc comment
  Syntax.RoleAnnotD {} -> ItemKind.RoleAnnotation
  Syntax.DerivD {} -> ItemKind.StandaloneDeriving

-- | Determine ItemKind from a type/class declaration.
itemKindFromTyClDecl :: Syntax.TyClDecl Ghc.GhcPs -> ItemKind.ItemKind
itemKindFromTyClDecl tyClDecl = case tyClDecl of
  Syntax.FamDecl _ famDecl -> itemKindFromFamilyDecl famDecl
  Syntax.SynDecl {} -> ItemKind.TypeSynonym
  Syntax.DataDecl _ _ _ _ dataDefn -> itemKindFromDataDefn dataDefn
  Syntax.ClassDecl {} -> ItemKind.Class

-- | Determine ItemKind from a data definition.
itemKindFromDataDefn :: Syntax.HsDataDefn Ghc.GhcPs -> ItemKind.ItemKind
itemKindFromDataDefn dataDefn = case Syntax.dd_cons dataDefn of
  Syntax.NewTypeCon {} -> ItemKind.Newtype
  Syntax.DataTypeCons isTypeData _ ->
    if isTypeData
      then ItemKind.TypeData
      else ItemKind.DataType

-- | Determine ItemKind from a family declaration.
itemKindFromFamilyDecl :: Syntax.FamilyDecl Ghc.GhcPs -> ItemKind.ItemKind
itemKindFromFamilyDecl famDecl = case Syntax.fdInfo famDecl of
  Syntax.DataFamily -> ItemKind.DataFamily
  Syntax.OpenTypeFamily -> ItemKind.OpenTypeFamily
  Syntax.ClosedTypeFamily {} -> ItemKind.ClosedTypeFamily

-- | Determine ItemKind from a binding.
itemKindFromBind :: Syntax.HsBindLR Ghc.GhcPs Ghc.GhcPs -> ItemKind.ItemKind
itemKindFromBind bind = case bind of
  Syntax.FunBind {Syntax.fun_id = lName} -> functionOrOperator lName
  Syntax.PatBind {} -> ItemKind.PatternBinding
  Syntax.VarBind {} -> ItemKind.Function
  Syntax.PatSynBind {} -> ItemKind.PatternSynonym

-- | Determine ItemKind from a signature.
itemKindFromSig :: Syntax.Sig Ghc.GhcPs -> ItemKind.ItemKind
itemKindFromSig sig = case sig of
  Syntax.TypeSig {} -> ItemKind.Function
  Syntax.PatSynSig {} -> ItemKind.PatternSynonym
  Syntax.ClassOpSig {} -> ItemKind.ClassMethod
  Syntax.FixSig {} -> ItemKind.FixitySignature
  Syntax.InlineSig {} -> ItemKind.InlineSignature
  Syntax.SpecSig {} -> ItemKind.SpecialiseSignature
  Syntax.SpecSigE {} -> ItemKind.SpecialiseSignature
  Syntax.MinimalSig {} -> ItemKind.MinimalPragma
  Syntax.CompleteMatchSig {} -> ItemKind.CompletePragma
  _ -> ItemKind.Function

-- | Determine ItemKind from an instance declaration.
itemKindFromInstDecl :: Syntax.InstDecl Ghc.GhcPs -> ItemKind.ItemKind
itemKindFromInstDecl inst = case inst of
  Syntax.ClsInstD {} -> ItemKind.ClassInstance
  Syntax.DataFamInstD {} -> ItemKind.DataFamilyInstance
  Syntax.TyFamInstD {} -> ItemKind.TypeFamilyInstance

-- | Return 'Operator' if the name is symbolic, 'Function' otherwise.
functionOrOperator :: Syntax.LIdP Ghc.GhcPs -> ItemKind.ItemKind
functionOrOperator lName =
  if Occurrence.isSymOcc . Reader.rdrNameOcc $ SrcLoc.unLoc lName
    then ItemKind.Operator
    else ItemKind.Function

-- | Determine ItemKind from a foreign declaration.
itemKindFromForeignDecl :: Syntax.ForeignDecl Ghc.GhcPs -> ItemKind.ItemKind
itemKindFromForeignDecl foreignDecl = case foreignDecl of
  Syntax.ForeignImport {} -> ItemKind.ForeignImport
  Syntax.ForeignExport {} -> ItemKind.ForeignExport