{-# Language ViewPatterns #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module GHC.Util.Scope (
   Scope
  ,scopeCreate,scopeMatch,scopeMove,possModules
) where

import GHC.Hs
import GHC.Types.SrcLoc
import GHC.Types.SourceText
import GHC.Data.FastString
import GHC.Types.Name.Reader
import GHC.Types.Name.Occurrence
import GHC.Types.PkgQual

import Language.Haskell.GhclibParserEx.GHC.Types.Name.Reader
import Language.Haskell.GhclibParserEx.GHC.Utils.Outputable

import Data.List.Extra
import Data.Maybe
import Data.Bifunctor

-- A scope is a list of import declarations.
newtype Scope = Scope [LImportDecl GhcPs]
               deriving (Semigroup Scope
Scope
Semigroup Scope =>
Scope
-> (Scope -> Scope -> Scope) -> ([Scope] -> Scope) -> Monoid Scope
[Scope] -> Scope
Scope -> Scope -> Scope
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
$cmempty :: Scope
mempty :: Scope
$cmappend :: Scope -> Scope -> Scope
mappend :: Scope -> Scope -> Scope
$cmconcat :: [Scope] -> Scope
mconcat :: [Scope] -> Scope
Monoid, NonEmpty Scope -> Scope
Scope -> Scope -> Scope
(Scope -> Scope -> Scope)
-> (NonEmpty Scope -> Scope)
-> (forall b. Integral b => b -> Scope -> Scope)
-> Semigroup Scope
forall b. Integral b => b -> Scope -> Scope
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
$c<> :: Scope -> Scope -> Scope
<> :: Scope -> Scope -> Scope
$csconcat :: NonEmpty Scope -> Scope
sconcat :: NonEmpty Scope -> Scope
$cstimes :: forall b. Integral b => b -> Scope -> Scope
stimes :: forall b. Integral b => b -> Scope -> Scope
Semigroup)

instance Show Scope where
    show :: Scope -> String
show (Scope [LImportDecl GhcPs]
x) = [GenLocated SrcSpanAnnA (ImportDecl GhcPs)] -> String
forall a. Outputable a => a -> String
unsafePrettyPrint [LImportDecl GhcPs]
[GenLocated SrcSpanAnnA (ImportDecl GhcPs)]
x

