    {-# LANGUAGE CPP #-}
    {-# LANGUAGE FlexibleContexts #-}
    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE Rank2Types #-}
    {-# LANGUAGE ScopedTypeVariables #-}

    -----------------------------------------------------------------------------

    -- |
    -- Module      :  Distribution.PackageDescription.Parsec
    -- Copyright   :  Isaac Jones 2003-2005
    -- License     :  BSD3
    --
    -- Maintainer  :  cabal-devel@haskell.org
    -- Portability :  portable
    --
    -- This defined parsers and partial pretty printers for the @.cabal@ format.
    module Distribution.PackageDescription.Parsec
      ( -- * Package descriptions
        parseGenericPackageDescription
      , parseGenericPackageDescriptionMaybe

        -- ** Parsing
      , ParseResult
      , runParseResult

        -- * New-style spec-version
      , scanSpecVersion

        -- ** Supplementary build information
      , parseHookedBuildInfo
      ) where

    import Distribution.Compat.Prelude
    import Prelude ()

    import Control.Monad.State.Strict (StateT, execStateT)
    import Control.Monad.Trans.Class (lift)
    import Distribution.CabalSpecVersion
    import Distribution.Compat.Lens
    import Distribution.FieldGrammar
    import Distribution.FieldGrammar.Parsec (NamelessField (..))
    import Distribution.Fields.ConfVar (parseConditionConfVar)
    import Distribution.Fields.Field (FieldName, getName)
    import Distribution.Fields.LexerMonad (LexWarning, toPWarnings)
    import Distribution.Fields.ParseResult
    import Distribution.Fields.Parser
    import Distribution.PackageDescription
    import Distribution.PackageDescription.Configuration (freeVars, transformAllBuildInfos)
    import Distribution.PackageDescription.FieldGrammar
    import Distribution.PackageDescription.Quirks (patchQuirks)
    import Distribution.Parsec (parsec, simpleParsecBS)
    import Distribution.Parsec.FieldLineStream (fieldLineStreamFromBS)
    import Distribution.Parsec.Position (Position (..), zeroPos)
    import Distribution.Parsec.Warning (PWarnType (..))
    import Distribution.Pretty (prettyShow)
    import Distribution.Utils.Generic (breakMaybe, fromUTF8BS, toUTF8BS, unfoldrM, validateUTF8)
    import Distribution.Version (Version, mkVersion, versionNumbers)

    import qualified Data.ByteString as BS
    import qualified Data.ByteString.Char8 as BS8
    import qualified Data.Map.Strict as Map
    import qualified Data.Set as Set
    import qualified Distribution.Compat.Newtype as Newtype
    import qualified Distribution.Compat.NonEmptySet as NES
    import qualified Distribution.Types.BuildInfo.Lens as L
    import qualified Distribution.Types.Executable.Lens as L
    import qualified Distribution.Types.ForeignLib.Lens as L
    import qualified Distribution.Types.GenericPackageDescription.Lens as L
    import qualified Distribution.Types.PackageDescription.Lens as L
    import qualified Distribution.Types.SetupBuildInfo.Lens as L
    import qualified Text.Parsec as P

    ------------------------------------------------------------------------------

    -- | Parses the given file into a 'GenericPackageDescription'.
    --
    -- In Cabal 1.2 the syntax for package descriptions was changed to a format
    -- with sections and possibly indented property descriptions.
    parseGenericPackageDescription :: BS.ByteString -> ParseResult GenericPackageDescription
    parseGenericPackageDescription :: ByteString -> ParseResult GenericPackageDescription
    parseGenericPackageDescription ByteString
    bs = do
      -- set scanned version
      Maybe Version -> ParseResult ()
    setCabalSpecVersion Maybe Version
    ver

      csv <- case Maybe Version
    ver of
        -- if we get too new version, fail right away
        Just Version
    v -> case [Int] -> Maybe CabalSpecVersion
    cabalSpecFromVersionDigits (Version -> [Int]
    versionNumbers Version
    v) of
          Just CabalSpecVersion
    csv -> Maybe CabalSpecVersion -> ParseResult (Maybe CabalSpecVersion)
    forall a. a -> ParseResult a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (CabalSpecVersion -> Maybe CabalSpecVersion
    forall a. a -> Maybe a
    Just CabalSpecVersion
    csv)
          Maybe CabalSpecVersion
    Nothing ->
            Position -> String -> ParseResult (Maybe CabalSpecVersion)
    forall a. Position -> String -> ParseResult a
    parseFatalFailure Position
    zeroPos (String -> ParseResult (Maybe CabalSpecVersion))
    -> String -> ParseResult (Maybe CabalSpecVersion)
    forall a b. (a -> b) -> a -> b
    $
              String
    "Unsupported cabal format version in cabal-version field: "
                String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Version -> String
    forall a. Pretty a => a -> String
    prettyShow Version
    v
                String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    ".\n"
                String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    cabalFormatVersionsDesc
        Maybe Version
    _ -> Maybe CabalSpecVersion -> ParseResult (Maybe CabalSpecVersion)
    forall a. a -> ParseResult a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Maybe CabalSpecVersion
    forall a. Maybe a
    Nothing

      case readFields' bs'' of
        Right ([Field Position]
    fs, [LexWarning]
    lexWarnings) -> do
          Bool -> ParseResult () -> ParseResult ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when Bool
    patched (ParseResult () -> ParseResult ())
    -> ParseResult () -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $
            Position -> PWarnType -> String -> ParseResult ()
    parseWarning Position
    zeroPos PWarnType
    PWTQuirkyCabalFile String
    "Legacy cabal file"
          -- UTF8 is validated in a prepass step, afterwards parsing is lenient.
          Maybe CabalSpecVersion
    -> [LexWarning]
    -> Maybe Int
    -> [Field Position]
    -> ParseResult GenericPackageDescription
    parseGenericPackageDescription' Maybe CabalSpecVersion
    csv [LexWarning]
    lexWarnings Maybe Int
    invalidUtf8 [Field Position]
    fs
        -- TODO: better marshalling of errors
        Left ParseError
    perr -> Position -> String -> ParseResult GenericPackageDescription
    forall a. Position -> String -> ParseResult a
    parseFatalFailure Position
    pos (ParseError -> String
    forall a. Show a => a -> String
    show ParseError
    perr)
          where
            ppos :: SourcePos
    ppos = ParseError -> SourcePos
    P.errorPos ParseError
    perr
            pos :: Position
    pos = Int -> Int -> Position
    Position (SourcePos -> Int
    P.sourceLine SourcePos
    ppos) (SourcePos -> Int
    P.sourceColumn SourcePos
    ppos)
      where
        (Bool
    patched, ByteString
    bs') = ByteString -> (Bool, ByteString)
    patchQuirks ByteString
    bs
        ver :: Maybe Version
    ver = ByteString -> Maybe Version
    scanSpecVersion ByteString
    bs'

        invalidUtf8 :: Maybe Int
    invalidUtf8 = ByteString -> Maybe Int
    validateUTF8 ByteString
    bs'

        -- if there are invalid utf8 characters, we make the bytestring valid.
        bs'' :: ByteString
    bs'' = case Maybe Int
    invalidUtf8 of
          Maybe Int
    Nothing -> ByteString
    bs'
          Just Int
    _ -> String -> ByteString
    toUTF8BS (ByteString -> String
    fromUTF8BS ByteString
    bs')

    -- | 'Maybe' variant of 'parseGenericPackageDescription'
    parseGenericPackageDescriptionMaybe :: BS.ByteString -> Maybe GenericPackageDescription
    parseGenericPackageDescriptionMaybe :: ByteString -> Maybe GenericPackageDescription
    parseGenericPackageDescriptionMaybe =
      ((Maybe Version, NonEmpty PError)
     -> Maybe GenericPackageDescription)
    -> (GenericPackageDescription -> Maybe GenericPackageDescription)
    -> Either
         (Maybe Version, NonEmpty PError) GenericPackageDescription
    -> Maybe GenericPackageDescription
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either (Maybe GenericPackageDescription
    -> (Maybe Version, NonEmpty PError)
    -> Maybe GenericPackageDescription
    forall a b. a -> b -> a
    const Maybe GenericPackageDescription
    forall a. Maybe a
    Nothing) GenericPackageDescription -> Maybe GenericPackageDescription
    forall a. a -> Maybe a
    Just (Either (Maybe Version, NonEmpty PError) GenericPackageDescription
     -> Maybe GenericPackageDescription)
    -> (ByteString
        -> Either
             (Maybe Version, NonEmpty PError) GenericPackageDescription)
    -> ByteString
    -> Maybe GenericPackageDescription
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ([PWarning],
     Either (Maybe Version, NonEmpty PError) GenericPackageDescription)
    -> Either
         (Maybe Version, NonEmpty PError) GenericPackageDescription
    forall a b. (a, b) -> b
    snd (([PWarning],
      Either (Maybe Version, NonEmpty PError) GenericPackageDescription)
     -> Either
          (Maybe Version, NonEmpty PError) GenericPackageDescription)
    -> (ByteString
        -> ([PWarning],
            Either (Maybe Version, NonEmpty PError) GenericPackageDescription))
    -> ByteString
    -> Either
         (Maybe Version, NonEmpty PError) GenericPackageDescription
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ParseResult GenericPackageDescription
    -> ([PWarning],
        Either (Maybe Version, NonEmpty PError) GenericPackageDescription)
    forall a.
    ParseResult a
    -> ([PWarning], Either (Maybe Version, NonEmpty PError) a)
    runParseResult (ParseResult GenericPackageDescription
     -> ([PWarning],
         Either (Maybe Version, NonEmpty PError) GenericPackageDescription))
    -> (ByteString -> ParseResult GenericPackageDescription)
    -> ByteString
    -> ([PWarning],
        Either (Maybe Version, NonEmpty PError) GenericPackageDescription)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> ParseResult GenericPackageDescription
    parseGenericPackageDescription

    fieldlinesToBS :: [FieldLine ann] -> BS.ByteString
    fieldlinesToBS :: forall ann. [FieldLine ann] -> ByteString
    fieldlinesToBS = ByteString -> [ByteString] -> ByteString
    BS.intercalate ByteString
    "\n" ([ByteString] -> ByteString)
    -> ([FieldLine ann] -> [ByteString])
    -> [FieldLine ann]
    -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (FieldLine ann -> ByteString) -> [FieldLine ann] -> [ByteString]
    forall a b. (a -> b) -> [a] -> [b]
    map (\(FieldLine ann
    _ ByteString
    bs) -> ByteString
    bs)

    -- Monad in which sections are parsed
    type SectionParser = StateT SectionS ParseResult

    -- | State of section parser
    data SectionS = SectionS
      { SectionS -> GenericPackageDescription
    _stateGpd :: !GenericPackageDescription
      , SectionS -> Map String CondTreeBuildInfo
    _stateCommonStanzas :: !(Map String CondTreeBuildInfo)
      }

    stateGpd :: Lens' SectionS GenericPackageDescription
    stateGpd :: Lens' SectionS GenericPackageDescription
    stateGpd GenericPackageDescription -> f GenericPackageDescription
    f (SectionS GenericPackageDescription
    gpd Map String CondTreeBuildInfo
    cs) = (\GenericPackageDescription
    x -> GenericPackageDescription
    -> Map String CondTreeBuildInfo -> SectionS
    SectionS GenericPackageDescription
    x Map String CondTreeBuildInfo
    cs) (GenericPackageDescription -> SectionS)
    -> f GenericPackageDescription -> f SectionS
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> GenericPackageDescription -> f GenericPackageDescription
    f GenericPackageDescription
    gpd
    {-# INLINE stateGpd #-}

    stateCommonStanzas :: Lens' SectionS (Map String CondTreeBuildInfo)
    stateCommonStanzas :: Lens' SectionS (Map String CondTreeBuildInfo)
    stateCommonStanzas Map String CondTreeBuildInfo -> f (Map String CondTreeBuildInfo)
    f (SectionS GenericPackageDescription
    gpd Map String CondTreeBuildInfo
    cs) = GenericPackageDescription
    -> Map String CondTreeBuildInfo -> SectionS
    SectionS GenericPackageDescription
    gpd (Map String CondTreeBuildInfo -> SectionS)
    -> f (Map String CondTreeBuildInfo) -> f SectionS
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Map String CondTreeBuildInfo -> f (Map String CondTreeBuildInfo)
    f Map String CondTreeBuildInfo
    cs
    {-# INLINE stateCommonStanzas #-}

    -- Note [Accumulating parser]
    --
    -- This parser has two "states":

    -- * first we parse fields of PackageDescription

    -- * then we parse sections (libraries, executables, etc)
    parseGenericPackageDescription'
      :: Maybe CabalSpecVersion
      -> [LexWarning]
      -> Maybe Int
      -> [Field Position]
      -> ParseResult GenericPackageDescription
    parseGenericPackageDescription' :: Maybe CabalSpecVersion
    -> [LexWarning]
    -> Maybe Int
    -> [Field Position]
    -> ParseResult GenericPackageDescription
    parseGenericPackageDescription' Maybe CabalSpecVersion
    scannedVer [LexWarning]
    lexWarnings Maybe Int
    utf8WarnPos [Field Position]
    fs = do
      [PWarning] -> ParseResult ()
    parseWarnings ([LexWarning] -> [PWarning]
    toPWarnings [LexWarning]
    lexWarnings)
      Maybe Int -> (Int -> ParseResult ()) -> ParseResult ()
    forall (t :: * -> *) (f :: * -> *) a b.
    (Foldable t, Applicative f) =>
    t a -> (a -> f b) -> f ()
    for_ Maybe Int
    utf8WarnPos ((Int -> ParseResult ()) -> ParseResult ())
    -> (Int -> ParseResult ()) -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $ \Int
    pos ->
        Position -> PWarnType -> String -> ParseResult ()
    parseWarning Position
    zeroPos PWarnType
    PWTUTF (String -> ParseResult ()) -> String -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $ String
    "UTF8 encoding problem at byte offset " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Int -> String
    forall a. Show a => a -> String
    show Int
    pos
      let (Syntax
    syntax, [Field Position]
    fs') = [Field Position] -> (Syntax, [Field Position])
    forall ann. [Field ann] -> (Syntax, [Field ann])
    sectionizeFields [Field Position]
    fs
      let (Fields Position
    fields, [Field Position]
    sectionFields) = [Field Position] -> (Fields Position, [Field Position])
    forall ann. [Field ann] -> (Fields ann, [Field ann])
    takeFields [Field Position]
    fs'

      -- cabal-version
      specVer <- case Maybe CabalSpecVersion
    scannedVer of
        Just CabalSpecVersion
    v -> CabalSpecVersion -> ParseResult CabalSpecVersion
    forall a. a -> ParseResult a
    forall (m :: * -> *) a. Monad m => a -> m a
    return CabalSpecVersion
    v
        Maybe CabalSpecVersion
    Nothing -> case ByteString -> Fields Position -> Maybe [NamelessField Position]
    forall k a. Ord k => k -> Map k a -> Maybe a
    Map.lookup ByteString
    "cabal-version" Fields Position
    fields Maybe [NamelessField Position]
    -> ([NamelessField Position] -> Maybe (NamelessField Position))
    -> Maybe (NamelessField Position)
    forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= [NamelessField Position] -> Maybe (NamelessField Position)
    forall a. [a] -> Maybe a
    safeLast of
          Maybe (NamelessField Position)
    Nothing -> CabalSpecVersion -> ParseResult CabalSpecVersion
    forall a. a -> ParseResult a
    forall (m :: * -> *) a. Monad m => a -> m a
    return CabalSpecVersion
    CabalSpecV1_0
          Just (MkNamelessField Position
    pos [FieldLine Position]
    fls) -> do
            -- version will be parsed twice, therefore we parse without warnings.
            v <-
              ParseResult CabalSpecVersion -> ParseResult CabalSpecVersion
    forall a. ParseResult a -> ParseResult a
    withoutWarnings (ParseResult CabalSpecVersion -> ParseResult CabalSpecVersion)
    -> ParseResult CabalSpecVersion -> ParseResult CabalSpecVersion
    forall a b. (a -> b) -> a -> b
    $
                (CabalSpecVersion -> SpecVersion)
    -> SpecVersion -> CabalSpecVersion
    forall o n. Newtype o n => (o -> n) -> n -> o
    Newtype.unpack' CabalSpecVersion -> SpecVersion
    SpecVersion
                  (SpecVersion -> CabalSpecVersion)
    -> ParseResult SpecVersion -> ParseResult CabalSpecVersion
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$>
                  -- Use version with || and && but before addition of ^>= and removal of -any
                  Position
    -> ParsecParser SpecVersion
    -> CabalSpecVersion
    -> [FieldLine Position]
    -> ParseResult SpecVersion
    forall a.
    Position
    -> ParsecParser a
    -> CabalSpecVersion
    -> [FieldLine Position]
    -> ParseResult a
    runFieldParser Position
    pos ParsecParser SpecVersion
    forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
    forall (m :: * -> *). CabalParsing m => m SpecVersion
    parsec CabalSpecVersion
    CabalSpecV1_24 [FieldLine Position]
    fls

            -- if it were at the beginning, scanner would found it
            when (v >= CabalSpecV2_2) $
              parseFailure pos $
                "cabal-version should be at the beginning of the file starting with spec version 2.2.\n"
                  ++ cabalFormatVersionsDesc

            return v

      -- reset cabal version, it might not be set
      let specVer' = [Int] -> Version
    mkVersion (CabalSpecVersion -> [Int]
    cabalSpecToVersionDigits CabalSpecVersion
    specVer)
      setCabalSpecVersion (Just specVer')

      -- Package description
      pd <- parseFieldGrammar specVer fields packageDescriptionFieldGrammar

      -- Check that scanned and parsed versions match.
      unless (specVer == specVersion pd) $
        parseFailure zeroPos $
          "Scanned and parsed cabal-versions don't match "
            ++ prettyShow (SpecVersion specVer)
            ++ " /= "
            ++ prettyShow (SpecVersion (specVersion pd))

      maybeWarnCabalVersion syntax pd

      -- Sections
      let gpd =
            GenericPackageDescription
    emptyGenericPackageDescription
              GenericPackageDescription
    -> (GenericPackageDescription -> GenericPackageDescription)
    -> GenericPackageDescription
    forall a b. a -> (a -> b) -> b
    & LensLike
      Identity
      GenericPackageDescription
      GenericPackageDescription
      PackageDescription
      PackageDescription
    Lens' GenericPackageDescription PackageDescription
    L.packageDescription LensLike
      Identity
      GenericPackageDescription
      GenericPackageDescription
      PackageDescription
      PackageDescription
    -> PackageDescription
    -> GenericPackageDescription
    -> GenericPackageDescription
    forall s t a b. ASetter s t a b -> b -> s -> t
    .~ PackageDescription
    pd
      gpd1 <- view stateGpd <$> execStateT (goSections specVer sectionFields) (SectionS gpd Map.empty)

      let gpd2 = CabalSpecVersion
    -> GenericPackageDescription -> GenericPackageDescription
    postProcessInternalDeps CabalSpecVersion
    specVer GenericPackageDescription
    gpd1
      checkForUndefinedFlags gpd2
      checkForUndefinedCustomSetup gpd2
      -- See nothunks test, without this deepseq we get (at least):
      -- Thunk in ThunkInfo {thunkContext = ["PackageIdentifier","PackageDescription","GenericPackageDescription"]}
      --
      -- TODO: re-benchmark, whether `deepseq` is important (both cabal-benchmarks and solver-benchmarks)
      -- TODO: remove the need for deepseq if `deepseq` in fact matters
      -- NOTE: IIRC it does affect (maximal) memory usage, which causes less GC pressure
      gpd2 `deepseq` return gpd2
      where
        safeLast :: [a] -> Maybe a
        safeLast :: forall a. [a] -> Maybe a
    safeLast = [a] -> Maybe a
    forall a. [a] -> Maybe a
    listToMaybe ([a] -> Maybe a) -> ([a] -> [a]) -> [a] -> Maybe a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [a] -> [a]
    forall a. [a] -> [a]
    reverse

        newSyntaxVersion :: CabalSpecVersion
        newSyntaxVersion :: CabalSpecVersion
    newSyntaxVersion = CabalSpecVersion
    CabalSpecV1_2

        maybeWarnCabalVersion :: Syntax -> PackageDescription -> ParseResult ()
        maybeWarnCabalVersion :: Syntax -> PackageDescription -> ParseResult ()
    maybeWarnCabalVersion Syntax
    syntax PackageDescription
    pkg
          | Syntax
    syntax Syntax -> Syntax -> Bool
    forall a. Eq a => a -> a -> Bool
    == Syntax
    NewSyntax Bool -> Bool -> Bool
    && PackageDescription -> CabalSpecVersion
    specVersion PackageDescription
    pkg CabalSpecVersion -> CabalSpecVersion -> Bool
    forall a. Ord a => a -> a -> Bool
    < CabalSpecVersion
    newSyntaxVersion =
              Position -> PWarnType -> String -> ParseResult ()
    parseWarning Position
    zeroPos PWarnType
    PWTNewSyntax (String -> ParseResult ()) -> String -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $
                String
    "A package using section syntax must specify at least\n"
                  String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    "'cabal-version: >= 1.2'."
        maybeWarnCabalVersion Syntax
    syntax PackageDescription
    pkg
          | Syntax
    syntax Syntax -> Syntax -> Bool
    forall a. Eq a => a -> a -> Bool
    == Syntax
    OldSyntax Bool -> Bool -> Bool
    && PackageDescription -> CabalSpecVersion
    specVersion PackageDescription
    pkg CabalSpecVersion -> CabalSpecVersion -> Bool
    forall a. Ord a => a -> a -> Bool
    >= CabalSpecVersion
    newSyntaxVersion =
              Position -> PWarnType -> String -> ParseResult ()
    parseWarning Position
    zeroPos PWarnType
    PWTOldSyntax (String -> ParseResult ()) -> String -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $
                String
    "A package using 'cabal-version: "
                  String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ SpecVersion -> String
    forall a. Pretty a => a -> String
    prettyShow (CabalSpecVersion -> SpecVersion
    SpecVersion (PackageDescription -> CabalSpecVersion
    specVersion PackageDescription
    pkg))
                  String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    "' must use section syntax. See the Cabal user guide for details."
        maybeWarnCabalVersion Syntax
    _ PackageDescription
    _ = () -> ParseResult ()
    forall a. a -> ParseResult a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

    -- See #4899
    cabalFormatVersionsDesc :: String
    cabalFormatVersionsDesc :: String
    cabalFormatVersionsDesc = String
    "Current cabal-version values are listed at https://cabal.readthedocs.io/en/stable/file-format-changelog.html."

    goSections :: CabalSpecVersion -> [Field Position] -> SectionParser ()
    goSections :: CabalSpecVersion
    -> [Field Position] -> StateT SectionS ParseResult ()
    goSections CabalSpecVersion
    specVer = (Field Position -> StateT SectionS ParseResult ())
    -> [Field Position] -> StateT SectionS ParseResult ()
    forall (t :: * -> *) (f :: * -> *) a b.
    (Foldable t, Applicative f) =>
    (a -> f b) -> t a -> f ()
    traverse_ Field Position -> StateT SectionS ParseResult ()
    process
      where
        process :: Field Position -> StateT SectionS ParseResult ()
    process (Field (Name Position
    pos ByteString
    name) [FieldLine Position]
    _) =
          ParseResult () -> StateT SectionS ParseResult ()
    forall (m :: * -> *) a. Monad m => m a -> StateT SectionS m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (ParseResult () -> StateT SectionS ParseResult ())
    -> ParseResult () -> StateT SectionS ParseResult ()
    forall a b. (a -> b) -> a -> b
    $
            Position -> PWarnType -> String -> ParseResult ()
    parseWarning Position
    pos PWarnType
    PWTTrailingFields (String -> ParseResult ()) -> String -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $
              String
    "Ignoring trailing fields after sections: " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ ByteString -> String
    forall a. Show a => a -> String
    show ByteString
    name
        process (Section Name Position
    name [SectionArg Position]
    args [Field Position]
    secFields) =
          Name Position
    -> [SectionArg Position]
    -> [Field Position]
    -> StateT SectionS ParseResult ()
    parseSection Name Position
    name [SectionArg Position]
    args [Field Position]
    secFields

        snoc :: a -> [a] -> [a]
    snoc a
    x [a]
    xs = [a]
    xs [a] -> [a] -> [a]
    forall a. [a] -> [a] -> [a]
    ++ [a
    x]

        hasCommonStanzas :: HasCommonStanzas
    hasCommonStanzas = CabalSpecVersion -> HasCommonStanzas
    specHasCommonStanzas CabalSpecVersion
    specVer

        -- we need signature, because this is polymorphic, but not-closed
        parseCondTree'
          :: L.HasBuildInfo a
          => ParsecFieldGrammar' a
          -- \^ grammar
          -> (BuildInfo -> a)
          -> Map String CondTreeBuildInfo
          -- \^ common stanzas
          -> [Field Position]
          -> ParseResult (CondTree ConfVar [Dependency] a)
        parseCondTree' :: forall a.
    HasBuildInfo a =>
    ParsecFieldGrammar' a
    -> (BuildInfo -> a)
    -> Map String CondTreeBuildInfo
    -> [Field Position]
    -> ParseResult (CondTree ConfVar [Dependency] a)
    parseCondTree' = CabalSpecVersion
    -> ParsecFieldGrammar' a
    -> (BuildInfo -> a)
    -> Map String CondTreeBuildInfo
    -> [Field Position]
    -> ParseResult (CondTree ConfVar [Dependency] a)
    forall a.
    HasBuildInfo a =>
    CabalSpecVersion
    -> ParsecFieldGrammar' a
    -> (BuildInfo -> a)
    -> Map String CondTreeBuildInfo
    -> [Field Position]
    -> ParseResult (CondTree ConfVar [Dependency] a)
    parseCondTreeWithCommonStanzas CabalSpecVersion
    specVer

        parseSection :: Name Position -> [SectionArg Position] -> [Field Position] -> SectionParser ()
        parseSection :: Name Position
    -> [SectionArg Position]
    -> [Field Position]
    -> StateT SectionS ParseResult ()
    parseSection (Name Position
    pos ByteString
    name) [SectionArg Position]
    args [Field Position]
    fields
          | HasCommonStanzas
    hasCommonStanzas HasCommonStanzas -> HasCommonStanzas -> Bool
    forall a. Eq a => a -> a -> Bool
    == HasCommonStanzas
    NoCommonStanzas
          , ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "common" = ParseResult () -> StateT SectionS ParseResult ()
    forall (m :: * -> *) a. Monad m => m a -> StateT SectionS m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (ParseResult () -> StateT SectionS ParseResult ())
    -> ParseResult () -> StateT SectionS ParseResult ()
    forall a b. (a -> b) -> a -> b
    $ do
              Position -> PWarnType -> String -> ParseResult ()
    parseWarning Position
    pos PWarnType
    PWTUnknownSection (String -> ParseResult ()) -> String -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $ String
    "Ignoring section: common. You should set cabal-version: 2.2 or larger to use common stanzas."
          | ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "common" = do
              commonStanzas <- Getting
      (Map String CondTreeBuildInfo)
      SectionS
      (Map String CondTreeBuildInfo)
    -> StateT SectionS ParseResult (Map String CondTreeBuildInfo)
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use Getting
      (Map String CondTreeBuildInfo)
      SectionS
      (Map String CondTreeBuildInfo)
    Lens' SectionS (Map String CondTreeBuildInfo)
    stateCommonStanzas
              name' <- lift $ parseCommonName pos args
              biTree <- lift $ parseCondTree' buildInfoFieldGrammar id commonStanzas fields

              case Map.lookup name' commonStanzas of
                Maybe CondTreeBuildInfo
    Nothing -> LensLike
      Identity
      SectionS
      SectionS
      (Map String CondTreeBuildInfo)
      (Map String CondTreeBuildInfo)
    Lens' SectionS (Map String CondTreeBuildInfo)
    stateCommonStanzas LensLike
      Identity
      SectionS
      SectionS
      (Map String CondTreeBuildInfo)
      (Map String CondTreeBuildInfo)
    -> Map String CondTreeBuildInfo -> StateT SectionS ParseResult ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> b -> m ()
    .= String
    -> CondTreeBuildInfo
    -> Map String CondTreeBuildInfo
    -> Map String CondTreeBuildInfo
    forall k a. Ord k => k -> a -> Map k a -> Map k a
    Map.insert String
    name' CondTreeBuildInfo
    biTree Map String CondTreeBuildInfo
    commonStanzas
                Just CondTreeBuildInfo
    _ ->
                  ParseResult () -> StateT SectionS ParseResult ()
    forall (m :: * -> *) a. Monad m => m a -> StateT SectionS m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (ParseResult () -> StateT SectionS ParseResult ())
    -> ParseResult () -> StateT SectionS ParseResult ()
    forall a b. (a -> b) -> a -> b
    $
                    Position -> String -> ParseResult ()
    parseFailure Position
    pos (String -> ParseResult ()) -> String -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $
                      String
    "Duplicate common stanza: " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    name'
          | ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "library" Bool -> Bool -> Bool
    && [SectionArg Position] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [SectionArg Position]
    args = do
              prev <- Getting
      (Maybe (CondTree ConfVar [Dependency] Library))
      SectionS
      (Maybe (CondTree ConfVar [Dependency] Library))
    -> StateT
         SectionS
         ParseResult
         (Maybe (CondTree ConfVar [Dependency] Library))
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use (Getting
       (Maybe (CondTree ConfVar [Dependency] Library))
       SectionS
       (Maybe (CondTree ConfVar [Dependency] Library))
     -> StateT
          SectionS
          ParseResult
          (Maybe (CondTree ConfVar [Dependency] Library)))
    -> Getting
         (Maybe (CondTree ConfVar [Dependency] Library))
         SectionS
         (Maybe (CondTree ConfVar [Dependency] Library))
    -> StateT
         SectionS
         ParseResult
         (Maybe (CondTree ConfVar [Dependency] Library))
    forall a b. (a -> b) -> a -> b
    $ LensLike
      (Const (Maybe (CondTree ConfVar [Dependency] Library)))
      SectionS
      SectionS
      GenericPackageDescription
      GenericPackageDescription
    Lens' SectionS GenericPackageDescription
    stateGpd LensLike
      (Const (Maybe (CondTree ConfVar [Dependency] Library)))
      SectionS
      SectionS
      GenericPackageDescription
      GenericPackageDescription
    -> ((Maybe (CondTree ConfVar [Dependency] Library)
         -> Const
              (Maybe (CondTree ConfVar [Dependency] Library))
              (Maybe (CondTree ConfVar [Dependency] Library)))
        -> GenericPackageDescription
        -> Const
             (Maybe (CondTree ConfVar [Dependency] Library))
             GenericPackageDescription)
    -> Getting
         (Maybe (CondTree ConfVar [Dependency] Library))
         SectionS
         (Maybe (CondTree ConfVar [Dependency] Library))
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Maybe (CondTree ConfVar [Dependency] Library)
     -> Const
          (Maybe (CondTree ConfVar [Dependency] Library))
          (Maybe (CondTree ConfVar [Dependency] Library)))
    -> GenericPackageDescription
    -> Const
         (Maybe (CondTree ConfVar [Dependency] Library))
         GenericPackageDescription
    Lens'
      GenericPackageDescription
      (Maybe (CondTree ConfVar [Dependency] Library))
    L.condLibrary
              when (isJust prev) $
                lift $
                  parseFailure pos $
                    "Multiple main libraries; have you forgotten to specify a name for an internal library?"

              commonStanzas <- use stateCommonStanzas
              let name'' = LibraryName
    LMainLibName
              lib <- lift $ parseCondTree' (libraryFieldGrammar name'') (libraryFromBuildInfo name'') commonStanzas fields
              --
              -- TODO check that not set
              stateGpd . L.condLibrary ?= lib

          -- Sublibraries
          -- TODO: check cabal-version
          | ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "library" = do
              commonStanzas <- Getting
      (Map String CondTreeBuildInfo)
      SectionS
      (Map String CondTreeBuildInfo)
    -> StateT SectionS ParseResult (Map String CondTreeBuildInfo)
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use Getting
      (Map String CondTreeBuildInfo)
      SectionS
      (Map String CondTreeBuildInfo)
    Lens' SectionS (Map String CondTreeBuildInfo)
    stateCommonStanzas
              name' <- parseUnqualComponentName pos args
              let name'' = UnqualComponentName -> LibraryName
    LSubLibName UnqualComponentName
    name'
              lib <- lift $ parseCondTree' (libraryFieldGrammar name'') (libraryFromBuildInfo name'') commonStanzas fields
              -- TODO check duplicate name here?
              stateGpd . L.condSubLibraries %= snoc (name', lib)

          -- TODO: check cabal-version
          | ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "foreign-library" = do
              commonStanzas <- Getting
      (Map String CondTreeBuildInfo)
      SectionS
      (Map String CondTreeBuildInfo)
    -> StateT SectionS ParseResult (Map String CondTreeBuildInfo)
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use Getting
      (Map String CondTreeBuildInfo)
      SectionS
      (Map String CondTreeBuildInfo)
    Lens' SectionS (Map String CondTreeBuildInfo)
    stateCommonStanzas
              name' <- parseUnqualComponentName pos args
              flib <- lift $ parseCondTree' (foreignLibFieldGrammar name') (fromBuildInfo' name') commonStanzas fields

              let hasType ForeignLib
    ts = ForeignLib -> ForeignLibType
    foreignLibType ForeignLib
    ts ForeignLibType -> ForeignLibType -> Bool
    forall a. Eq a => a -> a -> Bool
    /= ForeignLib -> ForeignLibType
    foreignLibType ForeignLib
    forall a. Monoid a => a
    mempty
              unless (onAllBranches hasType flib) $
                lift $
                  parseFailure pos $
                    concat
                      [ "Foreign library " ++ show (prettyShow name')
                      , " is missing required field \"type\" or the field "
                      , "is not present in all conditional branches. The "
                      , "available test types are: "
                      , intercalate ", " (map prettyShow knownForeignLibTypes)
                      ]

              -- TODO check duplicate name here?
              stateGpd . L.condForeignLibs %= snoc (name', flib)
          | ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "executable" = do
              commonStanzas <- Getting
      (Map String CondTreeBuildInfo)
      SectionS
      (Map String CondTreeBuildInfo)
    -> StateT SectionS ParseResult (Map String CondTreeBuildInfo)
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use Getting
      (Map String CondTreeBuildInfo)
      SectionS
      (Map String CondTreeBuildInfo)
    Lens' SectionS (Map String CondTreeBuildInfo)
    stateCommonStanzas
              name' <- parseUnqualComponentName pos args
              exe <- lift $ parseCondTree' (executableFieldGrammar name') (fromBuildInfo' name') commonStanzas fields
              -- TODO check duplicate name here?
              stateGpd . L.condExecutables %= snoc (name', exe)
          | ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "test-suite" = do
              commonStanzas <- Getting
      (Map String CondTreeBuildInfo)
      SectionS
      (Map String CondTreeBuildInfo)
    -> StateT SectionS ParseResult (Map String CondTreeBuildInfo)
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use Getting
      (Map String CondTreeBuildInfo)
      SectionS
      (Map String CondTreeBuildInfo)
    Lens' SectionS (Map String CondTreeBuildInfo)
    stateCommonStanzas
              name' <- parseUnqualComponentName pos args
              testStanza <- lift $ parseCondTree' testSuiteFieldGrammar (fromBuildInfo' name') commonStanzas fields
              testSuite <- lift $ traverse (validateTestSuite specVer pos) testStanza

              let hasType TestSuite
    ts = TestSuite -> TestSuiteInterface
    testInterface TestSuite
    ts TestSuiteInterface -> TestSuiteInterface -> Bool
    forall a. Eq a => a -> a -> Bool
    /= TestSuite -> TestSuiteInterface
    testInterface TestSuite
    forall a. Monoid a => a
    mempty
              unless (onAllBranches hasType testSuite) $
                lift $
                  parseFailure pos $
                    concat
                      [ "Test suite " ++ show (prettyShow name')
                      , concat $ case specVer of
                          CabalSpecVersion
    v
                            | CabalSpecVersion
    v CabalSpecVersion -> CabalSpecVersion -> Bool
    forall a. Ord a => a -> a -> Bool
    >= CabalSpecVersion
    CabalSpecV3_8 ->
                                [ String
    " is missing required field \"main-is\" or the field "
                                , String
    "is not present in all conditional branches."
                                ]
                          CabalSpecVersion
    _ ->
                            [ String
    " is missing required field \"type\" or the field "
                            , String
    "is not present in all conditional branches. The "
                            , String
    "available test types are: "
                            , String -> [String] -> String
    forall a. [a] -> [[a]] -> [a]
    intercalate String
    ", " ((TestType -> String) -> [TestType] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map TestType -> String
    forall a. Pretty a => a -> String
    prettyShow [TestType]
    knownTestTypes)
                            ]
                      ]

              -- TODO check duplicate name here?
              stateGpd . L.condTestSuites %= snoc (name', testSuite)
          | ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "benchmark" = do
              commonStanzas <- Getting
      (Map String CondTreeBuildInfo)
      SectionS
      (Map String CondTreeBuildInfo)
    -> StateT SectionS ParseResult (Map String CondTreeBuildInfo)
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use Getting
      (Map String CondTreeBuildInfo)
      SectionS
      (Map String CondTreeBuildInfo)
    Lens' SectionS (Map String CondTreeBuildInfo)
    stateCommonStanzas
              name' <- parseUnqualComponentName pos args
              benchStanza <- lift $ parseCondTree' benchmarkFieldGrammar (fromBuildInfo' name') commonStanzas fields
              bench <- lift $ traverse (validateBenchmark specVer pos) benchStanza

              let hasType Benchmark
    ts = Benchmark -> BenchmarkInterface
    benchmarkInterface Benchmark
    ts BenchmarkInterface -> BenchmarkInterface -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Benchmark -> BenchmarkInterface
    benchmarkInterface Benchmark
    forall a. Monoid a => a
    mempty
              unless (onAllBranches hasType bench) $
                lift $
                  parseFailure pos $
                    concat
                      [ "Benchmark " ++ show (prettyShow name')
                      , concat $ case specVer of
                          CabalSpecVersion
    v
                            | CabalSpecVersion
    v CabalSpecVersion -> CabalSpecVersion -> Bool
    forall a. Ord a => a -> a -> Bool
    >= CabalSpecVersion
    CabalSpecV3_8 ->
                                [ String
    " is missing required field \"main-is\" or the field "
                                , String
    "is not present in all conditional branches."
                                ]
                          CabalSpecVersion
    _ ->
                            [ String
    " is missing required field \"type\" or the field "
                            , String
    "is not present in all conditional branches. The "
                            , String
    "available benchmark types are: "
                            , String -> [String] -> String
    forall a. [a] -> [[a]] -> [a]
    intercalate String
    ", " ((BenchmarkType -> String) -> [BenchmarkType] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map BenchmarkType -> String
    forall a. Pretty a => a -> String
    prettyShow [BenchmarkType]
    knownBenchmarkTypes)
                            ]
                      ]

              -- TODO check duplicate name here?
              stateGpd . L.condBenchmarks %= snoc (name', bench)
          | ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "flag" = do
              name' <- Position -> [SectionArg Position] -> SectionParser ByteString
    parseNameBS Position
    pos [SectionArg Position]
    args
              name'' <- lift $ runFieldParser' [pos] parsec specVer (fieldLineStreamFromBS name') `recoverWith` mkFlagName ""
              flag <- lift $ parseFields specVer fields (flagFieldGrammar name'')
              -- Check default flag
              stateGpd . L.genPackageFlags %= snoc flag
          | ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "custom-setup" Bool -> Bool -> Bool
    && [SectionArg Position] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [SectionArg Position]
    args = do
              sbi <- ParseResult SetupBuildInfo
    -> StateT SectionS ParseResult SetupBuildInfo
    forall (m :: * -> *) a. Monad m => m a -> StateT SectionS m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (ParseResult SetupBuildInfo
     -> StateT SectionS ParseResult SetupBuildInfo)
    -> ParseResult SetupBuildInfo
    -> StateT SectionS ParseResult SetupBuildInfo
    forall a b. (a -> b) -> a -> b
    $ CabalSpecVersion
    -> [Field Position]
    -> ParsecFieldGrammar' SetupBuildInfo
    -> ParseResult SetupBuildInfo
    forall a.
    CabalSpecVersion
    -> [Field Position] -> ParsecFieldGrammar' a -> ParseResult a
    parseFields CabalSpecVersion
    specVer [Field Position]
    fields (Bool -> ParsecFieldGrammar' SetupBuildInfo
    forall (c :: * -> Constraint) (g :: * -> * -> *).
    (FieldGrammar c g, Functor (g SetupBuildInfo),
     c (List CommaVCat (Identity Dependency) Dependency)) =>
    Bool -> g SetupBuildInfo SetupBuildInfo
    setupBInfoFieldGrammar Bool
    False)
              stateGpd . L.packageDescription . L.setupBuildInfo ?= sbi
          | ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "source-repository" = do
              kind <- ParseResult RepoKind -> StateT SectionS ParseResult RepoKind
    forall (m :: * -> *) a. Monad m => m a -> StateT SectionS m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (ParseResult RepoKind -> StateT SectionS ParseResult RepoKind)
    -> ParseResult RepoKind -> StateT SectionS ParseResult RepoKind
    forall a b. (a -> b) -> a -> b
    $ case [SectionArg Position]
    args of
                [SecArgName Position
    spos ByteString
    secName] ->
                  [Position]
    -> ParsecParser RepoKind
    -> CabalSpecVersion
    -> FieldLineStream
    -> ParseResult RepoKind
    forall a.
    [Position]
    -> ParsecParser a
    -> CabalSpecVersion
    -> FieldLineStream
    -> ParseResult a
    runFieldParser' [Position
    spos] ParsecParser RepoKind
    forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
    forall (m :: * -> *). CabalParsing m => m RepoKind
    parsec CabalSpecVersion
    specVer (ByteString -> FieldLineStream
    fieldLineStreamFromBS ByteString
    secName) ParseResult RepoKind -> RepoKind -> ParseResult RepoKind
    forall a. ParseResult a -> a -> ParseResult a
    `recoverWith` RepoKind
    RepoHead
                [] -> do
                  Position -> String -> ParseResult ()
    parseFailure Position
    pos String
    "'source-repository' requires exactly one argument"
                  RepoKind -> ParseResult RepoKind
    forall a. a -> ParseResult a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure RepoKind
    RepoHead
                [SectionArg Position]
    _ -> do
                  Position -> String -> ParseResult ()
    parseFailure Position
    pos (String -> ParseResult ()) -> String -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $ String
    "Invalid source-repository kind " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ [SectionArg Position] -> String
    forall a. Show a => a -> String
    show [SectionArg Position]
    args
                  RepoKind -> ParseResult RepoKind
    forall a. a -> ParseResult a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure RepoKind
    RepoHead

              sr <- lift $ parseFields specVer fields (sourceRepoFieldGrammar kind)
              stateGpd . L.packageDescription . L.sourceRepos %= snoc sr
          | Bool
    otherwise =
              ParseResult () -> StateT SectionS ParseResult ()
    forall (m :: * -> *) a. Monad m => m a -> StateT SectionS m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (ParseResult () -> StateT SectionS ParseResult ())
    -> ParseResult () -> StateT SectionS ParseResult ()
    forall a b. (a -> b) -> a -> b
    $
                Position -> PWarnType -> String -> ParseResult ()
    parseWarning Position
    pos PWarnType
    PWTUnknownSection (String -> ParseResult ()) -> String -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $
                  String
    "Ignoring section: " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ ByteString -> String
    forall a. Show a => a -> String
    show ByteString
    name

    parseName :: Position -> [SectionArg Position] -> SectionParser String
    parseName :: Position
    -> [SectionArg Position] -> StateT SectionS ParseResult String
    parseName Position
    pos [SectionArg Position]
    args = ByteString -> String
    fromUTF8BS (ByteString -> String)
    -> SectionParser ByteString -> StateT SectionS ParseResult String
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Position -> [SectionArg Position] -> SectionParser ByteString
    parseNameBS Position
    pos [SectionArg Position]
    args

    parseNameBS :: Position -> [SectionArg Position] -> SectionParser BS.ByteString
    -- TODO: use strict parser
    parseNameBS :: Position -> [SectionArg Position] -> SectionParser ByteString
    parseNameBS Position
    pos [SectionArg Position]
    args = case [SectionArg Position]
    args of
      [SecArgName Position
    _pos ByteString
    secName] ->
        ByteString -> SectionParser ByteString
    forall a. a -> StateT SectionS ParseResult a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ByteString
    secName
      [SecArgStr Position
    _pos ByteString
    secName] ->
        ByteString -> SectionParser ByteString
    forall a. a -> StateT SectionS ParseResult a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ByteString
    secName
      [] -> do
        ParseResult () -> StateT SectionS ParseResult ()
    forall (m :: * -> *) a. Monad m => m a -> StateT SectionS m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (ParseResult () -> StateT SectionS ParseResult ())
    -> ParseResult () -> StateT SectionS ParseResult ()
    forall a b. (a -> b) -> a -> b
    $ Position -> String -> ParseResult ()
    parseFailure Position
    pos String
    "name required"
        ByteString -> SectionParser ByteString
    forall a. a -> StateT SectionS ParseResult a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ByteString
    ""
      [SectionArg Position]
    _ -> do
        -- TODO: pretty print args
        ParseResult () -> StateT SectionS ParseResult ()
    forall (m :: * -> *) a. Monad m => m a -> StateT SectionS m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (ParseResult () -> StateT SectionS ParseResult ())
    -> ParseResult () -> StateT SectionS ParseResult ()
    forall a b. (a -> b) -> a -> b
    $ Position -> String -> ParseResult ()
    parseFailure Position
    pos (String -> ParseResult ()) -> String -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $ String
    "Invalid name " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ [SectionArg Position] -> String
    forall a. Show a => a -> String
    show [SectionArg Position]
    args
        ByteString -> SectionParser ByteString
    forall a. a -> StateT SectionS ParseResult a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ByteString
    ""

    parseCommonName :: Position -> [SectionArg Position] -> ParseResult String
    parseCommonName :: Position -> [SectionArg Position] -> ParseResult String
    parseCommonName Position
    pos [SectionArg Position]
    args = case [SectionArg Position]
    args of
      [SecArgName Position
    _pos ByteString
    secName] ->
        String -> ParseResult String
    forall a. a -> ParseResult a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (String -> ParseResult String) -> String -> ParseResult String
    forall a b. (a -> b) -> a -> b
    $ ByteString -> String
    fromUTF8BS ByteString
    secName
      [SecArgStr Position
    _pos ByteString
    secName] ->
        String -> ParseResult String
    forall a. a -> ParseResult a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (String -> ParseResult String) -> String -> ParseResult String
    forall a b. (a -> b) -> a -> b
    $ ByteString -> String
    fromUTF8BS ByteString
    secName
      [] -> do
        Position -> String -> ParseResult ()
    parseFailure Position
    pos (String -> ParseResult ()) -> String -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $ String
    "name required"
        String -> ParseResult String
    forall a. a -> ParseResult a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure String
    ""
      [SectionArg Position]
    _ -> do
        -- TODO: pretty print args
        Position -> String -> ParseResult ()
    parseFailure Position
    pos (String -> ParseResult ()) -> String -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $ String
    "Invalid name " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ [SectionArg Position] -> String
    forall a. Show a => a -> String
    show [SectionArg Position]
    args
        String -> ParseResult String
    forall a. a -> ParseResult a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure String
    ""

    -- TODO: avoid conversion to 'String'.
    parseUnqualComponentName :: Position -> [SectionArg Position] -> SectionParser UnqualComponentName
    parseUnqualComponentName :: Position
    -> [SectionArg Position] -> SectionParser UnqualComponentName
    parseUnqualComponentName Position
    pos [SectionArg Position]
    args = String -> UnqualComponentName
    mkUnqualComponentName (String -> UnqualComponentName)
    -> StateT SectionS ParseResult String
    -> SectionParser UnqualComponentName
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Position
    -> [SectionArg Position] -> StateT SectionS ParseResult String
    parseName Position
    pos [SectionArg Position]
    args

    -- | Parse a non-recursive list of fields.
    parseFields
      :: CabalSpecVersion
      -> [Field Position]
      -- ^ fields to be parsed
      -> ParsecFieldGrammar' a
      -> ParseResult a
    parseFields :: forall a.
    CabalSpecVersion
    -> [Field Position] -> ParsecFieldGrammar' a -> ParseResult a
    parseFields CabalSpecVersion
    v [Field Position]
    fields ParsecFieldGrammar' a
    grammar = do
      let (Fields Position
    fs0, [[Section Position]]
    ss) = [Field Position] -> (Fields Position, [[Section Position]])
    forall ann. [Field ann] -> (Fields ann, [[Section ann]])
    partitionFields [Field Position]
    fields
      ([Section Position] -> ParseResult ())
    -> [[Section Position]] -> ParseResult ()
    forall (t :: * -> *) (f :: * -> *) a b.
    (Foldable t, Applicative f) =>
    (a -> f b) -> t a -> f ()
    traverse_ ((Section Position -> ParseResult ())
    -> [Section Position] -> ParseResult ()
    forall (t :: * -> *) (f :: * -> *) a b.
    (Foldable t, Applicative f) =>
    (a -> f b) -> t a -> f ()
    traverse_ Section Position -> ParseResult ()
    warnInvalidSubsection) [[Section Position]]
    ss
      CabalSpecVersion
    -> Fields Position -> ParsecFieldGrammar' a -> ParseResult a
    forall s a.
    CabalSpecVersion
    -> Fields Position -> ParsecFieldGrammar s a -> ParseResult a
    parseFieldGrammar CabalSpecVersion
    v Fields Position
    fs0 ParsecFieldGrammar' a
    grammar

    warnInvalidSubsection :: Section Position -> ParseResult ()
    warnInvalidSubsection :: Section Position -> ParseResult ()
    warnInvalidSubsection (MkSection (Name Position
    pos ByteString
    name) [SectionArg Position]
    _ [Field Position]
    _) =
      ParseResult () -> ParseResult ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (ParseResult () -> ParseResult ())
    -> ParseResult () -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $ Position -> String -> ParseResult ()
    parseFailure Position
    pos (String -> ParseResult ()) -> String -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $ String
    "invalid subsection " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ ByteString -> String
    forall a. Show a => a -> String
    show ByteString
    name

    parseCondTree
      :: forall a
       . L.HasBuildInfo a
      => CabalSpecVersion
      -> HasElif
      -- ^ accept @elif@
      -> ParsecFieldGrammar' a
      -- ^ grammar
      -> Map String CondTreeBuildInfo
      -- ^ common stanzas
      -> (BuildInfo -> a)
      -- ^ constructor from buildInfo
      -> (a -> [Dependency])
      -- ^ condition extractor
      -> [Field Position]
      -> ParseResult (CondTree ConfVar [Dependency] a)
    parseCondTree :: forall a.
    HasBuildInfo a =>
    CabalSpecVersion
    -> HasElif
    -> ParsecFieldGrammar' a
    -> Map String CondTreeBuildInfo
    -> (BuildInfo -> a)
    -> (a -> [Dependency])
    -> [Field Position]
    -> ParseResult (CondTree ConfVar [Dependency] a)
    parseCondTree CabalSpecVersion
    v HasElif
    hasElif ParsecFieldGrammar' a
    grammar Map String CondTreeBuildInfo
    commonStanzas BuildInfo -> a
    fromBuildInfo a -> [Dependency]
    cond = [Field Position] -> ParseResult (CondTree ConfVar [Dependency] a)
    go
      where
        go :: [Field Position] -> ParseResult (CondTree ConfVar [Dependency] a)
    go [Field Position]
    fields0 = do
          (fields, endo) <-
            if CabalSpecVersion
    v CabalSpecVersion -> CabalSpecVersion -> Bool
    forall a. Ord a => a -> a -> Bool
    >= CabalSpecVersion
    CabalSpecV3_0
              then CabalSpecVersion
    -> (BuildInfo -> a)
    -> Map String CondTreeBuildInfo
    -> [Field Position]
    -> ParseResult
         ([Field Position],
          CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] a)
    forall a.
    HasBuildInfo a =>
    CabalSpecVersion
    -> (BuildInfo -> a)
    -> Map String CondTreeBuildInfo
    -> [Field Position]
    -> ParseResult
         ([Field Position],
          CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] a)
    processImports CabalSpecVersion
    v BuildInfo -> a
    fromBuildInfo Map String CondTreeBuildInfo
    commonStanzas [Field Position]
    fields0
              else (Field Position -> ParseResult (Maybe (Field Position)))
    -> [Field Position] -> ParseResult [Maybe (Field Position)]
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> [a] -> f [b]
    traverse (CabalSpecVersion
    -> Field Position -> ParseResult (Maybe (Field Position))
    warnImport CabalSpecVersion
    v) [Field Position]
    fields0 ParseResult [Maybe (Field Position)]
    -> ([Maybe (Field Position)]
        -> ParseResult
             ([Field Position],
              CondTree ConfVar [Dependency] a
              -> CondTree ConfVar [Dependency] a))
    -> ParseResult
         ([Field Position],
          CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] a)
    forall a b. ParseResult a -> (a -> ParseResult b) -> ParseResult b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \[Maybe (Field Position)]
    fields1 -> ([Field Position],
     CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] a)
    -> ParseResult
         ([Field Position],
          CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] a)
    forall a. a -> ParseResult a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([Maybe (Field Position)] -> [Field Position]
    forall a. [Maybe a] -> [a]
    catMaybes [Maybe (Field Position)]
    fields1, CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] a
    forall a. a -> a
    id)

          let (fs, ss) = partitionFields fields
          x <- parseFieldGrammar v fs grammar
          branches <- concat <$> traverse parseIfs ss
          return $ endo $ CondNode x (cond x) branches

        parseIfs :: [Section Position] -> ParseResult [CondBranch ConfVar [Dependency] a]
        parseIfs :: [Section Position]
    -> ParseResult [CondBranch ConfVar [Dependency] a]
    parseIfs [] = [CondBranch ConfVar [Dependency] a]
    -> ParseResult [CondBranch ConfVar [Dependency] a]
    forall a. a -> ParseResult a
    forall (m :: * -> *) a. Monad m => a -> m a
    return []
        parseIfs (MkSection (Name Position
    _ ByteString
    name) [SectionArg Position]
    test [Field Position]
    fields : [Section Position]
    sections) | ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "if" = do
          test' <- [SectionArg Position] -> ParseResult (Condition ConfVar)
    parseConditionConfVar [SectionArg Position]
    test
          fields' <- go fields
          (elseFields, sections') <- parseElseIfs sections
          return (CondBranch test' fields' elseFields : sections')
        parseIfs (MkSection (Name Position
    pos ByteString
    name) [SectionArg Position]
    _ [Field Position]
    _ : [Section Position]
    sections) = do
          Position -> PWarnType -> String -> ParseResult ()
    parseWarning Position
    pos PWarnType
    PWTInvalidSubsection (String -> ParseResult ()) -> String -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $ String
    "invalid subsection " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ ByteString -> String
    forall a. Show a => a -> String
    show ByteString
    name
          [Section Position]
    -> ParseResult [CondBranch ConfVar [Dependency] a]
    parseIfs [Section Position]
    sections

        parseElseIfs
          :: [Section Position]
          -> ParseResult (Maybe (CondTree ConfVar [Dependency] a), [CondBranch ConfVar [Dependency] a])
        parseElseIfs :: [Section Position]
    -> ParseResult
         (Maybe (CondTree ConfVar [Dependency] a),
          [CondBranch ConfVar [Dependency] a])
    parseElseIfs [] = (Maybe (CondTree ConfVar [Dependency] a),
     [CondBranch ConfVar [Dependency] a])
    -> ParseResult
         (Maybe (CondTree ConfVar [Dependency] a),
          [CondBranch ConfVar [Dependency] a])
    forall a. a -> ParseResult a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe (CondTree ConfVar [Dependency] a)
    forall a. Maybe a
    Nothing, [])
        parseElseIfs (MkSection (Name Position
    pos ByteString
    name) [SectionArg Position]
    args [Field Position]
    fields : [Section Position]
    sections) | ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "else" = do
          Bool -> ParseResult () -> ParseResult ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    unless ([SectionArg Position] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [SectionArg Position]
    args) (ParseResult () -> ParseResult ())
    -> ParseResult () -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $
            Position -> String -> ParseResult ()
    parseFailure Position
    pos (String -> ParseResult ()) -> String -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $
              String
    "`else` section has section arguments " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ [SectionArg Position] -> String
    forall a. Show a => a -> String
    show [SectionArg Position]
    args
          elseFields <- [Field Position] -> ParseResult (CondTree ConfVar [Dependency] a)
    go [Field Position]
    fields
          sections' <- parseIfs sections
          return (Just elseFields, sections')
        parseElseIfs (MkSection (Name Position
    _ ByteString
    name) [SectionArg Position]
    test [Field Position]
    fields : [Section Position]
    sections)
          | HasElif
    hasElif HasElif -> HasElif -> Bool
    forall a. Eq a => a -> a -> Bool
    == HasElif
    HasElif
          , ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "elif" = do
              test' <- [SectionArg Position] -> ParseResult (Condition ConfVar)
    parseConditionConfVar [SectionArg Position]
    test
              fields' <- go fields
              (elseFields, sections') <- parseElseIfs sections
              -- we parse an empty 'Fields', to get empty value for a node
              a <- parseFieldGrammar v mempty grammar
              return (Just $ CondNode a (cond a) [CondBranch test' fields' elseFields], sections')
        parseElseIfs (MkSection (Name Position
    pos ByteString
    name) [SectionArg Position]
    _ [Field Position]
    _ : [Section Position]
    sections) | ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "elif" = do
          Position -> PWarnType -> String -> ParseResult ()
    parseWarning Position
    pos PWarnType
    PWTInvalidSubsection (String -> ParseResult ()) -> String -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $ String
    "invalid subsection \"elif\". You should set cabal-version: 2.2 or larger to use elif-conditionals."
          (,) Maybe (CondTree ConfVar [Dependency] a)
    forall a. Maybe a
    Nothing ([CondBranch ConfVar [Dependency] a]
     -> (Maybe (CondTree ConfVar [Dependency] a),
         [CondBranch ConfVar [Dependency] a]))
    -> ParseResult [CondBranch ConfVar [Dependency] a]
    -> ParseResult
         (Maybe (CondTree ConfVar [Dependency] a),
          [CondBranch ConfVar [Dependency] a])
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> [Section Position]
    -> ParseResult [CondBranch ConfVar [Dependency] a]
    parseIfs [Section Position]
    sections
        parseElseIfs [Section Position]
    sections = (,) Maybe (CondTree ConfVar [Dependency] a)
    forall a. Maybe a
    Nothing ([CondBranch ConfVar [Dependency] a]
     -> (Maybe (CondTree ConfVar [Dependency] a),
         [CondBranch ConfVar [Dependency] a]))
    -> ParseResult [CondBranch ConfVar [Dependency] a]
    -> ParseResult
         (Maybe (CondTree ConfVar [Dependency] a),
          [CondBranch ConfVar [Dependency] a])
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> [Section Position]
    -> ParseResult [CondBranch ConfVar [Dependency] a]
    parseIfs [Section Position]
    sections

    {- Note [Accumulating parser]

    Note: Outdated a bit

    In there parser, @'FieldDescr' a@ is transformed into @Map FieldName (a ->
    FieldParser a)@.  The weird value is used because we accumulate structure of
    @a@ by folding over the fields.  There are various reasons for that:

    \* Almost all fields are optional

    \* This is simple approach so declarative bi-directional format (parsing and
    printing) of structure could be specified (list of @'FieldDescr' a@)

    \* There are surface syntax fields corresponding to single field in the file:
      @license-file@ and @license-files@

    \* This is quite safe approach.

    When/if we re-implement the parser to support formatting preservging roundtrip
    with new AST, this all need to be rewritten.
    -}

    -------------------------------------------------------------------------------
    -- Common stanzas
    -------------------------------------------------------------------------------

    -- $commonStanzas
    --
    -- [Note: Common stanzas]
    --
    -- In Cabal 2.2 we support simple common stanzas:
    --
    -- * Commons stanzas define 'BuildInfo'
    --
    -- * import "fields" can only occur at top of other stanzas (think: imports)
    --
    -- In particular __there aren't__
    --
    -- * implicit stanzas
    --
    -- * More specific common stanzas (executable, test-suite).
    --
    --
    -- The approach uses the fact that 'BuildInfo' is a 'Monoid':
    --
    -- @
    -- mergeCommonStanza' :: HasBuildInfo comp => BuildInfo -> comp -> comp
    -- mergeCommonStanza' bi = over L.BuildInfo (bi <>)
    -- @
    --
    -- Real 'mergeCommonStanza' is more complicated as we have to deal with
    -- conditional trees.
    --
    -- The approach is simple, and have good properties:
    --
    -- * Common stanzas are parsed exactly once, even if not-used. Thus we report errors in them.
    type CondTreeBuildInfo = CondTree ConfVar [Dependency] BuildInfo

    -- | Create @a@ from 'BuildInfo'.
    -- This class is used to implement common stanza parsing.
    --
    -- Law: @view buildInfo . fromBuildInfo = id@
    --
    -- This takes name, as 'FieldGrammar's take names too.
    class L.HasBuildInfo a => FromBuildInfo a where
      fromBuildInfo' :: UnqualComponentName -> BuildInfo -> a

    libraryFromBuildInfo :: LibraryName -> BuildInfo -> Library
    libraryFromBuildInfo :: LibraryName -> BuildInfo -> Library
    libraryFromBuildInfo LibraryName
    n BuildInfo
    bi =
      Library
    emptyLibrary
        { libName = n
        , libVisibility = case n of
            LibraryName
    LMainLibName -> LibraryVisibility
    LibraryVisibilityPublic
            LSubLibName UnqualComponentName
    _ -> LibraryVisibility
    LibraryVisibilityPrivate
        , libBuildInfo = bi
        }

    instance FromBuildInfo BuildInfo where fromBuildInfo' :: UnqualComponentName -> BuildInfo -> BuildInfo
    fromBuildInfo' UnqualComponentName
    _ = BuildInfo -> BuildInfo
    forall a. a -> a
    id
    instance FromBuildInfo ForeignLib where fromBuildInfo' :: UnqualComponentName -> BuildInfo -> ForeignLib
    fromBuildInfo' UnqualComponentName
    n BuildInfo
    bi = ASetter
      ForeignLib ForeignLib UnqualComponentName UnqualComponentName
    -> UnqualComponentName -> ForeignLib -> ForeignLib
    forall s t a b. ASetter s t a b -> b -> s -> t
    set ASetter
      ForeignLib ForeignLib UnqualComponentName UnqualComponentName
    Lens' ForeignLib UnqualComponentName
    L.foreignLibName UnqualComponentName
    n (ForeignLib -> ForeignLib) -> ForeignLib -> ForeignLib
    forall a b. (a -> b) -> a -> b
    $ ASetter ForeignLib ForeignLib BuildInfo BuildInfo
    -> BuildInfo -> ForeignLib -> ForeignLib
    forall s t a b. ASetter s t a b -> b -> s -> t
    set ASetter ForeignLib ForeignLib BuildInfo BuildInfo
    forall a. HasBuildInfo a => Lens' a BuildInfo
    Lens' ForeignLib BuildInfo
    L.buildInfo BuildInfo
    bi ForeignLib
    emptyForeignLib
    instance FromBuildInfo Executable where fromBuildInfo' :: UnqualComponentName -> BuildInfo -> Executable
    fromBuildInfo' UnqualComponentName
    n BuildInfo
    bi = ASetter
      Executable Executable UnqualComponentName UnqualComponentName
    -> UnqualComponentName -> Executable -> Executable
    forall s t a b. ASetter s t a b -> b -> s -> t
    set ASetter
      Executable Executable UnqualComponentName UnqualComponentName
    Lens' Executable UnqualComponentName
    L.exeName UnqualComponentName
    n (Executable -> Executable) -> Executable -> Executable
    forall a b. (a -> b) -> a -> b
    $ ASetter Executable Executable BuildInfo BuildInfo
    -> BuildInfo -> Executable -> Executable
    forall s t a b. ASetter s t a b -> b -> s -> t
    set ASetter Executable Executable BuildInfo BuildInfo
    forall a. HasBuildInfo a => Lens' a BuildInfo
    Lens' Executable BuildInfo
    L.buildInfo BuildInfo
    bi Executable
    emptyExecutable

    instance FromBuildInfo TestSuiteStanza where
      fromBuildInfo' :: UnqualComponentName -> BuildInfo -> TestSuiteStanza
    fromBuildInfo' UnqualComponentName
    _ BuildInfo
    bi = Maybe TestType
    -> Maybe String
    -> Maybe ModuleName
    -> BuildInfo
    -> [String]
    -> TestSuiteStanza
    TestSuiteStanza Maybe TestType
    forall a. Maybe a
    Nothing Maybe String
    forall a. Maybe a
    Nothing Maybe ModuleName
    forall a. Maybe a
    Nothing BuildInfo
    bi []

    instance FromBuildInfo BenchmarkStanza where
      fromBuildInfo' :: UnqualComponentName -> BuildInfo -> BenchmarkStanza
    fromBuildInfo' UnqualComponentName
    _ BuildInfo
    bi = Maybe BenchmarkType
    -> Maybe String -> Maybe ModuleName -> BuildInfo -> BenchmarkStanza
    BenchmarkStanza Maybe BenchmarkType
    forall a. Maybe a
    Nothing Maybe String
    forall a. Maybe a
    Nothing Maybe ModuleName
    forall a. Maybe a
    Nothing BuildInfo
    bi

    parseCondTreeWithCommonStanzas
      :: forall a
       . L.HasBuildInfo a
      => CabalSpecVersion
      -> ParsecFieldGrammar' a
      -- ^ grammar
      -> (BuildInfo -> a)
      -- ^ construct fromBuildInfo
      -> Map String CondTreeBuildInfo
      -- ^ common stanzas
      -> [Field Position]
      -> ParseResult (CondTree ConfVar [Dependency] a)
    parseCondTreeWithCommonStanzas :: forall a.
    HasBuildInfo a =>
    CabalSpecVersion
    -> ParsecFieldGrammar' a
    -> (BuildInfo -> a)
    -> Map String CondTreeBuildInfo
    -> [Field Position]
    -> ParseResult (CondTree ConfVar [Dependency] a)
    parseCondTreeWithCommonStanzas CabalSpecVersion
    v ParsecFieldGrammar' a
    grammar BuildInfo -> a
    fromBuildInfo Map String CondTreeBuildInfo
    commonStanzas [Field Position]
    fields = do
      (fields', endo) <- CabalSpecVersion
    -> (BuildInfo -> a)
    -> Map String CondTreeBuildInfo
    -> [Field Position]
    -> ParseResult
         ([Field Position],
          CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] a)
    forall a.
    HasBuildInfo a =>
    CabalSpecVersion
    -> (BuildInfo -> a)
    -> Map String CondTreeBuildInfo
    -> [Field Position]
    -> ParseResult
         ([Field Position],
          CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] a)
    processImports CabalSpecVersion
    v BuildInfo -> a
    fromBuildInfo Map String CondTreeBuildInfo
    commonStanzas [Field Position]
    fields
      x <- parseCondTree v hasElif grammar commonStanzas fromBuildInfo (view L.targetBuildDepends) fields'
      return (endo x)
      where
        hasElif :: HasElif
    hasElif = CabalSpecVersion -> HasElif
    specHasElif CabalSpecVersion
    v

    processImports
      :: forall a
       . L.HasBuildInfo a
      => CabalSpecVersion
      -> (BuildInfo -> a)
      -- ^ construct fromBuildInfo
      -> Map String CondTreeBuildInfo
      -- ^ common stanzas
      -> [Field Position]
      -> ParseResult ([Field Position], CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] a)
    processImports :: forall a.
    HasBuildInfo a =>
    CabalSpecVersion
    -> (BuildInfo -> a)
    -> Map String CondTreeBuildInfo
    -> [Field Position]
    -> ParseResult
         ([Field Position],
          CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] a)
    processImports CabalSpecVersion
    v BuildInfo -> a
    fromBuildInfo Map String CondTreeBuildInfo
    commonStanzas = [CondTreeBuildInfo]
    -> [Field Position]
    -> ParseResult
         ([Field Position],
          CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] a)
    go []
      where
        hasCommonStanzas :: HasCommonStanzas
    hasCommonStanzas = CabalSpecVersion -> HasCommonStanzas
    specHasCommonStanzas CabalSpecVersion
    v

        getList' :: List CommaFSep Token String -> [String]
        getList' :: List CommaFSep Token String -> [String]
    getList' = List CommaFSep Token String -> [String]
    forall o n. Newtype o n => n -> o
    Newtype.unpack

        go :: [CondTreeBuildInfo]
    -> [Field Position]
    -> ParseResult
         ([Field Position],
          CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] a)
    go [CondTreeBuildInfo]
    acc (Field (Name Position
    pos ByteString
    name) [FieldLine Position]
    _ : [Field Position]
    fields)
          | ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "import"
          , HasCommonStanzas
    hasCommonStanzas HasCommonStanzas -> HasCommonStanzas -> Bool
    forall a. Eq a => a -> a -> Bool
    == HasCommonStanzas
    NoCommonStanzas = do
              Position -> PWarnType -> String -> ParseResult ()
    parseWarning Position
    pos PWarnType
    PWTUnknownField String
    "Unknown field: import. You should set cabal-version: 2.2 or larger to use common stanzas"
              [CondTreeBuildInfo]
    -> [Field Position]
    -> ParseResult
         ([Field Position],
          CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] a)
    go [CondTreeBuildInfo]
    acc [Field Position]
    fields
        -- supported:
        go [CondTreeBuildInfo]
    acc (Field (Name Position
    pos ByteString
    name) [FieldLine Position]
    fls : [Field Position]
    fields) | ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "import" = do
          names <- List CommaFSep Token String -> [String]
    getList' (List CommaFSep Token String -> [String])
    -> ParseResult (List CommaFSep Token String)
    -> ParseResult [String]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Position
    -> ParsecParser (List CommaFSep Token String)
    -> CabalSpecVersion
    -> [FieldLine Position]
    -> ParseResult (List CommaFSep Token String)
    forall a.
    Position
    -> ParsecParser a
    -> CabalSpecVersion
    -> [FieldLine Position]
    -> ParseResult a
    runFieldParser Position
    pos ParsecParser (List CommaFSep Token String)
    forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
    forall (m :: * -> *).
    CabalParsing m =>
    m (List CommaFSep Token String)
    parsec CabalSpecVersion
    v [FieldLine Position]
    fls
          names' <- for names $ \String
    commonName ->
            case String -> Map String CondTreeBuildInfo -> Maybe CondTreeBuildInfo
    forall k a. Ord k => k -> Map k a -> Maybe a
    Map.lookup String
    commonName Map String CondTreeBuildInfo
    commonStanzas of
              Maybe CondTreeBuildInfo
    Nothing -> do
                Position -> String -> ParseResult ()
    parseFailure Position
    pos (String -> ParseResult ()) -> String -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $ String
    "Undefined common stanza imported: " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    commonName
                Maybe CondTreeBuildInfo -> ParseResult (Maybe CondTreeBuildInfo)
    forall a. a -> ParseResult a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Maybe CondTreeBuildInfo
    forall a. Maybe a
    Nothing
              Just CondTreeBuildInfo
    commonTree ->
                Maybe CondTreeBuildInfo -> ParseResult (Maybe CondTreeBuildInfo)
    forall a. a -> ParseResult a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (CondTreeBuildInfo -> Maybe CondTreeBuildInfo
    forall a. a -> Maybe a
    Just CondTreeBuildInfo
    commonTree)

          go (acc ++ catMaybes names') fields

        -- parse actual CondTree
        go [CondTreeBuildInfo]
    acc [Field Position]
    fields = do
          fields' <- [Maybe (Field Position)] -> [Field Position]
    forall a. [Maybe a] -> [a]
    catMaybes ([Maybe (Field Position)] -> [Field Position])
    -> ParseResult [Maybe (Field Position)]
    -> ParseResult [Field Position]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (Field Position -> ParseResult (Maybe (Field Position)))
    -> [Field Position] -> ParseResult [Maybe (Field Position)]
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> [a] -> f [b]
    traverse (CabalSpecVersion
    -> Field Position -> ParseResult (Maybe (Field Position))
    warnImport CabalSpecVersion
    v) [Field Position]
    fields
          pure $ (fields', \CondTree ConfVar [Dependency] a
    x -> (CondTreeBuildInfo
     -> CondTree ConfVar [Dependency] a
     -> CondTree ConfVar [Dependency] a)
    -> CondTree ConfVar [Dependency] a
    -> [CondTreeBuildInfo]
    -> CondTree ConfVar [Dependency] a
    forall a b. (a -> b -> b) -> b -> [a] -> b
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr ((BuildInfo -> a)
    -> CondTreeBuildInfo
    -> CondTree ConfVar [Dependency] a
    -> CondTree ConfVar [Dependency] a
    forall a.
    HasBuildInfo a =>
    (BuildInfo -> a)
    -> CondTreeBuildInfo
    -> CondTree ConfVar [Dependency] a
    -> CondTree ConfVar [Dependency] a
    mergeCommonStanza BuildInfo -> a
    fromBuildInfo) CondTree ConfVar [Dependency] a
    x [CondTreeBuildInfo]
    acc)

    -- | Warn on "import" fields, also map to Maybe, so errorneous fields can be filtered
    warnImport :: CabalSpecVersion -> Field Position -> ParseResult (Maybe (Field Position))
    warnImport :: CabalSpecVersion
    -> Field Position -> ParseResult (Maybe (Field Position))
    warnImport CabalSpecVersion
    v (Field (Name Position
    pos ByteString
    name) [FieldLine Position]
    _) | ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "import" = do
      if CabalSpecVersion -> HasCommonStanzas
    specHasCommonStanzas CabalSpecVersion
    v HasCommonStanzas -> HasCommonStanzas -> Bool
    forall a. Eq a => a -> a -> Bool
    == HasCommonStanzas
    NoCommonStanzas
        then Position -> PWarnType -> String -> ParseResult ()
    parseWarning Position
    pos PWarnType
    PWTUnknownField String
    "Unknown field: import. You should set cabal-version: 2.2 or larger to use common stanzas"
        else Position -> PWarnType -> String -> ParseResult ()
    parseWarning Position
    pos PWarnType
    PWTUnknownField String
    "Unknown field: import. Common stanza imports should be at the top of the enclosing section"
      Maybe (Field Position) -> ParseResult (Maybe (Field Position))
    forall a. a -> ParseResult a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe (Field Position)
    forall a. Maybe a
    Nothing
    warnImport CabalSpecVersion
    _ Field Position
    f = Maybe (Field Position) -> ParseResult (Maybe (Field Position))
    forall a. a -> ParseResult a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (Field Position -> Maybe (Field Position)
    forall a. a -> Maybe a
    Just Field Position
    f)

    mergeCommonStanza
      :: L.HasBuildInfo a
      => (BuildInfo -> a)
      -> CondTree ConfVar [Dependency] BuildInfo
      -> CondTree ConfVar [Dependency] a
      -> CondTree ConfVar [Dependency] a
    mergeCommonStanza :: forall a.
    HasBuildInfo a =>
    (BuildInfo -> a)
    -> CondTreeBuildInfo
    -> CondTree ConfVar [Dependency] a
    -> CondTree ConfVar [Dependency] a
    mergeCommonStanza BuildInfo -> a
    fromBuildInfo (CondNode BuildInfo
    bi [Dependency]
    _ [CondBranch ConfVar [Dependency] BuildInfo]
    bis) (CondNode a
    x [Dependency]
    _ [CondBranch ConfVar [Dependency] a]
    cs) =
      a
    -> [Dependency]
    -> [CondBranch ConfVar [Dependency] a]
    -> CondTree ConfVar [Dependency] a
    forall v c a. a -> c -> [CondBranch v c a] -> CondTree v c a
    CondNode a
    x' (a
    x' a -> Getting [Dependency] a [Dependency] -> [Dependency]
    forall s a. s -> Getting a s a -> a
    ^. Getting [Dependency] a [Dependency]
    forall a. HasBuildInfo a => Lens' a [Dependency]
    Lens' a [Dependency]
    L.targetBuildDepends) [CondBranch ConfVar [Dependency] a]
    cs'
      where
        -- new value is old value with buildInfo field _prepended_.
        x' :: a
    x' = a
    x a -> (a -> a) -> a
    forall a b. a -> (a -> b) -> b
    & LensLike Identity a a BuildInfo BuildInfo
    forall a. HasBuildInfo a => Lens' a BuildInfo
    Lens' a BuildInfo
    L.buildInfo LensLike Identity a a BuildInfo BuildInfo
    -> (BuildInfo -> BuildInfo) -> a -> a
    forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
    %~ (BuildInfo
    bi BuildInfo -> BuildInfo -> BuildInfo
    forall a. Semigroup a => a -> a -> a
    <>)

        -- tree components are appended together.
        cs' :: [CondBranch ConfVar [Dependency] a]
    cs' = (CondBranch ConfVar [Dependency] BuildInfo
     -> CondBranch ConfVar [Dependency] a)
    -> [CondBranch ConfVar [Dependency] BuildInfo]
    -> [CondBranch ConfVar [Dependency] a]
    forall a b. (a -> b) -> [a] -> [b]
    map ((BuildInfo -> a)
    -> CondBranch ConfVar [Dependency] BuildInfo
    -> CondBranch ConfVar [Dependency] a
    forall a b.
    (a -> b)
    -> CondBranch ConfVar [Dependency] a
    -> CondBranch ConfVar [Dependency] b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap BuildInfo -> a
    fromBuildInfo) [CondBranch ConfVar [Dependency] BuildInfo]
    bis [CondBranch ConfVar [Dependency] a]
    -> [CondBranch ConfVar [Dependency] a]
    -> [CondBranch ConfVar [Dependency] a]
    forall a. [a] -> [a] -> [a]
    ++ [CondBranch ConfVar [Dependency] a]
    cs

    -------------------------------------------------------------------------------
    -- Branches
    -------------------------------------------------------------------------------

    -- Check that a property holds on all branches of a condition tree
    onAllBranches :: forall v c a. Monoid a => (a -> Bool) -> CondTree v c a -> Bool
    onAllBranches :: forall v c a. Monoid a => (a -> Bool) -> CondTree v c a -> Bool
    onAllBranches a -> Bool
    p = a -> CondTree v c a -> Bool
    go a
    forall a. Monoid a => a
    mempty
      where
        -- If the current level of the tree satisfies the property, then we are
        -- done. If not, then one of the conditional branches below the current node
        -- must satisfy it. Each node may have multiple immediate children; we only
        -- one need one to satisfy the property because the configure step uses
        -- 'mappend' to join together the results of flag resolution.
        go :: a -> CondTree v c a -> Bool
        go :: a -> CondTree v c a -> Bool
    go a
    acc CondTree v c a
    ct =
          let acc' :: a
    acc' = a
    acc a -> a -> a
    forall a. Monoid a => a -> a -> a
    `mappend` CondTree v c a -> a
    forall v c a. CondTree v c a -> a
    condTreeData CondTree v c a
    ct
           in a -> Bool
    p a
    acc' Bool -> Bool -> Bool
    || (CondBranch v c a -> Bool) -> [CondBranch v c a] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any (a -> CondBranch v c a -> Bool
    goBranch a
    acc') (CondTree v c a -> [CondBranch v c a]
    forall v c a. CondTree v c a -> [CondBranch v c a]
    condTreeComponents CondTree v c a
    ct)

        -- Both the 'true' and the 'false' block must satisfy the property.
        goBranch :: a -> CondBranch v c a -> Bool
        goBranch :: a -> CondBranch v c a -> Bool
    goBranch a
    _ (CondBranch Condition v
    _ CondTree v c a
    _ Maybe (CondTree v c a)
    Nothing) = Bool
    False
        goBranch a
    acc (CondBranch Condition v
    _ CondTree v c a
    t (Just CondTree v c a
    e)) = a -> CondTree v c a -> Bool
    go a
    acc CondTree v c a
    t Bool -> Bool -> Bool
    && a -> CondTree v c a -> Bool
    go a
    acc CondTree v c a
    e

    -------------------------------------------------------------------------------
    -- Post parsing checks
    -------------------------------------------------------------------------------

    -- | Check that we
    --
    -- * don't use undefined flags (very bad)
    -- * define flags which are unused (just bad)
    checkForUndefinedFlags :: GenericPackageDescription -> ParseResult ()
    checkForUndefinedFlags :: GenericPackageDescription -> ParseResult ()
    checkForUndefinedFlags GenericPackageDescription
    gpd = do
      let definedFlags, usedFlags :: Set.Set FlagName
          definedFlags :: Set FlagName
    definedFlags = Getting (Set FlagName) GenericPackageDescription FlagName
    -> GenericPackageDescription -> Set FlagName
    forall a s. Getting (Set a) s a -> s -> Set a
    toSetOf (LensLike
      (Const (Set FlagName))
      GenericPackageDescription
      GenericPackageDescription
      [PackageFlag]
      [PackageFlag]
    Lens' GenericPackageDescription [PackageFlag]
    L.genPackageFlags LensLike
      (Const (Set FlagName))
      GenericPackageDescription
      GenericPackageDescription
      [PackageFlag]
      [PackageFlag]
    -> ((FlagName -> Const (Set FlagName) FlagName)
        -> [PackageFlag] -> Const (Set FlagName) [PackageFlag])
    -> Getting (Set FlagName) GenericPackageDescription FlagName
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (PackageFlag -> Const (Set FlagName) PackageFlag)
    -> [PackageFlag] -> Const (Set FlagName) [PackageFlag]
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> [a] -> f [b]
    traverse ((PackageFlag -> Const (Set FlagName) PackageFlag)
     -> [PackageFlag] -> Const (Set FlagName) [PackageFlag])
    -> ((FlagName -> Const (Set FlagName) FlagName)
        -> PackageFlag -> Const (Set FlagName) PackageFlag)
    -> (FlagName -> Const (Set FlagName) FlagName)
    -> [PackageFlag]
    -> Const (Set FlagName) [PackageFlag]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (PackageFlag -> FlagName)
    -> (FlagName -> Const (Set FlagName) FlagName)
    -> PackageFlag
    -> Const (Set FlagName) PackageFlag
    forall s a r. (s -> a) -> Getting r s a
    getting PackageFlag -> FlagName
    flagName) GenericPackageDescription
    gpd
          usedFlags :: Set FlagName
    usedFlags = Const (Set FlagName) GenericPackageDescription -> Set FlagName
    forall {k} a (b :: k). Const a b -> a
    getConst (Const (Set FlagName) GenericPackageDescription -> Set FlagName)
    -> Const (Set FlagName) GenericPackageDescription -> Set FlagName
    forall a b. (a -> b) -> a -> b
    $ (forall a.
     CondTree ConfVar [Dependency] a
     -> Const (Set FlagName) (CondTree ConfVar [Dependency] a))
    -> GenericPackageDescription
    -> Const (Set FlagName) GenericPackageDescription
    forall (f :: * -> *).
    Applicative f =>
    (forall a.
     CondTree ConfVar [Dependency] a
     -> f (CondTree ConfVar [Dependency] a))
    -> GenericPackageDescription -> f GenericPackageDescription
    L.allCondTrees CondTree ConfVar [Dependency] a
    -> Const (Set FlagName) (CondTree ConfVar [Dependency] a)
    forall a.
    CondTree ConfVar [Dependency] a
    -> Const (Set FlagName) (CondTree ConfVar [Dependency] a)
    forall c a.
    CondTree ConfVar c a -> Const (Set FlagName) (CondTree ConfVar c a)
    f GenericPackageDescription
    gpd

      -- Note: we can check for defined, but unused flags here too.
      Bool -> ParseResult () -> ParseResult ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    unless (Set FlagName
    usedFlags Set FlagName -> Set FlagName -> Bool
    forall a. Ord a => Set a -> Set a -> Bool
    `Set.isSubsetOf` Set FlagName
    definedFlags) (ParseResult () -> ParseResult ())
    -> ParseResult () -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $
        Position -> String -> ParseResult ()
    parseFailure Position
    zeroPos (String -> ParseResult ()) -> String -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $
          String
    "These flags are used without having been defined: "
            String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String -> [String] -> String
    forall a. [a] -> [[a]] -> [a]
    intercalate String
    ", " [FlagName -> String
    unFlagName FlagName
    fn | FlagName
    fn <- Set FlagName -> [FlagName]
    forall a. Set a -> [a]
    Set.toList (Set FlagName -> [FlagName]) -> Set FlagName -> [FlagName]
    forall a b. (a -> b) -> a -> b
    $ Set FlagName
    usedFlags Set FlagName -> Set FlagName -> Set FlagName
    forall a. Ord a => Set a -> Set a -> Set a
    `Set.difference` Set FlagName
    definedFlags]
      where
        f :: CondTree ConfVar c a -> Const (Set.Set FlagName) (CondTree ConfVar c a)
        f :: forall c a.
    CondTree ConfVar c a -> Const (Set FlagName) (CondTree ConfVar c a)
    f CondTree ConfVar c a
    ct = Set FlagName -> Const (Set FlagName) (CondTree ConfVar c a)
    forall {k} a (b :: k). a -> Const a b
    Const ([FlagName] -> Set FlagName
    forall a. Ord a => [a] -> Set a
    Set.fromList (CondTree ConfVar c a -> [FlagName]
    forall c a. CondTree ConfVar c a -> [FlagName]
    freeVars CondTree ConfVar c a
    ct))

    -- | Since @cabal-version: 1.24@ one can specify @custom-setup@.
    -- Let us require it.
    checkForUndefinedCustomSetup :: GenericPackageDescription -> ParseResult ()
    checkForUndefinedCustomSetup :: GenericPackageDescription -> ParseResult ()
    checkForUndefinedCustomSetup GenericPackageDescription
    gpd = do
      let pd :: PackageDescription
    pd = GenericPackageDescription -> PackageDescription
    packageDescription GenericPackageDescription
    gpd
      let csv :: CabalSpecVersion
    csv = PackageDescription -> CabalSpecVersion
    specVersion PackageDescription
    pd

      Bool -> ParseResult () -> ParseResult ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (PackageDescription -> BuildType
    buildType PackageDescription
    pd BuildType -> BuildType -> Bool
    forall a. Eq a => a -> a -> Bool
    == BuildType
    Custom Bool -> Bool -> Bool
    && Maybe SetupBuildInfo -> Bool
    forall a. Maybe a -> Bool
    isNothing (PackageDescription -> Maybe SetupBuildInfo
    setupBuildInfo PackageDescription
    pd)) (ParseResult () -> ParseResult ())
    -> ParseResult () -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $
        Bool -> ParseResult () -> ParseResult ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (CabalSpecVersion
    csv CabalSpecVersion -> CabalSpecVersion -> Bool
    forall a. Ord a => a -> a -> Bool
    >= CabalSpecVersion
    CabalSpecV1_24) (ParseResult () -> ParseResult ())
    -> ParseResult () -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $
          Position -> String -> ParseResult ()
    parseFailure Position
    zeroPos (String -> ParseResult ()) -> String -> ParseResult ()
    forall a b. (a -> b) -> a -> b
    $
            String
    "Since cabal-version: 1.24 specifying custom-setup section is mandatory"

    -------------------------------------------------------------------------------
    -- Post processing of internal dependencies
    -------------------------------------------------------------------------------

    -- Note [Dependencies on sublibraries]
    -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    --
    -- This is solution to https://github.com/haskell/cabal/issues/6083
    --
    -- Before 'cabal-version: 3.0' we didn't have a syntax specially
    -- for referring to internal libraries. Internal library names
    -- shadowed the outside ones.
    --
    -- Since 'cabal-version: 3.0' we have ability to write
    --
    --     build-depends: some-package:its-sub-lib >=1.2.3
    --
    -- This allows us to refer also to local packages by `this-package:sublib`.
    -- So since 'cabal-version: 3.4' to refer to *any*
    -- sublibrary we must use the two part syntax. Here's small table:
    --
    --                   | pre-3.4             |      3.4 and after            |
    -- ------------------|---------------------|-------------------------------|
    -- pkg-name          | may refer to sublib | always refers to external pkg |
    -- pkg-name:sublib   | refers to sublib    | refers to sublib              |
    -- pkg-name:pkg-name | may refer to sublib | always refers to external pkg |
    --
    -- In pre-3.4 case, if a package 'this-pkg' has a sublibrary 'pkg-name',
    -- all dependency definitions will refer to that sublirary.
    --
    -- In 3.4 and after case, 'pkg-name' will always refer to external package,
    -- and to use internal library you have to say 'this-pkg:pkg-name'.
    --
    -- In summary, In 3.4 and after, the internal names don't shadow,
    -- as there is an explicit syntax to refer to them,
    -- i.e. what you write is what you get;
    -- For pre-3.4 we post-process the file.
    --
    -- Similarly, we process mixins.
    -- See https://github.com/haskell/cabal/issues/6281
    --

    postProcessInternalDeps :: CabalSpecVersion -> GenericPackageDescription -> GenericPackageDescription
    postProcessInternalDeps :: CabalSpecVersion
    -> GenericPackageDescription -> GenericPackageDescription
    postProcessInternalDeps CabalSpecVersion
    specVer GenericPackageDescription
    gpd
      | CabalSpecVersion
    specVer CabalSpecVersion -> CabalSpecVersion -> Bool
    forall a. Ord a => a -> a -> Bool
    >= CabalSpecVersion
    CabalSpecV3_4 = GenericPackageDescription
    gpd
      | Bool
    otherwise = (BuildInfo -> BuildInfo)
    -> (SetupBuildInfo -> SetupBuildInfo)
    -> GenericPackageDescription
    -> GenericPackageDescription
    transformAllBuildInfos BuildInfo -> BuildInfo
    transformBI SetupBuildInfo -> SetupBuildInfo
    transformSBI GenericPackageDescription
    gpd
      where
        transformBI :: BuildInfo -> BuildInfo
        transformBI :: BuildInfo -> BuildInfo
    transformBI =
          ASetter BuildInfo BuildInfo [Dependency] [Dependency]
    -> ([Dependency] -> [Dependency]) -> BuildInfo -> BuildInfo
    forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
    over ASetter BuildInfo BuildInfo [Dependency] [Dependency]
    forall a. HasBuildInfo a => Lens' a [Dependency]
    Lens' BuildInfo [Dependency]
    L.targetBuildDepends ((Dependency -> [Dependency]) -> [Dependency] -> [Dependency]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap Dependency -> [Dependency]
    transformD)
            (BuildInfo -> BuildInfo)
    -> (BuildInfo -> BuildInfo) -> BuildInfo -> BuildInfo
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ASetter BuildInfo BuildInfo [Mixin] [Mixin]
    -> ([Mixin] -> [Mixin]) -> BuildInfo -> BuildInfo
    forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
    over ASetter BuildInfo BuildInfo [Mixin] [Mixin]
    forall a. HasBuildInfo a => Lens' a [Mixin]
    Lens' BuildInfo [Mixin]
    L.mixins ((Mixin -> Mixin) -> [Mixin] -> [Mixin]
    forall a b. (a -> b) -> [a] -> [b]
    map Mixin -> Mixin
    transformM)

        transformSBI :: SetupBuildInfo -> SetupBuildInfo
        transformSBI :: SetupBuildInfo -> SetupBuildInfo
    transformSBI = ASetter SetupBuildInfo SetupBuildInfo [Dependency] [Dependency]
    -> ([Dependency] -> [Dependency])
    -> SetupBuildInfo
    -> SetupBuildInfo
    forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
    over ASetter SetupBuildInfo SetupBuildInfo [Dependency] [Dependency]
    Lens' SetupBuildInfo [Dependency]
    L.setupDepends ((Dependency -> [Dependency]) -> [Dependency] -> [Dependency]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap Dependency -> [Dependency]
    transformD)

        transformD :: Dependency -> [Dependency]
        transformD :: Dependency -> [Dependency]
    transformD (Dependency PackageName
    pn VersionRange
    vr NonEmptySet LibraryName
    ln)
          | UnqualComponentName
    uqn UnqualComponentName -> Set UnqualComponentName -> Bool
    forall a. Ord a => a -> Set a -> Bool
    `Set.member` Set UnqualComponentName
    internalLibs
          , LibraryName
    LMainLibName LibraryName -> NonEmptySet LibraryName -> Bool
    forall a. Ord a => a -> NonEmptySet a -> Bool
    `NES.member` NonEmptySet LibraryName
    ln =
              case LibraryName
    -> NonEmptySet LibraryName -> Maybe (NonEmptySet LibraryName)
    forall a. Ord a => a -> NonEmptySet a -> Maybe (NonEmptySet a)
    NES.delete LibraryName
    LMainLibName NonEmptySet LibraryName
    ln of
                Maybe (NonEmptySet LibraryName)
    Nothing -> [Dependency
    dep]
                Just NonEmptySet LibraryName
    ln' -> [Dependency
    dep, PackageName
    -> VersionRange -> NonEmptySet LibraryName -> Dependency
    Dependency PackageName
    pn VersionRange
    vr NonEmptySet LibraryName
    ln']
          where
            uqn :: UnqualComponentName
    uqn = PackageName -> UnqualComponentName
    packageNameToUnqualComponentName PackageName
    pn
            dep :: Dependency
    dep = PackageName
    -> VersionRange -> NonEmptySet LibraryName -> Dependency
    Dependency PackageName
    thisPn VersionRange
    vr (LibraryName -> NonEmptySet LibraryName
    forall a. a -> NonEmptySet a
    NES.singleton (UnqualComponentName -> LibraryName
    LSubLibName UnqualComponentName
    uqn))
        transformD Dependency
    d = [Dependency
    d]

        transformM :: Mixin -> Mixin
        transformM :: Mixin -> Mixin
    transformM (Mixin PackageName
    pn LibraryName
    LMainLibName IncludeRenaming
    incl)
          | UnqualComponentName
    uqn UnqualComponentName -> Set UnqualComponentName -> Bool
    forall a. Ord a => a -> Set a -> Bool
    `Set.member` Set UnqualComponentName
    internalLibs =
              PackageName -> LibraryName -> IncludeRenaming -> Mixin
    mkMixin PackageName
    thisPn (UnqualComponentName -> LibraryName
    LSubLibName UnqualComponentName
    uqn) IncludeRenaming
    incl
          where
            uqn :: UnqualComponentName
    uqn = PackageName -> UnqualComponentName
    packageNameToUnqualComponentName PackageName
    pn
        transformM Mixin
    m = Mixin
    m

        thisPn :: PackageName
        thisPn :: PackageName
    thisPn = PackageIdentifier -> PackageName
    pkgName (PackageDescription -> PackageIdentifier
    package (GenericPackageDescription -> PackageDescription
    packageDescription GenericPackageDescription
    gpd))

        internalLibs :: Set UnqualComponentName
        internalLibs :: Set UnqualComponentName
    internalLibs =
          [UnqualComponentName] -> Set UnqualComponentName
    forall a. Ord a => [a] -> Set a
    Set.fromList
            [ UnqualComponentName
    n
            | (UnqualComponentName
    n, CondTree ConfVar [Dependency] Library
    _) <- GenericPackageDescription
    -> [(UnqualComponentName, CondTree ConfVar [Dependency] Library)]
    condSubLibraries GenericPackageDescription
    gpd
            ]

    -------------------------------------------------------------------------------
    -- Old syntax
    -------------------------------------------------------------------------------

    -- TODO: move to own module

    -- | "Sectionize" an old-style Cabal file.  A sectionized file has:
    --
    --  * all global fields at the beginning, followed by
    --
    --  * all flag declarations, followed by
    --
    --  * an optional library section, and an arbitrary number of executable
    --    sections (in any order).
    --
    -- The current implementation just gathers all library-specific fields
    -- in a library section and wraps all executable stanzas in an executable
    -- section.
    sectionizeFields :: [Field ann] -> (Syntax, [Field ann])
    sectionizeFields :: forall ann. [Field ann] -> (Syntax, [Field ann])
    sectionizeFields [Field ann]
    fs = case [Field ann] -> Maybe [(Name ann, [FieldLine ann])]
    forall ann. [Field ann] -> Maybe [(Name ann, [FieldLine ann])]
    classifyFields [Field ann]
    fs of
      Just [(Name ann, [FieldLine ann])]
    fields -> (Syntax
    OldSyntax, [(Name ann, [FieldLine ann])] -> [Field ann]
    forall ann. [(Name ann, [FieldLine ann])] -> [Field ann]
    convert [(Name ann, [FieldLine ann])]
    fields)
      Maybe [(Name ann, [FieldLine ann])]
    Nothing -> (Syntax
    NewSyntax, [Field ann]
    fs)
      where
        -- return 'Just' if all fields are simple fields
        classifyFields :: [Field ann] -> Maybe [(Name ann, [FieldLine ann])]
        classifyFields :: forall ann. [Field ann] -> Maybe [(Name ann, [FieldLine ann])]
    classifyFields = (Field ann -> Maybe (Name ann, [FieldLine ann]))
    -> [Field ann] -> Maybe [(Name ann, [FieldLine ann])]
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> [a] -> f [b]
    traverse Field ann -> Maybe (Name ann, [FieldLine ann])
    forall {ann}. Field ann -> Maybe (Name ann, [FieldLine ann])
    f
          where
            f :: Field ann -> Maybe (Name ann, [FieldLine ann])
    f (Field Name ann
    name [FieldLine ann]
    fieldlines) = (Name ann, [FieldLine ann]) -> Maybe (Name ann, [FieldLine ann])
    forall a. a -> Maybe a
    Just (Name ann
    name, [FieldLine ann]
    fieldlines)
            f Field ann
    _ = Maybe (Name ann, [FieldLine ann])
    forall a. Maybe a
    Nothing

        trim :: ByteString -> ByteString
    trim = (Word8 -> Bool) -> ByteString -> ByteString
    BS.dropWhile Word8 -> Bool
    isSpace' (ByteString -> ByteString)
    -> (ByteString -> ByteString) -> ByteString -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> ByteString
    BS.reverse (ByteString -> ByteString)
    -> (ByteString -> ByteString) -> ByteString -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Word8 -> Bool) -> ByteString -> ByteString
    BS.dropWhile Word8 -> Bool
    isSpace' (ByteString -> ByteString)
    -> (ByteString -> ByteString) -> ByteString -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> ByteString
    BS.reverse
        isSpace' :: Word8 -> Bool
    isSpace' = (Word8 -> Word8 -> Bool
    forall a. Eq a => a -> a -> Bool
    == Word8
    32)

        convert :: [(Name ann, [FieldLine ann])] -> [Field ann]
        convert :: forall ann. [(Name ann, [FieldLine ann])] -> [Field ann]
    convert [(Name ann, [FieldLine ann])]
    fields =
          let
            toField :: (Name ann, [FieldLine ann]) -> Field ann
    toField (Name ann
    name, [FieldLine ann]
    ls) = Name ann -> [FieldLine ann] -> Field ann
    forall ann. Name ann -> [FieldLine ann] -> Field ann
    Field Name ann
    name [FieldLine ann]
    ls
            -- "build-depends" is a local field now.  To be backwards
            -- compatible, we still allow it as a global field in old-style
            -- package description files and translate it to a local field by
            -- adding it to every non-empty section
            ([(Name ann, [FieldLine ann])]
    hdr0, [(Name ann, [FieldLine ann])]
    exes0) = ((Name ann, [FieldLine ann]) -> Bool)
    -> [(Name ann, [FieldLine ann])]
    -> ([(Name ann, [FieldLine ann])], [(Name ann, [FieldLine ann])])
    forall a. (a -> Bool) -> [a] -> ([a], [a])
    break ((ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "executable") (ByteString -> Bool)
    -> ((Name ann, [FieldLine ann]) -> ByteString)
    -> (Name ann, [FieldLine ann])
    -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Name ann -> ByteString
    forall ann. Name ann -> ByteString
    getName (Name ann -> ByteString)
    -> ((Name ann, [FieldLine ann]) -> Name ann)
    -> (Name ann, [FieldLine ann])
    -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Name ann, [FieldLine ann]) -> Name ann
    forall a b. (a, b) -> a
    fst) [(Name ann, [FieldLine ann])]
    fields
            ([(Name ann, [FieldLine ann])]
    hdr, [(Name ann, [FieldLine ann])]
    libfs0) = ((Name ann, [FieldLine ann]) -> Bool)
    -> [(Name ann, [FieldLine ann])]
    -> ([(Name ann, [FieldLine ann])], [(Name ann, [FieldLine ann])])
    forall a. (a -> Bool) -> [a] -> ([a], [a])
    partition (Bool -> Bool
    not (Bool -> Bool)
    -> ((Name ann, [FieldLine ann]) -> Bool)
    -> (Name ann, [FieldLine ann])
    -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ByteString -> [ByteString] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [ByteString]
    libFieldNames) (ByteString -> Bool)
    -> ((Name ann, [FieldLine ann]) -> ByteString)
    -> (Name ann, [FieldLine ann])
    -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Name ann -> ByteString
    forall ann. Name ann -> ByteString
    getName (Name ann -> ByteString)
    -> ((Name ann, [FieldLine ann]) -> Name ann)
    -> (Name ann, [FieldLine ann])
    -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Name ann, [FieldLine ann]) -> Name ann
    forall a b. (a, b) -> a
    fst) [(Name ann, [FieldLine ann])]
    hdr0

            ([(Name ann, [FieldLine ann])]
    deps, [(Name ann, [FieldLine ann])]
    libfs) =
              ((Name ann, [FieldLine ann]) -> Bool)
    -> [(Name ann, [FieldLine ann])]
    -> ([(Name ann, [FieldLine ann])], [(Name ann, [FieldLine ann])])
    forall a. (a -> Bool) -> [a] -> ([a], [a])
    partition
                ((ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "build-depends") (ByteString -> Bool)
    -> ((Name ann, [FieldLine ann]) -> ByteString)
    -> (Name ann, [FieldLine ann])
    -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Name ann -> ByteString
    forall ann. Name ann -> ByteString
    getName (Name ann -> ByteString)
    -> ((Name ann, [FieldLine ann]) -> Name ann)
    -> (Name ann, [FieldLine ann])
    -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Name ann, [FieldLine ann]) -> Name ann
    forall a b. (a, b) -> a
    fst)
                [(Name ann, [FieldLine ann])]
    libfs0

            exes :: [Field ann]
    exes = ([(Name ann, [FieldLine ann])]
     -> Maybe (Field ann, [(Name ann, [FieldLine ann])]))
    -> [(Name ann, [FieldLine ann])] -> [Field ann]
    forall b a. (b -> Maybe (a, b)) -> b -> [a]
    unfoldr [(Name ann, [FieldLine ann])]
    -> Maybe (Field ann, [(Name ann, [FieldLine ann])])
    toExe [(Name ann, [FieldLine ann])]
    exes0
            toExe :: [(Name ann, [FieldLine ann])]
    -> Maybe (Field ann, [(Name ann, [FieldLine ann])])
    toExe [] = Maybe (Field ann, [(Name ann, [FieldLine ann])])
    forall a. Maybe a
    Nothing
            toExe ((Name ann
    pos ByteString
    n, [FieldLine ann]
    ls) : [(Name ann, [FieldLine ann])]
    r)
              | ByteString
    n ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "executable" =
                  let ([(Name ann, [FieldLine ann])]
    efs, [(Name ann, [FieldLine ann])]
    r') = ((Name ann, [FieldLine ann]) -> Bool)
    -> [(Name ann, [FieldLine ann])]
    -> ([(Name ann, [FieldLine ann])], [(Name ann, [FieldLine ann])])
    forall a. (a -> Bool) -> [a] -> ([a], [a])
    break ((ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "executable") (ByteString -> Bool)
    -> ((Name ann, [FieldLine ann]) -> ByteString)
    -> (Name ann, [FieldLine ann])
    -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Name ann -> ByteString
    forall ann. Name ann -> ByteString
    getName (Name ann -> ByteString)
    -> ((Name ann, [FieldLine ann]) -> Name ann)
    -> (Name ann, [FieldLine ann])
    -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Name ann, [FieldLine ann]) -> Name ann
    forall a b. (a, b) -> a
    fst) [(Name ann, [FieldLine ann])]
    r
                   in (Field ann, [(Name ann, [FieldLine ann])])
    -> Maybe (Field ann, [(Name ann, [FieldLine ann])])
    forall a. a -> Maybe a
    Just (Name ann -> [SectionArg ann] -> [Field ann] -> Field ann
    forall ann.
    Name ann -> [SectionArg ann] -> [Field ann] -> Field ann
    Section (ann -> ByteString -> Name ann
    forall ann. ann -> ByteString -> Name ann
    Name ann
    pos ByteString
    "executable") [ann -> ByteString -> SectionArg ann
    forall ann. ann -> ByteString -> SectionArg ann
    SecArgName ann
    pos (ByteString -> SectionArg ann) -> ByteString -> SectionArg ann
    forall a b. (a -> b) -> a -> b
    $ ByteString -> ByteString
    trim (ByteString -> ByteString) -> ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $ [FieldLine ann] -> ByteString
    forall ann. [FieldLine ann] -> ByteString
    fieldlinesToBS [FieldLine ann]
    ls] (((Name ann, [FieldLine ann]) -> Field ann)
    -> [(Name ann, [FieldLine ann])] -> [Field ann]
    forall a b. (a -> b) -> [a] -> [b]
    map (Name ann, [FieldLine ann]) -> Field ann
    forall {ann}. (Name ann, [FieldLine ann]) -> Field ann
    toField ([(Name ann, [FieldLine ann])] -> [Field ann])
    -> [(Name ann, [FieldLine ann])] -> [Field ann]
    forall a b. (a -> b) -> a -> b
    $ [(Name ann, [FieldLine ann])]
    deps [(Name ann, [FieldLine ann])]
    -> [(Name ann, [FieldLine ann])] -> [(Name ann, [FieldLine ann])]
    forall a. [a] -> [a] -> [a]
    ++ [(Name ann, [FieldLine ann])]
    efs), [(Name ann, [FieldLine ann])]
    r')
            toExe [(Name ann, [FieldLine ann])]
    _ = String -> Maybe (Field ann, [(Name ann, [FieldLine ann])])
    forall a. HasCallStack => String -> a
    error String
    "unexpected input to 'toExe'"

            lib :: [Field ann]
    lib = case [(Name ann, [FieldLine ann])]
    libfs of
              [] -> []
              ((Name ann
    pos ByteString
    _, [FieldLine ann]
    _) : [(Name ann, [FieldLine ann])]
    _) ->
                [Name ann -> [SectionArg ann] -> [Field ann] -> Field ann
    forall ann.
    Name ann -> [SectionArg ann] -> [Field ann] -> Field ann
    Section (ann -> ByteString -> Name ann
    forall ann. ann -> ByteString -> Name ann
    Name ann
    pos ByteString
    "library") [] (((Name ann, [FieldLine ann]) -> Field ann)
    -> [(Name ann, [FieldLine ann])] -> [Field ann]
    forall a b. (a -> b) -> [a] -> [b]
    map (Name ann, [FieldLine ann]) -> Field ann
    forall {ann}. (Name ann, [FieldLine ann]) -> Field ann
    toField ([(Name ann, [FieldLine ann])] -> [Field ann])
    -> [(Name ann, [FieldLine ann])] -> [Field ann]
    forall a b. (a -> b) -> a -> b
    $ [(Name ann, [FieldLine ann])]
    deps [(Name ann, [FieldLine ann])]
    -> [(Name ann, [FieldLine ann])] -> [(Name ann, [FieldLine ann])]
    forall a. [a] -> [a] -> [a]
    ++ [(Name ann, [FieldLine ann])]
    libfs)]
           in
            ((Name ann, [FieldLine ann]) -> Field ann)
    -> [(Name ann, [FieldLine ann])] -> [Field ann]
    forall a b. (a -> b) -> [a] -> [b]
    map (Name ann, [FieldLine ann]) -> Field ann
    forall {ann}. (Name ann, [FieldLine ann]) -> Field ann
    toField [(Name ann, [FieldLine ann])]
    hdr [Field ann] -> [Field ann] -> [Field ann]
    forall a. [a] -> [a] -> [a]
    ++ [Field ann]
    lib [Field ann] -> [Field ann] -> [Field ann]
    forall a. [a] -> [a] -> [a]
    ++ [Field ann]
    exes

    -- | See 'sectionizeFields'.
    data Syntax = OldSyntax | NewSyntax
      deriving (Syntax -> Syntax -> Bool
    (Syntax -> Syntax -> Bool)
    -> (Syntax -> Syntax -> Bool) -> Eq Syntax
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Syntax -> Syntax -> Bool
    == :: Syntax -> Syntax -> Bool
    $c/= :: Syntax -> Syntax -> Bool
    /= :: Syntax -> Syntax -> Bool
    Eq, Int -> Syntax -> String -> String
    [Syntax] -> String -> String
    Syntax -> String
    (Int -> Syntax -> String -> String)
    -> (Syntax -> String)
    -> ([Syntax] -> String -> String)
    -> Show Syntax
    forall a.
    (Int -> a -> String -> String)
    -> (a -> String) -> ([a] -> String -> String) -> Show a
    $cshowsPrec :: Int -> Syntax -> String -> String
    showsPrec :: Int -> Syntax -> String -> String
    $cshow :: Syntax -> String
    show :: Syntax -> String
    $cshowList :: [Syntax] -> String -> String
    showList :: [Syntax] -> String -> String
    Show)

    -- TODO:
    libFieldNames :: [FieldName]
    libFieldNames :: [ByteString]
    libFieldNames = ParsecFieldGrammar' Library -> [ByteString]
    forall s a. ParsecFieldGrammar s a -> [ByteString]
    fieldGrammarKnownFieldList (LibraryName -> ParsecFieldGrammar' Library
    forall (c :: * -> Constraint) (g :: * -> * -> *).
    (FieldGrammar c g, Applicative (g Library),
     Applicative (g BuildInfo), c (Identity LibraryVisibility),
     c (List CommaFSep (Identity ExeDependency) ExeDependency),
     c (List
          CommaFSep (Identity LegacyExeDependency) LegacyExeDependency),
     c (List
          CommaFSep (Identity PkgconfigDependency) PkgconfigDependency),
     c (List CommaVCat (Identity Dependency) Dependency),
     c (List CommaVCat (Identity Mixin) Mixin),
     c (List CommaVCat (Identity ModuleReexport) ModuleReexport),
     c (List FSep (MQuoted Extension) Extension),
     c (List FSep (MQuoted Language) Language),
     c (List FSep FilePathNT String), c (List FSep Token String),
     c (List NoCommaFSep Token' String),
     c (List VCat (MQuoted ModuleName) ModuleName),
     c (List VCat FilePathNT String),
     c (List
          FSep
          (Identity (SymbolicPath PackageDir SourceDir))
          (SymbolicPath PackageDir SourceDir)),
     c (List VCat Token String), c (MQuoted Language)) =>
    LibraryName -> g Library Library
    libraryFieldGrammar LibraryName
    LMainLibName)

    -------------------------------------------------------------------------------
    -- Supplementary build information
    -------------------------------------------------------------------------------

    parseHookedBuildInfo :: BS.ByteString -> ParseResult HookedBuildInfo
    parseHookedBuildInfo :: ByteString -> ParseResult HookedBuildInfo
    parseHookedBuildInfo ByteString
    bs = case ByteString -> Either ParseError ([Field Position], [LexWarning])
    readFields' ByteString
    bs of
      Right ([Field Position]
    fs, [LexWarning]
    lexWarnings) -> do
        [LexWarning] -> [Field Position] -> ParseResult HookedBuildInfo
    parseHookedBuildInfo' [LexWarning]
    lexWarnings [Field Position]
    fs
      -- TODO: better marshalling of errors
      Left ParseError
    perr -> Position -> String -> ParseResult HookedBuildInfo
    forall a. Position -> String -> ParseResult a
    parseFatalFailure Position
    zeroPos (ParseError -> String
    forall a. Show a => a -> String
    show ParseError
    perr)

    parseHookedBuildInfo'
      :: [LexWarning]
      -> [Field Position]
      -> ParseResult HookedBuildInfo
    parseHookedBuildInfo' :: [LexWarning] -> [Field Position] -> ParseResult HookedBuildInfo
    parseHookedBuildInfo' [LexWarning]
    lexWarnings [Field Position]
    fs = do
      [PWarning] -> ParseResult ()
    parseWarnings ([LexWarning] -> [PWarning]
    toPWarnings [LexWarning]
    lexWarnings)
      (mLibFields, exes) <- [Field Position]
    -> ParseResult
         (Fields Position, [(UnqualComponentName, Fields Position)])
    stanzas [Field Position]
    fs
      mLib <- parseLib mLibFields
      biExes <- traverse parseExe exes
      return (mLib, biExes)
      where
        parseLib :: Fields Position -> ParseResult (Maybe BuildInfo)
        parseLib :: Fields Position -> ParseResult (Maybe BuildInfo)
    parseLib Fields Position
    fields
          | Fields Position -> Bool
    forall k a. Map k a -> Bool
    Map.null Fields Position
    fields = Maybe BuildInfo -> ParseResult (Maybe BuildInfo)
    forall a. a -> ParseResult a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Maybe BuildInfo
    forall a. Maybe a
    Nothing
          | Bool
    otherwise = BuildInfo -> Maybe BuildInfo
    forall a. a -> Maybe a
    Just (BuildInfo -> Maybe BuildInfo)
    -> ParseResult BuildInfo -> ParseResult (Maybe BuildInfo)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CabalSpecVersion
    -> Fields Position
    -> ParsecFieldGrammar' BuildInfo
    -> ParseResult BuildInfo
    forall s a.
    CabalSpecVersion
    -> Fields Position -> ParsecFieldGrammar s a -> ParseResult a
    parseFieldGrammar CabalSpecVersion
    cabalSpecLatest Fields Position
    fields ParsecFieldGrammar' BuildInfo
    forall (c :: * -> Constraint) (g :: * -> * -> *).
    (FieldGrammar c g, Applicative (g BuildInfo),
     c (List CommaFSep (Identity ExeDependency) ExeDependency),
     c (List
          CommaFSep (Identity LegacyExeDependency) LegacyExeDependency),
     c (List
          CommaFSep (Identity PkgconfigDependency) PkgconfigDependency),
     c (List CommaVCat (Identity Dependency) Dependency),
     c (List CommaVCat (Identity Mixin) Mixin),
     c (List FSep (MQuoted Extension) Extension),
     c (List FSep (MQuoted Language) Language),
     c (List FSep FilePathNT String), c (List FSep Token String),
     c (List NoCommaFSep Token' String),
     c (List VCat (MQuoted ModuleName) ModuleName),
     c (List VCat FilePathNT String),
     c (List
          FSep
          (Identity (SymbolicPath PackageDir SourceDir))
          (SymbolicPath PackageDir SourceDir)),
     c (List VCat Token String), c (MQuoted Language)) =>
    g BuildInfo BuildInfo
    buildInfoFieldGrammar

        parseExe :: (UnqualComponentName, Fields Position) -> ParseResult (UnqualComponentName, BuildInfo)
        parseExe :: (UnqualComponentName, Fields Position)
    -> ParseResult (UnqualComponentName, BuildInfo)
    parseExe (UnqualComponentName
    n, Fields Position
    fields) = do
          bi <- CabalSpecVersion
    -> Fields Position
    -> ParsecFieldGrammar' BuildInfo
    -> ParseResult BuildInfo
    forall s a.
    CabalSpecVersion
    -> Fields Position -> ParsecFieldGrammar s a -> ParseResult a
    parseFieldGrammar CabalSpecVersion
    cabalSpecLatest Fields Position
    fields ParsecFieldGrammar' BuildInfo
    forall (c :: * -> Constraint) (g :: * -> * -> *).
    (FieldGrammar c g, Applicative (g BuildInfo),
     c (List CommaFSep (Identity ExeDependency) ExeDependency),
     c (List
          CommaFSep (Identity LegacyExeDependency) LegacyExeDependency),
     c (List
          CommaFSep (Identity PkgconfigDependency) PkgconfigDependency),
     c (List CommaVCat (Identity Dependency) Dependency),
     c (List CommaVCat (Identity Mixin) Mixin),
     c (List FSep (MQuoted Extension) Extension),
     c (List FSep (MQuoted Language) Language),
     c (List FSep FilePathNT String), c (List FSep Token String),
     c (List NoCommaFSep Token' String),
     c (List VCat (MQuoted ModuleName) ModuleName),
     c (List VCat FilePathNT String),
     c (List
          FSep
          (Identity (SymbolicPath PackageDir SourceDir))
          (SymbolicPath PackageDir SourceDir)),
     c (List VCat Token String), c (MQuoted Language)) =>
    g BuildInfo BuildInfo
    buildInfoFieldGrammar
          pure (n, bi)

        stanzas :: [Field Position] -> ParseResult (Fields Position, [(UnqualComponentName, Fields Position)])
        stanzas :: [Field Position]
    -> ParseResult
         (Fields Position, [(UnqualComponentName, Fields Position)])
    stanzas [Field Position]
    fields = do
          let ([Field Position]
    hdr0, Maybe ([FieldLine Position], [Field Position])
    exes0) = (Field Position -> Maybe [FieldLine Position])
    -> [Field Position]
    -> ([Field Position],
        Maybe ([FieldLine Position], [Field Position]))
    forall a b. (a -> Maybe b) -> [a] -> ([a], Maybe (b, [a]))
    breakMaybe Field Position -> Maybe [FieldLine Position]
    forall {ann}. Field ann -> Maybe [FieldLine ann]
    isExecutableField [Field Position]
    fields
          hdr <- [Field Position] -> ParseResult (Fields Position)
    toFields [Field Position]
    hdr0
          exes <- unfoldrM (traverse toExe) exes0
          pure (hdr, exes)

        toFields :: [Field Position] -> ParseResult (Fields Position)
        toFields :: [Field Position] -> ParseResult (Fields Position)
    toFields [Field Position]
    fields = do
          let (Fields Position
    fields', [[Section Position]]
    ss) = [Field Position] -> (Fields Position, [[Section Position]])
    forall ann. [Field ann] -> (Fields ann, [[Section ann]])
    partitionFields [Field Position]
    fields
          ([Section Position] -> ParseResult ())
    -> [[Section Position]] -> ParseResult ()
    forall (t :: * -> *) (f :: * -> *) a b.
    (Foldable t, Applicative f) =>
    (a -> f b) -> t a -> f ()
    traverse_ ((Section Position -> ParseResult ())
    -> [Section Position] -> ParseResult ()
    forall (t :: * -> *) (f :: * -> *) a b.
    (Foldable t, Applicative f) =>
    (a -> f b) -> t a -> f ()
    traverse_ Section Position -> ParseResult ()
    warnInvalidSubsection) [[Section Position]]
    ss
          Fields Position -> ParseResult (Fields Position)
    forall a. a -> ParseResult a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Fields Position
    fields'

        toExe
          :: ([FieldLine Position], [Field Position])
          -> ParseResult ((UnqualComponentName, Fields Position), Maybe ([FieldLine Position], [Field Position]))
        toExe :: ([FieldLine Position], [Field Position])
    -> ParseResult
         ((UnqualComponentName, Fields Position),
          Maybe ([FieldLine Position], [Field Position]))
    toExe ([FieldLine Position]
    fss, [Field Position]
    fields) = do
          name <- Position
    -> ParsecParser UnqualComponentName
    -> CabalSpecVersion
    -> [FieldLine Position]
    -> ParseResult UnqualComponentName
    forall a.
    Position
    -> ParsecParser a
    -> CabalSpecVersion
    -> [FieldLine Position]
    -> ParseResult a
    runFieldParser Position
    zeroPos ParsecParser UnqualComponentName
    forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
    forall (m :: * -> *). CabalParsing m => m UnqualComponentName
    parsec CabalSpecVersion
    cabalSpecLatest [FieldLine Position]
    fss
          let (hdr0, rest) = breakMaybe isExecutableField fields
          hdr <- toFields hdr0
          pure ((name, hdr), rest)

        isExecutableField :: Field ann -> Maybe [FieldLine ann]
    isExecutableField (Field (Name ann
    _ ByteString
    name) [FieldLine ann]
    fss)
          | ByteString
    name ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    "executable" = [FieldLine ann] -> Maybe [FieldLine ann]
    forall a. a -> Maybe a
    Just [FieldLine ann]
    fss
          | Bool
    otherwise = Maybe [FieldLine ann]
    forall a. Maybe a
    Nothing
        isExecutableField Field ann
    _ = Maybe [FieldLine ann]
    forall a. Maybe a
    Nothing

    -------------------------------------------------------------------------------
    -- Scan of spec version
    -------------------------------------------------------------------------------

    -- | Quickly scan new-style spec-version
    --
    -- A new-style spec-version declaration begins the .cabal file and
    -- follow the following case-insensitive grammar (expressed in
    -- RFC5234 ABNF):
    --
    -- @
    -- newstyle-spec-version-decl = "cabal-version" *WS ":" *WS newstyle-pec-version *WS
    --
    -- spec-version               = NUM "." NUM [ "." NUM ]
    --
    -- NUM    = DIGIT0 / DIGITP 1*DIGIT0
    -- DIGIT0 = %x30-39
    -- DIGITP = %x31-39
    -- WS = %20
    -- @
    scanSpecVersion :: BS.ByteString -> Maybe Version
    scanSpecVersion :: ByteString -> Maybe Version
    scanSpecVersion ByteString
    bs = do
      fstline' : _ <- [ByteString] -> Maybe [ByteString]
    forall a. a -> Maybe a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (ByteString -> [ByteString]
    BS8.lines ByteString
    bs)

      -- parse <newstyle-spec-version-decl>
      -- normalise: remove all whitespace, convert to lower-case
      let fstline = (Word8 -> Word8) -> ByteString -> ByteString
    BS.map Word8 -> Word8
    toLowerW8 (ByteString -> ByteString) -> ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $ (Word8 -> Bool) -> ByteString -> ByteString
    BS.filter (Word8 -> Word8 -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Word8
    0x20) ByteString
    fstline'
      ["cabal-version", vers] <- pure (BS8.split ':' fstline)

      -- parse <spec-version>
      --
      -- This is currently more tolerant regarding leading 0 digits.
      --
      ver <- simpleParsecBS vers
      guard $ case versionNumbers ver of
        [Int
    _, Int
    _] -> Bool
    True
        [Int
    _, Int
    _, Int
    _] -> Bool
    True
        [Int]
    _ -> Bool
    False

      pure ver
      where
        -- \| Translate ['A'..'Z'] to ['a'..'z']
        toLowerW8 :: Word8 -> Word8
        toLowerW8 :: Word8 -> Word8
    toLowerW8 Word8
    w
          | Word8
    0x40 Word8 -> Word8 -> Bool
    forall a. Ord a => a -> a -> Bool
    < Word8
    w Bool -> Bool -> Bool
    && Word8
    w Word8 -> Word8 -> Bool
    forall a. Ord a => a -> a -> Bool
    < Word8
    0x5b = Word8
    w Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    + Word8
    0x20
          | Bool
    otherwise = Word8
    w