content: {-# LANGUAGE CPP #-}
  {-# LANGUAGE FlexibleContexts #-}
  {-# LANGUAGE FlexibleInstances #-}
  {-# LANGUAGE ScopedTypeVariables #-}
  {-# LANGUAGE TypeSynonymInstances #-}
  --------------------------------------------------------------------------------
  -- Module      : Variables
  
  -- |
  --
  
  -- ---------------------------------------------------------------------
  
  module Language.Haskell.Refact.Utils.Variables
    (
    -- ** Variable analysis
      isFieldName
    , isClassName
    , isInstanceName
    , isDeclaredInRdr
  
    , FreeNames(..),DeclaredNames(..)
    , hsFreeAndDeclaredRdr
    , hsFreeAndDeclaredNameStrings
    , hsFreeAndDeclaredPNs
  
    , getDeclaredTypesRdr
    , getDeclaredVarsRdr
  
    , hsVisibleNamesRdr, hsVisibleDsRdr
    , hsFDsFromInsideRdr, hsFDNamesFromInsideRdr, hsFDNamesFromInsideRdrPure
  
    , rdrName2Name, rdrName2NamePure
    , eqRdrNamePure
    -- , rdrName2Name'
    , sameNameSpace
  
    -- ** Identifiers, expressions, patterns and declarations
    , FindEntity(..)
    , findNameInRdr
    , findNamesRdr
    , sameOccurrence
    , definedPNsRdr,definedNamesRdr
    , definingDeclsRdrNames,definingDeclsRdrNames',definingSigsRdrNames
    , definingTyClDeclsNames
    , definesRdr,definesDeclRdr,definesNameRdr
    , definesTypeSigRdr,definesSigDRdr
  
    , hsTypeVbls
    , hsNamessRdr
    , findLRdrName
    , locToNameRdr, locToNameRdrPure
    , locToRdrName
    ) where
  
  import Control.Monad.State
  import Data.List
  import Data.Maybe
  import Data.Monoid
  
  import Language.Haskell.Refact.Utils.GhcVersionSpecific
  import Language.Haskell.Refact.Utils.LocUtils
  import Language.Haskell.Refact.Utils.Monad
  import Language.Haskell.Refact.Utils.MonadFunctions
  import Language.Haskell.Refact.Utils.Types
  
  import Language.Haskell.GHC.ExactPrint.Types
  import Language.Haskell.GHC.ExactPrint
  import Language.Haskell.GHC.ExactPrint.Utils
  
  
  -- Modules from GHC
  import qualified Bag           as GHC
  import qualified GHC           as GHC
  import qualified Name          as GHC
  -- import qualified Outputable    as GHC
  import qualified RdrName       as GHC
  
  import qualified Data.Generics as SYB
  import qualified GHC.SYB.Utils as SYB
  
  import qualified Data.Map as Map
  
  import Data.Generics.Strafunski.StrategyLib.StrategyLib hiding (liftIO,MonadPlus,mzero)
  
  -- ---------------------------------------------------------------------
  
  class (SYB.Data a, SYB.Typeable a) => FindEntity a where
  
    -- | Returns True is a syntax phrase, say a, is part of another
    -- syntax phrase, say b.
    -- NOTE: very important: only do a shallow check
    findEntity:: (SYB.Data b) => a -> b -> Bool
  
  -- ---------------------------------------------------------------------
  
  {-# DEPRECATED FindEntity "Can't use Renamed in GHC 8" #-}
  instance FindEntity GHC.Name where
  
    findEntity n t = fromMaybe False res
     where
      res = SYB.somethingStaged SYB.Renamer Nothing (Nothing `SYB.mkQ` worker) t
  
      worker (name::GHC.Name)
        | n == name = Just True
      worker _ = Nothing
  
  
  -- This instance does not make sense, it will only find the specific RdrName
  -- where it was found, not any other instances of it.
  instance FindEntity (GHC.Located GHC.RdrName) where
  
    findEntity ln t =
      case SYB.something (nameSybQuery checkRdr) t of
        Nothing -> False
        _       -> True
      where
        checkRdr :: GHC.Located GHC.RdrName -> Maybe Bool
        checkRdr n
          | sameOccurrence n ln = Just True
          | otherwise = Nothing
  
  -- ---------------------------------------------------------------------
  
  -- TODO: should the location be matched too in this case?
  instance FindEntity (GHC.Located GHC.Name) where
  
    findEntity n t = fromMaybe False res
     where
      res = SYB.somethingStaged SYB.Renamer Nothing (Nothing `SYB.mkQ` worker) t
  
      worker (name::GHC.Located GHC.Name)
        | n == name = Just True
      worker _ = Nothing
  
  
  -- ---------------------------------------------------------------------
  
  instance FindEntity (GHC.LHsExpr GHC.RdrName) where
  
    findEntity e t = fromMaybe False res
     where
      res = SYB.something (Nothing `SYB.mkQ` worker) t
  
      worker (expr :: GHC.LHsExpr GHC.RdrName)
        | sameOccurrence e expr = Just True
      worker _ = Nothing
  
  -- TODO: remove this instance
  instance FindEntity (GHC.LHsExpr GHC.Name) where
  
    findEntity e t = fromMaybe False res
     where
      res = SYB.something (Nothing `SYB.mkQ` worker) t
  
      worker (expr :: GHC.LHsExpr GHC.Name)
        | sameOccurrence e expr = Just True
      worker _ = Nothing
  
  -- ---------------------------------------------------------------------
  
  instance FindEntity (GHC.Located (GHC.HsBindLR GHC.Name GHC.Name)) where
    findEntity e t = fromMaybe False res
     where
      res = SYB.somethingStaged SYB.Renamer Nothing (Nothing `SYB.mkQ` worker) t
  
      worker (expr::(GHC.Located (GHC.HsBindLR GHC.Name GHC.Name)))
        | sameOccurrence e expr = Just True
      worker _ = Nothing
  
  instance FindEntity (GHC.Located (GHC.HsDecl GHC.Name)) where
    findEntity d t = fromMaybe False res
     where
      res = SYB.somethingStaged SYB.Renamer Nothing (Nothing `SYB.mkQ` worker) t
  
      worker (decl::(GHC.Located (GHC.HsDecl GHC.Name)))
        | sameOccurrence d decl = Just True
      worker _ = Nothing
  
  -- ---------------------------------------------------------------------
  
  -- TODO: AZ: pretty sure this can be simplified, depends if we need to
  --          manage transformed stuff too though.
  
  -- | Return True if syntax phrases t1 and t2 refer to the same one.
  sameOccurrence :: (GHC.Located t) -> (GHC.Located t) -> Bool
  sameOccurrence (GHC.L l1 _) (GHC.L l2 _)
   = l1 == l2
  
  
  -- ---------------------------------------------------------------------
  
  -- | For free variables
  data FreeNames = FN { fn :: [GHC.Name] }
  
  -- | For declared variables
  data DeclaredNames = DN { dn :: [GHC.Name] }
  
  instance Show FreeNames where
    show (FN ls) = "FN " ++ showGhcQual ls
  
  instance Show DeclaredNames where
    show (DN ls) = "DN " ++ showGhcQual ls
  
  instance Monoid FreeNames where
    mempty = FN []
    mappend (FN a) (FN b) = FN (a `mappend` b)
  
  instance Monoid DeclaredNames where
    mempty = DN []
    mappend (DN a) (DN b) = DN (a `mappend` b)
  
  
  emptyFD :: (FreeNames,DeclaredNames)
  emptyFD = (FN [], DN [])
  
  -- ---------------------------------------------------------------------
  -- | True if the name is a field name
  isFieldName :: GHC.Name -> Bool
  isFieldName _n = error "undefined isFieldName"
  
  -- ---------------------------------------------------------------------
  -- | True if the name is a field name
  isClassName :: GHC.Name -> Bool
  isClassName _n = error "undefined isClassName"
  
  -- ---------------------------------------------------------------------
  -- | True if the name is a class instance
  isInstanceName :: GHC.Name -> Bool
  isInstanceName _n = error "undefined isInstanceName"
  
  
  -- ---------------------------------------------------------------------
  -- | Collect those type variables that are declared in a given syntax phrase t. In
  -- the returned result, the first list is always be empty.
  hsTypeVbls::(SYB.Data t) => t -> ([GHC.RdrName],[GHC.RdrName])
  hsTypeVbls =ghead "hsTypeVbls".(applyTU (stop_tdTU (failTU `adhocTU` pnt)))
    where
      -- pnt (PNT (PN i (UniqueNames.S loc)) (Type _) _) = return ([], [(PN i (UniqueNames.S loc))])
      pnt n | GHC.rdrNameSpace n == GHC.tvName = return ([], [n])
      pnt _ = mzero
  
  
  -------------------------------------------------------------------------------
  
  isDeclaredInRdr :: NameMap -> GHC.Name -> [GHC.LHsDecl GHC.RdrName] -> Bool
  isDeclaredInRdr nm name decls = nonEmptyList $ definingDeclsRdrNames nm [name] decls False True
  
  -- ---------------------------------------------------------------------
  
  -- |The same as `hsFreeAndDeclaredPNs` except that the returned
  -- variables are in the String format.
  hsFreeAndDeclaredNameStrings :: (SYB.Data t)
    => t -> RefactGhc ([String],[String])
  hsFreeAndDeclaredNameStrings t = do
    (f,d) <- hsFreeAndDeclaredPNs t
    return ((nub.map showGhc) f, (nub.map showGhc) d)
  
  -- ---------------------------------------------------------------------
  
  -- | Return the free and declared Names in the given syntax fragment. The syntax
  -- fragment MUST be parameterised by RdrName, else the empty list will be
  -- returned.
  hsFreeAndDeclaredPNs :: (SYB.Data t) => t -> RefactGhc ([GHC.Name],[GHC.Name])
  hsFreeAndDeclaredPNs t = do
    nm <- getRefactNameMap
    -- TODO: Change the return type to (FreeNames,DeclaredNames)
    let (FN f,DN d) = hsFreeAndDeclaredRdr nm t
    return (f,d)
  
  -- ---------------------------------------------------------------------
  
  -- | Collect the free and declared variables (in the GHC.Name format)
  -- in a given syntax phrase t. In the result, the first list contains
  -- the free variables, and the second list contains the declared
  -- variables.
  -- Expects ParsedSource
  hsFreeAndDeclaredRdr :: (SYB.Data t) => NameMap -> t -> (FreeNames,DeclaredNames)
  hsFreeAndDeclaredRdr nm t = res
    where
      fd = hsFreeAndDeclaredRdr' nm t
      (FN f,DN d) = case fd of
        Left _err -> mempty
        Right v -> v
      res = (FN (f \\ d),DN d)
  
  hsFreeAndDeclaredRdr':: (SYB.Data t) => NameMap -> t -> Either String (FreeNames,DeclaredNames)
  hsFreeAndDeclaredRdr' nm t = do
        (FN f,DN d) <- hsFreeAndDeclared'
        -- let (f',d') = ( filter (not . GHC.isTyVarName) $ nub f
        --               , filter (not . GHC.isTyVarName) $ nub d)
        let (f',d') = ( nub f
                      , nub d)
        return (FN f',DN d')
  
     where
            hsFreeAndDeclared' :: Either String (FreeNames,DeclaredNames)
            hsFreeAndDeclared'  = applyTU (stop_tdTU (failTU
                                                        `adhocTU` expr
                                                        `adhocTU` pat
                                                        `adhocTU` bndrs
                                                        `adhocTU` binds
                                                        `adhocTU` bindList
                                                        `adhocTU` match
                                                        `adhocTU` stmtlist
                                                        `adhocTU` stmts
                                                        `adhocTU` rhs
                                                        `adhocTU` ltydecl
                                                        `adhocTU` tyvarbndrs
                                                        `adhocTU` lhstyvarbndr
  #if __GLASGOW_HASKELL__ > 710
                                                        `adhocTU` lsigtype
  #endif
                                                        `adhocTU` sig
                                                        `adhocTU` datadefn
                                                        `adhocTU` condecl
                                                        `adhocTU` condetails
                                                        `adhocTU` condeclfield
                                                        `adhocTU` hstype
                                                         )) t
  
  
            -- expr --
  #if __GLASGOW_HASKELL__ <= 710
            expr (GHC.L l (GHC.HsVar n))
  #else
            expr (GHC.L l (GHC.HsVar (GHC.L _ n)))
  #endif
              = return (FN [rdrName2NamePure nm (GHC.L l n)],DN [])
  
  #if __GLASGOW_HASKELL__ <= 710
            expr (GHC.L _ (GHC.OpApp e1 (GHC.L l (GHC.HsVar n)) _ e2)) = do
  #else
            expr (GHC.L _ (GHC.OpApp e1 (GHC.L l (GHC.HsVar (GHC.L _ n))) _ e2)) = do
  #endif
                efed <- hsFreeAndDeclaredRdr' nm [e1,e2]
                fd   <- addFree (rdrName2NamePure nm (GHC.L l n)) efed
                return fd
  
            expr (GHC.L _ ((GHC.HsLam (GHC.MG matches _ _ _))) :: GHC.LHsExpr GHC.RdrName) =
               hsFreeAndDeclaredRdr' nm matches
  
            expr (GHC.L _ ((GHC.HsLet decls e)) :: GHC.LHsExpr GHC.RdrName) =
              do
                (FN df,DN dd) <- hsFreeAndDeclaredRdr' nm decls
                (FN ef,_)  <- hsFreeAndDeclaredRdr' nm e
                return (FN (df `union` (ef \\ dd)),DN [])
  
  #if __GLASGOW_HASKELL__ <= 710
            expr (GHC.L _ (GHC.RecordCon ln _ e)) = do
  #else
            expr (GHC.L _ (GHC.RecordCon ln _ _ e)) = do
  #endif
              fd <- hsFreeAndDeclaredRdr' nm e
              addFree (rdrName2NamePure nm ln) fd   --Need Testing
  
            expr (GHC.L _ (GHC.EAsPat ln e)) = do
              fd <- (hsFreeAndDeclaredRdr' nm e)
              addFree (rdrName2NamePure nm ln) fd
  
            expr _ = mzero
  
  
            -- rhs --
            rhs ((GHC.GRHSs g ds) :: GHC.GRHSs GHC.RdrName (GHC.LHsExpr GHC.RdrName))
              = do (FN df,DN dd) <- hsFreeAndDeclaredRdr' nm g
                   (FN ef,DN ed) <- hsFreeAndDeclaredRdr' nm ds
                   return (FN $ df ++ ef, DN $ dd ++ ed)
  
  
            -- pat --
            pat :: GHC.LPat GHC.RdrName -> Either String (FreeNames,DeclaredNames)
            pat (GHC.L _ (GHC.WildPat _)) = mzero
  #if __GLASGOW_HASKELL__ <= 710
            pat (GHC.L l (GHC.VarPat n))
  #else
            pat (GHC.L l (GHC.VarPat (GHC.L _ n)))
  #endif
              = return (FN [],DN [rdrName2NamePure nm (GHC.L l n)])
            pat (GHC.L _ (GHC.AsPat ln p)) = do
              (f,DN d) <- hsFreeAndDeclaredRdr' nm p
              return (f,DN (rdrName2NamePure nm ln:d))
  
            pat (GHC.L _ (GHC.ParPat p)) = pat p
            pat (GHC.L _ (GHC.BangPat p)) = pat p
            pat (GHC.L _ (GHC.ListPat ps _ _)) = do
              fds <- mapM pat ps
              return $ mconcat fds
            pat (GHC.L _ (GHC.TuplePat ps _ _)) = do
              fds <- mapM pat ps
              return $ mconcat fds
            pat (GHC.L _ (GHC.PArrPat ps _)) = do
              fds <- mapM pat ps
              return $ mconcat fds
            pat (GHC.L _ (GHC.ConPatIn n det)) = do
              (FN f,DN d) <- details det
              return $ (FN [rdrName2NamePure nm n],DN d) <> (FN [],DN f)
            pat (GHC.L _ (GHC.ViewPat e p _)) = do
              fde <- hsFreeAndDeclaredRdr' nm e
              fdp <- pat p
              return $ fde <> fdp
            -- pat (GHC.QuasiQuotePat _)
            pat (GHC.L _ (GHC.LitPat _)) = return emptyFD
  #if __GLASGOW_HASKELL__ <= 710
            pat (GHC.L _ (GHC.NPat _ _ _)) = return emptyFD
            pat (GHC.L _ (GHC.NPlusKPat n _ _ _)) = return (FN [],DN [rdrName2NamePure nm n])
  #else
            pat (GHC.L _ (GHC.NPat _ _ _ _)) = return emptyFD
            pat (GHC.L _ (GHC.NPlusKPat n _ _ _ _ _)) = return (FN [],DN [rdrName2NamePure nm n])
  #endif
            pat (GHC.L _ _p@(GHC.SigPatIn p b)) = do
              fdp <- pat p
              (FN fb,DN _db) <- hsFreeAndDeclaredRdr' nm b
              -- error $ "pat.SigPatIn:(b,fb,db)" ++ showGhc (b,fb,db)
              return $ fdp <> (FN fb,DN [])
            pat (GHC.L _ (GHC.SigPatOut p _)) = pat p
            pat (GHC.L l (GHC.CoPat _ p _)) = pat (GHC.L l p)
  
            pat (GHC.L _ (GHC.LazyPat p)) = pat p
  
            pat (GHC.L _ (GHC.ConPatOut {})) = error $ "hsFreeAndDeclaredRdr'.pat:impossible: ConPatOut"
  
  #if __GLASGOW_HASKELL__ <= 710
            pat (GHC.L _ (GHC.SplicePat (GHC.HsSplice _ e))) = hsFreeAndDeclaredRdr' nm e
  #else
            pat (GHC.L _ (GHC.SplicePat (GHC.HsQuasiQuote {})))     = return (FN [], DN [])
            pat (GHC.L _ (GHC.SplicePat (GHC.HsTypedSplice _ e)))   = hsFreeAndDeclaredRdr' nm e
            pat (GHC.L _ (GHC.SplicePat (GHC.HsUntypedSplice _ e))) = hsFreeAndDeclaredRdr' nm e
  #endif
  
  #if __GLASGOW_HASKELL__ <= 710
            pat (GHC.L _ (GHC.QuasiQuotePat _)) = return (FN [], DN [])
  #endif
  
            -- pat p = error $ "hsFreeAndDeclaredRdr'.pat:unimplemented:" ++ (showGhc p)
  
            -- ---------------------------
  
            details :: GHC.HsConPatDetails GHC.RdrName -> Either String (FreeNames,DeclaredNames)
            details (GHC.PrefixCon  args) = do
              fds <- mapM pat args
              return $ mconcat fds
            details (GHC.RecCon recf) =
              recfields recf
            details (GHC.InfixCon arg1 arg2) = do
              fds <- mapM pat [arg1,arg2]
              return $ mconcat fds
  
            -- Note: this one applies to HsRecFields in LPats
            recfields :: (GHC.HsRecFields GHC.RdrName (GHC.LPat GHC.RdrName)) -> Either String (FreeNames,DeclaredNames)
            recfields (GHC.HsRecFields fields _) = do
              let args = map (\(GHC.L _ (GHC.HsRecField _ arg _)) -> arg) fields
              fds <- mapM pat args
              return $ mconcat fds
  
            -- -----------------------
  
  #if __GLASGOW_HASKELL__ <= 710
            bndrs :: GHC.HsWithBndrs GHC.RdrName (GHC.LHsType GHC.RdrName) -> Either String (FreeNames,DeclaredNames)
            bndrs (GHC.HsWB thing _ _ _) = do
              (FN ft,DN _dt) <- hsFreeAndDeclaredRdr' nm thing
              return (FN ft,DN [])
  #else
            bndrs :: GHC.LHsSigWcType GHC.RdrName -> Either String (FreeNames,DeclaredNames)
            bndrs (GHC.HsIB _ (GHC.HsWC _ _ ty)) = do
              (FN ft,DN _dt) <- hsFreeAndDeclaredRdr' nm ty
              -- return (FN dt,DN [])
              return (FN ft,DN [])
  #endif
  
            -- ---------------------------
  
            bindList (ds :: [GHC.LHsBind GHC.RdrName])
              =do (FN f,DN d) <- recurseList ds
                  return (FN (f\\d),DN d)
  
            -- match and patBind, same type--
  #if __GLASGOW_HASKELL__ <= 710
            binds ((GHC.FunBind ln _ (GHC.MG matches _ _ _) _ _fvs _) :: GHC.HsBind GHC.RdrName)
  #else
            binds ((GHC.FunBind ln (GHC.MG matches _ _ _) _ _fvs _) :: GHC.HsBind GHC.RdrName)
  #endif
              = do
                  (FN pf,_pd) <- hsFreeAndDeclaredRdr' nm matches
                  let n = rdrName2NamePure nm ln
                  return (FN (pf \\ [n]) ,DN [n])
  
            -- patBind --
            binds (GHC.PatBind pat' prhs _ _ds _) =
              do
                (FN pf,DN pd) <- hsFreeAndDeclaredRdr' nm pat'
                (FN rf,DN rd) <- hsFreeAndDeclaredRdr' nm prhs
                return (FN $ pf `union` (rf \\ pd),DN $ pd ++ rd)
  
            binds _ = mzero
  
            match ((GHC.Match _fn pats _mtype mrhs) :: GHC.Match GHC.RdrName (GHC.LHsExpr GHC.RdrName))
              = do
                (FN pf,DN pd) <- hsFreeAndDeclaredRdr' nm pats
                (FN rf,DN rd) <- hsFreeAndDeclaredRdr' nm mrhs
                return (FN (pf `union` (rf \\ (pd `union` rd))),DN [])
  
            stmtlist (ds :: [GHC.ExprLStmt GHC.RdrName]) = do
              (FN f,DN d) <- recurseList ds
              -- unless (null ds) $ do
              --   -- error $ "hsFreeAndDeclaredRdr'.stmtlist ds=" ++ showGhc ds
              --   error $ "hsFreeAndDeclaredRdr'.stmtlist (f,d)=" ++ showGhc (f,d)
              return (FN (f\\d),DN d)
  
            -- stmts --
  #if __GLASGOW_HASKELL__ <= 710
            stmts ((GHC.BindStmt pat' expre _bindOp _failOp) :: GHC.Stmt GHC.RdrName (GHC.LHsExpr GHC.RdrName)) = do
  #else
            stmts ((GHC.BindStmt pat' expre _bindOp _failOp _) :: GHC.Stmt GHC.RdrName (GHC.LHsExpr GHC.RdrName)) = do
  #endif
              -- TODO ++AZ++ : Not sure it is meaningful to pull
              --               anything out of bindOp/failOp
              (FN pf,DN pd)  <- hsFreeAndDeclaredRdr' nm pat'
              -- error $ "hsFreeAndDeclaredRdr'.stmts.BindStmt (pf,pd)=" ++ showGhc (pf,pd)
              (FN ef,_ed) <- hsFreeAndDeclaredRdr' nm expre
              let sf1 = []
              return (FN $ pf `union` ef `union` (sf1\\pd),DN pd) -- pd) -- Check this
  
            stmts ((GHC.LetStmt binds') :: GHC.Stmt GHC.RdrName (GHC.LHsExpr GHC.RdrName)) =
              hsFreeAndDeclaredRdr' nm binds'
  
            stmts _ = mzero
  
            -- tycldecls -----------------
  
            ltydecl :: GHC.TyClDecl GHC.RdrName -> Either String (FreeNames,DeclaredNames)
  
            ltydecl (GHC.FamDecl fd) = hsFreeAndDeclaredRdr' nm fd
            ltydecl (GHC.SynDecl ln _bndrs _rhs _fvs)
                = return (FN [],DN [rdrName2NamePure nm ln])
  #if __GLASGOW_HASKELL__ <= 710
            ltydecl (GHC.DataDecl ln tyvars defn _fvs) = do
                -- let dds = map (rdrName2NamePure nm) $ concatMap (GHC.con_names . GHC.unLoc) $ GHC.dd_cons defn
  #else
            ltydecl (GHC.DataDecl ln tyvars defn _c _fvs) = do
  #endif
                (FN fs,DN dds) <- hsFreeAndDeclaredRdr' nm  defn
                (FN _ft,DN dt) <- hsFreeAndDeclaredRdr' nm  tyvars
                return (FN (fs \\ dt),DN (rdrName2NamePure nm ln:dds))
            ltydecl (GHC.ClassDecl ctx ln tyvars
                             _fds sigs meths ats atds _docs _fvs) = do
               ct  <- hsFreeAndDeclaredRdr' nm ctx
               (_,DN tv)  <- hsFreeAndDeclaredRdr' nm tyvars
               ss  <- recurseList sigs
               md  <- hsFreeAndDeclaredRdr' nm meths
               ad  <- hsFreeAndDeclaredRdr' nm ats
               atd <- hsFreeAndDeclaredRdr' nm atds
               let (FN ff,DN df) = ((FN [],DN [rdrName2NamePure nm ln]) <> md <> ad <> atd <> ct <> ss)
               return (FN (nub ff \\ tv), DN df)
  
            ------------------------------
  
  #if __GLASGOW_HASKELL__ <= 710
            tyvarbndrs :: GHC.LHsTyVarBndrs GHC.RdrName -> Either String (FreeNames,DeclaredNames)
            tyvarbndrs (GHC.HsQTvs _implicit explicit) = do
              recurseList explicit
  #else
            tyvarbndrs :: GHC.LHsQTyVars GHC.RdrName -> Either String (FreeNames,DeclaredNames)
            tyvarbndrs (GHC.HsQTvs _implicit explicit _dependent ) = recurseList explicit
  #endif
  
            lhstyvarbndr :: GHC.LHsTyVarBndr GHC.RdrName -> Either String (FreeNames,DeclaredNames)
  #if __GLASGOW_HASKELL__ <= 710
            lhstyvarbndr (GHC.L l (GHC.UserTyVar n)) = return (FN [], DN [rdrName2NamePure nm (GHC.L l n)])
  #else
            lhstyvarbndr (GHC.L _ (GHC.UserTyVar ln)) = return (FN [], DN [rdrName2NamePure nm ln])
  #endif
            lhstyvarbndr (GHC.L _ (GHC.KindedTyVar ln lk)) = do
              ks <- hsFreeAndDeclaredRdr' nm lk
              return ((FN [], DN [rdrName2NamePure nm ln]) <> ks)
  
            ------------------------------
  
  #if __GLASGOW_HASKELL__ > 710
            lsigtype :: GHC.LHsSigType GHC.RdrName -> Either String (FreeNames,DeclaredNames)
            lsigtype (GHC.HsIB _ typ) = do
              hsFreeAndDeclaredRdr' nm typ
  #endif
  
            ------------------------------
  
            sig :: GHC.Sig GHC.RdrName -> Either String (FreeNames,DeclaredNames)
  #if __GLASGOW_HASKELL__ <= 710
            sig (GHC.TypeSig lns typ _) = do
  #else
            sig (GHC.TypeSig lns typ) = do
  #endif
              (FN ft, dt) <- hsFreeAndDeclaredRdr' nm typ
              -- error $ "sig:ft=" ++ (intercalate "," $ map (\n -> showGhc n ++ (occAttributes $ GHC.occName n)) ft)
              return ((FN [],DN (map (rdrName2NamePure nm ) lns))
                       <> (FN (filter (not . GHC.isTyVarName) ft), dt))
  #if __GLASGOW_HASKELL__ <= 710
            sig (GHC.PatSynSig ln (_ef,GHC.HsQTvs _ns bndrs) ctx1 ctx2 typ) = do
              (_, DN bs) <- hsFreeAndDeclaredRdr' nm bndrs
              c1s <- hsFreeAndDeclaredRdr' nm ctx1
              c2s <- hsFreeAndDeclaredRdr' nm ctx2
              ts  <- hsFreeAndDeclaredRdr' nm typ
              let (FN f,DN d) = c1s <> c2s <> ts
                  fd = (FN (f \\ bs), DN d )
              return ((FN [],DN [rdrName2NamePure nm ln]) <> fd)
  #else
            sig (GHC.PatSynSig ln typ) = do
              ts <- hsFreeAndDeclaredRdr' nm typ
              return ((FN [],DN [rdrName2NamePure nm ln]) <> ts)
  #endif
  #if __GLASGOW_HASKELL__ <= 710
            sig (GHC.GenericSig lns typ) = do
  #else
            sig (GHC.ClassOpSig _ lns typ) = do
  #endif
              ts <- hsFreeAndDeclaredRdr' nm typ
              return ((FN [],DN (map (rdrName2NamePure nm) lns)) <> ts)
            sig (GHC.IdSig _ ) = error $ "hsFreeAndDeclaredRdr:IdSig should not occur"
            sig (GHC.FixSig fsig) = hsFreeAndDeclaredRdr' nm fsig
            sig (GHC.InlineSig ln _) = do
              return ((FN [],DN [rdrName2NamePure nm ln]) )
            sig (GHC.SpecSig ln typs _) = do
              ts <- recurseList typs
              return ((FN [rdrName2NamePure nm ln],DN []) <> ts)
            sig (GHC.SpecInstSig _ ssig) = hsFreeAndDeclaredRdr' nm ssig
            sig (GHC.MinimalSig _ _) = return mempty
  
            ------------------------------
  
            datadefn :: GHC.HsDataDefn GHC.RdrName -> Either String (FreeNames,DeclaredNames)
            datadefn (GHC.HsDataDefn _ ctxt mtyp mkind cons mderivs) = do
               cts <- mapM (hsFreeAndDeclaredRdr' nm) $ GHC.unLoc ctxt
               ts  <- maybeHelper mtyp
               ks  <- maybeHelper mkind
               cs  <- mapM (hsFreeAndDeclaredRdr' nm) cons
               ds  <- case mderivs of
                        Nothing           -> return (FN [],DN [])
                        Just (GHC.L _ ds) -> recurseList ds
               -- error $ "hit datadefn:[cts,ts,ks,cs,ds]=" ++ show (cts++ [ts,ks,ds] ++ cs)
               return $ mconcat [mconcat cts,ts,ks,mconcat cs,ds]
  
            ------------------------------
  
            condecl :: GHC.LConDecl GHC.RdrName -> Either String (FreeNames,DeclaredNames)
  #if __GLASGOW_HASKELL__ <= 710
            condecl (GHC.L _ (GHC.ConDecl ns _expr (GHC.HsQTvs _ns bndrs) ctxt
                                          dets res _ depc_syntax)) =
              case res of
                GHC.ResTyGADT ls typ -> do
                  (ft,_) <- hsFreeAndDeclaredRdr' nm typ
                  return (ft,DN (map (rdrName2NamePure nm) ns))
                GHC.ResTyH98 -> do
                  cs <- hsFreeAndDeclaredRdr' nm ctxt
                  ds <- hsFreeAndDeclaredRdr' nm dets
                  return ((FN [], DN (map (rdrName2NamePure nm) ns)) <> cs <> ds)
  #else
            condecl (GHC.L _ (GHC.ConDeclGADT ns typ _)) = do
              (ft,_) <- hsFreeAndDeclaredRdr' nm typ
              return (ft,DN (map (rdrName2NamePure nm) ns))
            condecl (GHC.L _ (GHC.ConDeclH98 n _ mctxt dets _)) = do
               cs <- maybeHelper mctxt
               ds <- hsFreeAndDeclaredRdr' nm dets
               return ((FN [], DN ([rdrName2NamePure nm n])) <> cs <> ds)
  #endif
  
            ------------------------------
  
            -- condetails :: GHC.HsConDetails (GHC.LBangType GHC.RdrName) (GHC.Located [GHC.LConDeclField GHC.RdrName])
            condetails :: GHC.HsConDeclDetails GHC.RdrName -> Either String (FreeNames,DeclaredNames)
            condetails (GHC.PrefixCon args)      = do
              -- TODO: get rid of the tyvars
              (FN fs,d) <- recurseList args
              return (FN (filter (not . GHC.isTyVarName) fs),d)
            condetails (GHC.RecCon (GHC.L _ fs)) = recurseList fs
            condetails (GHC.InfixCon a1 a2)      = do
              -- TODO: get rid of the tyvars
              (FN fs,d) <- recurseList [a1,a2]
              return (FN (filter (not . GHC.isTyVarName) fs),d)
  
            ------------------------------
  
            condeclfield :: GHC.LConDeclField GHC.RdrName -> Either String (FreeNames,DeclaredNames)
            condeclfield (GHC.L _ (GHC.ConDeclField fns typ _)) = do
  #if __GLASGOW_HASKELL__ <= 710
              let ns = fns
  #else
              let ns = map (GHC.rdrNameFieldOcc . GHC.unLoc) fns
  #endif
              dt <- hsFreeAndDeclaredRdr' nm typ
              return ((FN [],DN (map (rdrName2NamePure nm) ns)) <> dt)
  
            ------------------------------
  
            hstype :: GHC.LHsType GHC.RdrName -> Either String (FreeNames,DeclaredNames)
  #if __GLASGOW_HASKELL__ <= 710
            hstype (GHC.L _ (GHC.HsForAllTy _ _ _ _ typ)) = hsFreeAndDeclaredRdr' nm typ
  #else
            hstype (GHC.L _ (GHC.HsForAllTy _ typ)) = hsFreeAndDeclaredRdr' nm typ
  #endif
  #if __GLASGOW_HASKELL__ <= 710
            hstype (GHC.L l (GHC.HsTyVar n)) = return (FN [rdrName2NamePure nm (GHC.L l n)],DN [])
  #else
            hstype (GHC.L _ (GHC.HsTyVar n)) = return (FN [rdrName2NamePure nm n],DN [])
  #endif
            hstype (GHC.L _ (GHC.HsAppTy t1 t2)) = recurseList [t1,t2]
            hstype (GHC.L _ (GHC.HsFunTy t1 t2)) = recurseList [t1,t2]
            hstype (GHC.L _ (GHC.HsListTy typ)) = hsFreeAndDeclaredRdr' nm typ
            hstype (GHC.L _ (GHC.HsPArrTy typ)) = hsFreeAndDeclaredRdr' nm typ
            hstype (GHC.L _ (GHC.HsTupleTy _ typs)) = recurseList typs
            hstype (GHC.L _ (GHC.HsOpTy t1 _ t2)) = recurseList [t1,t2]
            hstype (GHC.L _ (GHC.HsParTy typ)) = hsFreeAndDeclaredRdr' nm typ
            hstype (GHC.L _ (GHC.HsIParamTy _ typ)) = hsFreeAndDeclaredRdr' nm typ
            hstype (GHC.L _ (GHC.HsEqTy t1 t2)) = recurseList [t1,t2]
            hstype (GHC.L _ (GHC.HsKindSig t1 t2)) = recurseList [t1,t2]
  #if __GLASGOW_HASKELL__ <= 710
            hstype (GHC.L _ (GHC.HsQuasiQuoteTy _)) = return emptyFD
  #endif
            hstype (GHC.L _ (GHC.HsSpliceTy _ _)) = return (FN [],DN [])
            hstype (GHC.L _ (GHC.HsDocTy _ typ)) = hsFreeAndDeclaredRdr' nm typ
            hstype (GHC.L _ (GHC.HsBangTy _ typ)) = hsFreeAndDeclaredRdr' nm typ
            hstype (GHC.L _ (GHC.HsRecTy cons)) = recurseList cons
            hstype (GHC.L _ (GHC.HsCoreTy _)) = return emptyFD
            hstype (GHC.L _ (GHC.HsExplicitListTy _ typs)) = recurseList typs
            hstype (GHC.L _ (GHC.HsExplicitTupleTy _ typs)) = recurseList typs
            hstype (GHC.L _ (GHC.HsTyLit _)) = return emptyFD
  #if __GLASGOW_HASKELL__ <= 710
            hstype (GHC.L _ (GHC.HsWrapTy _ typ)) = hsFreeAndDeclaredRdr' nm typ
  #endif
  #if __GLASGOW_HASKELL__ <= 710
            hstype (GHC.L _ (GHC.HsWildcardTy)) = return (FN [],DN [])
            hstype (GHC.L l (GHC.HsNamedWildcardTy n)) = return (FN [rdrName2NamePure nm (GHC.L l n)],DN [])
  #else
            hstype (GHC.L _ (GHC.HsWildCardTy _)) = return (FN [],DN [])
  #endif
  #if __GLASGOW_HASKELL__ > 710
            hstype (GHC.L _ (GHC.HsQualTy (GHC.L _ ctxt) ty)) = recurseList (ty:ctxt)
            hstype (GHC.L _ (GHC.HsAppsTy as)) = do
              fds <- mapM doApp as
              return $ mconcat fds
              where
                doApp (GHC.L _ (GHC.HsAppInfix n)) = return (FN [rdrName2NamePure nm n],DN [])
                doApp (GHC.L _ (GHC.HsAppPrefix ty)) = hstype ty
  #endif
  
            -- ---------------------------------
  
            recurseList xs = do
              fds <- mapM (hsFreeAndDeclaredRdr' nm) xs
              return $ mconcat fds
  
            maybeHelper mv = case mv of
              Nothing -> return (FN [], DN [])
              Just v -> hsFreeAndDeclaredRdr' nm v
  
            ------------------------------
  
            addFree :: GHC.Name -> (FreeNames,DeclaredNames)
                    -> Either String (FreeNames,DeclaredNames)
            addFree free (FN fr,de) = return (FN $ [free] `union` fr, de)
  
  
  -- ---------------------------------------------------------------------
  
  -- |Get the names of all types declared in the given declaration
  -- getDeclaredTypesRdr :: GHC.LTyClDecl GHC.RdrName -> RefactGhc [GHC.Name]
  getDeclaredTypesRdr :: GHC.LHsDecl GHC.RdrName -> RefactGhc [GHC.Name]
  getDeclaredTypesRdr (GHC.L _ (GHC.TyClD decl)) = do
    nm <- getRefactNameMap
    case decl of
  #if __GLASGOW_HASKELL__ <= 710
      (GHC.FamDecl (GHC.FamilyDecl _ ln _ _)) -> return [rdrName2NamePure nm ln]
  #else
      (GHC.FamDecl (GHC.FamilyDecl _ ln _ _ _)) -> return [rdrName2NamePure nm ln]
  #endif
      (GHC.SynDecl ln  _ _ _) -> return [rdrName2NamePure nm ln]
  #if __GLASGOW_HASKELL__ <= 710
      (GHC.DataDecl ln _ defn _) -> do
        let dds = concatMap (GHC.con_names . GHC.unLoc) $ GHC.dd_cons defn
  #else
      (GHC.DataDecl ln _ defn _ _) -> do
        let dds = concatMap (GHC.getConNames . GHC.unLoc) $ GHC.dd_cons defn
  #endif
        let ddns = map (rdrName2NamePure nm) dds
        return $ [rdrName2NamePure nm ln] ++ ddns
  
      (GHC.ClassDecl _ ln _vars _fds sigs meths ats _atdefs _ _fvs) -> do
        -- msn <- getMsn meths
        let msn = getDeclaredVarsRdr nm (map wrapDecl $ GHC.bagToList meths)
        let fds = map (GHC.fdLName . GHC.unLoc) ats
            fds' = map (rdrName2NamePure nm) fds
        return $ nub $ [rdrName2NamePure nm ln] ++ ssn ++ msn ++ fds' -- ++ asn
        where
          getLSig :: GHC.LSig GHC.RdrName -> [GHC.Name]
  #if __GLASGOW_HASKELL__ <= 710
          getLSig (GHC.L _ (GHC.TypeSig ns _ _))  = map (rdrName2NamePure nm) ns
  #else
          getLSig (GHC.L _ (GHC.TypeSig ns _))  = map (rdrName2NamePure nm) ns
  #endif
  #if __GLASGOW_HASKELL__ <= 710
          getLSig (GHC.L _ (GHC.GenericSig ns _)) = map (rdrName2NamePure nm) ns
  #else
          getLSig (GHC.L _ (GHC.ClassOpSig _ ns _)) = map (rdrName2NamePure nm) ns
  #endif
          getLSig (GHC.L _ (GHC.IdSig _n)) = []
          getLSig (GHC.L _ (GHC.InlineSig ln2 _)) = [rdrName2NamePure nm ln2]
          getLSig (GHC.L _ (GHC.SpecSig ln2 _ _)) = [rdrName2NamePure nm ln2]
          getLSig (GHC.L _ (GHC.SpecInstSig _ _)) = []
          getLSig (GHC.L _ (GHC.FixSig _)) = []
  #if __GLASGOW_HASKELL__ <= 710
          getLSig (GHC.L _ (GHC.PatSynSig _ _ _ _ _)) = error "To implement: getLSig PatSynSig"
  #else
          getLSig (GHC.L _ (GHC.PatSynSig _ _)) = error "To implement: getLSig PatSynSig"
  #endif
          getLSig (GHC.L _ (GHC.MinimalSig _ _)) = error "To implement: getLSig PatSynSig"
  
          ssn = concatMap getLSig sigs
  getDeclaredTypesRdr _ = return []
  
  -- ---------------------------------------------------------------------
  
  -- | Return True if the specified Name ocuurs in the given syntax phrase.
  findNameInRdr :: (SYB.Data t) => NameMap -> GHC.Name -> t -> Bool
  findNameInRdr nm pn t = findNamesRdr nm [pn] t
  
  -- ---------------------------------------------------------------------
  
  -- | Return True if any of the specified PNames ocuur in the given syntax phrase.
  findNamesRdr :: (SYB.Data t) => NameMap -> [GHC.Name] -> t -> Bool
  findNamesRdr nm pns t =
    isJust $ SYB.something (inName) t
      where
        -- r = (SYB.everythingStaged SYB.Parser mappend mempty (inName) t)
  
        checker :: GHC.Located GHC.RdrName -> Maybe Bool
        checker ln
           | elem (GHC.nameUnique (rdrName2NamePure nm ln)) uns = Just True
        checker _ = Nothing
  
        inName :: (SYB.Typeable a) => a -> Maybe Bool
        inName = nameSybQuery checker
  
        uns = map GHC.nameUnique pns
  
  -- ---------------------------------------------------------------------
  
  definedPNsRdr :: GHC.LHsDecl GHC.RdrName -> [GHC.Located GHC.RdrName]
  #if __GLASGOW_HASKELL__ <= 710
  definedPNsRdr (GHC.L _ (GHC.ValD (GHC.FunBind pname _ _ _ _ _)))   = [pname]
  #else
  definedPNsRdr (GHC.L _ (GHC.ValD (GHC.FunBind pname _ _ _ _)))   = [pname]
  #endif
  definedPNsRdr (GHC.L _ (GHC.ValD (GHC.PatBind p _rhs _ty _fvs _))) = (hsNamessRdr p)
  -- VarBind will never occur in ParsedSource
  -- TODO: what about GHC.AbsBinds?
  definedPNsRdr  _ = []
  
  -- ---------------------------------------------------------------------
  
  definedNamesRdr :: NameMap -> GHC.LHsDecl GHC.RdrName -> [GHC.Name]
  definedNamesRdr nameMap bind = map (rdrName2NamePure nameMap) (definedPNsRdr bind)
  
  -- ---------------------------------------------------------------------
  
  -- |Find those declarations(function\/pattern binding) which define
  -- the specified GHC.Names. incTypeSig indicates whether the
  -- corresponding type signature will be included.
  definingDeclsRdrNames ::
              NameMap
              -> [GHC.Name]   -- ^ The specified identifiers.
              -> [GHC.LHsDecl GHC.RdrName] -- ^ A collection of declarations.
              -> Bool       -- ^ True means to include the type signature.
              -> Bool       -- ^ True means to look at the local declarations as well.
              -> [GHC.LHsDecl GHC.RdrName]  -- ^ The result.
  definingDeclsRdrNames nameMap pns ds incTypeSig recursive = concatMap defining ds
  -- TODO: Maybe Use hsFreeAndDeclaredRdr to see what is declared in a decl. Recursive?
    where
     defining decl
       = if recursive
          then SYB.everything  (++) ([]  `SYB.mkQ` definesDecl `SYB.extQ` definesBind)  decl
          else definesDecl decl
       where
        definesDecl :: (GHC.LHsDecl GHC.RdrName) -> [GHC.LHsDecl GHC.RdrName]
  #if __GLASGOW_HASKELL__ <= 710
        definesDecl decl'@(GHC.L _ (GHC.ValD (GHC.FunBind _ _ _ _ _ _)))
  #else
        definesDecl decl'@(GHC.L _ (GHC.ValD (GHC.FunBind _ _ _ _ _)))
  #endif
          | any (\n -> definesDeclRdr nameMap n decl') pns = [decl']
  
        definesDecl decl'@(GHC.L _l (GHC.ValD (GHC.PatBind _p _rhs _ty _fvs _)))
          | any (\n -> definesDeclRdr nameMap n decl') pns = [decl']
  
        definesDecl decl'@(GHC.L _l (GHC.TyClD _))
          | any (\n -> definesNameRdr nameMap n decl') pns = [decl']
  
        definesDecl decl'@(GHC.L _l (GHC.SigD _))
          | incTypeSig && any (\n -> definesNameRdr nameMap n decl') pns = [decl']
  
        definesDecl _ = []
  
        definesBind :: (GHC.LHsBind GHC.RdrName) -> [GHC.LHsDecl GHC.RdrName]
        definesBind (GHC.L l b) = definesDecl (GHC.L l (GHC.ValD b))
  
  -- ---------------------------------------------------------------------
  
  -- |Find those declarations(function\/pattern binding) which define
  -- the specified GHC.Names. incTypeSig indicates whether the corresponding type
  -- signature will be included.
  definingDeclsRdrNames' :: (SYB.Data t)
              => NameMap
              -> [GHC.Name]   -- ^ The specified identifiers.
              -> t            -- ^ A collection of declarations.
              -> [GHC.LHsDecl GHC.RdrName]  -- ^ The result.
  definingDeclsRdrNames' nameMap pns ds = defining ds
    where
     defining decl
       = SYB.everythingStaged SYB.Renamer (++) [] ([]  `SYB.mkQ` defines' `SYB.extQ` definesBind) decl
       where
        defines' :: (GHC.LHsDecl GHC.RdrName) -> [GHC.LHsDecl GHC.RdrName]
        defines' decl'@(GHC.L _ (GHC.ValD (GHC.FunBind{})))
          | any (\n -> definesDeclRdr nameMap n decl') pns = [decl']
  
        defines' decl'@(GHC.L _l (GHC.ValD (GHC.PatBind _p _rhs _ty _fvs _)))
          | any (\n -> definesDeclRdr nameMap n decl') pns = [decl']
  
        defines' decl'@(GHC.L _l (GHC.TyClD _))
          | any (\n -> definesDeclRdr nameMap n decl') pns = [decl']
  
        defines' _ = []
  
        definesBind :: (GHC.LHsBind GHC.RdrName) -> [GHC.LHsDecl GHC.RdrName]
        definesBind (GHC.L l b) = defines' (GHC.L l (GHC.ValD b))
  
  -- ---------------------------------------------------------------------
  
  -- |Find those type signatures for the specified GHC.Names.
  definingSigsRdrNames :: (SYB.Data t) =>
              NameMap
              ->[GHC.Name] -- ^ The specified identifiers.
              ->t        -- ^ A collection of declarations.
              ->[GHC.LSig GHC.RdrName]  -- ^ The result.
  definingSigsRdrNames nameMap pns ds = def ds
    where
     def decl
       -- = SYB.everythingStaged SYB.Renamer (++) [] ([]  `SYB.mkQ` inSig) decl
       = SYB.everything (++) ([]  `SYB.mkQ` inSig `SYB.extQ` inSigDecl) decl
       where
        inSigDecl :: GHC.LHsDecl GHC.RdrName -> [GHC.LSig GHC.RdrName]
        inSigDecl (GHC.L l (GHC.SigD s)) = inSig (GHC.L l s)
        inSigDecl _ = []
  
        inSig :: (GHC.LSig GHC.RdrName) -> [GHC.LSig GHC.RdrName]
  #if __GLASGOW_HASKELL__ <= 710
        inSig (GHC.L l (GHC.TypeSig ns t p))
         | defines' ns /= [] = [(GHC.L l (GHC.TypeSig (defines' ns) t p))]
  #else
        inSig (GHC.L l (GHC.TypeSig ns t))
         | defines' ns /= [] = [(GHC.L l (GHC.TypeSig (defines' ns) t))]
  #endif
        inSig _ = []
  
        defines' :: [GHC.Located GHC.RdrName] -> [GHC.Located GHC.RdrName]
        defines' p
          -- = filter (\(GHC.L _ n) -> n `elem` pns) p
          = let
               isDefined :: GHC.Located GHC.RdrName -> [GHC.Located GHC.RdrName]
               isDefined ln = if (rdrName2NamePure nameMap ln) `elem` pns
                                then [ln]
                                else []
            in concatMap isDefined p
  
  -- ---------------------------------------------------------------------
  
  -- |Find those declarations which define the specified GHC.Names.
  definingTyClDeclsNames:: (SYB.Data t)
              => NameMap
              -> [GHC.Name]   -- ^ The specified identifiers.
              -> t -- ^ A collection of declarations.
              -> [GHC.LTyClDecl GHC.RdrName]  -- ^ The result.
  definingTyClDeclsNames nm pns t = defining t
    where
     defining decl
       = SYB.everythingStaged SYB.Parser (++) []
                     ([]  `SYB.mkQ` defines'
                          `SYB.extQ` definesDecl) decl
       where
        defines' :: (GHC.LTyClDecl GHC.RdrName) -> [GHC.LTyClDecl GHC.RdrName]
  #if __GLASGOW_HASKELL__ <= 710
        defines' decl'@(GHC.L _ (GHC.FamDecl (GHC.FamilyDecl _ pname _ _)))
  #else
        defines' decl'@(GHC.L _ (GHC.FamDecl (GHC.FamilyDecl _ pname _ _ _)))
  #endif
          | elem (GHC.nameUnique $ rdrName2NamePure nm pname) uns = [decl']
          | otherwise = []
  
        defines' decl'@(GHC.L _ (GHC.SynDecl pname _ _ _))
          | elem (GHC.nameUnique $ rdrName2NamePure nm pname) uns = [decl']
          | otherwise = []
  
  #if __GLASGOW_HASKELL__ <= 710
        defines' decl'@(GHC.L _ (GHC.DataDecl _ _ _ _))
  #else
        defines' decl'@(GHC.L _ (GHC.DataDecl _ _ _ _ _))
  #endif
          --   elem (GHC.nameUnique $ rdrName2NamePure nm pname) uns = [decl']
          | not $ null (dus `intersect` uns) = [decl']
          | otherwise = []
          where
            (_,DN ds) = hsFreeAndDeclaredRdr nm decl'
            dus = map GHC.nameUnique ds
  
        defines' decl'@(GHC.L _ (GHC.ClassDecl _ pname _ _ _ _ _ _ _ _))
          | elem (GHC.nameUnique $ rdrName2NamePure nm pname) uns = [decl']
          | otherwise = []
  
        definesDecl (GHC.L l (GHC.TyClD d)) = defines' (GHC.L l d)
        definesDecl _ = []
  
        uns = map (\n -> GHC.nameUnique n) pns
  
  -- ---------------------------------------------------------------------
  
  -- | Return True if the function\/pattern binding defines the
  -- specified identifier.
  definesRdr :: NameMap -> GHC.Name -> GHC.LHsBind GHC.RdrName -> Bool
  #if __GLASGOW_HASKELL__ <= 710
  definesRdr nm  nin (GHC.L _ (GHC.FunBind ln _ _ _ _ _))
  #else
  definesRdr nm nin (GHC.L _ (GHC.FunBind ln _ _ _ _))
  #endif
    = GHC.nameUnique (rdrName2NamePure nm ln) == GHC.nameUnique nin
  definesRdr nm n (GHC.L _ (GHC.PatBind p _rhs _ty _fvs _))
    = elem n (map (rdrName2NamePure nm) (hsNamessRdr p))
  definesRdr _ _ _= False
  
  
  -- |Unwraps a LHsDecl and calls definesRdr on the result if a HsBind or calls clsDeclDefinesRdr if a TyClD
  definesDeclRdr :: NameMap -> GHC.Name -> GHC.LHsDecl GHC.RdrName -> Bool
  definesDeclRdr nameMap nin (GHC.L l (GHC.ValD d)) = definesRdr nameMap nin (GHC.L l d)
  definesDeclRdr nameMap nin (GHC.L _ (GHC.TyClD ty)) = clsDeclDefinesRdr nameMap nin ty
  definesDeclRdr _ _ _ = False
  
  -- | Return True of the type class declaration defines the
  -- specified identifier
  clsDeclDefinesRdr :: NameMap -> GHC.Name -> GHC.TyClDecl GHC.RdrName -> Bool
  clsDeclDefinesRdr nameMap nin (GHC.SynDecl (GHC.L ln _nm) _ty _rhs _) =
    case Map.lookup ln nameMap of
      Nothing -> False
      Just n  -> GHC.nameUnique n == GHC.nameUnique nin
  clsDeclDefinesRdr _ _ _ = False
  
  -- | Returns True if the provided Name is defined in the LHsDecl
  definesNameRdr :: NameMap -> GHC.Name -> GHC.LHsDecl GHC.RdrName -> Bool
  definesNameRdr nameMap nin (GHC.L l (GHC.ValD d))  = definesRdr nameMap nin (GHC.L l d)
  definesNameRdr nameMap nin d = nin `elem` declared
    where
      (_,DN declared) = hsFreeAndDeclaredRdr nameMap d
  -- definesDeclRdr _ _ _ = False
  
  -- ---------------------------------------------------------------------
  
  -- | Return True if the declaration defines the type signature of the
  -- specified identifier.
  definesTypeSigRdr :: NameMap -> GHC.Name -> GHC.Sig GHC.RdrName -> Bool
  #if __GLASGOW_HASKELL__ <= 710
  definesTypeSigRdr nameMap pn (GHC.TypeSig names _typ _)
  #else
  definesTypeSigRdr nameMap pn (GHC.TypeSig names _typ)
  #endif
    = elem (GHC.nameUnique pn) (map (GHC.nameUnique . rdrName2NamePure nameMap) names)
  -- definesTypeSigRdr _ _  _ = False
  definesTypeSigRdr _ _  x = error $ "definesTypeSigRdr : got " ++ SYB.showData SYB.Parser 0 x
  
  -- |Unwraps a LHsDecl and calls definesRdr on the result if a Sig
  definesSigDRdr :: NameMap -> GHC.Name -> GHC.LHsDecl GHC.RdrName -> Bool
  definesSigDRdr nameMap nin (GHC.L _ (GHC.SigD d)) = definesTypeSigRdr nameMap nin d
  definesSigDRdr _ _ _ = False
  
  -- ---------------------------------------------------------------------
  
  -- |Get all the names in the given syntax element
  hsNamessRdr :: (SYB.Data t) => t -> [GHC.Located GHC.RdrName]
  hsNamessRdr t = nub $ fromMaybe [] r
    where
       r = (SYB.everythingStaged SYB.Parser mappend mempty (inName) t)
  
       checker :: GHC.Located GHC.RdrName -> Maybe [GHC.Located GHC.RdrName]
       checker x = Just [x]
  
       inName :: (SYB.Typeable a) => a -> Maybe [GHC.Located GHC.RdrName]
       inName = nameSybQuery checker
  
  -- ---------------------------------------------------------------------
  
  -- |Does the given 'GHC.Name' appear as a 'GHC.Located' 'GHC.RdrName' anywhere in 't'?
  findLRdrName :: (SYB.Data t) => NameMap -> GHC.Name -> t -> Bool
  findLRdrName nm n t = isJust $ SYB.something isMatch t
    where
      checker :: GHC.Located GHC.RdrName -> Maybe Bool
      checker x
        | GHC.nameUnique (rdrName2NamePure nm x) == GHC.nameUnique n = Just True
        | otherwise = Nothing
  
      isMatch :: (SYB.Typeable a) => a -> Maybe Bool
      isMatch = nameSybQuery checker
  
  -- ---------------------------------------------------------------------
  
  
  getDeclaredVarsRdr :: NameMap -> [GHC.LHsDecl GHC.RdrName] -> [GHC.Name]
  getDeclaredVarsRdr nm bs = concatMap vars bs
    where
        vars :: (GHC.LHsDecl GHC.RdrName) -> [GHC.Name]
  #if __GLASGOW_HASKELL__ <= 710
        vars (GHC.L _ (GHC.ValD (GHC.FunBind ln _ _ _ _fvs _)))   = [rdrName2NamePure nm ln]
  #else
        vars (GHC.L _ (GHC.ValD (GHC.FunBind ln _ _ _ _fvs)))   = [rdrName2NamePure nm ln]
  #endif
        vars (GHC.L _ (GHC.ValD (GHC.PatBind p _rhs _ty _fvs _))) = (map (rdrName2NamePure nm) $ hsNamessRdr p)
        vars _ = []
  
  --------------------------------------------------------------------------------
  -- | Same as `hsVisiblePNsRdr' except that the returned identifiers are
  -- in String format.
  hsVisibleNamesRdr:: (SYB.Data t2)
    => GHC.Name -> t2 -> RefactGhc [String]
  hsVisibleNamesRdr e t = do
      nm <- getRefactNameMap
      (DN d) <- hsVisibleDsRdr nm e t
      return ((nub . map showGhc) d)
  
  ------------------------------------------------------------------------
  
  -- | Given a 'Name' n and a syntax phrase t, if n occurs in t, then return those
  -- variables which are declared in t and accessible to n, otherwise
  -- return [].
  hsVisibleDsRdr :: (SYB.Data t)
               => NameMap -> GHC.Name -> t -> RefactGhc DeclaredNames
  -- TODO: DeclaredNames is probably the wrong type. Perhaps create VisibleNames
  --       And perhaps use a NameSet or Set, to avoid the nub call
  hsVisibleDsRdr nm e t = do
    -- logm $ "hsVisibleDsRdr:(e,t)=" ++ (SYB.showData SYB.Renamer 0 (e,t))
    (DN d) <- res
    return (DN (nub d))
    where
      -- TODO: this is effectively a recursive descent approach, where
      --       each syntax element processor knows exactly what it needs
      --       in terms of sub-elements. Hence as an optimisation,
      --       consider calling the relevent element directly, instead
      --       of looping back into the main function.
      --  OR, use a more effective recursion scheme
      res = (const err -- (DN [])
            `SYB.extQ` parsed
            `SYB.extQ` lvalbinds
            `SYB.extQ` valbinds
            `SYB.extQ` lhsdecls
            `SYB.extQ` lhsdecl
            `SYB.extQ` lhsbindslr
            `SYB.extQ` hsbinds
            `SYB.extQ` hsbind
            `SYB.extQ` hslocalbinds
            `SYB.extQ` lmatch
            `SYB.extQ` match
            `SYB.extQ` grhss
            `SYB.extQ` lgrhs
            `SYB.extQ` lexpr
            `SYB.extQ` tyclgroups
            `SYB.extQ` tyclgroup
            `SYB.extQ` tycldeclss
            `SYB.extQ` tycldecls
            `SYB.extQ` ltycldecl
            `SYB.extQ` tycldecl
            `SYB.extQ` hsdatadefn
            `SYB.extQ` condecl
            `SYB.extQ` instdecls
            `SYB.extQ` instdecl
            `SYB.extQ` lhstype
            `SYB.extQ` lsigs
            `SYB.extQ` lsig
            `SYB.extQ` lstmts
            `SYB.extQ` lstmt
            `SYB.extQ` lpats
            `SYB.extQ` lpat
  #if __GLASGOW_HASKELL__ > 710
            `SYB.extQ` ibndrs
            `SYB.extQ` lsigty
  #endif
            `SYB.extQ` lanndecl
            ) t
  
      -- err2 = error $ "hsVisibleDsRdr:err2:no match for:" ++ (SYB.showData SYB.Renamer 0 t)
  
      parsed :: GHC.ParsedSource -> RefactGhc DeclaredNames
      parsed p
        | findNameInRdr nm e p = do
           -- dfds <- mapM (hsVisibleDsRdr nm e) $ GHC.hsmodDecls $ GHC.unLoc p
           -- logm $ "hsVisibleDsRdr parsedSource:decls starting"
           dfds <- mapM (declFun ( hsVisibleDsRdr nm e) ) $ GHC.hsmodDecls $ GHC.unLoc p
           -- logm $ "hsVisibleDsRdr parsedSource:decls done"
           return $ mconcat dfds
      parsed _ = return (DN [])
  
      lvalbinds :: (GHC.Located (GHC.HsLocalBinds GHC.RdrName)) -> RefactGhc DeclaredNames
      lvalbinds (GHC.L _ (GHC.HsValBinds vb)) = valbinds vb
      lvalbinds (GHC.L _ (GHC.HsIPBinds _))   = return (DN [])
      lvalbinds (GHC.L _ GHC.EmptyLocalBinds) = return (DN [])
  
      valbinds :: (GHC.HsValBinds GHC.RdrName) -> RefactGhc DeclaredNames
      valbinds vb@(GHC.ValBindsIn bindsBag sigs)
        | findNameInRdr nm e vb = do
            fdsb <- mapM (hsVisibleDsRdr nm e) $ GHC.bagToList bindsBag
            fdss <- mapM (hsVisibleDsRdr nm e) sigs
            return $ mconcat fdss <> mconcat fdsb
      valbinds vb@(GHC.ValBindsOut _binds _sigs)
        | findNameInRdr nm e vb = do
            -- logm $ "hsVisibleDsRdr valbinds:ValBindsOut:impossible for RdrName"
            return (DN [])
  
      valbinds _ = do
        -- logm $ "hsVisibleDsRdr nm.valbinds:not matched"
        return (DN [])
  
      lhsdecls :: [GHC.LHsDecl GHC.RdrName] -> RefactGhc DeclaredNames
      lhsdecls ds
        | findNameInRdr nm e ds = do
           dfds <- mapM (declFun ( hsVisibleDsRdr nm e) ) ds
           return $ mconcat dfds
      lhsdecls _ = return (DN [])
  
      lhsdecl :: GHC.LHsDecl GHC.RdrName -> RefactGhc DeclaredNames
      lhsdecl (GHC.L l dd) = do
          -- logm $ "hsVisibleDsRdr.lhsdecl"
          case dd of
              GHC.TyClD d       -> hsVisibleDsRdr nm e (GHC.L l d)
              GHC.InstD d       -> hsVisibleDsRdr nm e (GHC.L l d)
              GHC.DerivD d      -> hsVisibleDsRdr nm e (GHC.L l d)
              GHC.ValD d        -> hsVisibleDsRdr nm e (GHC.L l d)
              GHC.SigD d        -> hsVisibleDsRdr nm e (GHC.L l d)
              GHC.DefD d        -> hsVisibleDsRdr nm e (GHC.L l d)
              GHC.ForD d        -> hsVisibleDsRdr nm e (GHC.L l d)
              GHC.WarningD d    -> hsVisibleDsRdr nm e (GHC.L l d)
              GHC.AnnD d        -> hsVisibleDsRdr nm e (GHC.L l d)
              GHC.RuleD d       -> hsVisibleDsRdr nm e (GHC.L l d)
              GHC.VectD d       -> hsVisibleDsRdr nm e (GHC.L l d)
              GHC.SpliceD d     -> hsVisibleDsRdr nm e (GHC.L l d)
              GHC.DocD d        -> hsVisibleDsRdr nm e (GHC.L l d)
              GHC.RoleAnnotD d  -> hsVisibleDsRdr nm e (GHC.L l d)
  #if __GLASGOW_HASKELL__ < 711
              GHC.QuasiQuoteD d -> hsVisibleDsRdr nm e (GHC.L l d)
  #endif
  
      lhsbindslr :: GHC.LHsBinds GHC.RdrName -> RefactGhc DeclaredNames
      lhsbindslr bs = do
        fds <- mapM (hsVisibleDsRdr nm e) $ GHC.bagToList bs
        return $ mconcat fds
  
      hsbinds :: [GHC.LHsBind GHC.RdrName] -> RefactGhc DeclaredNames
      hsbinds ds
        | findNameInRdr nm e ds = do
          fds <- mapM (hsVisibleDsRdr nm e) ds
          return $ mconcat fds
      hsbinds _ = return (DN [])
  
      hsbind :: (GHC.LHsBind GHC.RdrName) -> RefactGhc DeclaredNames
  #if __GLASGOW_HASKELL__ <= 710
      hsbind ((GHC.L _ (GHC.FunBind _n _ (GHC.MG matches _ _ _) _ _ _)))
  #else
      hsbind ((GHC.L _ (GHC.FunBind _n (GHC.MG (GHC.L _ matches) _ _ _) _ _ _)))
  #endif
        | findNameInRdr nm e matches = do
            fds <- mapM (hsVisibleDsRdr nm e) matches
            return $ mconcat fds
      hsbind _ = do
        return (DN [])
  
  
      hslocalbinds :: (GHC.HsLocalBinds GHC.RdrName) -> RefactGhc DeclaredNames
      hslocalbinds (GHC.HsValBinds binds)
        | findNameInRdr nm e binds = hsVisibleDsRdr nm e binds
      hslocalbinds (GHC.HsIPBinds binds)
        | findNameInRdr nm e binds = hsVisibleDsRdr nm e binds
      hslocalbinds (GHC.EmptyLocalBinds) = return (DN [])
      hslocalbinds _ = return (DN [])
  
      lmatch :: (GHC.LMatch GHC.RdrName (GHC.LHsExpr GHC.RdrName)) -> RefactGhc DeclaredNames
      lmatch (GHC.L _ m) = match m
  
      match :: (GHC.Match GHC.RdrName (GHC.LHsExpr GHC.RdrName)) -> RefactGhc DeclaredNames
      match (GHC.Match _fn pats _mtyp rhs)
        | findNameInRdr nm e rhs || findNameInRdr nm e pats = do
             -- logm $ "hsVisibleDsRdr nm.lmatch:doing rhs"
             let (_pf,pd) = hsFreeAndDeclaredRdr nm pats
             -- logm $ "hsVisibleDsRdr nm.lmatch:(pf,pd)=" ++ (show (_pf,pd))
             rd <- hsVisibleDsRdr nm e rhs
             -- logm $ "hsVisibleDsRdr nm.lmatch:rd=" ++ (show rd)
             return (pd <> rd)
      match _ =return  (DN [])
  
      grhss :: (GHC.GRHSs GHC.RdrName (GHC.LHsExpr GHC.RdrName)) -> RefactGhc DeclaredNames
      grhss (GHC.GRHSs guardedRhss lstmts')
        | findNameInRdr nm e guardedRhss || findNameInRdr nm e lstmts' = do
            -- logm "hsVisibleDsRdr nm.grhss:about to do lstmts"
            fds <- mapM (hsVisibleDsRdr nm e) guardedRhss
            -- sfds <- hsVisibleDsRdr nm e lstmts'
            let (_,sfds) = hsFreeAndDeclaredRdr nm lstmts'
            return $ mconcat (sfds:fds)
      grhss _ = do
        -- logm $ "hsVisibleDsRdr.grhss: no match"
        return (DN [])
  
      lgrhs :: GHC.LGRHS GHC.RdrName (GHC.LHsExpr GHC.RdrName) -> RefactGhc DeclaredNames
      lgrhs (GHC.L _ (GHC.GRHS guards ex))
        | findNameInRdr nm e guards = hsVisibleDsRdr nm e guards
        | findNameInRdr nm e ex     = do
          r <- hsVisibleDsRdr nm e ex
          -- logm $ "hsVisibleDsRdr.lgrhs:r=" ++ show r
          return r
      lgrhs _ = do
        -- logm $ "hsVisibleDsRdr.lgrhs: no match"
        return (DN [])
  
  
      lexpr :: GHC.LHsExpr GHC.RdrName -> RefactGhc DeclaredNames
  #if __GLASGOW_HASKELL__ <= 710
      lexpr (GHC.L l (GHC.HsVar n))
  #else
      lexpr (GHC.L l (GHC.HsVar (GHC.L _ n)))
  #endif
        | findNameInRdr nm e n  = do
          -- logm $ "hsVisibleDsRdr.lexpr.HsVar entity found"
          return (DN [rdrName2NamePure nm (GHC.L l n)])
      lexpr (GHC.L _ (GHC.HsLet lbinds expr))
        | findNameInRdr nm e lbinds || findNameInRdr nm e expr  = do
          -- logm $ "hsVisibleDsRdr.lexpr.HsLet entity found"
          let (_,lds) = hsFreeAndDeclaredRdr nm lbinds
          let (_,eds) = hsFreeAndDeclaredRdr nm expr
          return $ lds <> eds
  
      lexpr expr
        | findNameInRdr nm e expr = do
          -- logm $ "hsVisibleDsRdr nm.lexpr.(e,expr):" ++ (showGhc (e,expr))
          let (FN efs,eds)         = hsFreeAndDeclaredRdr nm expr
          let (FN _eefs,DN eeds) = hsFreeAndDeclaredRdr nm e
          -- logm $ "hsVisibleDsRdr nm.lexpr (efs,_d,_eefs,eeds) " ++ show (efs,_d,_eefs,eeds)
          return (DN (efs \\ eeds) <> eds)
  
      lexpr x = do
        -- logm $ "hsVisibleDsRdr.lexpr:miss for:" ++ SYB.showData SYB.Parser 0 x
        return (DN [])
  
      -- ---------------------------------
  
      tyclgroups :: [GHC.TyClGroup GHC.RdrName] -> RefactGhc DeclaredNames
      tyclgroups tgrps
        | findNameInRdr nm e tgrps = do
          fds <- mapM (hsVisibleDsRdr nm e) tgrps
          return $ mconcat fds
      tyclgroups _ = return (DN [])
  
      tyclgroup :: GHC.TyClGroup GHC.RdrName -> RefactGhc DeclaredNames
      tyclgroup (GHC.TyClGroup tyclds _roles)
        | findNameInRdr nm e tyclds = do
          fds <- mapM (hsVisibleDsRdr nm e) tyclds
          return $ mconcat fds
      tyclgroup _ = return (DN [])
  
      tycldeclss :: [[GHC.LTyClDecl GHC.RdrName]] -> RefactGhc DeclaredNames
      tycldeclss tcds
        | findNameInRdr nm e tcds = do
          fds <- mapM (hsVisibleDsRdr nm e) tcds
          return $ mconcat fds
      tycldeclss _ = return (DN [])
  
      tycldecls :: [GHC.LTyClDecl GHC.RdrName] -> RefactGhc DeclaredNames
      tycldecls tcds
        | findNameInRdr nm e tcds = do
          fds <- mapM (hsVisibleDsRdr nm e) tcds
          return $ mconcat fds
      tycldecls _ = return (DN [])
  
      ltycldecl :: GHC.LTyClDecl GHC.RdrName -> RefactGhc DeclaredNames
      ltycldecl tcd
        | findNameInRdr nm e tcd = do
          let (_,ds) = hsFreeAndDeclaredRdr nm tcd
          return ds
      ltycldecl _ = return (DN [])
  
      tycldecl :: GHC.TyClDecl GHC.RdrName -> RefactGhc DeclaredNames
      tycldecl tcd
        | findNameInRdr nm e tcd = do
          let (_,ds) = hsFreeAndDeclaredRdr nm tcd
          return ds
      tycldecl _ = return (DN [])
  
      hsdatadefn :: GHC.HsDataDefn GHC.RdrName -> RefactGhc DeclaredNames
      hsdatadefn tcd
        | findNameInRdr nm e tcd = do
          let (_,ds) = hsFreeAndDeclaredRdr nm tcd
          return ds
      hsdatadefn _ = return (DN [])
  
      condecl :: GHC.ConDecl GHC.RdrName -> RefactGhc DeclaredNames
      condecl tcd
        | findNameInRdr nm e tcd = do
          let (_,ds) = hsFreeAndDeclaredRdr nm tcd
          return ds
      condecl _ = return (DN [])
  
      -- ---------------------------------
  
      instdecls :: [GHC.LInstDecl GHC.RdrName] -> RefactGhc DeclaredNames
      instdecls ds
        | findNameInRdr nm e ds = do
          fds <- mapM (hsVisibleDsRdr nm e) ds
          return $ mconcat fds
      instdecls _ = return (DN [])
  
      instdecl :: GHC.LInstDecl GHC.RdrName -> RefactGhc DeclaredNames
      instdecl (GHC.L _ (GHC.ClsInstD (GHC.ClsInstDecl polytyp binds sigs tyfaminsts dfaminsts _)))
        | findNameInRdr nm e polytyp    = hsVisibleDsRdr nm e polytyp
        | findNameInRdr nm e binds      = hsVisibleDsRdr nm e binds
        | findNameInRdr nm e sigs       = hsVisibleDsRdr nm e sigs
        | findNameInRdr nm e tyfaminsts = hsVisibleDsRdr nm e tyfaminsts
        | findNameInRdr nm e dfaminsts  = hsVisibleDsRdr nm e dfaminsts
        | otherwise = return (DN [])
      instdecl (GHC.L _ (GHC.DataFamInstD (GHC.DataFamInstDecl _ln pats defn _)))
        | findNameInRdr nm e pats = hsVisibleDsRdr nm e pats
        | findNameInRdr nm e defn = hsVisibleDsRdr nm e defn
        | otherwise = return (DN [])
      instdecl (GHC.L _ (GHC.TyFamInstD (GHC.TyFamInstDecl eqn _)))
        | findNameInRdr nm e eqn = hsVisibleDsRdr nm e eqn
        | otherwise = return (DN [])
  
      lhstype :: GHC.LHsType GHC.RdrName -> RefactGhc DeclaredNames
  #if __GLASGOW_HASKELL__ <= 710
      lhstype tv@(GHC.L l (GHC.HsTyVar n))
  #else
      lhstype tv@(GHC.L l (GHC.HsTyVar (GHC.L _ n)))
  #endif
        | findNameInRdr nm e tv = return (DN [rdrName2NamePure nm (GHC.L l n)])
        | otherwise       = return (DN [])
      lhstype (GHC.L _ (GHC.HsForAllTy {}))
          = return (DN [])
      lhstype (GHC.L _ (GHC.HsFunTy{})) = return (DN [])
      lhstype ty = do
        -- logm $ "lshtype: TypeUtils 1588" ++ SYB.showData SYB.Renamer 0 ty
        return (DN [])
  
      -- -----------------------
  
      lsigs :: [GHC.LSig GHC.RdrName] -> RefactGhc DeclaredNames
      lsigs ss = do
        fds <- mapM (hsVisibleDsRdr nm e) ss
        return $ mconcat fds
  
      -- -----------------------
  
      lsig :: GHC.LSig GHC.RdrName -> RefactGhc DeclaredNames
  #if __GLASGOW_HASKELL__ <= 710
      lsig (GHC.L _ (GHC.TypeSig _ns typ _))
  #else
      lsig (GHC.L _ (GHC.TypeSig _ns typ))
  #endif
        | findNameInRdr nm e typ = hsVisibleDsRdr nm e typ
  #if __GLASGOW_HASKELL__ <= 710
      lsig (GHC.L _ (GHC.GenericSig _n typ))
  #else
      lsig (GHC.L _ (GHC.ClassOpSig _ _n (GHC.HsIB _ typ)))
  #endif
        | findNameInRdr nm e typ = hsVisibleDsRdr nm e typ
      lsig (GHC.L _ (GHC.IdSig _)) = return (DN [])
      lsig (GHC.L _ (GHC.InlineSig _ _)) = return (DN [])
      lsig (GHC.L _ (GHC.SpecSig _n typ _))
        | findNameInRdr nm e typ = hsVisibleDsRdr nm e typ
      lsig (GHC.L _ (GHC.SpecInstSig _ _)) = return (DN [])
  
      lsig _ = return (DN [])
  
      -- -----------------------
  
      lstmts :: [GHC.LStmt GHC.RdrName (GHC.LHsExpr GHC.RdrName)] -> RefactGhc DeclaredNames
      lstmts ds
        | findNameInRdr nm e ds = do
          fds <- mapM (hsVisibleDsRdr nm e) ds
          return $ mconcat fds
      lstmts _ = return (DN [])
  
      -- -----------------------
  
      lstmt :: GHC.LStmt GHC.RdrName (GHC.LHsExpr GHC.RdrName) -> RefactGhc DeclaredNames
  #if __GLASGOW_HASKELL__ <= 710
      lstmt (GHC.L _ (GHC.LastStmt ex _)) = hsVisibleDsRdr nm e ex
  #else
      lstmt (GHC.L _ (GHC.LastStmt ex _ _)) = hsVisibleDsRdr nm e ex
  #endif
  #if __GLASGOW_HASKELL__ <= 710
      lstmt (GHC.L _ (GHC.BindStmt pa ex _ _)) = do
  #else
      lstmt (GHC.L _ (GHC.BindStmt pa ex _ _ _)) = do
  #endif
        fdp <- hsVisibleDsRdr nm e pa
        fde <- hsVisibleDsRdr nm e ex
        return (fdp <> fde)
      lstmt (GHC.L _ (GHC.BodyStmt ex _ _ _)) = hsVisibleDsRdr nm e ex
  
      lstmt (GHC.L _ (GHC.LetStmt bs)) = hsVisibleDsRdr nm e bs
  #if __GLASGOW_HASKELL__ <= 710
      lstmt (GHC.L _ (GHC.ParStmt ps _ _)) = hsVisibleDsRdr nm e ps
  #else
      lstmt (GHC.L _ (GHC.ParStmt ps _ _ _)) = hsVisibleDsRdr nm e ps
  #endif
  #if __GLASGOW_HASKELL__ <= 710
      lstmt (GHC.L _ (GHC.TransStmt _ stmts _ using mby _ _ _)) = do
  #else
      lstmt (GHC.L _ (GHC.TransStmt _ stmts _ using mby _ _ _ _)) = do
  #endif
        fds <- hsVisibleDsRdr nm e stmts
        fdu <- hsVisibleDsRdr nm e using
        fdb <- case mby of
          Nothing -> return (DN [])
          Just ex -> hsVisibleDsRdr nm e ex
        return $ fds <> fdu <> fdb
  #if __GLASGOW_HASKELL__ <= 710
      lstmt (GHC.L _ (GHC.RecStmt stmts _ _ _ _ _ _ _ _)) = hsVisibleDsRdr nm e stmts
  #else
      lstmt (GHC.L _ (GHC.RecStmt stmts _ _ _ _ _ _ _ _ _)) = hsVisibleDsRdr nm e stmts
  #endif
  
  #if __GLASGOW_HASKELL__ > 710
      lstmt (GHC.L _ (GHC.ApplicativeStmt {})) = return mempty
  #endif
      -- lstmt _ = return (DN [])
  
      -- -----------------------
  
      lpats :: [GHC.LPat GHC.RdrName] -> RefactGhc DeclaredNames
      lpats ps
        | findNameInRdr nm e ps = do
          fds <- mapM (hsVisibleDsRdr nm e) ps
          return $ mconcat fds
      lpats _ = return (DN [])
  
      -- -----------------------
  
      lpat :: GHC.LPat GHC.RdrName -> RefactGhc DeclaredNames
      lpat (GHC.L _ (GHC.WildPat _)) = return (DN [])
  #if __GLASGOW_HASKELL__ <= 710
      lpat (GHC.L l (GHC.VarPat n))
  #else
      lpat (GHC.L l (GHC.VarPat (GHC.L _ n)))
  #endif
        = return (DN [rdrName2NamePure nm (GHC.L l n)])
      lpat (GHC.L _ (GHC.AsPat ln p)) = do
        (DN dp) <- lpat p
        return (DN (rdrName2NamePure nm ln:dp))
  
      lpat (GHC.L _ (GHC.ParPat p)) = lpat p
      lpat (GHC.L _ (GHC.BangPat p)) = lpat p
      lpat (GHC.L _ (GHC.ListPat ps _ _)) = do
        fds <- mapM lpat ps
        return $ mconcat fds
      lpat (GHC.L _ (GHC.TuplePat ps _ _)) = do
        fds <- mapM lpat ps
        return $ mconcat fds
      lpat (GHC.L _ (GHC.PArrPat ps _)) = do
        fds <- mapM lpat ps
        return $ mconcat fds
      lpat (GHC.L _ (GHC.ConPatIn n det)) = do
        (DN d) <- details det
        return $ (DN (rdrName2NamePure nm n:d))
      -- lpat (GHC.ConPatOut )
      lpat (GHC.L _ (GHC.ViewPat ex p _)) = do
        fde <- hsVisibleDsRdr nm e ex
        fdp <- lpat p
        return $ fde <> fdp
      -- lpat (GHC.QuasiQuotePat _)
      lpat (GHC.L _ (GHC.LitPat _)) = return (DN [])
  #if __GLASGOW_HASKELL__ <= 710
      lpat (GHC.L _ (GHC.NPat _ _ _)) = return (DN [])
      lpat (GHC.L _ (GHC.NPlusKPat n _ _ _)) = return (DN [rdrName2NamePure nm n])
  #else
      lpat (GHC.L _ (GHC.NPat _ _ _ _)) = return (DN [])
      lpat (GHC.L _ (GHC.NPlusKPat n _ _ _ _ _)) = return (DN [rdrName2NamePure nm n])
  #endif
      lpat (GHC.L _ _p@(GHC.SigPatIn p b)) = do
        dp <- lpat p
        db <- hsVisibleDsRdr nm e b
        -- error $ "lpat.SigPatIn:(b,fb,db)" ++ showGhc (b,fb,db)
        return $ dp <> db
      lpat (GHC.L _ (GHC.SigPatOut p _)) = lpat p
      lpat (GHC.L l (GHC.CoPat _ p _)) = lpat (GHC.L l p)
  
      lpat (GHC.L _ (GHC.LazyPat p)) = lpat p
      lpat (GHC.L _ (GHC.ConPatOut {})) = error $ "hsFreeAndDeclared.lpat:impossible GHC.ConPatOut"
  #if __GLASGOW_HASKELL__ <= 710
      lpat (GHC.L _ (GHC.QuasiQuotePat _)) = return mempty
      lpat (GHC.L _ (GHC.SplicePat (GHC.HsSplice _ expr))) = hsVisibleDsRdr nm e expr
  #else
      lpat (GHC.L _ (GHC.SplicePat (GHC.HsTypedSplice _ expr)))   = hsVisibleDsRdr nm e expr
      lpat (GHC.L _ (GHC.SplicePat (GHC.HsUntypedSplice _ expr))) = hsVisibleDsRdr nm e expr
      lpat (GHC.L _ (GHC.SplicePat (GHC.HsQuasiQuote {})))        = return mempty
  #endif
  
      -- ---------------------------
  
      details :: GHC.HsConPatDetails GHC.RdrName -> RefactGhc DeclaredNames
      details (GHC.PrefixCon  args) = do
        fds <- mapM lpat args
        return $ mconcat fds
      details (GHC.RecCon recf) =
        recfields recf
      details (GHC.InfixCon arg1 arg2) = do
        fds <- mapM lpat [arg1,arg2]
        return $ mconcat fds
  
      -- Note: this one applies to HsRecFields in LPats
      recfields :: (GHC.HsRecFields GHC.RdrName (GHC.LPat GHC.RdrName)) -> RefactGhc DeclaredNames
      recfields (GHC.HsRecFields fields _) = do
        let args = map (\(GHC.L _ (GHC.HsRecField _ arg _)) -> arg) fields
        fds <- mapM lpat args
        return $ mconcat fds
  
      -- -----------------------
  #if __GLASGOW_HASKELL__ > 710
      ibndrs :: GHC.LHsSigWcType GHC.RdrName -> RefactGhc DeclaredNames
      ibndrs (GHC.HsIB _ (GHC.HsWC _ _ ty)) = hsVisibleDsRdr nm e ty
  
      lsigty :: GHC.LHsSigType GHC.RdrName -> RefactGhc DeclaredNames
      lsigty (GHC.HsIB _ ty) = hsVisibleDsRdr nm e ty
  #endif
      -- -----------------------
      lanndecl :: GHC.LAnnDecl GHC.RdrName -> RefactGhc DeclaredNames
      lanndecl (GHC.L _ (GHC.HsAnnotation _ _ expr)) = hsVisibleDsRdr nm e expr
      -- -----------------------
  
      err = error $ "hsVisibleDsRdr nm:no match for:" ++ (SYB.showData SYB.Parser 0 t)
  
  -- ---------------------------------------------------------------------
  
  -- |`hsFDsFromInsideRdr` is different from `hsFreeAndDeclaredPNs` in
  -- that: given an syntax phrase t, `hsFDsFromInsideRdr` returns not only
  -- the declared variables that are visible from outside of t, but also
  -- those declared variables that are visible to the main expression
  -- inside t.
  -- NOTE: Expects to be given ParsedSource
  hsFDsFromInsideRdr :: (SYB.Data t)
                    => NameMap ->  t -> (FreeNames,DeclaredNames)
  hsFDsFromInsideRdr nm t = hsFDsFromInsideRdr' t
     where
       hsFDsFromInsideRdr' :: (SYB.Data t) => t -> (FreeNames,DeclaredNames)
       hsFDsFromInsideRdr' t1 = (FN $ nub f', DN $ nub d')
         where
            r1 = applyTU (once_tdTU (failTU  `adhocTU` parsed
                                             `adhocTU` decl
                                             `adhocTU` match
                                             `adhocTU` expr
                                             `adhocTU` stmts )) t1
            -- let (f',d') = fromMaybe ([],[]) r1
            (FN f',DN d') = fromMaybe (FN [],DN []) r1
            -- (FN f',DN d') = r1
  
       parsed :: GHC.ParsedSource -> Maybe (FreeNames,DeclaredNames)
       parsed p = return $ hsFreeAndDeclaredRdr nm p
  
       -- ----------------------
  
       match :: GHC.Match GHC.RdrName (GHC.LHsExpr GHC.RdrName) -> Maybe (FreeNames,DeclaredNames)
       match (GHC.Match _fn pats _type rhs) = do
         let (FN pf, DN pd) = hsFreeAndDeclaredRdr nm pats
             (FN rf, DN rd) = hsFreeAndDeclaredRdr nm rhs
         return (FN $ nub (pf `union` (rf \\ pd)),
                 DN $ nub (pd `union` rd))
  
       -- ----------------------
  
       decl :: GHC.HsBind GHC.RdrName -> Maybe (FreeNames,DeclaredNames)
  #if __GLASGOW_HASKELL__ <= 710
       decl (GHC.FunBind (GHC.L _ _) _ (GHC.MG matches _ _ _) _ _ _) = do
  #else
       decl (GHC.FunBind (GHC.L _ _) (GHC.MG (GHC.L _ matches) _ _ _) _ _ _) = do
  #endif
         let
           fds = map hsFDsFromInsideRdr' matches
           -- error (show $ nameToString n)
         return (FN $ nub (concat $ map (fn . fst) fds), DN $ nub (concat $ map (dn . snd) fds))
  
       decl ((GHC.PatBind p rhs _ _ _) :: GHC.HsBind GHC.RdrName) = do
         let
           (FN pf, DN pd) = hsFreeAndDeclaredRdr nm p
           (FN rf, DN rd) = hsFreeAndDeclaredRdr nm rhs
         return
             (FN $ nub (pf `union` (rf \\ pd)),
              DN $ nub (pd `union` rd))
  
       decl ((GHC.VarBind p rhs _) :: GHC.HsBind GHC.RdrName) = do
         let
           (FN pf, DN pd) = hsFreeAndDeclaredRdr nm p
           (FN rf, DN rd) = hsFreeAndDeclaredRdr nm rhs
         return
             (FN $ nub (pf `union` (rf \\ pd)),
              DN $ nub (pd `union` rd))
  
       decl _ = mzero
  
       -- ----------------------
  
       expr ((GHC.HsLet decls e) :: GHC.HsExpr GHC.RdrName) = do
         let
           (FN df,DN dd) = hsFreeAndDeclaredRdr nm decls
           (FN ef,_)     = hsFreeAndDeclaredRdr nm e
         return (FN $ nub (df `union` (ef \\ dd)), DN $ nub dd)
  
       expr ((GHC.HsLam (GHC.MG matches _ _ _)) :: GHC.HsExpr GHC.RdrName) =
         return $ hsFreeAndDeclaredRdr nm matches
  
       expr ((GHC.HsCase e (GHC.MG matches _ _ _)) :: GHC.HsExpr GHC.RdrName) = do
         let
           (FN ef,_)     = hsFreeAndDeclaredRdr nm e
           (FN df,DN dd) = hsFreeAndDeclaredRdr nm matches
         return (FN $ nub (df `union` (ef \\ dd)), DN $ nub dd)
  
       expr _ = return (FN [],DN [])
  
  #if __GLASGOW_HASKELL__ <= 710
       stmts ((GHC.BindStmt pat e1 e2 e3) :: GHC.Stmt GHC.RdrName (GHC.LHsExpr GHC.RdrName)) = do
  #else
       stmts ((GHC.BindStmt pat e1 e2 e3 _) :: GHC.Stmt GHC.RdrName (GHC.LHsExpr GHC.RdrName)) = do
  #endif
         let
           (FN pf,DN pd)  = hsFreeAndDeclaredRdr nm pat
           (FN ef,DN _ed) = hsFreeAndDeclaredRdr nm e1
           (FN df,DN dd)  = hsFreeAndDeclaredRdr nm [e2,e3]
         return
             (FN $ nub (pf `union` (((ef \\ dd) `union` df) \\ pd)), DN $ nub (pd `union` dd))
  
       stmts ((GHC.LetStmt binds) :: GHC.Stmt GHC.RdrName (GHC.LHsExpr GHC.RdrName)) =
         return $ hsFreeAndDeclaredRdr nm binds
  
       stmts _ = return (FN [],DN [])
  
  
  -- ---------------------------------------------------------------------
  
  -- | The same as `hsFDsFromInside` except that the returned variables
  -- are in the String format
  hsFDNamesFromInsideRdr ::(SYB.Data t) => t -> RefactGhc ([String],[String])
  hsFDNamesFromInsideRdr t = do
    nm <- getRefactNameMap
    return (hsFDNamesFromInsideRdrPure nm t)
    -- (FN f,DN d) <- hsFDsFromInsideRdr nm t
    -- return ((nub.map showGhc) f, (nub.map showGhc) d)
  
  -- | The same as `hsFDsFromInside` except that the returned variables
  -- are in the String format
  hsFDNamesFromInsideRdrPure :: (SYB.Data t) => NameMap -> t -> ([String],[String])
  hsFDNamesFromInsideRdrPure nm t = ((nub.map showGhc) f, (nub.map showGhc) d)
    where
      (FN f,DN d) = hsFDsFromInsideRdr nm t
  
  -- ---------------------------------------------------------------------
  
  rdrName2Name :: GHC.Located GHC.RdrName -> RefactGhc GHC.Name
  rdrName2Name ln = do
    nameMap <- getRefactNameMap
    return (rdrName2NamePure nameMap ln)
  
  rdrName2NamePure :: NameMap -> GHC.Located GHC.RdrName -> GHC.Name
  rdrName2NamePure _nameMap (GHC.L _ (GHC.Exact n)) = n
  rdrName2NamePure nameMap (GHC.L lrn _) =
    fromMaybe (error $ "rdrName2NamePure: no name found for" ++ showGhc lrn)
    -- fromMaybe (error $ "rdrName2NamePure: no name found for (lrn,e,nameMap)=" ++ showGhc (lrn,e,nameMap))
               (Map.lookup lrn nameMap)
  
  eqRdrNamePure :: NameMap -> GHC.Located GHC.RdrName -> GHC.Name -> Bool
  eqRdrNamePure nameMap rn n
    = GHC.nameUnique (rdrName2NamePure nameMap rn) == GHC.nameUnique n
  
  -- ---------------------------------------------------------------------
  
  -- | Returns True if both @GHC.Name@s are in the same @GHC.NameSpace@.
  sameNameSpace :: GHC.Name -> GHC.Name -> Bool
  sameNameSpace n1 n2
    = (GHC.occNameSpace $ GHC.nameOccName n1) == (GHC.occNameSpace $ GHC.nameOccName n2)
  
  -- ---------------------------------------------------------------------
  
  -- |Find the identifier(in GHC.Name format) whose start position is
  -- (row,col) in the file specified by the fileName, and returns
  -- `Nothing` if such an identifier does not exist.
  locToNameRdr :: (SYB.Data t)
                       => SimpPos          -- ^ The row and column number
                       -> t                -- ^ The syntax phrase, parameterised by RdrName
                       -> RefactGhc (Maybe GHC.Name)  -- ^ The result
  locToNameRdr pos t = do
     nm <- getRefactNameMap
     let mn = locToRdrName pos t
     return $ fmap (rdrName2NamePure nm) mn
  
  -- |Find the identifier(in GHC.Name format) whose start position is
  -- (row,col) in the file specified by the fileName, and returns
  -- `Nothing` if such an identifier does not exist.
  locToNameRdrPure :: (SYB.Data t)
                      => NameMap
                      -> SimpPos         -- ^ The row and column number
                      -> t               -- ^ The syntax phrase, parameterised by RdrName
                      -> Maybe GHC.Name  -- ^ The result
  locToNameRdrPure nm pos t =
    let mn = locToRdrName pos t
    in fmap (rdrName2NamePure nm) mn
  
  -- |Find the identifier(in GHC.RdrName format) whose start position is
  -- (row,col) in the file specified by the fileName, and returns
  -- `Nothing` if such an identifier does not exist.
  locToRdrName::(SYB.Data t)
                      =>SimpPos          -- ^ The row and column number
                      ->t                -- ^ The syntax phrase
                      -> Maybe (GHC.Located GHC.RdrName)  -- ^ The result
  locToRdrName (row,col) t = locToName' (row,col) t
  
  
  -- |Worker for both locToName and locToRdrName.
  -- NOTE: provides for FunBind MatchGroups where only the first name is
  -- retained in the AST
  
  locToName':: forall a t.(SYB.Data t, SYB.Data a)
                      =>SimpPos          -- ^ The row and column number
                      ->t                -- ^ The syntax phrase
                      -> Maybe (GHC.Located a)  -- ^ The result
  locToName' (row,col) t = res1
       where
          res1 :: Maybe (GHC.Located a)
          res1 = SYB.something (nameSybQuery checker) t
  
          checker pnt =
            -- trace ("locToName':pnt=" ++ show (GHC.getLoc pnt)) $
            if inScope pnt
               then Just pnt
               else Nothing
  
          -- ++AZ++:TODO: Is inScope actually required?
          inScope :: GHC.Located e -> Bool
          inScope (GHC.L l _) =
            case l of
              (GHC.UnhelpfulSpan _) -> False
              (GHC.RealSrcSpan ss)  ->
                -- (GHC.srcSpanFile ss == fileName) &&
                (GHC.srcSpanStartLine ss <= row) &&
                (GHC.srcSpanEndLine ss   >= row) &&
                (col >= (GHC.srcSpanStartCol ss)) &&
                (col <= (GHC.srcSpanEndCol   ss))
  
  -- EOF
  