-- Create a 'Scope from a module's import declarations.
scopeCreate :: HsModule GhcPs -> Scope
scopeCreate :: HsModule GhcPs -> Scope
scopeCreate HsModule GhcPs
xs = [LImportDecl GhcPs] -> Scope
Scope ([LImportDecl GhcPs] -> Scope) -> [LImportDecl GhcPs] -> Scope
forall a b. (a -> b) -> a -> b
$ [LImportDecl GhcPs
GenLocated SrcSpanAnnA (ImportDecl GhcPs)
prelude | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (GenLocated SrcSpanAnnA (ImportDecl GhcPs) -> Bool)
-> [GenLocated SrcSpanAnnA (ImportDecl GhcPs)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any LImportDecl GhcPs -> Bool
GenLocated SrcSpanAnnA (ImportDecl GhcPs) -> Bool
isPrelude [LImportDecl GhcPs]
[GenLocated SrcSpanAnnA (ImportDecl GhcPs)]
res] [GenLocated SrcSpanAnnA (ImportDecl GhcPs)]
-> [GenLocated SrcSpanAnnA (ImportDecl GhcPs)]
-> [GenLocated SrcSpanAnnA (ImportDecl GhcPs)]
forall a. [a] -> [a] -> [a]
++ [LImportDecl GhcPs]
[GenLocated SrcSpanAnnA (ImportDecl GhcPs)]
res
  where
    -- Package qualifier of an import declaration.
    pkg :: LImportDecl GhcPs -> Maybe StringLiteral
    pkg :: LImportDecl GhcPs -> Maybe StringLiteral
pkg (L SrcSpanAnnA
_ ImportDecl GhcPs
x) =
      case ImportDecl GhcPs -> ImportDeclPkgQual GhcPs
forall pass. ImportDecl pass -> ImportDeclPkgQual pass
ideclPkgQual ImportDecl GhcPs
x of
        RawPkgQual StringLiteral
s -> StringLiteral -> Maybe StringLiteral
forall a. a -> Maybe a
Just StringLiteral
s
        ImportDeclPkgQual GhcPs
RawPkgQual
NoRawPkgQual -> Maybe StringLiteral
forall a. Maybe a
Nothing

    -- The import declarations contained by the module 'xs'.
    res :: [LImportDecl GhcPs]
    res :: [LImportDecl GhcPs]
res = [LImportDecl GhcPs
GenLocated SrcSpanAnnA (ImportDecl GhcPs)
x | GenLocated SrcSpanAnnA (ImportDecl GhcPs)
x <- HsModule GhcPs -> [LImportDecl GhcPs]
forall p. HsModule p -> [LImportDecl p]
hsmodImports HsModule GhcPs
xs
             , LImportDecl GhcPs -> Maybe StringLiteral
pkg LImportDecl GhcPs
GenLocated SrcSpanAnnA (ImportDecl GhcPs)
x Maybe StringLiteral -> Maybe StringLiteral -> Bool
forall a. Eq a => a -> a -> Bool
/= StringLiteral -> Maybe StringLiteral
forall a. a -> Maybe a
Just (SourceText -> FastString -> Maybe RealSrcSpan -> StringLiteral
StringLiteral SourceText
NoSourceText (String -> FastString
fsLit String
"hint") Maybe RealSrcSpan
forall a. Maybe a
Nothing)
          ]

    -- Mock up an import declaration corresponding to 'import Prelude'.
    prelude :: LImportDecl GhcPs
    prelude :: LImportDecl GhcPs
prelude = ImportDecl GhcPs -> GenLocated SrcSpanAnnA (ImportDecl GhcPs)
forall a an. a -> LocatedAn an a
noLocA (ImportDecl GhcPs -> GenLocated SrcSpanAnnA (ImportDecl GhcPs))
-> ImportDecl GhcPs -> GenLocated SrcSpanAnnA (ImportDecl GhcPs)
forall a b. (a -> b) -> a -> b
$ ModuleName -> ImportDecl GhcPs
simpleImportDecl (String -> ModuleName
mkModuleName String
"Prelude")

    -- Predicate to test for a 'Prelude' import declaration.
    isPrelude :: LImportDecl GhcPs -> Bool
    isPrelude :: LImportDecl GhcPs -> Bool
isPrelude (L SrcSpanAnnA
_ ImportDecl GhcPs
x) = ModuleName -> String
moduleNameString (GenLocated SrcSpanAnnA ModuleName -> ModuleName
forall l e. GenLocated l e -> e
unLoc (ImportDecl GhcPs -> XRec GhcPs ModuleName
forall pass. ImportDecl pass -> XRec pass ModuleName
ideclName ImportDecl GhcPs
x)) String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"Prelude"

-- Test if two names in two scopes may be referring to the same
-- thing. This is the case if the names are equal and (1) denote a
-- builtin type or data constructor or (2) the intersection of the
-- candidate modules where the two names arise is non-empty.
scopeMatch :: (Scope, LocatedN RdrName) -> (Scope, LocatedN RdrName) -> Bool
scopeMatch :: (Scope, GenLocated SrcSpanAnnN RdrName)
-> (Scope, GenLocated SrcSpanAnnN RdrName) -> Bool
scopeMatch (Scope
a, GenLocated SrcSpanAnnN RdrName
x) (Scope
b, GenLocated SrcSpanAnnN RdrName
y)
  | GenLocated SrcSpanAnnN RdrName -> Bool
isSpecial GenLocated SrcSpanAnnN RdrName
x Bool -> Bool -> Bool
&& GenLocated SrcSpanAnnN RdrName -> Bool
isSpecial GenLocated SrcSpanAnnN RdrName
y = GenLocated SrcSpanAnnN RdrName -> String
rdrNameStr GenLocated SrcSpanAnnN RdrName
x String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== GenLocated SrcSpanAnnN RdrName -> String
rdrNameStr GenLocated SrcSpanAnnN RdrName
y
  | GenLocated SrcSpanAnnN RdrName -> Bool
isSpecial GenLocated SrcSpanAnnN RdrName
x Bool -> Bool -> Bool
|| GenLocated SrcSpanAnnN RdrName -> Bool
isSpecial GenLocated SrcSpanAnnN RdrName
y = Bool
False
  | Bool
otherwise =
     GenLocated SrcSpanAnnN RdrName -> String
rdrNameStr (GenLocated SrcSpanAnnN RdrName -> GenLocated SrcSpanAnnN RdrName
unqual GenLocated SrcSpanAnnN RdrName
x) String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== GenLocated SrcSpanAnnN RdrName -> String
rdrNameStr (GenLocated SrcSpanAnnN RdrName -> GenLocated SrcSpanAnnN RdrName
unqual GenLocated SrcSpanAnnN RdrName
y) Bool -> Bool -> Bool
&& Bool -> Bool
not (Scope -> GenLocated SrcSpanAnnN RdrName -> [ModuleName]
possModules Scope
a GenLocated SrcSpanAnnN RdrName
x [ModuleName] -> [ModuleName] -> Bool
forall a. Ord a => [a] -> [a] -> Bool
`disjointOrd` Scope -> GenLocated SrcSpanAnnN RdrName -> [ModuleName]
possModules Scope
b GenLocated SrcSpanAnnN RdrName
y)

-- Given a name in a scope, and a new scope, create a name for the new
-- scope that will refer to the same thing. If the resulting name is
-- ambiguous, pick a plausible candidate.
scopeMove :: (Scope, LocatedN RdrName) -> Scope -> LocatedN RdrName
scopeMove :: (Scope, GenLocated SrcSpanAnnN RdrName)
-> Scope -> GenLocated SrcSpanAnnN RdrName
scopeMove (Scope
a, x :: GenLocated SrcSpanAnnN RdrName
x@(GenLocated SrcSpanAnnN RdrName -> Maybe OccName
fromQual -> Just OccName
name)) (Scope [LImportDecl GhcPs]
b) = case [ImportDecl GhcPs]
imps of
  [] | -- If `possModules a x` includes Prelude, but `b` does not contain any module that may import `x`,
       -- then unqualify `x` and assume that it is from Prelude (#1298).
       (GenLocated SrcSpanAnnN RdrName -> Bool)
-> [GenLocated SrcSpanAnnN RdrName] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (\(L SrcSpanAnnN
_ RdrName
x) -> (ModuleName -> String
moduleNameString (ModuleName -> String)
-> ((ModuleName, OccName) -> ModuleName)
-> (ModuleName, OccName)
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ModuleName, OccName) -> ModuleName
forall a b. (a, b) -> a
fst ((ModuleName, OccName) -> String)
-> Maybe (ModuleName, OccName) -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RdrName -> Maybe (ModuleName, OccName)
isQual_maybe RdrName
x) Maybe String -> Maybe String -> Bool
forall a. Eq a => a -> a -> Bool
== String -> Maybe String
forall a. a -> Maybe a
Just String
"Prelude") [GenLocated SrcSpanAnnN RdrName]
real -> GenLocated SrcSpanAnnN RdrName -> GenLocated SrcSpanAnnN RdrName
unqual GenLocated SrcSpanAnnN RdrName
x
     | Bool
otherwise -> GenLocated SrcSpanAnnN RdrName
-> [GenLocated SrcSpanAnnN RdrName]
-> GenLocated SrcSpanAnnN RdrName
forall a. a -> [a] -> a
headDef GenLocated SrcSpanAnnN RdrName
x [GenLocated SrcSpanAnnN RdrName]
real
  ImportDecl GhcPs
imp:[ImportDecl GhcPs]
_ | (ImportDecl GhcPs -> Bool) -> [ImportDecl GhcPs] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (\ImportDecl GhcPs
x -> ImportDecl GhcPs -> ImportDeclQualifiedStyle
forall pass. ImportDecl pass -> ImportDeclQualifiedStyle
ideclQualified ImportDecl GhcPs
x ImportDeclQualifiedStyle -> ImportDeclQualifiedStyle -> Bool
forall a. Eq a => a -> a -> Bool
/= ImportDeclQualifiedStyle
NotQualified) [ImportDecl GhcPs]
imps -> RdrName -> GenLocated SrcSpanAnnN RdrName
forall a an. a -> LocatedAn an a
noLocA (RdrName -> GenLocated SrcSpanAnnN RdrName)
-> RdrName -> GenLocated SrcSpanAnnN RdrName
forall a b. (a -> b) -> a -> b
$ ModuleName -> OccName -> RdrName
mkRdrQual (GenLocated SrcSpanAnnA ModuleName -> ModuleName
forall l e. GenLocated l e -> e
unLoc (GenLocated SrcSpanAnnA ModuleName -> ModuleName)
-> (Maybe (GenLocated SrcSpanAnnA ModuleName)
    -> GenLocated SrcSpanAnnA ModuleName)
-> Maybe (GenLocated SrcSpanAnnA ModuleName)
-> ModuleName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GenLocated SrcSpanAnnA ModuleName
-> Maybe (GenLocated SrcSpanAnnA ModuleName)
-> GenLocated SrcSpanAnnA ModuleName
forall a. a -> Maybe a -> a
fromMaybe (ImportDecl GhcPs -> XRec GhcPs ModuleName
forall pass. ImportDecl pass -> XRec pass ModuleName
ideclName ImportDecl GhcPs
imp) (Maybe (GenLocated SrcSpanAnnA ModuleName) -> ModuleName)
-> Maybe (GenLocated SrcSpanAnnA ModuleName) -> ModuleName
forall a b. (a -> b) -> a -> b
$ (ImportDecl GhcPs -> Maybe (GenLocated SrcSpanAnnA ModuleName))
-> [ImportDecl GhcPs] -> Maybe (GenLocated SrcSpanAnnA ModuleName)
forall a b. (a -> Maybe b) -> [a] -> Maybe b
firstJust ImportDecl GhcPs -> Maybe (XRec GhcPs ModuleName)
ImportDecl GhcPs -> Maybe (GenLocated SrcSpanAnnA ModuleName)
forall pass. ImportDecl pass -> Maybe (XRec pass ModuleName)
ideclAs [ImportDecl GhcPs]
imps) OccName
name
        | Bool
otherwise -> GenLocated SrcSpanAnnN RdrName -> GenLocated SrcSpanAnnN RdrName
unqual GenLocated SrcSpanAnnN RdrName
x
  where
    real :: [LocatedN RdrName]
    real :: [GenLocated SrcSpanAnnN RdrName]
real = [RdrName -> GenLocated SrcSpanAnnN RdrName
forall a an. a -> LocatedAn an a
noLocA (RdrName -> GenLocated SrcSpanAnnN RdrName)
-> RdrName -> GenLocated SrcSpanAnnN RdrName
forall a b. (a -> b) -> a -> b
$ ModuleName -> OccName -> RdrName
mkRdrQual ModuleName
m OccName
name | ModuleName
m <- Scope -> GenLocated SrcSpanAnnN RdrName -> [ModuleName]
possModules Scope
a GenLocated SrcSpanAnnN RdrName
x]

    imps :: [ImportDecl GhcPs]
    imps :: [ImportDecl GhcPs]
imps = [GenLocated SrcSpanAnnA (ImportDecl GhcPs) -> ImportDecl GhcPs
forall l e. GenLocated l e -> e
unLoc GenLocated SrcSpanAnnA (ImportDecl GhcPs)
i | GenLocated SrcSpanAnnN RdrName
r <- [GenLocated SrcSpanAnnN RdrName]
real, GenLocated SrcSpanAnnA (ImportDecl GhcPs)
i <- [LImportDecl GhcPs]
[GenLocated SrcSpanAnnA (ImportDecl GhcPs)]
b, LImportDecl GhcPs -> GenLocated SrcSpanAnnN RdrName -> IsImported
possImport LImportDecl GhcPs
GenLocated SrcSpanAnnA (ImportDecl GhcPs)
i GenLocated SrcSpanAnnN RdrName
r IsImported -> IsImported -> Bool
forall a. Eq a => a -> a -> Bool
/= IsImported
NotImported]
scopeMove (Scope
_, GenLocated SrcSpanAnnN RdrName
x) Scope
_ = GenLocated SrcSpanAnnN RdrName
x

-- Calculate which modules a name could possibly lie in. If 'x' is
-- qualified but no imported element matches it, assume the user just
-- lacks an import.
-- 'prelude' is added to the result, unless we are certain which module a name is from (#1298).
possModules :: Scope -> LocatedN RdrName -> [ModuleName]
possModules :: Scope -> GenLocated SrcSpanAnnN RdrName -> [ModuleName]
possModules (Scope [LImportDecl GhcPs]
is) GenLocated SrcSpanAnnN RdrName
x =
    [ModuleName
prelude | ModuleName
prelude ModuleName -> [ModuleName] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` ((ModuleName, Bool) -> ModuleName)
-> [(ModuleName, Bool)] -> [ModuleName]
forall a b. (a -> b) -> [a] -> [b]
map (ModuleName, Bool) -> ModuleName
forall a b. (a, b) -> a
fst [(ModuleName, Bool)]
res, Bool -> Bool
not (((ModuleName, Bool) -> Bool) -> [(ModuleName, Bool)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (ModuleName, Bool) -> Bool
forall a b. (a, b) -> b
snd [(ModuleName, Bool)]
res)] [ModuleName] -> [ModuleName] -> [ModuleName]
forall a. [a] -> [a] -> [a]
++ ((ModuleName, Bool) -> ModuleName)
-> [(ModuleName, Bool)] -> [ModuleName]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (ModuleName, Bool) -> ModuleName
forall a b. (a, b) -> a
fst [(ModuleName, Bool)]
res
  where
    -- The 'Bool' signals whether we are certain that 'x' is imported from the module.
    res0, res :: [(ModuleName, Bool)]
    res0 :: [(ModuleName, Bool)]
res0 = [ (GenLocated SrcSpanAnnA ModuleName -> ModuleName
forall l e. GenLocated l e -> e
unLoc (GenLocated SrcSpanAnnA ModuleName -> ModuleName)
-> GenLocated SrcSpanAnnA ModuleName -> ModuleName
forall a b. (a -> b) -> a -> b
$ ImportDecl GhcPs -> XRec GhcPs ModuleName
forall pass. ImportDecl pass -> XRec pass ModuleName
ideclName (ImportDecl GhcPs -> XRec GhcPs ModuleName)
-> ImportDecl GhcPs -> XRec GhcPs ModuleName
forall a b. (a -> b) -> a -> b
$ GenLocated SrcSpanAnnA (ImportDecl GhcPs) -> ImportDecl GhcPs
forall l e. GenLocated l e -> e
unLoc GenLocated SrcSpanAnnA (ImportDecl GhcPs)
i, IsImported
isImported IsImported -> IsImported -> Bool
forall a. Eq a => a -> a -> Bool
== IsImported
Imported)
           | GenLocated SrcSpanAnnA (ImportDecl GhcPs)
i <- [LImportDecl GhcPs]
[GenLocated SrcSpanAnnA (ImportDecl GhcPs)]
is, let isImported :: IsImported
isImported = LImportDecl GhcPs -> GenLocated SrcSpanAnnN RdrName -> IsImported
possImport LImportDecl GhcPs
GenLocated SrcSpanAnnA (ImportDecl GhcPs)
i GenLocated SrcSpanAnnN RdrName
x, IsImported
isImported IsImported -> IsImported -> Bool
forall a. Eq a => a -> a -> Bool
/= IsImported
NotImported ]

    res :: [(ModuleName, Bool)]
res | GenLocated SrcSpanAnnN RdrName -> Bool
isSpecial GenLocated SrcSpanAnnN RdrName
x = [(String -> ModuleName
mkModuleName String
"", Bool
True)]
        | L SrcSpanAnnN
_ (Qual ModuleName
mod OccName
_) <- GenLocated SrcSpanAnnN RdrName
x = [(ModuleName
mod, Bool
True) | [(ModuleName, Bool)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(ModuleName, Bool)]
res0] [(ModuleName, Bool)]
-> [(ModuleName, Bool)] -> [(ModuleName, Bool)]
forall a. [a] -> [a] -> [a]
++ [(ModuleName, Bool)]
res0
        | Bool
otherwise = [(ModuleName, Bool)]
res0

    prelude :: ModuleName
prelude = String -> ModuleName
mkModuleName String
"Prelude"

data IsImported = Imported | PossiblyImported | NotImported  deriving (IsImported -> IsImported -> Bool
(IsImported -> IsImported -> Bool)
-> (IsImported -> IsImported -> Bool) -> Eq IsImported
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: IsImported -> IsImported -> Bool
== :: IsImported -> IsImported -> Bool
$c/= :: IsImported -> IsImported -> Bool
/= :: IsImported -> IsImported -> Bool
Eq)

-- Determine if 'x' could possibly lie in the module named by the
-- import declaration 'i'.
possImport :: LImportDecl GhcPs -> LocatedN RdrName -> IsImported
possImport :: LImportDecl GhcPs -> GenLocated SrcSpanAnnN RdrName -> IsImported
possImport LImportDecl GhcPs
i GenLocated SrcSpanAnnN RdrName
n | GenLocated SrcSpanAnnN RdrName -> Bool
isSpecial GenLocated SrcSpanAnnN RdrName
n = IsImported
NotImported
possImport (L SrcSpanAnnA
_ ImportDecl GhcPs
i) (L SrcSpanAnnN
_ (Qual ModuleName
mod OccName
x)) =
  if ModuleName
mod ModuleName -> [ModuleName] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ModuleName]
ms Bool -> Bool -> Bool
&& IsImported
NotImported IsImported -> IsImported -> Bool
forall a. Eq a => a -> a -> Bool
/= LImportDecl GhcPs -> GenLocated SrcSpanAnnN RdrName -> IsImported
possImport (ImportDecl GhcPs -> GenLocated SrcSpanAnnA (ImportDecl GhcPs)
forall a an. a -> LocatedAn an a
noLocA ImportDecl GhcPs
i{ideclQualified=NotQualified}) (RdrName -> GenLocated SrcSpanAnnN RdrName
forall a an. a -> LocatedAn an a
noLocA (RdrName -> GenLocated SrcSpanAnnN RdrName)
-> RdrName -> GenLocated SrcSpanAnnN RdrName
forall a b. (a -> b) -> a -> b
$ OccName -> RdrName
mkRdrUnqual OccName
x)
    then IsImported
Imported
    else IsImported
NotImported
  where ms :: [ModuleName]
ms = (GenLocated SrcSpanAnnA ModuleName -> ModuleName)
-> [GenLocated SrcSpanAnnA ModuleName] -> [ModuleName]
forall a b. (a -> b) -> [a] -> [b]
map GenLocated SrcSpanAnnA ModuleName -> ModuleName
forall l e. GenLocated l e -> e
unLoc ([GenLocated SrcSpanAnnA ModuleName] -> [ModuleName])
-> [GenLocated SrcSpanAnnA ModuleName] -> [ModuleName]
forall a b. (a -> b) -> a -> b
$ ImportDecl GhcPs -> XRec GhcPs ModuleName
forall pass. ImportDecl pass -> XRec pass ModuleName
ideclName ImportDecl GhcPs
i GenLocated SrcSpanAnnA ModuleName
-> [GenLocated SrcSpanAnnA ModuleName]
-> [GenLocated SrcSpanAnnA ModuleName]
forall a. a -> [a] -> [a]
: Maybe (GenLocated SrcSpanAnnA ModuleName)
-> [GenLocated SrcSpanAnnA ModuleName]
forall a. Maybe a -> [a]
maybeToList (ImportDecl GhcPs -> Maybe (XRec GhcPs ModuleName)
forall pass. ImportDecl pass -> Maybe (XRec pass ModuleName)
ideclAs ImportDecl GhcPs
i)
possImport (L SrcSpanAnnA
_ ImportDecl GhcPs
i) (L SrcSpanAnnN
_ (Unqual OccName
x)) =
  if ImportDecl GhcPs -> ImportDeclQualifiedStyle
forall pass. ImportDecl pass -> ImportDeclQualifiedStyle
ideclQualified ImportDecl GhcPs
i ImportDeclQualifiedStyle -> ImportDeclQualifiedStyle -> Bool
forall a. Eq a => a -> a -> Bool
== ImportDeclQualifiedStyle
NotQualified
    then IsImported
-> ((ImportListInterpretation,
     LocatedL [GenLocated SrcSpanAnnA (IE GhcPs)])
    -> IsImported)
-> Maybe
     (ImportListInterpretation,
      LocatedL [GenLocated SrcSpanAnnA (IE GhcPs)])
-> IsImported
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IsImported
PossiblyImported ((Bool, LocatedL [LIE GhcPs]) -> IsImported
(Bool, LocatedL [GenLocated SrcSpanAnnA (IE GhcPs)]) -> IsImported
f ((Bool, LocatedL [GenLocated SrcSpanAnnA (IE GhcPs)])
 -> IsImported)
-> ((ImportListInterpretation,
     LocatedL [GenLocated SrcSpanAnnA (IE GhcPs)])
    -> (Bool, LocatedL [GenLocated SrcSpanAnnA (IE GhcPs)]))
-> (ImportListInterpretation,
    LocatedL [GenLocated SrcSpanAnnA (IE GhcPs)])
-> IsImported
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ImportListInterpretation -> Bool)
-> (ImportListInterpretation,
    LocatedL [GenLocated SrcSpanAnnA (IE GhcPs)])
-> (Bool, LocatedL [GenLocated SrcSpanAnnA (IE GhcPs)])
forall a b c. (a -> b) -> (a, c) -> (b, c)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first (ImportListInterpretation -> ImportListInterpretation -> Bool
forall a. Eq a => a -> a -> Bool
== ImportListInterpretation
EverythingBut)) (ImportDecl GhcPs
-> Maybe (ImportListInterpretation, XRec GhcPs [LIE GhcPs])
forall pass.
ImportDecl pass
-> Maybe (ImportListInterpretation, XRec pass [LIE pass])
ideclImportList ImportDecl GhcPs
i)
    else IsImported
NotImported
  where
    f :: (Bool, LocatedL [LIE GhcPs]) -> IsImported
    f :: (Bool, LocatedL [LIE GhcPs]) -> IsImported
f (Bool
hide, L SrcSpanAnnL
_ [LIE GhcPs]
xs)
      | Bool
hide = if Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
True Maybe Bool -> [Maybe Bool] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Maybe Bool]
ms then IsImported
NotImported else IsImported
PossiblyImported
      | Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
True Maybe Bool -> [Maybe Bool] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Maybe Bool]
ms = IsImported
Imported
      | Maybe Bool
forall a. Maybe a
Nothing Maybe Bool -> [Maybe Bool] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Maybe Bool]
ms = IsImported
PossiblyImported
      | Bool
otherwise = IsImported
NotImported
      where ms :: [Maybe Bool]
ms = (GenLocated SrcSpanAnnA (IE GhcPs) -> Maybe Bool)
-> [GenLocated SrcSpanAnnA (IE GhcPs)] -> [Maybe Bool]
forall a b. (a -> b) -> [a] -> [b]
map LIE GhcPs -> Maybe Bool
GenLocated SrcSpanAnnA (IE GhcPs) -> Maybe Bool
g [LIE GhcPs]
[GenLocated SrcSpanAnnA (IE GhcPs)]
xs

    tag :: String
    tag :: String
tag = OccName -> String
occNameString OccName
x

    g :: LIE GhcPs -> Maybe Bool -- Does this import cover the name 'x'?
    g :: LIE GhcPs -> Maybe Bool
g (L SrcSpanAnnA
_ (IEVar XIEVar GhcPs
_ LIEWrappedName GhcPs
y)) = Bool -> Maybe Bool
forall a. a -> Maybe a
Just (Bool -> Maybe Bool) -> Bool -> Maybe Bool
forall a b. (a -> b) -> a -> b
$ String
tag String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== LIEWrappedName GhcPs -> String
unwrapName LIEWrappedName GhcPs
y
    g (L SrcSpanAnnA
_ (IEThingAbs XIEThingAbs GhcPs
_ LIEWrappedName GhcPs
y)) = Bool -> Maybe Bool
forall a. a -> Maybe a
Just (Bool -> Maybe Bool) -> Bool -> Maybe Bool
forall a b. (a -> b) -> a -> b
$ String
tag String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== LIEWrappedName GhcPs -> String
unwrapName LIEWrappedName GhcPs
y
    g (L SrcSpanAnnA
_ (IEThingAll XIEThingAll GhcPs
_ LIEWrappedName GhcPs
y)) = if String
tag String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== LIEWrappedName GhcPs -> String
unwrapName LIEWrappedName GhcPs
y then Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
True else Maybe Bool
forall a. Maybe a
Nothing
    g (L SrcSpanAnnA
_ (IEThingWith XIEThingWith GhcPs
_ LIEWrappedName GhcPs
y IEWildcard
_wildcard [LIEWrappedName GhcPs]
ys)) = Bool -> Maybe Bool
forall a. a -> Maybe a
Just (Bool -> Maybe Bool) -> Bool -> Maybe Bool
forall a b. (a -> b) -> a -> b
$ String
tag String -> [String] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` LIEWrappedName GhcPs -> String
unwrapName LIEWrappedName GhcPs
y String -> [String] -> [String]
forall a. a -> [a] -> [a]
: (GenLocated SrcSpanAnnA (IEWrappedName GhcPs) -> String)
-> [GenLocated SrcSpanAnnA (IEWrappedName GhcPs)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map LIEWrappedName GhcPs -> String
GenLocated SrcSpanAnnA (IEWrappedName GhcPs) -> String
unwrapName [LIEWrappedName GhcPs]
[GenLocated SrcSpanAnnA (IEWrappedName GhcPs)]
ys
    g LIE GhcPs
_ = Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
False

    unwrapName :: LIEWrappedName GhcPs -> String
    unwrapName :: LIEWrappedName GhcPs -> String
unwrapName LIEWrappedName GhcPs
x = OccName -> String
occNameString (RdrName -> OccName
rdrNameOcc (RdrName -> OccName) -> RdrName -> OccName
forall a b. (a -> b) -> a -> b
$ IEWrappedName GhcPs -> IdP GhcPs
forall (p :: Pass). IEWrappedName (GhcPass p) -> IdP (GhcPass p)
ieWrappedName (GenLocated SrcSpanAnnA (IEWrappedName GhcPs) -> IEWrappedName GhcPs
forall l e. GenLocated l e -> e
unLoc LIEWrappedName GhcPs
GenLocated SrcSpanAnnA (IEWrappedName GhcPs)
x))
possImport LImportDecl GhcPs
_ GenLocated SrcSpanAnnN RdrName
_ = IsImported
NotImported