    {-# LANGUAGE LambdaCase #-}
    {-# LANGUAGE RankNTypes #-}
    {-# LANGUAGE RecordWildCards #-}

    -- | Manipulations on import lists.
    module Ormolu.Imports
      ( normalizeImports,
      )
    where

    import Data.Bifunctor
    import Data.Char (isAlphaNum)
    import Data.Function (on)
    import Data.List (foldl', nubBy, sortBy, sortOn)
    import Data.Map.Strict (Map)
    import qualified Data.Map.Strict as M
    import FastString (FastString)
    import GHC hiding (GhcPs, IE)
    import GHC.Hs.Extension
    import GHC.Hs.ImpExp (IE (..))
    import Ormolu.Utils (notImplemented, showOutputable)

    -- | Sort and normalize imports.
    normalizeImports :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]
    normalizeImports :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]
    normalizeImports =
      ((ImportId, LImportDecl GhcPs) -> LImportDecl GhcPs)
    -> [(ImportId, LImportDecl GhcPs)] -> [LImportDecl GhcPs]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (ImportId, LImportDecl GhcPs) -> LImportDecl GhcPs
    forall a b. (a, b) -> b
    snd
        ([(ImportId, LImportDecl GhcPs)] -> [LImportDecl GhcPs])
    -> ([LImportDecl GhcPs] -> [(ImportId, LImportDecl GhcPs)])
    -> [LImportDecl GhcPs]
    -> [LImportDecl GhcPs]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Map ImportId (LImportDecl GhcPs) -> [(ImportId, LImportDecl GhcPs)]
    forall k a. Map k a -> [(k, a)]
    M.toAscList
        (Map ImportId (LImportDecl GhcPs)
     -> [(ImportId, LImportDecl GhcPs)])
    -> ([LImportDecl GhcPs] -> Map ImportId (LImportDecl GhcPs))
    -> [LImportDecl GhcPs]
    -> [(ImportId, LImportDecl GhcPs)]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (LImportDecl GhcPs -> LImportDecl GhcPs -> LImportDecl GhcPs)
    -> [(ImportId, LImportDecl GhcPs)]
    -> Map ImportId (LImportDecl GhcPs)
    forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
    M.fromListWith LImportDecl GhcPs -> LImportDecl GhcPs -> LImportDecl GhcPs
    combineImports
        ([(ImportId, LImportDecl GhcPs)]
     -> Map ImportId (LImportDecl GhcPs))
    -> ([LImportDecl GhcPs] -> [(ImportId, LImportDecl GhcPs)])
    -> [LImportDecl GhcPs]
    -> Map ImportId (LImportDecl GhcPs)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (LImportDecl GhcPs -> (ImportId, LImportDecl GhcPs))
    -> [LImportDecl GhcPs] -> [(ImportId, LImportDecl GhcPs)]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (\x :: LImportDecl GhcPs
    x -> (LImportDecl GhcPs -> ImportId
    importId LImportDecl GhcPs
    x, LImportDecl GhcPs -> LImportDecl GhcPs
    forall l.
    GenLocated l (ImportDecl GhcPs) -> GenLocated l (ImportDecl GhcPs)
    g LImportDecl GhcPs
    x))
      where
        g :: GenLocated l (ImportDecl GhcPs) -> GenLocated l (ImportDecl GhcPs)
    g (L l :: l
    l ImportDecl {..}) =
          l -> ImportDecl GhcPs -> GenLocated l (ImportDecl GhcPs)
    forall l e. l -> e -> GenLocated l e
    L
            l
    l
            ImportDecl :: forall pass.
    XCImportDecl pass
    -> SourceText
    -> Located ModuleName
    -> Maybe StringLiteral
    -> Bool
    -> Bool
    -> ImportDeclQualifiedStyle
    -> Bool
    -> Maybe (Located ModuleName)
    -> Maybe (Bool, Located [LIE pass])
    -> ImportDecl pass
    ImportDecl
              { ideclHiding :: Maybe (Bool, Located [LIE GhcPs])
    ideclHiding = (Located [LIE GhcPs] -> Located [LIE GhcPs])
    -> (Bool, Located [LIE GhcPs]) -> (Bool, Located [LIE GhcPs])
    forall (p :: * -> * -> *) b c a.
    Bifunctor p =>
    (b -> c) -> p a b -> p a c
    second (([LIE GhcPs] -> [LIE GhcPs])
    -> Located [LIE GhcPs] -> Located [LIE GhcPs]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap [LIE GhcPs] -> [LIE GhcPs]
    normalizeLies) ((Bool, Located [LIE GhcPs]) -> (Bool, Located [LIE GhcPs]))
    -> Maybe (Bool, Located [LIE GhcPs])
    -> Maybe (Bool, Located [LIE GhcPs])
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Maybe (Bool, Located [LIE GhcPs])
    ideclHiding,
                ..
              }
        g _ = String -> GenLocated l (ImportDecl GhcPs)
    forall a. String -> a
    notImplemented "XImportDecl"

    -- | Combine two import declarations. It should be assumed that 'ImportId's
    -- are equal.
    combineImports ::
      LImportDecl GhcPs ->
      LImportDecl GhcPs ->
      LImportDecl GhcPs
    combineImports :: LImportDecl GhcPs -> LImportDecl GhcPs -> LImportDecl GhcPs
    combineImports (L lx :: SrcSpan
    lx ImportDecl {..}) (L _ y :: ImportDecl GhcPs
    y) =
      SrcSpan -> ImportDecl GhcPs -> LImportDecl GhcPs
    forall l e. l -> e -> GenLocated l e
    L
        SrcSpan
    lx
        ImportDecl :: forall pass.
    XCImportDecl pass
    -> SourceText
    -> Located ModuleName
    -> Maybe StringLiteral
    -> Bool
    -> Bool
    -> ImportDeclQualifiedStyle
    -> Bool
    -> Maybe (Located ModuleName)
    -> Maybe (Bool, Located [LIE pass])
    -> ImportDecl pass
    ImportDecl
          { ideclHiding :: Maybe (Bool, Located [LIE GhcPs])
    ideclHiding = case (Maybe (Bool, Located [LIE GhcPs])
    ideclHiding, ImportDecl GhcPs -> Maybe (Bool, Located [LIE GhcPs])
    forall pass. ImportDecl pass -> Maybe (Bool, Located [LIE pass])
    GHC.ideclHiding ImportDecl GhcPs
    y) of
              (Just (hiding :: Bool
    hiding, L l' :: SrcSpan
    l' xs :: [LIE GhcPs]
    xs), Just (_, L _ ys :: [LIE GhcPs]
    ys)) ->
                (Bool, Located [LIE GhcPs]) -> Maybe (Bool, Located [LIE GhcPs])
    forall a. a -> Maybe a
    Just (Bool
    hiding, (SrcSpan -> [LIE GhcPs] -> Located [LIE GhcPs]
    forall l e. l -> e -> GenLocated l e
    L SrcSpan
    l' ([LIE GhcPs] -> [LIE GhcPs]
    normalizeLies ([LIE GhcPs]
    xs [LIE GhcPs] -> [LIE GhcPs] -> [LIE GhcPs]
    forall a. [a] -> [a] -> [a]
    ++ [LIE GhcPs]
    ys))))
              _ -> Maybe (Bool, Located [LIE GhcPs])
    forall a. Maybe a
    Nothing,
            ..
          }
    combineImports _ _ = String -> LImportDecl GhcPs
    forall a. String -> a
    notImplemented "XImportDecl"

    -- | Import id, a collection of all things that justify having a separate
    -- import entry. This is used for merging of imports. If two imports have
    -- the same 'ImportId' they can be merged.
    data ImportId = ImportId
      { ImportId -> Bool
    importIsPrelude :: Bool,
        ImportId -> ModuleName
    importIdName :: ModuleName,
        ImportId -> Maybe FastString
    importPkgQual :: Maybe FastString,
        ImportId -> Bool
    importSource :: Bool,
        ImportId -> Bool
    importSafe :: Bool,
        ImportId -> Bool
    importQualified :: Bool,
        ImportId -> Bool
    importImplicit :: Bool,
        ImportId -> Maybe ModuleName
    importAs :: Maybe ModuleName,
        ImportId -> Maybe Bool
    importHiding :: Maybe Bool
      }
      deriving (ImportId -> ImportId -> Bool
    (ImportId -> ImportId -> Bool)
    -> (ImportId -> ImportId -> Bool) -> Eq ImportId
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: ImportId -> ImportId -> Bool
    $c/= :: ImportId -> ImportId -> Bool
    == :: ImportId -> ImportId -> Bool
    $c== :: ImportId -> ImportId -> Bool
    Eq, Eq ImportId
    Eq ImportId =>
    (ImportId -> ImportId -> Ordering)
    -> (ImportId -> ImportId -> Bool)
    -> (ImportId -> ImportId -> Bool)
    -> (ImportId -> ImportId -> Bool)
    -> (ImportId -> ImportId -> Bool)
    -> (ImportId -> ImportId -> ImportId)
    -> (ImportId -> ImportId -> ImportId)
    -> Ord ImportId
    ImportId -> ImportId -> Bool
    ImportId -> ImportId -> Ordering
    ImportId -> ImportId -> ImportId
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    min :: ImportId -> ImportId -> ImportId
    $cmin :: ImportId -> ImportId -> ImportId
    max :: ImportId -> ImportId -> ImportId
    $cmax :: ImportId -> ImportId -> ImportId
    >= :: ImportId -> ImportId -> Bool
    $c>= :: ImportId -> ImportId -> Bool
    > :: ImportId -> ImportId -> Bool
    $c> :: ImportId -> ImportId -> Bool
    <= :: ImportId -> ImportId -> Bool
    $c<= :: ImportId -> ImportId -> Bool
    < :: ImportId -> ImportId -> Bool
    $c< :: ImportId -> ImportId -> Bool
    compare :: ImportId -> ImportId -> Ordering
    $ccompare :: ImportId -> ImportId -> Ordering
    $cp1Ord :: Eq ImportId
    Ord)

    -- | Obtain an 'ImportId' for a given import.
    importId :: LImportDecl GhcPs -> ImportId
    importId :: LImportDecl GhcPs -> ImportId
    importId (L _ ImportDecl {..}) =
      ImportId :: Bool
    -> ModuleName
    -> Maybe FastString
    -> Bool
    -> Bool
    -> Bool
    -> Bool
    -> Maybe ModuleName
    -> Maybe Bool
    -> ImportId
    ImportId
        { importIsPrelude :: Bool
    importIsPrelude = Bool
    isPrelude,
          importIdName :: ModuleName
    importIdName = ModuleName
    moduleName,
          importPkgQual :: Maybe FastString
    importPkgQual = StringLiteral -> FastString
    sl_fs (StringLiteral -> FastString)
    -> Maybe StringLiteral -> Maybe FastString
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Maybe StringLiteral
    ideclPkgQual,
          importSource :: Bool
    importSource = Bool
    ideclSource,
          importSafe :: Bool
    importSafe = Bool
    ideclSafe,
          importQualified :: Bool
    importQualified = case ImportDeclQualifiedStyle
    ideclQualified of
            QualifiedPre -> Bool
    True
            QualifiedPost -> Bool
    True
            NotQualified -> Bool
    False,
          importImplicit :: Bool
    importImplicit = Bool
    ideclImplicit,
          importAs :: Maybe ModuleName
    importAs = Located ModuleName -> ModuleName
    forall a. HasSrcSpan a => a -> SrcSpanLess a
    unLoc (Located ModuleName -> ModuleName)
    -> Maybe (Located ModuleName) -> Maybe ModuleName
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Maybe (Located ModuleName)
    ideclAs,
          importHiding :: Maybe Bool
    importHiding = (Bool, Located [LIE GhcPs]) -> Bool
    forall a b. (a, b) -> a
    fst ((Bool, Located [LIE GhcPs]) -> Bool)
    -> Maybe (Bool, Located [LIE GhcPs]) -> Maybe Bool
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Maybe (Bool, Located [LIE GhcPs])
    ideclHiding
        }
      where
        isPrelude :: Bool
    isPrelude = ModuleName -> String
    moduleNameString ModuleName
    moduleName String -> String -> Bool
    forall a. Eq a => a -> a -> Bool
    == "Prelude"
        moduleName :: SrcSpanLess (Located ModuleName)
    moduleName = Located ModuleName -> SrcSpanLess (Located ModuleName)
    forall a. HasSrcSpan a => a -> SrcSpanLess a
    unLoc Located ModuleName
    ideclName
    importId _ = String -> ImportId
    forall a. String -> a
    notImplemented "XImportDecl"

    -- | Normalize a collection of import\/export items.
    normalizeLies :: [LIE GhcPs] -> [LIE GhcPs]
    normalizeLies :: [LIE GhcPs] -> [LIE GhcPs]
    normalizeLies = (LIE GhcPs -> IEWrappedNameOrd) -> [LIE GhcPs] -> [LIE GhcPs]
    forall b a. Ord b => (a -> b) -> [a] -> [a]
    sortOn (IE GhcPs -> IEWrappedNameOrd
    getIewn (IE GhcPs -> IEWrappedNameOrd)
    -> (LIE GhcPs -> IE GhcPs) -> LIE GhcPs -> IEWrappedNameOrd
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . LIE GhcPs -> IE GhcPs
    forall a. HasSrcSpan a => a -> SrcSpanLess a
    unLoc) ([LIE GhcPs] -> [LIE GhcPs])
    -> ([LIE GhcPs] -> [LIE GhcPs]) -> [LIE GhcPs] -> [LIE GhcPs]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Map IEWrappedNameOrd (LIE GhcPs) -> [LIE GhcPs]
    forall k a. Map k a -> [a]
    M.elems (Map IEWrappedNameOrd (LIE GhcPs) -> [LIE GhcPs])
    -> ([LIE GhcPs] -> Map IEWrappedNameOrd (LIE GhcPs))
    -> [LIE GhcPs]
    -> [LIE GhcPs]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Map IEWrappedNameOrd (LIE GhcPs)
     -> LIE GhcPs -> Map IEWrappedNameOrd (LIE GhcPs))
    -> Map IEWrappedNameOrd (LIE GhcPs)
    -> [LIE GhcPs]
    -> Map IEWrappedNameOrd (LIE GhcPs)
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' Map IEWrappedNameOrd (LIE GhcPs)
    -> LIE GhcPs -> Map IEWrappedNameOrd (LIE GhcPs)
    combine Map IEWrappedNameOrd (LIE GhcPs)
    forall k a. Map k a
    M.empty
      where
        combine ::
          Map IEWrappedNameOrd (LIE GhcPs) ->
          LIE GhcPs ->
          Map IEWrappedNameOrd (LIE GhcPs)
        combine :: Map IEWrappedNameOrd (LIE GhcPs)
    -> LIE GhcPs -> Map IEWrappedNameOrd (LIE GhcPs)
    combine m :: Map IEWrappedNameOrd (LIE GhcPs)
    m (L new_l :: SrcSpan
    new_l new :: IE GhcPs
    new) =
          let wname :: IEWrappedNameOrd
    wname = IE GhcPs -> IEWrappedNameOrd
    getIewn IE GhcPs
    new
              normalizeWNames :: [LIEWrappedName RdrName] -> [LIEWrappedName RdrName]
    normalizeWNames =
                (LIEWrappedName RdrName -> LIEWrappedName RdrName -> Bool)
    -> [LIEWrappedName RdrName] -> [LIEWrappedName RdrName]
    forall a. (a -> a -> Bool) -> [a] -> [a]
    nubBy (\x :: LIEWrappedName RdrName
    x y :: LIEWrappedName RdrName
    y -> LIEWrappedName RdrName -> LIEWrappedName RdrName -> Ordering
    compareLIewn LIEWrappedName RdrName
    x LIEWrappedName RdrName
    y Ordering -> Ordering -> Bool
    forall a. Eq a => a -> a -> Bool
    == Ordering
    EQ) ([LIEWrappedName RdrName] -> [LIEWrappedName RdrName])
    -> ([LIEWrappedName RdrName] -> [LIEWrappedName RdrName])
    -> [LIEWrappedName RdrName]
    -> [LIEWrappedName RdrName]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (LIEWrappedName RdrName -> LIEWrappedName RdrName -> Ordering)
    -> [LIEWrappedName RdrName] -> [LIEWrappedName RdrName]
    forall a. (a -> a -> Ordering) -> [a] -> [a]
    sortBy LIEWrappedName RdrName -> LIEWrappedName RdrName -> Ordering
    compareLIewn
              alter :: Maybe (LIE GhcPs) -> Maybe (LIE GhcPs)
    alter = \case
                Nothing -> LIE GhcPs -> Maybe (LIE GhcPs)
    forall a. a -> Maybe a
    Just (LIE GhcPs -> Maybe (LIE GhcPs))
    -> (IE GhcPs -> LIE GhcPs) -> IE GhcPs -> Maybe (LIE GhcPs)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . SrcSpan -> IE GhcPs -> LIE GhcPs
    forall l e. l -> e -> GenLocated l e
    L SrcSpan
    new_l (IE GhcPs -> Maybe (LIE GhcPs)) -> IE GhcPs -> Maybe (LIE GhcPs)
    forall a b. (a -> b) -> a -> b
    $
                  case IE GhcPs
    new of
                    IEThingWith NoExtField n :: LIEWrappedName (IdP GhcPs)
    n wildcard :: IEWildcard
    wildcard g :: [LIEWrappedName (IdP GhcPs)]
    g flbl :: [Located (FieldLbl (IdP GhcPs))]
    flbl ->
                      XIEThingWith GhcPs
    -> LIEWrappedName (IdP GhcPs)
    -> IEWildcard
    -> [LIEWrappedName (IdP GhcPs)]
    -> [Located (FieldLbl (IdP GhcPs))]
    -> IE GhcPs
    forall pass.
    XIEThingWith pass
    -> LIEWrappedName (IdP pass)
    -> IEWildcard
    -> [LIEWrappedName (IdP pass)]
    -> [Located (FieldLbl (IdP pass))]
    -> IE pass
    IEThingWith NoExtField
    XIEThingWith GhcPs
    NoExtField LIEWrappedName (IdP GhcPs)
    n IEWildcard
    wildcard ([LIEWrappedName RdrName] -> [LIEWrappedName RdrName]
    normalizeWNames [LIEWrappedName (IdP GhcPs)]
    [LIEWrappedName RdrName]
    g) [Located (FieldLbl (IdP GhcPs))]
    flbl
                    other :: IE GhcPs
    other -> IE GhcPs
    other
                Just old :: LIE GhcPs
    old ->
                  let f :: IE GhcPs -> IE GhcPs
    f = \case
                        IEVar NoExtField n :: LIEWrappedName (IdP GhcPs)
    n -> XIEVar GhcPs -> LIEWrappedName (IdP GhcPs) -> IE GhcPs
    forall pass. XIEVar pass -> LIEWrappedName (IdP pass) -> IE pass
    IEVar NoExtField
    XIEVar GhcPs
    NoExtField LIEWrappedName (IdP GhcPs)
    n
                        IEThingAbs NoExtField _ -> IE GhcPs
    new
                        IEThingAll NoExtField n :: LIEWrappedName (IdP GhcPs)
    n -> XIEThingAll GhcPs -> LIEWrappedName (IdP GhcPs) -> IE GhcPs
    forall pass.
    XIEThingAll pass -> LIEWrappedName (IdP pass) -> IE pass
    IEThingAll NoExtField
    XIEThingAll GhcPs
    NoExtField LIEWrappedName (IdP GhcPs)
    n
                        IEThingWith NoExtField n :: LIEWrappedName (IdP GhcPs)
    n wildcard :: IEWildcard
    wildcard g :: [LIEWrappedName (IdP GhcPs)]
    g flbl :: [Located (FieldLbl (IdP GhcPs))]
    flbl ->
                          case IE GhcPs
    new of
                            IEVar NoExtField _ ->
                              String -> IE GhcPs
    forall a. HasCallStack => String -> a
    error "Ormolu.Imports broken presupposition"
                            IEThingAbs NoExtField _ ->
                              XIEThingWith GhcPs
    -> LIEWrappedName (IdP GhcPs)
    -> IEWildcard
    -> [LIEWrappedName (IdP GhcPs)]
    -> [Located (FieldLbl (IdP GhcPs))]
    -> IE GhcPs
    forall pass.
    XIEThingWith pass
    -> LIEWrappedName (IdP pass)
    -> IEWildcard
    -> [LIEWrappedName (IdP pass)]
    -> [Located (FieldLbl (IdP pass))]
    -> IE pass
    IEThingWith NoExtField
    XIEThingWith GhcPs
    NoExtField LIEWrappedName (IdP GhcPs)
    n IEWildcard
    wildcard [LIEWrappedName (IdP GhcPs)]
    g [Located (FieldLbl (IdP GhcPs))]
    flbl
                            IEThingAll NoExtField n' :: LIEWrappedName (IdP GhcPs)
    n' ->
                              XIEThingAll GhcPs -> LIEWrappedName (IdP GhcPs) -> IE GhcPs
    forall pass.
    XIEThingAll pass -> LIEWrappedName (IdP pass) -> IE pass
    IEThingAll NoExtField
    XIEThingAll GhcPs
    NoExtField LIEWrappedName (IdP GhcPs)
    n'
                            IEThingWith NoExtField n' :: LIEWrappedName (IdP GhcPs)
    n' wildcard' :: IEWildcard
    wildcard' g' :: [LIEWrappedName (IdP GhcPs)]
    g' flbl' :: [Located (FieldLbl (IdP GhcPs))]
    flbl' ->
                              let combinedWildcard :: IEWildcard
    combinedWildcard =
                                    case (IEWildcard
    wildcard, IEWildcard
    wildcard') of
                                      (IEWildcard _, _) -> Int -> IEWildcard
    IEWildcard 0
                                      (_, IEWildcard _) -> Int -> IEWildcard
    IEWildcard 0
                                      _ -> IEWildcard
    NoIEWildcard
                               in XIEThingWith GhcPs
    -> LIEWrappedName (IdP GhcPs)
    -> IEWildcard
    -> [LIEWrappedName (IdP GhcPs)]
    -> [Located (FieldLbl (IdP GhcPs))]
    -> IE GhcPs
    forall pass.
    XIEThingWith pass
    -> LIEWrappedName (IdP pass)
    -> IEWildcard
    -> [LIEWrappedName (IdP pass)]
    -> [Located (FieldLbl (IdP pass))]
    -> IE pass
    IEThingWith
                                    NoExtField
    XIEThingWith GhcPs
    NoExtField
                                    LIEWrappedName (IdP GhcPs)
    n'
                                    IEWildcard
    combinedWildcard
                                    ([LIEWrappedName RdrName] -> [LIEWrappedName RdrName]
    normalizeWNames ([LIEWrappedName (IdP GhcPs)]
    [LIEWrappedName RdrName]
    g [LIEWrappedName RdrName]
    -> [LIEWrappedName RdrName] -> [LIEWrappedName RdrName]
    forall a. Semigroup a => a -> a -> a
    <> [LIEWrappedName (IdP GhcPs)]
    [LIEWrappedName RdrName]
    g'))
                                    [Located (FieldLbl (IdP GhcPs))]
    flbl'
                            IEModuleContents NoExtField _ -> String -> IE GhcPs
    forall a. String -> a
    notImplemented "IEModuleContents"
                            IEGroup NoExtField _ _ -> String -> IE GhcPs
    forall a. String -> a
    notImplemented "IEGroup"
                            IEDoc NoExtField _ -> String -> IE GhcPs
    forall a. String -> a
    notImplemented "IEDoc"
                            IEDocNamed NoExtField _ -> String -> IE GhcPs
    forall a. String -> a
    notImplemented "IEDocNamed"
                            XIE x :: XXIE GhcPs
    x -> NoExtCon -> IE GhcPs
    forall a. NoExtCon -> a
    noExtCon NoExtCon
    XXIE GhcPs
    x
                        IEModuleContents NoExtField _ -> String -> IE GhcPs
    forall a. String -> a
    notImplemented "IEModuleContents"
                        IEGroup NoExtField _ _ -> String -> IE GhcPs
    forall a. String -> a
    notImplemented "IEGroup"
                        IEDoc NoExtField _ -> String -> IE GhcPs
    forall a. String -> a
    notImplemented "IEDoc"
                        IEDocNamed NoExtField _ -> String -> IE GhcPs
    forall a. String -> a
    notImplemented "IEDocNamed"
                        XIE x :: XXIE GhcPs
    x -> NoExtCon -> IE GhcPs
    forall a. NoExtCon -> a
    noExtCon NoExtCon
    XXIE GhcPs
    x
                   in LIE GhcPs -> Maybe (LIE GhcPs)
    forall a. a -> Maybe a
    Just (IE GhcPs -> IE GhcPs
    f (IE GhcPs -> IE GhcPs) -> LIE GhcPs -> LIE GhcPs
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> LIE GhcPs
    old)
           in (Maybe (LIE GhcPs) -> Maybe (LIE GhcPs))
    -> IEWrappedNameOrd
    -> Map IEWrappedNameOrd (LIE GhcPs)
    -> Map IEWrappedNameOrd (LIE GhcPs)
    forall k a.
    Ord k =>
    (Maybe a -> Maybe a) -> k -> Map k a -> Map k a
    M.alter Maybe (LIE GhcPs) -> Maybe (LIE GhcPs)
    alter IEWrappedNameOrd
    wname Map IEWrappedNameOrd (LIE GhcPs)
    m

    -- | A wrapper for @'IEWrappedName' 'RdrName'@ that allows us to define an
    -- 'Ord' instance for it.
    newtype IEWrappedNameOrd = IEWrappedNameOrd (IEWrappedName RdrName)
      deriving (IEWrappedNameOrd -> IEWrappedNameOrd -> Bool
    (IEWrappedNameOrd -> IEWrappedNameOrd -> Bool)
    -> (IEWrappedNameOrd -> IEWrappedNameOrd -> Bool)
    -> Eq IEWrappedNameOrd
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: IEWrappedNameOrd -> IEWrappedNameOrd -> Bool
    $c/= :: IEWrappedNameOrd -> IEWrappedNameOrd -> Bool
    == :: IEWrappedNameOrd -> IEWrappedNameOrd -> Bool
    $c== :: IEWrappedNameOrd -> IEWrappedNameOrd -> Bool
    Eq)

    instance Ord IEWrappedNameOrd where
      compare :: IEWrappedNameOrd -> IEWrappedNameOrd -> Ordering
    compare (IEWrappedNameOrd x :: IEWrappedName RdrName
    x) (IEWrappedNameOrd y :: IEWrappedName RdrName
    y) = IEWrappedName RdrName -> IEWrappedName RdrName -> Ordering
    compareIewn IEWrappedName RdrName
    x IEWrappedName RdrName
    y

    -- | Project @'IEWrappedName' 'RdrName'@ from @'IE' 'GhcPs'@.
    getIewn :: IE GhcPs -> IEWrappedNameOrd
    getIewn :: IE GhcPs -> IEWrappedNameOrd
    getIewn = \case
      IEVar NoExtField x :: LIEWrappedName (IdP GhcPs)
    x -> IEWrappedName RdrName -> IEWrappedNameOrd
    IEWrappedNameOrd (LIEWrappedName RdrName -> SrcSpanLess (LIEWrappedName RdrName)
    forall a. HasSrcSpan a => a -> SrcSpanLess a
    unLoc LIEWrappedName (IdP GhcPs)
    LIEWrappedName RdrName
    x)
      IEThingAbs NoExtField x :: LIEWrappedName (IdP GhcPs)
    x -> IEWrappedName RdrName -> IEWrappedNameOrd
    IEWrappedNameOrd (LIEWrappedName RdrName -> SrcSpanLess (LIEWrappedName RdrName)
    forall a. HasSrcSpan a => a -> SrcSpanLess a
    unLoc LIEWrappedName (IdP GhcPs)
    LIEWrappedName RdrName
    x)
      IEThingAll NoExtField x :: LIEWrappedName (IdP GhcPs)
    x -> IEWrappedName RdrName -> IEWrappedNameOrd
    IEWrappedNameOrd (LIEWrappedName RdrName -> SrcSpanLess (LIEWrappedName RdrName)
    forall a. HasSrcSpan a => a -> SrcSpanLess a
    unLoc LIEWrappedName (IdP GhcPs)
    LIEWrappedName RdrName
    x)
      IEThingWith NoExtField x :: LIEWrappedName (IdP GhcPs)
    x _ _ _ -> IEWrappedName RdrName -> IEWrappedNameOrd
    IEWrappedNameOrd (LIEWrappedName RdrName -> SrcSpanLess (LIEWrappedName RdrName)
    forall a. HasSrcSpan a => a -> SrcSpanLess a
    unLoc LIEWrappedName (IdP GhcPs)
    LIEWrappedName RdrName
    x)
      IEModuleContents NoExtField _ -> String -> IEWrappedNameOrd
    forall a. String -> a
    notImplemented "IEModuleContents"
      IEGroup NoExtField _ _ -> String -> IEWrappedNameOrd
    forall a. String -> a
    notImplemented "IEGroup"
      IEDoc NoExtField _ -> String -> IEWrappedNameOrd
    forall a. String -> a
    notImplemented "IEDoc"
      IEDocNamed NoExtField _ -> String -> IEWrappedNameOrd
    forall a. String -> a
    notImplemented "IEDocNamed"
      XIE x :: XXIE GhcPs
    x -> NoExtCon -> IEWrappedNameOrd
    forall a. NoExtCon -> a
    noExtCon NoExtCon
    XXIE GhcPs
    x

    -- | Like 'compareIewn' for located wrapped names.
    compareLIewn :: LIEWrappedName RdrName -> LIEWrappedName RdrName -> Ordering
    compareLIewn :: LIEWrappedName RdrName -> LIEWrappedName RdrName -> Ordering
    compareLIewn = IEWrappedName RdrName -> IEWrappedName RdrName -> Ordering
    compareIewn (IEWrappedName RdrName -> IEWrappedName RdrName -> Ordering)
    -> (LIEWrappedName RdrName -> IEWrappedName RdrName)
    -> LIEWrappedName RdrName
    -> LIEWrappedName RdrName
    -> Ordering
    forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
    `on` LIEWrappedName RdrName -> IEWrappedName RdrName
    forall a. HasSrcSpan a => a -> SrcSpanLess a
    unLoc

    -- | Compare two @'IEWrapppedName' 'RdrName'@ things.
    compareIewn :: IEWrappedName RdrName -> IEWrappedName RdrName -> Ordering
    compareIewn :: IEWrappedName RdrName -> IEWrappedName RdrName -> Ordering
    compareIewn (IEName x :: Located RdrName
    x) (IEName y :: Located RdrName
    y) = Located RdrName -> SrcSpanLess (Located RdrName)
    forall a. HasSrcSpan a => a -> SrcSpanLess a
    unLoc Located RdrName
    x RdrName -> RdrName -> Ordering
    `compareRdrName` Located RdrName -> SrcSpanLess (Located RdrName)
    forall a. HasSrcSpan a => a -> SrcSpanLess a
    unLoc Located RdrName
    y
    compareIewn (IEName _) (IEPattern _) = Ordering
    LT
    compareIewn (IEName _) (IEType _) = Ordering
    LT
    compareIewn (IEPattern _) (IEName _) = Ordering
    GT
    compareIewn (IEPattern x :: Located RdrName
    x) (IEPattern y :: Located RdrName
    y) = Located RdrName -> SrcSpanLess (Located RdrName)
    forall a. HasSrcSpan a => a -> SrcSpanLess a
    unLoc Located RdrName
    x RdrName -> RdrName -> Ordering
    `compareRdrName` Located RdrName -> SrcSpanLess (Located RdrName)
    forall a. HasSrcSpan a => a -> SrcSpanLess a
    unLoc Located RdrName
    y
    compareIewn (IEPattern _) (IEType _) = Ordering
    LT
    compareIewn (IEType _) (IEName _) = Ordering
    GT
    compareIewn (IEType _) (IEPattern _) = Ordering
    GT
    compareIewn (IEType x :: Located RdrName
    x) (IEType y :: Located RdrName
    y) = Located RdrName -> SrcSpanLess (Located RdrName)
    forall a. HasSrcSpan a => a -> SrcSpanLess a
    unLoc Located RdrName
    x RdrName -> RdrName -> Ordering
    `compareRdrName` Located RdrName -> SrcSpanLess (Located RdrName)
    forall a. HasSrcSpan a => a -> SrcSpanLess a
    unLoc Located RdrName
    y

    compareRdrName :: RdrName -> RdrName -> Ordering
    compareRdrName :: RdrName -> RdrName -> Ordering
    compareRdrName x :: RdrName
    x y :: RdrName
    y =
      case (RdrName -> String
    getNameStr RdrName
    x, RdrName -> String
    getNameStr RdrName
    y) of
        ([], []) -> Ordering
    EQ
        ((_ : _), []) -> Ordering
    GT
        ([], (_ : _)) -> Ordering
    LT
        ((x' :: Char
    x' : _), (y' :: Char
    y' : _)) ->
          case (Char -> Bool
    isAlphaNum Char
    x', Char -> Bool
    isAlphaNum Char
    y') of
            (False, False) -> RdrName
    x RdrName -> RdrName -> Ordering
    forall a. Ord a => a -> a -> Ordering
    `compare` RdrName
    y
            (True, False) -> Ordering
    LT
            (False, True) -> Ordering
    GT
            (True, True) -> RdrName
    x RdrName -> RdrName -> Ordering
    forall a. Ord a => a -> a -> Ordering
    `compare` RdrName
    y
      where
        getNameStr :: RdrName -> String
    getNameStr = OccName -> String
    forall o. Outputable o => o -> String
    showOutputable (OccName -> String) -> (RdrName -> OccName) -> RdrName -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . RdrName -> OccName
    rdrNameOcc