module UnitTests.Distribution.Simple.Program.GHC (tests) where

import Data.Algorithm.Diff (PolyDiff (..), getDiff)
import Test.Tasty          (TestTree, testGroup)
import Test.Tasty.HUnit

import Distribution.PackageDescription (emptyPackageDescription)
import Distribution.Simple.Program.GHC (normaliseGhcArgs)
import Distribution.Version            (mkVersion)

tests :: TestTree
tests = testGroup "Distribution.Simple.Program.GHC"
    [ testGroup "normaliseGhcArgs"
        [ testCase "options added in GHC-8.8" $ do
            let flags :: [String]
                flags = normaliseGhcArgs
                    (Just $ mkVersion [8,8,1])
                    emptyPackageDescription
                    options_8_8_all

            assertListEquals flags options_8_8_affects

        , testCase "options added in GHC-8.10" $ do
            let flags :: [String]
                flags = normaliseGhcArgs
                    (Just $ mkVersion [8,10,1])
                    emptyPackageDescription
                    options_8_10_all

            assertListEquals flags options_8_10_affects

        , testCase "options added in GHC-9.0" $ do
            let flags :: [String]
                flags = normaliseGhcArgs
                    (Just $ mkVersion [9,0,1])
                    emptyPackageDescription
                    options_9_0_all

            assertListEquals flags options_9_0_affects
        ]
    ]

assertListEquals :: (Eq a, Show a) => [a] -> [a] -> Assertion
assertListEquals xs ys
    | xs == ys = return ()
    | otherwise = assertFailure $ unlines $
        "Lists are not equal" :
        [ case d of
            First x  -> "- " ++ show x
            Second y -> "+ " ++ show y
            Both x _ -> "  " ++ show x
        | d <- getDiff xs ys
        ]

-------------------------------------------------------------------------------
-- GHC 8.8
-------------------------------------------------------------------------------

-- | Options added in GHC-8.8, to generate:
--
-- @
-- ghc-8.6.5 --show-options | sort > 8.6.5.txt
-- ghc-8.8.1 --show-options | sort > 8.8.1.txt
-- diff -u 8.6.5 8.8.1
-- @
--
-- - remove -W(no-)error=, -W(no-)warn flags.
-- - split into all and flags which may affect artifacts
options_8_8_all :: [String]
options_8_8_all =
    [ "-ddump-cfg-weights"
    , "-dno-suppress-stg-exts"
    , "-dsuppress-stg-exts"
    , "-Wmissed-extra-shared-lib"
    , "-Wmissing-deriving-strategies"
    , "-Wmissing-space-after-bang"
    , "-Wno-missed-extra-shared-lib"
    , "-Wno-missing-deriving-strategies"
    , "-Wno-missing-space-after-bang"
    , "-fno-show-docs-of-hole-fits"
    , "-fshow-docs-of-hole-fits"
    ] ++ options_8_8_affects

options_8_8_affects :: [String]
options_8_8_affects =
    [ "-fblock-layout-cfg"
    , "-fblock-layout-weightless"
    , "-fblock-layout-weights"
    , "-fclear-plugins"
    , "-fkeep-cafs"
    , "-fno-block-layout-cfg"
    , "-fno-block-layout-weightless"
    , "-fno-keep-cafs"
    , "-fno-safe-haskell"
    , "-fno-stg-lift-lams"
    , "-fno-stg-lift-lams-known"
    , "-fno-validate-ide-info"
    , "-fno-write-ide-info"
    , "-fstg-lift-lams"
    , "-fstg-lift-lams-known"
    , "-fstg-lift-lams-non-rec-args"
    , "-fstg-lift-lams-non-rec-args-any"
    , "-fstg-lift-lams-rec-args"
    , "-fstg-lift-lams-rec-args-any"
    , "-fvalidate-ide-info"
    , "-fwrite-ide-info"
    , "-hiedir"
    , "-hiesuf"
    , "-keep-hscpp-file"
    , "-keep-hscpp-files"
    ]

-------------------------------------------------------------------------------
-- GHC 8.10
-------------------------------------------------------------------------------

options_8_10_all :: [String]
options_8_10_all =
    [ "-ddump-cmm-verbose-by-proc"
    , "-ddump-stg-final"
    , "-ddump-stg-unarised"
    , "-Wderiving-defaults"
    , "-Winferred-safe-imports"
    , "-Wmissing-safe-haskell-mode"
    , "-Wno-deriving-defaults"
    , "-Wno-inferred-safe-imports"
    , "-Wno-missing-safe-haskell-mode"
    , "-Wno-prepositive-qualified-module"
    , "-Wno-redundant-record-wildcards"
    , "-Wno-unused-packages"
    , "-Wno-unused-record-wildcards"
    , "-Wprepositive-qualified-module"
    , "-Wredundant-record-wildcards"
    , "-Wunused-packages"
    , "-Wunused-record-wildcards"
    , "-fdefer-diagnostics"
    , "-fkeep-going"
    , "-fprint-axiom-incomps"
    , "-fno-defer-diagnostics"
    , "-fno-keep-going"
    , "-fno-print-axiom-incomps"
    ] ++ options_8_10_affects

options_8_10_affects :: [String]
options_8_10_affects =
    [ "-dno-typeable-binds"
    , "-fbinary-blob-threshold"
    , "-fmax-pmcheck-models"
    , "-fplugin-trustworthy"
    , "-include-cpp-deps"
    , "-optcxx"
    ]

-------------------------------------------------------------------------------
-- GHC-9.0
-------------------------------------------------------------------------------

options_9_0_all :: [String]
options_9_0_all =
    [ "-ddump-cmm-opt"
    , "-ddump-cpranal"
    , "-ddump-cpr-signatures"
    , "-ddump-hie"
    -- NOTE: we filter out -dlinear-core-lint
    -- we filter, -dcore-lint, -dstg-lint etc.
    , "-dlinear-core-lint"
    ] ++ options_9_0_affects

options_9_0_affects :: [String]
options_9_0_affects =
    [ "-fcmm-static-pred"
    ]

-------------------------------------------------------------------------------
-- GHC-9.2
-------------------------------------------------------------------------------

options_9_2_all :: [String]
options_9_2_all =
    [ "-dynohi"
    , "-ddump-c-backend"
    , "-ddump-stg-from-core"
    , "-ddump-stg"
    , "-ddump-faststrings"
    , "--run"
    , "-ffamily-application-cache"
    , "-fno-family-application-cache"
    ] ++ options_9_2_affects

options_9_2_affects :: [String]
options_9_2_affects =
    [ "-fprof-callers"
    , "-funfolding-case-threshold"
    , "-funfolding-case-scaling"
    , "-fdistinct-constructor-tables"
    , "-finfo-table-map"
    , "-fexpose-internal-symbols"
    , "-finline-generics"
    , "-finline-generics-aggressively"
    , "-fno-expose-internal-symbols"
    , "-fno-inline-generics"
    , "-fno-inline-generics-aggressively"
    ]
