1
1
mirror of https://github.com/github/semantic.git synced 2024-12-01 00:33:59 +03:00

Remove the CHECK-JQ directive.

This commit is contained in:
Rob Rix 2019-12-20 11:43:15 -05:00
parent bfec95a992
commit f78d90aaae
No known key found for this signature in database
GPG Key ID: F188A01508EA1CF7
7 changed files with 6 additions and 83 deletions

View File

@ -4,12 +4,10 @@
module Directive ( Directive (..) module Directive ( Directive (..)
, readDirectivesFromFile , readDirectivesFromFile
, describe , describe
, toProcess
) where ) where
import Analysis.Concrete (Concrete (..)) import Analysis.Concrete (Concrete (..))
import Control.Algebra import Control.Algebra
import Control.Applicative
import Control.Monad import Control.Monad
import Control.Monad.Trans.Resource (ResourceT, runResourceT) import Control.Monad.Trans.Resource (ResourceT, runResourceT)
import Core.Core (Core) import Core.Core (Core)
@ -27,7 +25,6 @@ import qualified Streaming.Prelude as Stream
import Syntax.Term (Term) import Syntax.Term (Term)
import qualified System.Path as Path import qualified System.Path as Path
import qualified System.Path.PartClass as Path.Class import qualified System.Path.PartClass as Path.Class
import System.Process
import qualified Text.Parser.Token.Style as Style import qualified Text.Parser.Token.Style as Style
import Text.Trifecta (CharParsing, TokenParsing (..)) import Text.Trifecta (CharParsing, TokenParsing (..))
import qualified Text.Trifecta as Trifecta import qualified Text.Trifecta as Trifecta
@ -39,13 +36,11 @@ describe to the test suite how to query the results of a given test
case. A directive that looks like this: case. A directive that looks like this:
@ @
# CHECK-JQ: has("mach") # CHECK-RESULT: key: value
@ @
would, after converting the contents of the file to a Core expression, would test that the value for @key@ in the result evaluates to the given
dump that expression to JSON and pipe said JSON to @jq -e concrete value.
'has("mach")@, which will return an error code unless the passed JSON
is a hash containing the @"mach"@ key.
This syntax was inspired by LLVM's This syntax was inspired by LLVM's
[FileCheck](https://llvm.org/docs/CommandGuide/FileCheck.html). This [FileCheck](https://llvm.org/docs/CommandGuide/FileCheck.html). This
@ -56,8 +51,7 @@ significantly and has been a successful strategy for the LLVM and Rust
projects. projects.
-} -}
data Directive = JQ ByteString -- | @# CHECK-JQ: expr@ data Directive = Tree (Term Core Name) -- | @# CHECK-TREE: core@
| Tree (Term Core Name) -- | @# CHECK-TREE: core@
| Result Text (Concrete (Term (Core.Ann Source.Span :+: Core))) -- | @# CHECK-RESULT key: expected | Result Text (Concrete (Term (Core.Ann Source.Span :+: Core))) -- | @# CHECK-RESULT key: expected
| Fails -- | @# CHECK-FAILS@ fails unless translation fails. | Fails -- | @# CHECK-FAILS@ fails unless translation fails.
deriving (Eq, Show) deriving (Eq, Show)
@ -81,17 +75,11 @@ readDirectivesFromFile
describe :: Directive -> String describe :: Directive -> String
describe Fails = "<expect failure>" describe Fails = "<expect failure>"
describe (Tree t) = Core.Pretty.showCore t describe (Tree t) = Core.Pretty.showCore t
describe (JQ b) = ByteString.unpack b
describe (Result t e) = T.unpack t <> ": " <> show e describe (Result t e) = T.unpack t <> ": " <> show e
fails :: CharParsing m => m Directive fails :: CharParsing m => m Directive
fails = Fails <$ Trifecta.string "# CHECK-FAILS" fails = Fails <$ Trifecta.string "# CHECK-FAILS"
jq :: (Monad m, CharParsing m) => m Directive
jq = do
void $ Trifecta.string "# CHECK-JQ: "
JQ . ByteString.pack <$> many (Trifecta.noneOf "\n")
tree :: (Monad m, TokenParsing m) => m Directive tree :: (Monad m, TokenParsing m) => m Directive
tree = do tree = do
void $ Trifecta.string "# CHECK-TREE: " void $ Trifecta.string "# CHECK-TREE: "
@ -113,12 +101,8 @@ concrete = Trifecta.choice
] ]
directive :: (Monad m, TokenParsing m) => m Directive directive :: (Monad m, TokenParsing m) => m Directive
directive = Trifecta.choice [ fails, result, jq, tree ] directive = Trifecta.choice [ fails, result, tree ]
parseDirective :: ByteString -> Either String Directive parseDirective :: ByteString -> Either String Directive
parseDirective = Trifecta.foldResult (Left . show) Right parseDirective = Trifecta.foldResult (Left . show) Right
. Trifecta.parseByteString (directive <* Trifecta.eof) mempty . Trifecta.parseByteString (directive <* Trifecta.eof) mempty
toProcess :: Directive -> CreateProcess
toProcess (JQ d) = proc "jq" ["-e", ByteString.unpack d]
toProcess x = error ("can't call toProcess on " <> show x)

