hydra-build-0.17.5: src/main/haskell/Hydra/Build/Comparereportlogic.hs
-- Note: this is an automatically generated file. Do not edit.
-- | Pure snapshot-compare decision helpers: per-module status/diff-count and the whole-report tally, over content both sides already read
module Hydra.Build.Comparereportlogic where
import qualified Hydra.Ast as Ast
import qualified Hydra.Build.Walk as Walk
import qualified Hydra.Coders as Coders
import qualified Hydra.Core as Core
import qualified Hydra.Docs as Docs
import qualified Hydra.Error.Checking as Checking
import qualified Hydra.Error.Core as ErrorCore
import qualified Hydra.Error.File as ErrorFile
import qualified Hydra.Error.Packaging as ErrorPackaging
import qualified Hydra.Error.System as ErrorSystem
import qualified Hydra.Errors as Errors
import qualified Hydra.File as File
import qualified Hydra.Graph as Graph
import qualified Hydra.Json.Model as Model
import qualified Hydra.Overlay.Haskell.Lib.Equality as Equality
import qualified Hydra.Overlay.Haskell.Lib.Lists as Lists
import qualified Hydra.Overlay.Haskell.Lib.Literals as Literals
import qualified Hydra.Overlay.Haskell.Lib.Logic as Logic
import qualified Hydra.Overlay.Haskell.Lib.Math as Math
import qualified Hydra.Overlay.Haskell.Lib.Optionals as Optionals
import qualified Hydra.Overlay.Haskell.Lib.Ordering as Ordering
import qualified Hydra.Overlay.Haskell.Lib.Pairs as Pairs
import qualified Hydra.Overlay.Haskell.Lib.Strings as Strings
import qualified Hydra.Packaging as Packaging
import qualified Hydra.Parsing as Parsing
import qualified Hydra.Paths as Paths
import qualified Hydra.Query as Query
import qualified Hydra.Regex as Regex
import qualified Hydra.Relational as Relational
import qualified Hydra.System as System
import qualified Hydra.Tabular as Tabular
import qualified Hydra.Testing as Testing
import qualified Hydra.Time as Time
import qualified Hydra.Topology as Topology
import qualified Hydra.Typed as Typed
import qualified Hydra.Typing as Typing
import qualified Hydra.Util as Util
import qualified Hydra.Validation as Validation
import qualified Hydra.Variants as Variants
import Prelude hiding (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
import qualified Data.Scientific as Sci
-- | The whole compare-report (rows, byteEqCount, total) over enumerated module triples
buildReport :: [(t0, (Maybe String, (Maybe String)))] -> ([(t0, (String, Int))], (Int, Int))
buildReport inputs =
let rows =
Lists.map (\t -> compareModule (Pairs.first t) (Pairs.first (Pairs.second t)) (Pairs.second (Pairs.second t))) inputs
byteEqCount = Lists.length (Lists.filter (\r -> Equality.equal (Pairs.first (Pairs.second r)) "byteEq") rows)
in (rows, (byteEqCount, (Lists.length rows)))
-- | Compare one module (both sides pre-read) to a (name, statusTag, diffLines) triple
compareModule :: t0 -> Maybe String -> Maybe String -> (t0, (String, Int))
compareModule name ourContent canonContent =
Optionals.match ourContent (name, ("missing", 0)) (\ours -> Optionals.match canonContent (name, ("missing", 0)) (\canon -> Logic.ifElse (Equality.equal ours canon) (name, ("byteEq", 0)) (name, ("differ", (diffLineCount ours canon)))))
-- | Symmetric count of lines present in one content but not the other
diffLineCount :: String -> String -> Int
diffLineCount a b =
let aLines = Strings.splitOn "\n" a
bLines = Strings.splitOn "\n" b
onlyA = Lists.length (Lists.filter (\x -> Logic.not (Lists.member x bLines)) aLines)
onlyB = Lists.length (Lists.filter (\y -> Logic.not (Lists.member y aLines)) bLines)
in (Math.add onlyA onlyB)
-- | The .json entries (sorted), with the .json suffix stripped, as module names
moduleNamesFromEntries :: [String] -> [String]
moduleNamesFromEntries entries = Lists.map (\e -> stripJsonSuffix e) (Walk.filterByExtension "json" entries)
-- | The formatted per-module lines plus the byte-identical tally line
renderReport :: ([(String, (String, Int))], (Int, Int)) -> String
renderReport report =
let rows = Pairs.first report
byteEqCount = Pairs.first (Pairs.second report)
total = Pairs.second (Pairs.second report)
rowLines = Lists.map (\r -> renderRow r) rows
summary =
Strings.concat [
Literals.showInt32 byteEqCount,
"/",
(Literals.showInt32 total),
" byte-identical"]
in (Strings.join "\n" (Lists.concat [
rowLines,
[
summary]]))
-- | One report row rendered as a line: name: status[ (n lines differ)]
renderRow :: (String, (String, Int)) -> String
renderRow row =
let name = Pairs.first row
status = Pairs.first (Pairs.second row)
diffLines = Pairs.second (Pairs.second row)
in (Logic.ifElse (Equality.equal status "differ") (Strings.concat [
name,
": ",
status,
" (",
(Literals.showInt32 diffLines),
" lines differ)"]) (Strings.concat [
name,
": ",
status]))
-- | Whether every compared module was byte-identical (byteEqCount == total)
reportPassed :: Eq t1 => ((t0, (t1, t1)) -> Bool)
reportPassed report = Equality.equal (Pairs.first (Pairs.second report)) (Pairs.second (Pairs.second report))
-- | Strip a trailing .json from an entry name, yielding the module name
stripJsonSuffix :: String -> String
stripJsonSuffix entry =
let parts = Strings.splitOn "." entry
in (Logic.ifElse (Ordering.gt (Lists.length parts) 1) (Strings.join "." (Lists.take (Math.sub (Lists.length parts) 1) parts)) entry)