2019-02-01 01:13:26 +03:00
|
|
|
{-# LANGUAGE TypeApplications #-}
|
2018-09-18 01:49:18 +03:00
|
|
|
module Main (main) where
|
|
|
|
|
2019-02-01 01:13:26 +03:00
|
|
|
import Control.Effect
|
2018-09-18 01:49:18 +03:00
|
|
|
import Control.Exception (displayException)
|
2018-09-18 23:00:31 +03:00
|
|
|
import Control.Monad
|
2019-02-01 01:13:26 +03:00
|
|
|
import Control.Monad.IO.Class
|
2018-09-18 01:49:18 +03:00
|
|
|
import qualified Data.ByteString as B
|
|
|
|
import Data.ByteString.Builder
|
|
|
|
import qualified Data.ByteString.Char8 as BC
|
|
|
|
import Data.Either
|
2018-10-23 22:28:21 +03:00
|
|
|
import Data.File (file)
|
2018-09-18 23:00:31 +03:00
|
|
|
import Data.Foldable
|
2018-09-18 01:49:18 +03:00
|
|
|
import Data.List
|
2018-09-18 23:00:31 +03:00
|
|
|
import Data.Maybe
|
|
|
|
import Data.Quieterm
|
|
|
|
import Data.Typeable (cast)
|
2018-09-18 01:49:18 +03:00
|
|
|
import Data.Void
|
2018-09-18 23:00:31 +03:00
|
|
|
import Parsing.Parser
|
2019-02-20 22:23:18 +03:00
|
|
|
import Semantic.Api (TermOutputFormat (..), parseTermBuilder)
|
2018-09-18 01:49:18 +03:00
|
|
|
import Semantic.Config (Config (..), Options (..), defaultOptions)
|
|
|
|
import qualified Semantic.IO as IO
|
|
|
|
import Semantic.Task
|
2018-10-23 22:28:21 +03:00
|
|
|
import Semantic.Task.Files
|
2018-09-18 23:00:31 +03:00
|
|
|
import System.Directory
|
2018-09-18 01:49:18 +03:00
|
|
|
import System.Exit (die)
|
|
|
|
import System.FilePath.Glob
|
|
|
|
import System.FilePath.Posix
|
|
|
|
import System.Process
|
|
|
|
import Test.Hspec
|
|
|
|
|
|
|
|
|
|
|
|
main :: IO ()
|
|
|
|
main = withOptions opts $ \ config logger statter -> hspec . parallel $ do
|
2019-02-20 22:23:18 +03:00
|
|
|
let args = TaskSession config "-" False logger statter
|
2018-09-18 01:49:18 +03:00
|
|
|
|
|
|
|
runIO setupExampleRepos
|
|
|
|
|
2018-09-18 02:46:45 +03:00
|
|
|
for_ languages $ \ lang@LanguageExample{..} -> do
|
|
|
|
let tsDir = languagesDir </> languageName </> ("vendor/tree-sitter-" <> languageName)
|
|
|
|
parallel . describe languageName $ parseExamples args lang tsDir
|
2018-09-18 01:49:18 +03:00
|
|
|
|
|
|
|
where
|
2019-02-11 22:27:22 +03:00
|
|
|
parseExamples session LanguageExample{..} tsDir = do
|
2018-09-18 02:46:45 +03:00
|
|
|
knownFailures <- runIO $ knownFailuresForPath tsDir languageKnownFailuresTxt
|
|
|
|
files <- runIO $ globDir1 (compile ("**/*" <> languageExtension)) (tsDir </> languageExampleDir)
|
2018-09-18 01:49:18 +03:00
|
|
|
for_ files $ \file -> it file $ do
|
2019-02-11 22:27:22 +03:00
|
|
|
res <- runTask session (parseFilePath file)
|
2018-09-18 23:00:31 +03:00
|
|
|
case res of
|
|
|
|
Left (SomeException e) -> case cast e of
|
|
|
|
-- We have a number of known assignment timeouts, consider these pending specs instead of failing the build.
|
2018-11-14 01:59:20 +03:00
|
|
|
Just AssignmentTimedOut -> pendingWith $ show (displayException e)
|
|
|
|
Just ParserTimedOut -> pendingWith $ show (displayException e)
|
2018-09-18 23:00:31 +03:00
|
|
|
-- Other exceptions are true failures
|
|
|
|
_ -> expectationFailure (show (displayException e))
|
|
|
|
_ -> if file `elem` knownFailures
|
|
|
|
then pendingWith $ "Known parse failures " <> show (const "Assignment: OK" <$> res)
|
|
|
|
else res `shouldSatisfy` isRight
|
2018-09-18 01:49:18 +03:00
|
|
|
|
2018-09-18 18:36:40 +03:00
|
|
|
setupExampleRepos = readProcess "script/clone-example-repos" mempty mempty >>= print
|
2018-09-18 01:49:18 +03:00
|
|
|
opts = defaultOptions { optionsFailOnWarning = True, optionsLogLevel = Nothing }
|
|
|
|
|
2018-09-18 02:46:45 +03:00
|
|
|
knownFailuresForPath :: FilePath -> Maybe FilePath -> IO [FilePath]
|
|
|
|
knownFailuresForPath _ Nothing = pure []
|
|
|
|
knownFailuresForPath tsDir (Just path) = do
|
|
|
|
known <- BC.lines <$> B.readFile (tsDir </> path)
|
2018-09-18 23:00:31 +03:00
|
|
|
pure $ (tsDir </>) . BC.unpack <$> stripComments known
|
|
|
|
where stripComments = filter (\line -> not (BC.null line) && BC.head line == '#')
|
2018-09-18 01:49:18 +03:00
|
|
|
|
2018-09-18 02:46:45 +03:00
|
|
|
data LanguageExample
|
|
|
|
= LanguageExample
|
|
|
|
{ languageName :: FilePath
|
|
|
|
, languageExtension :: FilePath
|
|
|
|
, languageExampleDir :: FilePath
|
|
|
|
, languageKnownFailuresTxt :: Maybe FilePath
|
|
|
|
} deriving (Eq, Show)
|
|
|
|
|
|
|
|
le :: FilePath -> FilePath -> FilePath -> Maybe FilePath -> LanguageExample
|
|
|
|
le = LanguageExample
|
2018-09-18 01:49:18 +03:00
|
|
|
|
2018-09-18 02:46:45 +03:00
|
|
|
languages :: [LanguageExample]
|
|
|
|
languages =
|
|
|
|
[ le "python" ".py" "examples" (Just "script/known_failures.txt")
|
2018-12-12 19:14:16 +03:00
|
|
|
, le "ruby" ".rb" "examples" (Just "script/known_failures.txt")
|
2018-09-18 23:00:31 +03:00
|
|
|
, le "typescript" ".ts" "examples" (Just "script/known_failures.txt")
|
2018-09-19 01:32:56 +03:00
|
|
|
, le "typescript" ".js" "examples" Nothing -- parse JavaScript with TypeScript parser.
|
2019-01-31 18:59:37 +03:00
|
|
|
, le "go" ".go" "examples" (Just "script/known-failures.txt")
|
2018-09-18 23:00:31 +03:00
|
|
|
|
|
|
|
-- TODO: Java assignment errors need to be investigated
|
2018-09-18 02:46:45 +03:00
|
|
|
-- , le "java" ".java" "examples/guava" (Just "script/known_failures_guava.txt")
|
|
|
|
-- , le "java" ".java" "examples/elasticsearch" (Just "script/known_failures_elasticsearch.txt")
|
|
|
|
-- , le "java" ".java" "examples/RxJava" (Just "script/known_failures_RxJava.txt")
|
2018-09-18 23:00:31 +03:00
|
|
|
|
|
|
|
-- TODO: Haskell assignment errors need to be investigated
|
2018-09-18 02:46:45 +03:00
|
|
|
-- , le "haskell" ".hs" "examples/effects" (Just "script/known-failures-effects.txt")
|
|
|
|
-- , le "haskell" ".hs" "examples/postgrest" (Just "script/known-failures-postgrest.txt")
|
|
|
|
-- , le "haskell" ".hs" "examples/ivory" (Just "script/known-failures-ivory.txt")
|
2018-09-18 01:49:18 +03:00
|
|
|
|
|
|
|
-- , ("php", ".php") -- TODO: No parse-examples in tree-sitter yet
|
|
|
|
]
|
|
|
|
|
2019-02-01 01:13:26 +03:00
|
|
|
parseFilePath :: (Member (Error SomeException) sig, Member Distribute sig, Member Task sig, Member Files sig, Carrier sig m, MonadIO m) => FilePath -> m Bool
|
|
|
|
parseFilePath path = readBlob (file path) >>= parseTermBuilder @[] TermShow . pure >>= const (pure True)
|
2018-09-18 01:49:18 +03:00
|
|
|
|
|
|
|
languagesDir :: FilePath
|
|
|
|
languagesDir = "vendor/haskell-tree-sitter/languages"
|