View File

@ -8,11 +8,9 @@ module Instances () where
-- we should keep track of them in a dedicated file. -- we should keep track of them in a dedicated file.
import Analysis.File import Analysis.File
import Analysis.ScopeGraph
import Core.Name (Name (..)) import Core.Name (Name (..))
import Data.Aeson import Data.Aeson
import qualified Data.Map as Map import Data.Text (pack)
import Data.Text (Text, pack)
import qualified System.Path as Path import qualified System.Path as Path
deriving newtype instance ToJSON Name deriving newtype instance ToJSON Name
@ -27,21 +25,3 @@ instance ToJSON a => ToJSON (File a) where
instance ToJSON Path.AbsRelFile where instance ToJSON Path.AbsRelFile where
toJSON p = toJSON (pack (Path.toString p)) toJSON p = toJSON (pack (Path.toString p))
instance ToJSON Ref where
toJSON (Ref path span) = object
[ "kind" .= ("ref" :: Text)
, "path" .= path
, "span" .= span
]
instance ToJSON Decl where
toJSON Decl{declSymbol, declPath, declSpan} = object
[ "kind" .= ("decl" :: Text)
, "symbol" .= declSymbol
, "path" .= declPath
, "span" .= declSpan
]
instance ToJSON ScopeGraph where
toJSON (ScopeGraph sc) = toJSON . Map.mapKeys declSymbol $ sc

View File

