2018-07-16 18:07:40 +03:00
|
|
|
{-# LANGUAGE PackageImports #-}
|
|
|
|
|
|
|
|
module Graphing.Calls.Spec ( spec ) where
|
|
|
|
|
|
|
|
import Prelude hiding (readFile)
|
|
|
|
import SpecHelpers hiding (readFile)
|
|
|
|
|
|
|
|
import Algebra.Graph
|
|
|
|
import Data.List (uncons)
|
|
|
|
|
2018-07-16 18:12:17 +03:00
|
|
|
import "semantic" Data.Graph (Graph (..), topologicalSort)
|
2018-09-07 02:29:59 +03:00
|
|
|
import Data.Graph.ControlFlowVertex
|
2018-07-16 18:07:40 +03:00
|
|
|
import qualified Data.Language as Language
|
2018-07-16 18:12:17 +03:00
|
|
|
import Semantic.Graph
|
2018-07-16 18:07:40 +03:00
|
|
|
|
2019-06-15 07:53:02 +03:00
|
|
|
callGraphPythonProject :: [FilePath] -> IO (Semantic.Graph.Graph ControlFlowVertex)
|
2019-02-02 02:04:23 +03:00
|
|
|
callGraphPythonProject paths = runTaskOrDie $ do
|
2018-07-16 18:07:40 +03:00
|
|
|
let proxy = Proxy @'Language.Python
|
|
|
|
let lang = Language.Python
|
2018-10-23 22:28:21 +03:00
|
|
|
blobs <- catMaybes <$> traverse readBlobFromFile (flip File lang <$> paths)
|
2018-08-03 21:14:08 +03:00
|
|
|
package <- fmap snd <$> parsePackage pythonParser (Project (takeDirectory (maybe "/" fst (uncons paths))) blobs lang [])
|
2018-07-24 21:06:14 +03:00
|
|
|
modules <- topologicalSort <$> runImportGraphToModules proxy package
|
2018-07-16 18:07:40 +03:00
|
|
|
runCallGraph proxy False modules package
|
|
|
|
|
|
|
|
spec :: Spec
|
|
|
|
spec = describe "call graphing" $ do
|
|
|
|
|
2018-07-18 17:53:46 +03:00
|
|
|
let needs r v = unGraph r `shouldSatisfy` hasVertex v
|
2018-07-16 20:13:05 +03:00
|
|
|
|
2018-07-16 18:07:40 +03:00
|
|
|
it "should work for a simple example" $ do
|
|
|
|
res <- callGraphPythonProject ["test/fixtures/python/graphing/simple/simple.py"]
|
2018-07-18 17:53:46 +03:00
|
|
|
res `needs` Variable "magnus" "simple.py" (Span (Pos 4 1) (Pos 4 7))
|
2018-07-16 18:12:17 +03:00
|
|
|
|
|
|
|
it "should evaluate both sides of an if-statement" $ do
|
|
|
|
res <- callGraphPythonProject ["test/fixtures/python/graphing/conditional/conditional.py"]
|
2018-07-18 17:53:46 +03:00
|
|
|
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))
|
2018-07-16 18:36:17 +03:00
|
|
|
|
|
|
|
it "should continue even when a type error is encountered" $ do
|
|
|
|
res <- callGraphPythonProject ["test/fixtures/python/graphing/typeerror/typeerror.py"]
|
2018-07-18 17:53:46 +03:00
|
|
|
res `needs` Variable "lup" "typeerror.py" (Span (Pos 5 1) (Pos 5 4))
|
2018-07-16 18:36:17 +03:00
|
|
|
|
|
|
|
it "should continue when an unbound variable is encountered" $ do
|
|
|
|
res <- callGraphPythonProject ["test/fixtures/python/graphing/unbound/unbound.py"]
|
2018-07-18 17:53:46 +03:00
|
|
|
res `needs` Variable "lucretia" "unbound.py" (Span (Pos 5 1) (Pos 5 9))
|