|
5 | 5 | {-# LANGUAGE DeriveTraversable #-} |
6 | 6 | {-# LANGUAGE MultiWayIf #-} |
7 | 7 | {-# LANGUAGE OverloadedStrings #-} |
| 8 | +{-# LANGUAGE ScopedTypeVariables #-} |
8 | 9 | -- | License: GPL-3.0-or-later AND BSD-3-Clause |
9 | 10 | -- |
10 | 11 | module Cabal.Project ( |
@@ -59,6 +60,7 @@ import qualified Distribution.FieldGrammar as C |
59 | 60 | import qualified Distribution.Fields as C |
60 | 61 | import qualified Distribution.PackageDescription as C |
61 | 62 | import qualified Distribution.Parsec as C |
| 63 | +import qualified Distribution.Fields.ConfVar as C |
62 | 64 |
|
63 | 65 | import Cabal.Internal.Glob |
64 | 66 | import Cabal.Internal.Newtypes |
@@ -154,7 +156,7 @@ instance (NFData c, NFData b, NFData a) => NFData (Project c b a) where |
154 | 156 | rnf x7 `seq` rnf x8 `seq` rnf x9 `seq` |
155 | 157 | rnfList rnfPrettyField x10 |
156 | 158 | where |
157 | | - rnfList :: (a -> ()) -> [a] -> () |
| 159 | + rnfList :: (x -> ()) -> [x] -> () |
158 | 160 | rnfList _ [] = () |
159 | 161 | rnfList f (x:xs) = f x `seq` rnfList f xs |
160 | 162 |
|
@@ -227,13 +229,13 @@ parseProject = parseWith $ \fields0 -> do |
227 | 229 | -- Right (CondNode {condTreeData = ["foo","bar/*.cabal"], condTreeConstraints = (), condTreeComponents = []}) |
228 | 230 | -- |
229 | 231 | parseProjectWithConditionals :: FilePath -> ByteString -> Either (ParseError NonEmpty) (C.CondTree C.ConfVar () (Project Void String String)) |
230 | | -parseProjectWithConditionals = parseWith $ \fields0 -> do |
231 | | - let (fields1, sections) = C.partitionFields fields0 |
| 232 | +parseProjectWithConditionals = parseWith $ \fields0 -> flip parseCondTree fields0 $ \fields1 sections -> do |
232 | 233 | let fields2 = M.filterWithKey (\k _ -> k `elem` knownFields) fields1 |
233 | | - (\n -> C.CondNode n () []) <$> parse fields0 fields2 sections |
| 234 | + parse fields0 fields2 sections |
234 | 235 | where |
235 | 236 | knownFields = C.fieldGrammarKnownFieldList $ grammar [] |
236 | 237 |
|
| 238 | + parse :: [C.Field a] -> C.Fields C.Position -> [[C.Section C.Position]] -> C.ParseResult (Project Void String String) |
237 | 239 | parse otherFields fields sections = do |
238 | 240 | let prettyOtherFields = map void $ C.fromParsecFields $ filter otherFieldName otherFields |
239 | 241 | prj <- C.parseFieldGrammar C.cabalSpecLatest fields $ grammar prettyOtherFields |
@@ -419,3 +421,62 @@ readPackagesOfProject :: Project uri opt FilePath -> IO (Either (ParseError NonE |
419 | 421 | readPackagesOfProject prj = runExceptT $ for prj $ \fp -> do |
420 | 422 | contents <- liftIO $ BS.readFile fp |
421 | 423 | either throwE (\gpd -> return (fp, gpd)) (parsePackage fp contents) |
| 424 | + |
| 425 | +------------------------------------------------------------------------------- |
| 426 | +-- Read package files |
| 427 | +------------------------------------------------------------------------------- |
| 428 | + |
| 429 | +parseCondTree |
| 430 | + :: forall a. (C.Fields C.Position -> [[C.Section C.Position]] -> C.ParseResult a) -- ^ parse |
| 431 | + -> [C.Field C.Position] |
| 432 | + -> C.ParseResult (C.CondTree C.ConfVar () a) |
| 433 | +parseCondTree subparse = go |
| 434 | + where |
| 435 | + go fields = do |
| 436 | + let (fs, ss) = C.partitionFields fields |
| 437 | + (ss', branches) <- second concat . unzip <$> traverse (parseIfs id id) ss |
| 438 | + x <- subparse fs ss' |
| 439 | + return $ C.CondNode x () branches |
| 440 | + |
| 441 | + parseIfs |
| 442 | + :: ([C.Section C.Position] -> [C.Section C.Position]) |
| 443 | + -> ([C.CondBranch C.ConfVar () a] -> [C.CondBranch C.ConfVar () a]) |
| 444 | + -> [C.Section C.Position] |
| 445 | + -> C.ParseResult ([C.Section C.Position], [C.CondBranch C.ConfVar () a]) |
| 446 | + parseIfs accS accB [] = return (accS [], accB []) |
| 447 | + parseIfs accS accB (C.MkSection (C.Name _ name) test fields : sections) | name == "if" = do |
| 448 | + test' <- C.parseConditionConfVar test |
| 449 | + fields' <- go fields |
| 450 | + -- TODO: (elseFields, sections') <- parseElseIfs sections |
| 451 | + let condTree :: C.CondBranch C.ConfVar () a |
| 452 | + condTree = C.CondBranch test' fields' Nothing |
| 453 | + parseIfs accS (accB . (condTree :)) sections |
| 454 | + parseIfs accS accB (section : sections) = do |
| 455 | + parseIfs (accS . (section :)) accB sections |
| 456 | + |
| 457 | +{- |
| 458 | + parseElseIfs |
| 459 | + :: [Section Position] |
| 460 | + -> ParseResult (Maybe (CondTree ConfVar [Dependency] a), [CondBranch ConfVar [Dependency] a]) |
| 461 | + parseElseIfs [] = return (Nothing, []) |
| 462 | + parseElseIfs (MkSection (Name pos name) args fields : sections) | name == "else" = do |
| 463 | + unless (null args) $ |
| 464 | + parseFailure pos $ |
| 465 | + "`else` section has section arguments " ++ show args |
| 466 | + elseFields <- go fields |
| 467 | + sections' <- parseIfs sections |
| 468 | + return (Just elseFields, sections') |
| 469 | + parseElseIfs (MkSection (Name _ name) test fields : sections) |
| 470 | + | hasElif == HasElif |
| 471 | + , name == "elif" = do |
| 472 | + test' <- parseConditionConfVar test |
| 473 | + fields' <- go fields |
| 474 | + (elseFields, sections') <- parseElseIfs sections |
| 475 | + -- we parse an empty 'Fields', to get empty value for a node |
| 476 | + a <- parseFieldGrammar v mempty grammar |
| 477 | + return (Just $ CondNode a (cond a) [CondBranch test' fields' elseFields], sections') |
| 478 | + parseElseIfs (MkSection (Name pos name) _ _ : sections) | name == "elif" = do |
| 479 | + parseWarning pos PWTInvalidSubsection $ "invalid subsection \"elif\". You should set cabal-version: 2.2 or larger to use elif-conditionals." |
| 480 | + (,) Nothing <$> parseIfs sections |
| 481 | + parseElseIfs sections = (,) Nothing <$> parseIfs sections |
| 482 | +-} |
0 commit comments