diff --git a/lib/Peast/Renderer.php b/lib/Peast/Renderer.php index 536c4074..44674e5d 100644 --- a/lib/Peast/Renderer.php +++ b/lib/Peast/Renderer.php @@ -195,14 +195,16 @@ protected function renderNode(Syntax\Node\Node $node) ")"; break; case "CatchClause": - $code .= "catch" . - $this->renderOpts->sao . - "(" . - $this->renderOpts->sirb . - $this->renderNode($node->getParam()) . - $this->renderOpts->sirb . - ")" . - $this->renderStatementBlock($node->getBody(), true); + $code .= "catch"; + if ($params = $node->getParam()) { + $code .= $this->renderOpts->sao . + "(" . + $this->renderOpts->sirb . + $this->renderNode($params) . + $this->renderOpts->sirb . + ")"; + } + $code .= $this->renderStatementBlock($node->getBody(), true); break; case "ClassExpression": case "ClassDeclaration": diff --git a/lib/Peast/Syntax/ES2019/Parser.php b/lib/Peast/Syntax/ES2019/Parser.php index 21aa6c2e..7f038390 100644 --- a/lib/Peast/Syntax/ES2019/Parser.php +++ b/lib/Peast/Syntax/ES2019/Parser.php @@ -18,4 +18,33 @@ */ class Parser extends \Peast\Syntax\ES2018\Parser { + /** + * Parses the catch block of a try-catch statement + * + * @return Node\CatchClause|null + */ + protected function parseCatch() + { + if ($token = $this->scanner->consume("catch")) { + + $node = $this->createNode("CatchClause", $token); + + if ($this->scanner->consume("(")) { + if (!($param = $this->parseCatchParameter()) || + !$this->scanner->consume(")")) { + return $this->error(); + } + $node->setParam($param); + } + + if (!($body = $this->parseBlock())) { + return $this->error(); + } + + $node->setBody($body); + + return $this->completeNode($node); + } + return null; + } } \ No newline at end of file diff --git a/lib/Peast/Syntax/Node/CatchClause.php b/lib/Peast/Syntax/Node/CatchClause.php index 7e345048..550d42ba 100644 --- a/lib/Peast/Syntax/Node/CatchClause.php +++ b/lib/Peast/Syntax/Node/CatchClause.php @@ -57,8 +57,9 @@ public function getParam() * * @return $this */ - public function setParam(Pattern $param) + public function setParam($param) { + $this->assertType($param, "Pattern", true); $this->param = $param; return $this; } diff --git a/test/Peast/Syntax/ES2019/ES2019Test.php b/test/Peast/Syntax/ES2019/ES2019Test.php index 317f30e4..227cbc5e 100644 --- a/test/Peast/Syntax/ES2019/ES2019Test.php +++ b/test/Peast/Syntax/ES2019/ES2019Test.php @@ -10,6 +10,17 @@ protected function getTestVersions() return array("ES2015", "ES2016", "ES2017", "ES2018", "ES2019"); } + protected function getExcludedTests() + { + $excluded = parent::getExcludedTests(); + return array_merge( + $excluded, + array( + "TryStatement/InvalidCatch2.js" + ) + ); + } + public function stringCharsProvider() { $chars = parent::stringCharsProvider(); diff --git a/test/Peast/Syntax/ES2019/files/TryStatement/CatchNoParam.Render.txt b/test/Peast/Syntax/ES2019/files/TryStatement/CatchNoParam.Render.txt new file mode 100644 index 00000000..5753f6cb --- /dev/null +++ b/test/Peast/Syntax/ES2019/files/TryStatement/CatchNoParam.Render.txt @@ -0,0 +1,15 @@ +try { + fn(); +} catch { + console.log("error"); +} +/**************************************************/ +try{fn();}catch{console.log("error");} +/**************************************************/ +try +{ + fn( ); +} catch +{ + console.log( "error" ); +} \ No newline at end of file diff --git a/test/Peast/Syntax/ES2019/files/TryStatement/CatchNoParam.Tokens.json b/test/Peast/Syntax/ES2019/files/TryStatement/CatchNoParam.Tokens.json new file mode 100644 index 00000000..c97c9ba6 --- /dev/null +++ b/test/Peast/Syntax/ES2019/files/TryStatement/CatchNoParam.Tokens.json @@ -0,0 +1,308 @@ +[ + { + "type": "Keyword", + "value": "try", + "range": [ + 0, + 3 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + { + "type": "Punctuator", + "value": "{", + "range": [ + 4, + 5 + ], + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 5 + } + } + }, + { + "type": "Identifier", + "value": "fn", + "range": [ + 7, + 9 + ], + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 3 + } + } + }, + { + "type": "Punctuator", + "value": "(", + "range": [ + 9, + 10 + ], + "loc": { + "start": { + "line": 2, + "column": 3 + }, + "end": { + "line": 2, + "column": 4 + } + } + }, + { + "type": "Punctuator", + "value": ")", + "range": [ + 10, + 11 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 5 + } + } + }, + { + "type": "Punctuator", + "value": ";", + "range": [ + 11, + 12 + ], + "loc": { + "start": { + "line": 2, + "column": 5 + }, + "end": { + "line": 2, + "column": 6 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 13, + 14 + ], + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + } + }, + { + "type": "Keyword", + "value": "catch", + "range": [ + 15, + 20 + ], + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 7 + } + } + }, + { + "type": "Punctuator", + "value": "{", + "range": [ + 21, + 22 + ], + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 9 + } + } + }, + { + "type": "Identifier", + "value": "console", + "range": [ + 24, + 31 + ], + "loc": { + "start": { + "line": 4, + "column": 1 + }, + "end": { + "line": 4, + "column": 8 + } + } + }, + { + "type": "Punctuator", + "value": ".", + "range": [ + 31, + 32 + ], + "loc": { + "start": { + "line": 4, + "column": 8 + }, + "end": { + "line": 4, + "column": 9 + } + } + }, + { + "type": "Identifier", + "value": "log", + "range": [ + 32, + 35 + ], + "loc": { + "start": { + "line": 4, + "column": 9 + }, + "end": { + "line": 4, + "column": 12 + } + } + }, + { + "type": "Punctuator", + "value": "(", + "range": [ + 35, + 36 + ], + "loc": { + "start": { + "line": 4, + "column": 12 + }, + "end": { + "line": 4, + "column": 13 + } + } + }, + { + "type": "String", + "value": "\"error\"", + "range": [ + 36, + 43 + ], + "loc": { + "start": { + "line": 4, + "column": 13 + }, + "end": { + "line": 4, + "column": 20 + } + } + }, + { + "type": "Punctuator", + "value": ")", + "range": [ + 43, + 44 + ], + "loc": { + "start": { + "line": 4, + "column": 20 + }, + "end": { + "line": 4, + "column": 21 + } + } + }, + { + "type": "Punctuator", + "value": ";", + "range": [ + 44, + 45 + ], + "loc": { + "start": { + "line": 4, + "column": 21 + }, + "end": { + "line": 4, + "column": 22 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 46, + 47 + ], + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + } + } +] \ No newline at end of file diff --git a/test/Peast/Syntax/ES2019/files/TryStatement/CatchNoParam.js b/test/Peast/Syntax/ES2019/files/TryStatement/CatchNoParam.js new file mode 100644 index 00000000..9a6af6b1 --- /dev/null +++ b/test/Peast/Syntax/ES2019/files/TryStatement/CatchNoParam.js @@ -0,0 +1,5 @@ +try { + fn(); +} catch { + console.log("error"); +} \ No newline at end of file diff --git a/test/Peast/Syntax/ES2019/files/TryStatement/CatchNoParam.json b/test/Peast/Syntax/ES2019/files/TryStatement/CatchNoParam.json new file mode 100644 index 00000000..168bf5fa --- /dev/null +++ b/test/Peast/Syntax/ES2019/files/TryStatement/CatchNoParam.json @@ -0,0 +1,256 @@ +{ + "type": "Program", + "body": [ + { + "type": "TryStatement", + "block": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "fn", + "range": [ + 7, + 9 + ], + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 3 + } + } + }, + "arguments": [], + "range": [ + 7, + 11 + ], + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 5 + } + } + }, + "range": [ + 7, + 12 + ], + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 6 + } + } + } + ], + "range": [ + 4, + 14 + ], + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 3, + "column": 1 + } + } + }, + "handler": { + "type": "CatchClause", + "param": null, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "computed": false, + "object": { + "type": "Identifier", + "name": "console", + "range": [ + 24, + 31 + ], + "loc": { + "start": { + "line": 4, + "column": 1 + }, + "end": { + "line": 4, + "column": 8 + } + } + }, + "property": { + "type": "Identifier", + "name": "log", + "range": [ + 32, + 35 + ], + "loc": { + "start": { + "line": 4, + "column": 9 + }, + "end": { + "line": 4, + "column": 12 + } + } + }, + "range": [ + 24, + 35 + ], + "loc": { + "start": { + "line": 4, + "column": 1 + }, + "end": { + "line": 4, + "column": 12 + } + } + }, + "arguments": [ + { + "type": "Literal", + "value": "error", + "raw": "\"error\"", + "range": [ + 36, + 43 + ], + "loc": { + "start": { + "line": 4, + "column": 13 + }, + "end": { + "line": 4, + "column": 20 + } + } + } + ], + "range": [ + 24, + 44 + ], + "loc": { + "start": { + "line": 4, + "column": 1 + }, + "end": { + "line": 4, + "column": 21 + } + } + }, + "range": [ + 24, + 45 + ], + "loc": { + "start": { + "line": 4, + "column": 1 + }, + "end": { + "line": 4, + "column": 22 + } + } + } + ], + "range": [ + 21, + 47 + ], + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 5, + "column": 1 + } + } + }, + "range": [ + 15, + 47 + ], + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 5, + "column": 1 + } + } + }, + "finalizer": null, + "range": [ + 0, + 47 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + } + } + ], + "sourceType": "script", + "range": [ + 0, + 47 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + } +} \ No newline at end of file