@ -5,23 +5,17 @@ module Main (main) where
import Analysis.Concrete (Concrete) import Analysis.Concrete (Concrete)
import qualified Analysis.Concrete as Concrete import qualified Analysis.Concrete as Concrete
import Analysis.File import Analysis.File
import Analysis.ScopeGraph
import Control.Algebra import Control.Algebra
import Control.Carrier.Fail.Either import Control.Carrier.Fail.Either
import Control.Carrier.Reader import Control.Carrier.Reader
import Control.Monad hiding (fail) import Control.Monad hiding (fail)
import Control.Monad.Catch
import Control.Monad.IO.Class import Control.Monad.IO.Class
import Core.Core import Core.Core
import qualified Core.Eval as Eval import qualified Core.Eval as Eval
import Core.Name import Core.Name
import qualified Core.Parser import qualified Core.Parser
import Core.Pretty import Core.Pretty
import qualified Data.Aeson as Aeson
import qualified Data.Aeson.Encode.Pretty as Aeson
import qualified Data.ByteString.Char8 as ByteString import qualified Data.ByteString.Char8 as ByteString
import qualified Data.ByteString.Lazy.Char8 as ByteString.Lazy
import qualified Data.ByteString.Streaming.Char8 as ByteStream
import Data.Foldable import Data.Foldable
import Data.Function import Data.Function
import qualified Data.IntMap as IntMap import qualified Data.IntMap as IntMap
@ -34,8 +28,6 @@ import qualified Language.Python.Core as Py
import Language.Python.Failure import Language.Python.Failure
import Prelude hiding (fail) import Prelude hiding (fail)
import Source.Span import Source.Span
import Streaming
import qualified Streaming.Process
import Syntax.Term import Syntax.Term
import Syntax.Var (closed) import Syntax.Var (closed)
import System.Directory import System.Directory
@ -43,7 +35,6 @@ import System.Exit
import System.Path ((</>)) import System.Path ((</>))
import qualified System.Path as Path import qualified System.Path as Path
import qualified System.Path.Directory as Path import qualified System.Path.Directory as Path
import Text.Show.Pretty (ppShow)
import qualified Text.Trifecta as Trifecta import qualified Text.Trifecta as Trifecta
import qualified TreeSitter.Python as TSP import qualified TreeSitter.Python as TSP
import qualified TreeSitter.Unmarshal as TS import qualified TreeSitter.Unmarshal as TS
@ -62,32 +53,6 @@ parsePrelude = do
Right r -> pure r Right r -> pure r
Left s -> HUnit.assertFailure ("Couldn't parse prelude: " <> s) Left s -> HUnit.assertFailure ("Couldn't parse prelude: " <> s)
assertJQExpressionSucceeds :: Show a => Directive.Directive -> a -> Term (Ann Span :+: Core) Name -> HUnit.Assertion
assertJQExpressionSucceeds directive tree core = do
prelude <- parsePrelude
let allTogether = (named' "__semantic_prelude" :<- prelude) >>>= core
bod <- case scopeGraph Eval.eval [File (Path.absRel "<interactive>") (Span (Pos 1 1) (Pos 1 1)) allTogether] of
(heap, [File _ _ (Right result)]) -> pure $ Aeson.object
[ "scope" Aeson..= heap
, "heap" Aeson..= result
]
other -> HUnit.assertFailure ("Couldn't run scope dumping mechanism: " <> showCore (stripAnnotations allTogether) <> "\n" <> show other)
let ignore = ByteStream.effects . hoist ByteStream.effects
sgJSON = ByteStream.fromLazy $ Aeson.encode bod
jqPipeline = Streaming.Process.withStreamingProcess (Directive.toProcess directive) sgJSON ignore
errorMsg = "jq(1) returned non-zero exit code"
dirMsg = "jq expression: " <> show directive
jsonMsg = "JSON value: " <> ByteString.Lazy.unpack (Aeson.encodePretty bod)
astMsg = "AST (pretty): " <> ppShow tree
treeMsg = "Core expr (pretty): " <> showCore (stripAnnotations core)
treeMsg' = "Core expr (Show): " <> ppShow (stripAnnotations core)
catch @_ @Streaming.Process.ProcessExitedUnsuccessfully jqPipeline $ \err -> do
HUnit.assertFailure (unlines [errorMsg, dirMsg, jsonMsg, astMsg, treeMsg, treeMsg', show err])
-- handles CHECK-RESULT directives -- handles CHECK-RESULT directives
assertEvaluatesTo :: Term (Ann Span :+: Core) Name -> Text -> Concrete (Term (Ann Span :+: Core)) -> HUnit.Assertion assertEvaluatesTo :: Term (Ann Span :+: Core) Name -> Text -> Concrete (Term (Ann Span :+: Core)) -> HUnit.Assertion
assertEvaluatesTo core k val = do assertEvaluatesTo core k val = do
@ -137,7 +102,6 @@ checkPythonFile fp = HUnit.testCaseSteps (Path.toString fp) $ \step -> withFroze
(Right (Left err), _) -> HUnit.assertFailure ("Compilation failed: " <> err) (Right (Left err), _) -> HUnit.assertFailure ("Compilation failed: " <> err)
(Right (Right _), Directive.Fails) -> HUnit.assertFailure "Expected translation to fail" (Right (Right _), Directive.Fails) -> HUnit.assertFailure "Expected translation to fail"
(Right (Right item), Directive.Result k v) -> assertEvaluatesTo item k v (Right (Right item), Directive.Result k v) -> assertEvaluatesTo item k v
(Right (Right item), Directive.JQ _) -> assertJQExpressionSucceeds directive result item
(Right (Right item), Directive.Tree t) -> assertTreeEqual (stripAnnotations item) t (Right (Right item), Directive.Tree t) -> assertTreeEqual (stripAnnotations item) t
milestoneFixtures :: IO Tasty.TestTree milestoneFixtures :: IO Tasty.TestTree

View File

@ -1 +0,0 @@
# CHECK-JQ: .scope | has("__semantic_prelude") # prelude should be present

View File

@ -1,2 +1 @@
# CHECK-JQ: .scope | has("__semantic_prelude")
pass pass

View File

@ -1,4 +1,3 @@
# CHECK-JQ: .scope | has("hello") and has("goodbye")
# CHECK-TREE: { hello <- #unit; goodbye <- #unit; #record { hello: hello, goodbye: goodbye }} # CHECK-TREE: { hello <- #unit; goodbye <- #unit; #record { hello: hello, goodbye: goodbye }}
# CHECK-RESULT hello: #unit # CHECK-RESULT hello: #unit
hello = () hello = ()

View File

@ -1,5 +1,3 @@
# CHECK-JQ: .scope.zilch[0].b[0].span == { start: [8, 8], end: [ 8, 16 ] }
# CHECK-JQ: .scope.result[0].a[0].span == { start: [5, 8], end: [ 5, 16 ] }
def const(a, b): def const(a, b):
def result(): def result():