    {-# LANGUAGE ImportQualifiedPost #-}
    module Extension(
      defaultExtensions,
      configExtensions,
      extensionImpliedEnabledBy,
      extensionImplies
      ) where

    import Data.List.Extra
    import Data.Map qualified as Map
    import GHC.LanguageExtensions.Type
    import Language.Haskell.GhclibParserEx.GHC.Driver.Session qualified as GhclibParserEx

    badExtensions :: [Extension]
    badExtensions =
      [Extension]
    reallyBadExtensions [Extension] -> [Extension] -> [Extension]
    forall a. [a] -> [a] -> [a]
    ++
      [ Extension
    Arrows -- steals proc
      , Extension
    UnboxedTuples, Extension
    UnboxedSums -- breaks (#) lens operator
      , Extension
    QuasiQuotes -- breaks [x| ...], making whitespace free list comps break
      , {- DoRec , -} Extension
    RecursiveDo -- breaks rec
      , Extension
    LexicalNegation -- changes '-', see https://github.com/ndmitchell/hlint/issues/1230
      -- These next two change syntax significantly and must be opt-in.
      , Extension
    OverloadedRecordDot
      , Extension
    OverloadedRecordUpdate
      ]

    reallyBadExtensions :: [Extension]
    reallyBadExtensions =
      [ Extension
    TransformListComp -- steals the group keyword
      , Extension
    StaticPointers -- steals the static keyword
      {- , XmlSyntax , RegularPatterns -} -- steals a-b and < operators
      , Extension
    AlternativeLayoutRule -- Does not play well with 'MultiWayIf'
      , Extension
    NegativeLiterals -- Was not enabled by HSE and enabling breaks tests.
      , Extension
    StarIsType -- conflicts with TypeOperators. StarIsType is currently enabled by default,
                   -- so adding it here has no effect, but it may not be the case in future GHC releases.
      , Extension
    MonadComprehensions -- Discussed in https://github.com/ndmitchell/hlint/issues/1261
      ]

    -- | Extensions we turn on by default when parsing. Aim to parse as
    -- many files as we can.
    defaultExtensions :: [Extension]
    defaultExtensions :: [Extension]
    defaultExtensions = [Extension]
    forall a. (Enum a, Bounded a) => [a]
    enumerate [Extension] -> [Extension] -> [Extension]
    forall a. Eq a => [a] -> [a] -> [a]
    \\ [Extension]
    badExtensions

    -- | Extensions we turn on when reading config files, don't have to deal with the whole world
    --   of variations - in particular, we might require spaces in some places.
    configExtensions :: [Extension]
    configExtensions :: [Extension]
    configExtensions = [Extension]
    forall a. (Enum a, Bounded a) => [a]
    enumerate [Extension] -> [Extension] -> [Extension]
    forall a. Eq a => [a] -> [a] -> [a]
    \\ [Extension]
    reallyBadExtensions

    -- | This extension implies the following extensions are
    -- enabled/disabled.
    extensionImplies :: Extension -> ([Extension], [Extension])
    extensionImplies :: Extension -> ([Extension], [Extension])
    extensionImplies = \Extension
    x ->([Extension], [Extension])
    -> Extension
    -> Map Extension ([Extension], [Extension])
    -> ([Extension], [Extension])
    forall k a. Ord k => a -> k -> Map k a -> a
    Map.findWithDefault ([], []) Extension
    x Map Extension ([Extension], [Extension])
    mp
      where mp :: Map Extension ([Extension], [Extension])
    mp = [(Extension, ([Extension], [Extension]))]
    -> Map Extension ([Extension], [Extension])
    forall k a. Ord k => [(k, a)] -> Map k a
    Map.fromList [(Extension, ([Extension], [Extension]))]
    extensionImplications

    -- 'x' is implied enabled by the result extensions.
    extensionImpliedEnabledBy :: Extension -> [Extension]
    extensionImpliedEnabledBy :: Extension -> [Extension]
    extensionImpliedEnabledBy = \Extension
    x -> [Extension]
    -> Extension -> Map Extension [Extension] -> [Extension]
    forall k a. Ord k => a -> k -> Map k a -> a
    Map.findWithDefault [] Extension
    x Map Extension [Extension]
    mp
      where
        mp :: Map Extension [Extension]
    mp = ([Extension] -> [Extension] -> [Extension])
    -> [(Extension, [Extension])] -> Map Extension [Extension]
    forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
    Map.fromListWith [Extension] -> [Extension] -> [Extension]
    forall a. [a] -> [a] -> [a]
    (++) [(Extension
    b, [Extension
    a]) | (Extension
    a, ([Extension]
    bs, [Extension]
    _)) <- [(Extension, ([Extension], [Extension]))]
    extensionImplications, Extension
    b <- [Extension]
    bs]

    -- 'x' is implied disabled by the result extensions. Not called at this time.
    _extensionImpliedDisabledBy :: Extension -> [Extension]
    _extensionImpliedDisabledBy :: Extension -> [Extension]
    _extensionImpliedDisabledBy = \Extension
    x -> [Extension]
    -> Extension -> Map Extension [Extension] -> [Extension]
    forall k a. Ord k => a -> k -> Map k a -> a
    Map.findWithDefault [] Extension
    x Map Extension [Extension]
    mp
      where
        mp :: Map Extension [Extension]
    mp = ([Extension] -> [Extension] -> [Extension])
    -> [(Extension, [Extension])] -> Map Extension [Extension]
    forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
    Map.fromListWith [Extension] -> [Extension] -> [Extension]
    forall a. [a] -> [a] -> [a]
    (++) [(Extension
    b, [Extension
    a]) | (Extension
    a, ([Extension]
    _, [Extension]
    bs)) <- [(Extension, ([Extension], [Extension]))]
    extensionImplications, Extension
    b <- [Extension]
    bs]

    -- | (a, bs) means extension a implies all of bs. Uses GHC source at
    -- DynFlags.impliedXFlags
    extensionImplications :: [(Extension, ([Extension], [Extension]))]
    extensionImplications :: [(Extension, ([Extension], [Extension]))]
    extensionImplications = [(Extension, ([Extension], [Extension]))]
    GhclibParserEx.extensionImplications