{-# LANGUAGE PackageImports #-} module Graphing.Calls.Spec ( spec ) where import Prelude hiding (readFile) import SpecHelpers hiding (readFile) import Algebra.Graph import "semantic" Data.Graph (Graph (..), topologicalSort) import Data.Graph.ControlFlowVertex import qualified Data.Language as Language import Semantic.Graph import qualified System.Path as Path callGraphPythonProject :: Path.RelFile -> IO (Semantic.Graph.Graph ControlFlowVertex) callGraphPythonProject path = runTaskOrDie $ do let proxy = Proxy @'Language.Python let lang = Language.Python blob <- readBlobFromFile' (fileForRelPath path) package <- fmap snd <$> parsePackage pythonParser (Project (Path.toString (Path.takeDirectory path)) [blob] lang []) modules <- topologicalSort <$> runImportGraphToModules proxy package runCallGraph proxy False modules package spec :: Spec spec = describe "call graphing" $ do let needs r v = unGraph r `shouldSatisfy` hasVertex v it "should work for a simple example" $ do res <- callGraphPythonProject (Path.relFile "test/fixtures/python/graphing/simple/simple.py") res `needs` Variable "magnus" "simple.py" (Span (Pos 4 1) (Pos 4 7)) it "should evaluate both sides of an if-statement" $ do res <- callGraphPythonProject (Path.relFile "test/fixtures/python/graphing/conditional/conditional.py") res `needs` Variable "merle" "conditional.py" (Span (Pos 5 5) (Pos 5 10)) res `needs` Variable "taako" "conditional.py" (Span (Pos 8 5) (Pos 8 10)) it "should continue even when a type error is encountered" $ do res <- callGraphPythonProject (Path.relFile "test/fixtures/python/graphing/typeerror/typeerror.py") res `needs` Variable "lup" "typeerror.py" (Span (Pos 5 1) (Pos 5 4)) it "should continue when an unbound variable is encountered" $ do res <- callGraphPythonProject (Path.relFile "test/fixtures/python/graphing/unbound/unbound.py") res `needs` Variable "lucretia" "unbound.py" (Span (Pos 5 1) (Pos 5 9))