{-# language QuasiQuotes #-} module GraphSpec where import Data.String.Interpolate import GHC import Test.Hspec import Graph import Helper import Ast getDeadNames :: IO [String] getDeadNames = do ast <- eitherToError $ parse ["Foo.hs"] let graph = usedTopLevelNames ast roots <- eitherToError $ return $ findExports ast [mkModuleName "Foo"] return $ fmap showName $ deadNames graph roots spec :: Spec spec = do describe "deadNames" $ do it "detects unused top-level names" $ do withFoo [i| module Foo (foo) where foo = () bar = () |] $ do getDeadNames `shouldReturn` ["Foo.bar"] it "allows to specify multiple roots" $ do withFoo [i| module Foo (r1, r2) where r1 = foo r2 = bar foo = () bar = () baz = () |] $ do getDeadNames `shouldReturn` ["Foo.baz"] it "detects usage of names in instance methods" $ do withFoo [i| module Foo () where data A = A instance Show A where show A = foo foo = "foo" |] $ do getDeadNames `shouldReturn` [] it "returns dead names in topological order" $ do withFoo [i| module Foo () where b = c a = b c = () |] $ do getDeadNames `shouldReturn` (words "Foo.a Foo.b Foo.c") it "finds used names in default implementations of methods in class declarations" $ do withFoo [i| module Foo () where class A a where a :: a -> String a _ = foo foo = "foo" |] $ do getDeadNames `shouldReturn` []