Skip to content

Commit

Permalink
Make check deal correctly with multiple branches
Browse files Browse the repository at this point in the history
`cabal check` had a problem recognising fields in presence of
multiple branches. This patch fixes the problem and does not
meaningfully increases CI time of particularly taxing tests
(like “duplicate flagged dependencies” from MemoryUsage).
  • Loading branch information
ffaf1 committed Mar 2, 2024
1 parent f5e96f1 commit aacb9be
Showing 1 changed file with 45 additions and 3 deletions.
48 changes: 45 additions & 3 deletions Cabal/src/Distribution/PackageDescription/Check/Conditional.hs
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,16 @@ updateTargetAnnotation t ta = ta{taTarget = taTarget ta <> t}
-- doc for more info).
annotateCondTree
:: forall a
. Monoid a
. (Eq a, Monoid a)
=> [PackageFlag] -- User flags.
-> TargetAnnotation a
-> CondTree ConfVar [Dependency] a
-> CondTree ConfVar [Dependency] (TargetAnnotation a)
annotateCondTree fs ta (CondNode a c bs) =
let ta' = updateTargetAnnotation a ta
bs' = map (annotateBranch ta') bs
in CondNode ta' c bs'
bs'' = crossAnnotateBranches defTrueFlags bs'
in CondNode ta' c bs''
where
annotateBranch
:: TargetAnnotation a
Expand Down Expand Up @@ -107,12 +108,53 @@ annotateCondTree fs ta (CondNode a c bs) =
)
fs

defTrueFlags :: [PackageFlag]
defTrueFlags = filter flagDefault fs

-- Propagate contextual information in CondTree branches. This is
-- needed as CondTree is a rosetree and not a binary tree.
crossAnnotateBranches
:: forall a
. (Eq a, Monoid a)
=> [PackageFlag] -- `default: true` flags.
-> [CondBranch ConfVar [Dependency] (TargetAnnotation a)]
-> [CondBranch ConfVar [Dependency] (TargetAnnotation a)]
crossAnnotateBranches fs bs = map crossAnnBranch bs
where
crossAnnBranch
:: CondBranch ConfVar [Dependency] (TargetAnnotation a)
-> CondBranch ConfVar [Dependency] (TargetAnnotation a)
crossAnnBranch wr =
let
rs = filter (/= wr) bs
ts = mapMaybe realiseBranch rs
in
utaBranch (mconcat ts) wr

realiseBranch :: CondBranch ConfVar [Dependency] (TargetAnnotation a) -> Maybe a
realiseBranch b =
let -- We are only interested in True by default package flags.
rbf :: ConfVar -> Either ConfVar Bool
rbf (PackageFlag n) | elem n (map flagName fs) = Right True
rbf _ = Right False
ms = simplifyCondBranch rbf (fmap taTarget b)
in fmap snd ms

utaBranch
:: a
-> CondBranch ConfVar [Dependency] (TargetAnnotation a)
-> CondBranch ConfVar [Dependency] (TargetAnnotation a)
utaBranch a (CondBranch k t mt) =
let utt (CondNode ka c wbs) =
(CondNode (updateTargetAnnotation a ka) c wbs)
in CondBranch k (utt t) (utt <$> mt)

-- | A conditional target is a library, exe, benchmark etc., destructured
-- in a CondTree. Traversing method: we render the branches, pass a
-- relevant context, collect checks.
checkCondTarget
:: forall m a
. (Monad m, Monoid a)
. (Monad m, Eq a, Monoid a)
=> [PackageFlag] -- User flags.
-> (a -> CheckM m ()) -- Check function (a = target).
-> (UnqualComponentName -> a -> a)
Expand Down

0 comments on commit aacb9be

Please sign in to comment.