From 968da4eff913c15b8fd6f65ed19545609cb79d76 Mon Sep 17 00:00:00 2001 From: Chris Seufert Date: Mon, 22 Mar 2021 22:05:47 +1100 Subject: [PATCH 1/2] Added support for union types in function parameters & function return types --- src/parser/expr.js | 2 +- src/parser/function.js | 22 +- test/snapshot/__snapshots__/acid.test.js.snap | 272 +++++----- .../__snapshots__/arrowfunc.test.js.snap | 12 +- .../snapshot/__snapshots__/class.test.js.snap | 24 +- .../__snapshots__/classreference.test.js.snap | 24 +- .../__snapshots__/function.test.js.snap | 317 +++++++++--- .../__snapshots__/location.test.js.snap | 34 +- .../parentreference.test.js.snap | 40 +- .../__snapshots__/selfreference.test.js.snap | 40 +- .../__snapshots__/typereference.test.js.snap | 480 ++++++++++-------- test/snapshot/function.test.js | 18 + 12 files changed, 818 insertions(+), 467 deletions(-) diff --git a/src/parser/expr.js b/src/parser/expr.js index ec8e46c14..6312f5887 100644 --- a/src/parser/expr.js +++ b/src/parser/expr.js @@ -588,7 +588,7 @@ module.exports = { nullable = true; this.next(); } - returnType = this.read_type(); + returnType = this.read_types(); } if (this.expect(this.tok.T_DOUBLE_ARROW)) this.next(); const body = this.read_expr(); diff --git a/src/parser/function.js b/src/parser/function.js index a9f79b75e..dcb83522d 100644 --- a/src/parser/function.js +++ b/src/parser/function.js @@ -128,7 +128,7 @@ module.exports = { nullable = true; this.next(); } - returnType = this.read_type(); + returnType = this.read_types(); } if (type === 1) { // closure @@ -202,14 +202,14 @@ module.exports = { const node = this.node("parameter"); let parameterName = null; let value = null; - let type = null; + let types = null; let nullable = false; if (this.token === "?") { this.next(); nullable = true; } - type = this.read_type(); - if (nullable && !type) { + types = this.read_types(); + if (nullable && !types) { this.raiseError( "Expecting a type definition combined with nullable operator" ); @@ -225,7 +225,19 @@ module.exports = { if (this.token == "=") { value = this.next().read_expr(); } - return node(parameterName, type, value, isRef, isVariadic, nullable); + return node(parameterName, types, value, isRef, isVariadic, nullable); + }, + read_types() { + const types = []; + let type = this.read_type(); + if (!type) return null; + types.push(type); + while (this.token === "|") { + this.next(); + type = this.read_type(); + types.push(type); + } + return types.length === 0 ? null : types; }, /** * Reads a list of arguments diff --git a/test/snapshot/__snapshots__/acid.test.js.snap b/test/snapshot/__snapshots__/acid.test.js.snap index 8f985d852..881eb710a 100644 --- a/test/snapshot/__snapshots__/acid.test.js.snap +++ b/test/snapshot/__snapshots__/acid.test.js.snap @@ -1739,24 +1739,26 @@ Program { "name": "Am_I_Uggly", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "loc": Location { - "end": Position { - "column": 39, - "line": 50, - "offset": 1014, - }, - "source": "bool", - "start": Position { - "column": 35, - "line": 50, - "offset": 1010, + "type": Array [ + TypeReference { + "kind": "typereference", + "loc": Location { + "end": Position { + "column": 39, + "line": 50, + "offset": 1014, + }, + "source": "bool", + "start": Position { + "column": 35, + "line": 50, + "offset": 1010, + }, }, + "name": "bool", + "raw": "bool", }, - "name": "bool", - "raw": "bool", - }, + ], "visibility": "public", }, Method { @@ -1798,24 +1800,26 @@ Program { "name": "broken", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "loc": Location { - "end": Position { - "column": 38, - "line": 51, - "offset": 1054, - }, - "source": "bool", - "start": Position { - "column": 34, - "line": 51, - "offset": 1050, + "type": Array [ + TypeReference { + "kind": "typereference", + "loc": Location { + "end": Position { + "column": 38, + "line": 51, + "offset": 1054, + }, + "source": "bool", + "start": Position { + "column": 34, + "line": 51, + "offset": 1050, + }, }, + "name": "bool", + "raw": "bool", }, - "name": "bool", - "raw": "bool", - }, + ], "visibility": "protected", }, Method { @@ -1857,24 +1861,26 @@ Program { "name": "isWhiteSnowAlive", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "loc": Location { - "end": Position { - "column": 55, - "line": 52, - "offset": 1111, - }, - "source": "bool", - "start": Position { - "column": 51, - "line": 52, - "offset": 1107, + "type": Array [ + TypeReference { + "kind": "typereference", + "loc": Location { + "end": Position { + "column": 55, + "line": 52, + "offset": 1111, + }, + "source": "bool", + "start": Position { + "column": 51, + "line": 52, + "offset": 1107, + }, }, + "name": "bool", + "raw": "bool", }, - "name": "bool", - "raw": "bool", - }, + ], "visibility": "protected", }, ], @@ -2185,24 +2191,26 @@ Program { "name": "arrow", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "loc": Location { - "end": Position { - "column": 29, - "line": 61, - "offset": 1238, - }, - "source": "bool", - "start": Position { - "column": 25, - "line": 61, - "offset": 1234, + "type": Array [ + TypeReference { + "kind": "typereference", + "loc": Location { + "end": Position { + "column": 29, + "line": 61, + "offset": 1238, + }, + "source": "bool", + "start": Position { + "column": 25, + "line": 61, + "offset": 1234, + }, }, + "name": "bool", + "raw": "bool", }, - "name": "bool", - "raw": "bool", - }, + ], "value": Boolean { "kind": "boolean", "loc": Location { @@ -2842,24 +2850,26 @@ Program { "name": "draw", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "loc": Location { - "end": Position { - "column": 54, - "line": 61, - "offset": 1263, - }, - "source": "string", - "start": Position { - "column": 48, - "line": 61, - "offset": 1257, + "type": Array [ + TypeReference { + "kind": "typereference", + "loc": Location { + "end": Position { + "column": 54, + "line": 61, + "offset": 1263, + }, + "source": "string", + "start": Position { + "column": 48, + "line": 61, + "offset": 1257, + }, }, + "name": "string", + "raw": "string", }, - "name": "string", - "raw": "string", - }, + ], "visibility": "public", }, Method { @@ -4013,24 +4023,26 @@ next: "name": "sparta", }, "nullable": true, - "type": TypeReference { - "kind": "typereference", - "loc": Location { - "end": Position { - "column": 26, - "line": 79, - "offset": 1617, - }, - "source": "int", - "start": Position { - "column": 23, - "line": 79, - "offset": 1614, + "type": Array [ + TypeReference { + "kind": "typereference", + "loc": Location { + "end": Position { + "column": 26, + "line": 79, + "offset": 1617, + }, + "source": "int", + "start": Position { + "column": 23, + "line": 79, + "offset": 1614, + }, }, + "name": "int", + "raw": "int", }, - "name": "int", - "raw": "int", - }, + ], }, ExpressionStatement { "expression": Assign { @@ -4139,24 +4151,26 @@ next: "name": "bar", }, "nullable": true, - "type": TypeReference { - "kind": "typereference", - "loc": Location { - "end": Position { - "column": 22, - "line": 95, - "offset": 1897, - }, - "source": "int", - "start": Position { - "column": 19, - "line": 95, - "offset": 1894, + "type": Array [ + TypeReference { + "kind": "typereference", + "loc": Location { + "end": Position { + "column": 22, + "line": 95, + "offset": 1897, + }, + "source": "int", + "start": Position { + "column": 19, + "line": 95, + "offset": 1894, + }, }, + "name": "int", + "raw": "int", }, - "name": "int", - "raw": "int", - }, + ], "value": Number { "kind": "number", "loc": Location { @@ -6701,24 +6715,26 @@ next: }, }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "loc": Location { - "end": Position { - "column": 56, - "line": 95, - "offset": 1931, - }, - "source": "bool", - "start": Position { - "column": 52, - "line": 95, - "offset": 1927, + "type": Array [ + TypeReference { + "kind": "typereference", + "loc": Location { + "end": Position { + "column": 56, + "line": 95, + "offset": 1931, + }, + "source": "bool", + "start": Position { + "column": 52, + "line": 95, + "offset": 1927, + }, }, + "name": "bool", + "raw": "bool", }, - "name": "bool", - "raw": "bool", - }, + ], "uses": Array [ Variable { "curly": false, diff --git a/test/snapshot/__snapshots__/arrowfunc.test.js.snap b/test/snapshot/__snapshots__/arrowfunc.test.js.snap index d38fb334d..1176a6c5a 100644 --- a/test/snapshot/__snapshots__/arrowfunc.test.js.snap +++ b/test/snapshot/__snapshots__/arrowfunc.test.js.snap @@ -382,11 +382,13 @@ Program { "isStatic": false, "kind": "arrowfunc", "nullable": true, - "type": TypeReference { - "kind": "typereference", - "name": "string", - "raw": "string", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + ], }, }, "kind": "expressionstatement", diff --git a/test/snapshot/__snapshots__/class.test.js.snap b/test/snapshot/__snapshots__/class.test.js.snap index e64d302eb..4614c43a9 100644 --- a/test/snapshot/__snapshots__/class.test.js.snap +++ b/test/snapshot/__snapshots__/class.test.js.snap @@ -790,11 +790,13 @@ Program { "name": "data", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "array", - "raw": "array", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "array", + "raw": "array", + }, + ], "value": NullKeyword { "kind": "nullkeyword", "raw": "null", @@ -1163,11 +1165,13 @@ Program { "name": "foo", }, "nullable": false, - "type": Name { - "kind": "name", - "name": "bar", - "resolution": "uqn", - }, + "type": Array [ + Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + ], "visibility": "protected", }, ], diff --git a/test/snapshot/__snapshots__/classreference.test.js.snap b/test/snapshot/__snapshots__/classreference.test.js.snap index cbc8d39a2..7577752c4 100644 --- a/test/snapshot/__snapshots__/classreference.test.js.snap +++ b/test/snapshot/__snapshots__/classreference.test.js.snap @@ -13,11 +13,13 @@ Program { "name": "arg", }, "nullable": false, - "type": Name { - "kind": "name", - "name": "Foo\\\\Foo", - "resolution": "qn", - }, + "type": Array [ + Name { + "kind": "name", + "name": "Foo\\\\Foo", + "resolution": "qn", + }, + ], "value": null, "variadic": false, }, @@ -54,11 +56,13 @@ Program { "name": "arg", }, "nullable": false, - "type": Name { - "kind": "name", - "name": "Foo", - "resolution": "uqn", - }, + "type": Array [ + Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + ], "value": null, "variadic": false, }, diff --git a/test/snapshot/__snapshots__/function.test.js.snap b/test/snapshot/__snapshots__/function.test.js.snap index 67e7f1119..2dc3547b8 100644 --- a/test/snapshot/__snapshots__/function.test.js.snap +++ b/test/snapshot/__snapshots__/function.test.js.snap @@ -13,11 +13,13 @@ Program { "name": "a", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "int", - "raw": "int", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + ], "value": Number { "kind": "number", "value": "1", @@ -32,11 +34,13 @@ Program { "name": "b", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "float", - "raw": "float", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "float", + "raw": "float", + }, + ], "value": Number { "kind": "number", "value": "1", @@ -51,11 +55,13 @@ Program { "name": "c", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "bool", - "raw": "bool", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "bool", + "raw": "bool", + }, + ], "value": Number { "kind": "number", "value": "1", @@ -70,11 +76,13 @@ Program { "name": "d", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "string", - "raw": "string", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + ], "value": null, "variadic": false, }, @@ -86,11 +94,13 @@ Program { "name": "e", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "callable", - "raw": "callable", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "callable", + "raw": "callable", + }, + ], "value": null, "variadic": false, }, @@ -102,11 +112,13 @@ Program { "name": "f", }, "nullable": false, - "type": Name { - "kind": "name", - "name": "int\\\\bar", - "resolution": "qn", - }, + "type": Array [ + Name { + "kind": "name", + "name": "int\\\\bar", + "resolution": "qn", + }, + ], "value": null, "variadic": false, }, @@ -118,11 +130,13 @@ Program { "name": "params", }, "nullable": true, - "type": TypeReference { - "kind": "typereference", - "name": "array", - "raw": "array", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "array", + "raw": "array", + }, + ], "value": null, "variadic": true, }, @@ -138,11 +152,13 @@ Program { "name": "foo", }, "nullable": true, - "type": TypeReference { - "kind": "typereference", - "name": "object", - "raw": "object", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "object", + "raw": "object", + }, + ], }, ], "errors": Array [], @@ -253,11 +269,13 @@ Program { "name": "b", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "callable", - "raw": "callable", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "callable", + "raw": "callable", + }, + ], "value": null, "variadic": false, }, @@ -269,11 +287,13 @@ Program { "name": "params", }, "nullable": true, - "type": TypeReference { - "kind": "typereference", - "name": "array", - "raw": "array", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "array", + "raw": "array", + }, + ], "value": null, "variadic": true, }, @@ -289,11 +309,13 @@ Program { "name": "foo", }, "nullable": true, - "type": Name { - "kind": "name", - "name": "boolean", - "resolution": "uqn", - }, + "type": Array [ + Name { + "kind": "name", + "name": "boolean", + "resolution": "uqn", + }, + ], }, ExpressionStatement { "expression": Assign { @@ -336,11 +358,13 @@ Program { "isStatic": false, "kind": "closure", "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "array", - "raw": "array", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "array", + "raw": "array", + }, + ], "uses": Array [ Variable { "byref": true, @@ -445,6 +469,91 @@ Program { } `; +exports[`Function tests test function union types 1`] = ` +Program { + "children": Array [ + _Function { + "arguments": Array [ + Parameter { + "byref": false, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "a", + }, + "nullable": false, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + TypeReference { + "kind": "typereference", + "name": "float", + "raw": "float", + }, + ], + "value": Number { + "kind": "number", + "value": "1", + }, + "variadic": false, + }, + Parameter { + "byref": false, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "b", + }, + "nullable": false, + "type": Array [ + Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "Bar", + "resolution": "uqn", + }, + ], + "value": null, + "variadic": false, + }, + ], + "body": Block { + "children": Array [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + ], + }, + ], + "errors": Array [], + "kind": "program", +} +`; + exports[`Function tests test reserved word for function name error 1`] = ` Program { "children": Array [ @@ -477,6 +586,94 @@ Program { } `; +exports[`Function tests test short function union types 1`] = ` +Program { + "children": Array [ + ExpressionStatement { + "expression": Closure { + "arguments": Array [ + Parameter { + "byref": false, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "a", + }, + "nullable": false, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + TypeReference { + "kind": "typereference", + "name": "float", + "raw": "float", + }, + ], + "value": Number { + "kind": "number", + "value": "1", + }, + "variadic": false, + }, + Parameter { + "byref": false, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "b", + }, + "nullable": false, + "type": Array [ + Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "Bar", + "resolution": "uqn", + }, + ], + "value": null, + "variadic": false, + }, + ], + "body": String { + "isDoubleQuote": true, + "kind": "string", + "raw": "\\"\\"", + "unicode": false, + "value": "", + }, + "byref": false, + "isStatic": false, + "kind": "arrowfunc", + "nullable": false, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": Array [], + "kind": "program", +} +`; + exports[`Function tests test static closure 1`] = ` Program { "children": Array [ diff --git a/test/snapshot/__snapshots__/location.test.js.snap b/test/snapshot/__snapshots__/location.test.js.snap index 215194c72..ee4a249cd 100644 --- a/test/snapshot/__snapshots__/location.test.js.snap +++ b/test/snapshot/__snapshots__/location.test.js.snap @@ -9500,24 +9500,26 @@ Program { "name": "foo", }, "nullable": true, - "type": TypeReference { - "kind": "typereference", - "loc": Location { - "end": Position { - "column": 17, - "line": 1, - "offset": 17, - }, - "source": "int", - "start": Position { - "column": 14, - "line": 1, - "offset": 14, + "type": Array [ + TypeReference { + "kind": "typereference", + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "int", + "start": Position { + "column": 14, + "line": 1, + "offset": 14, + }, }, + "name": "int", + "raw": "int", }, - "name": "int", - "raw": "int", - }, + ], "value": Number { "kind": "number", "loc": Location { diff --git a/test/snapshot/__snapshots__/parentreference.test.js.snap b/test/snapshot/__snapshots__/parentreference.test.js.snap index 8c058bed2..84095efcd 100644 --- a/test/snapshot/__snapshots__/parentreference.test.js.snap +++ b/test/snapshot/__snapshots__/parentreference.test.js.snap @@ -13,10 +13,12 @@ Program { "name": "arg", }, "nullable": false, - "type": ParentReference { - "kind": "parentreference", - "raw": "PARENT", - }, + "type": Array [ + ParentReference { + "kind": "parentreference", + "raw": "PARENT", + }, + ], "value": null, "variadic": false, }, @@ -53,10 +55,12 @@ Program { "name": "arg", }, "nullable": false, - "type": ParentReference { - "kind": "parentreference", - "raw": "parent", - }, + "type": Array [ + ParentReference { + "kind": "parentreference", + "raw": "parent", + }, + ], "value": null, "variadic": false, }, @@ -159,10 +163,12 @@ Program { "name": "foo", }, "nullable": false, - "type": ParentReference { - "kind": "parentreference", - "raw": "PARENT", - }, + "type": Array [ + ParentReference { + "kind": "parentreference", + "raw": "PARENT", + }, + ], }, ], "errors": Array [], @@ -199,10 +205,12 @@ Program { "name": "foo", }, "nullable": false, - "type": ParentReference { - "kind": "parentreference", - "raw": "parent", - }, + "type": Array [ + ParentReference { + "kind": "parentreference", + "raw": "parent", + }, + ], }, ], "errors": Array [], diff --git a/test/snapshot/__snapshots__/selfreference.test.js.snap b/test/snapshot/__snapshots__/selfreference.test.js.snap index 5aad7363a..13284f872 100644 --- a/test/snapshot/__snapshots__/selfreference.test.js.snap +++ b/test/snapshot/__snapshots__/selfreference.test.js.snap @@ -13,10 +13,12 @@ Program { "name": "arg", }, "nullable": false, - "type": SelfReference { - "kind": "selfreference", - "raw": "SELF", - }, + "type": Array [ + SelfReference { + "kind": "selfreference", + "raw": "SELF", + }, + ], "value": null, "variadic": false, }, @@ -53,10 +55,12 @@ Program { "name": "arg", }, "nullable": false, - "type": SelfReference { - "kind": "selfreference", - "raw": "self", - }, + "type": Array [ + SelfReference { + "kind": "selfreference", + "raw": "self", + }, + ], "value": null, "variadic": false, }, @@ -159,10 +163,12 @@ Program { "name": "foo", }, "nullable": false, - "type": SelfReference { - "kind": "selfreference", - "raw": "SELF", - }, + "type": Array [ + SelfReference { + "kind": "selfreference", + "raw": "SELF", + }, + ], }, ], "errors": Array [], @@ -199,10 +205,12 @@ Program { "name": "foo", }, "nullable": false, - "type": SelfReference { - "kind": "selfreference", - "raw": "self", - }, + "type": Array [ + SelfReference { + "kind": "selfreference", + "raw": "self", + }, + ], }, ], "errors": Array [], diff --git a/test/snapshot/__snapshots__/typereference.test.js.snap b/test/snapshot/__snapshots__/typereference.test.js.snap index 2a23f38d7..a1417f7d0 100644 --- a/test/snapshot/__snapshots__/typereference.test.js.snap +++ b/test/snapshot/__snapshots__/typereference.test.js.snap @@ -13,11 +13,13 @@ Program { "name": "arg", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "array", - "raw": "ARRAY", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "array", + "raw": "ARRAY", + }, + ], "value": null, "variadic": false, }, @@ -54,11 +56,13 @@ Program { "name": "arg", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "array", - "raw": "array", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "array", + "raw": "array", + }, + ], "value": null, "variadic": false, }, @@ -111,11 +115,13 @@ Program { "name": "foo", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "array", - "raw": "ARRAY", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "array", + "raw": "ARRAY", + }, + ], }, ], "errors": Array [], @@ -152,11 +158,13 @@ Program { "name": "foo", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "array", - "raw": "array", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "array", + "raw": "array", + }, + ], }, ], "errors": Array [], @@ -177,11 +185,13 @@ Program { "name": "arg", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "bool", - "raw": "BOOL", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "bool", + "raw": "BOOL", + }, + ], "value": null, "variadic": false, }, @@ -218,11 +228,13 @@ Program { "name": "arg", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "bool", - "raw": "bool", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "bool", + "raw": "bool", + }, + ], "value": null, "variadic": false, }, @@ -275,11 +287,13 @@ Program { "name": "foo", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "bool", - "raw": "BOOL", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "bool", + "raw": "BOOL", + }, + ], }, ], "errors": Array [], @@ -316,11 +330,13 @@ Program { "name": "foo", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "bool", - "raw": "bool", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "bool", + "raw": "bool", + }, + ], }, ], "errors": Array [], @@ -341,11 +357,13 @@ Program { "name": "arg", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "callable", - "raw": "CALLABLE", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "callable", + "raw": "CALLABLE", + }, + ], "value": null, "variadic": false, }, @@ -382,11 +400,13 @@ Program { "name": "arg", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "callable", - "raw": "callable", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "callable", + "raw": "callable", + }, + ], "value": null, "variadic": false, }, @@ -439,11 +459,13 @@ Program { "name": "foo", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "callable", - "raw": "CALLABLE", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "callable", + "raw": "CALLABLE", + }, + ], }, ], "errors": Array [], @@ -480,11 +502,13 @@ Program { "name": "foo", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "callable", - "raw": "callable", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "callable", + "raw": "callable", + }, + ], }, ], "errors": Array [], @@ -505,11 +529,13 @@ Program { "name": "arg", }, "nullable": false, - "type": Name { - "kind": "name", - "name": "Foo\\\\Foo", - "resolution": "qn", - }, + "type": Array [ + Name { + "kind": "name", + "name": "Foo\\\\Foo", + "resolution": "qn", + }, + ], "value": null, "variadic": false, }, @@ -562,11 +588,13 @@ Program { "name": "foo", }, "nullable": false, - "type": Name { - "kind": "name", - "name": "Foo", - "resolution": "uqn", - }, + "type": Array [ + Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + ], }, ], "errors": Array [], @@ -603,11 +631,13 @@ Program { "name": "foo", }, "nullable": false, - "type": Name { - "kind": "name", - "name": "Foo\\\\Foo", - "resolution": "qn", - }, + "type": Array [ + Name { + "kind": "name", + "name": "Foo\\\\Foo", + "resolution": "qn", + }, + ], }, ], "errors": Array [], @@ -628,11 +658,13 @@ Program { "name": "arg", }, "nullable": false, - "type": Name { - "kind": "name", - "name": "Foo", - "resolution": "uqn", - }, + "type": Array [ + Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + ], "value": null, "variadic": false, }, @@ -669,11 +701,13 @@ Program { "name": "arg", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "float", - "raw": "FLOAT", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "float", + "raw": "FLOAT", + }, + ], "value": null, "variadic": false, }, @@ -710,11 +744,13 @@ Program { "name": "arg", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "float", - "raw": "float", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "float", + "raw": "float", + }, + ], "value": null, "variadic": false, }, @@ -767,11 +803,13 @@ Program { "name": "foo", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "float", - "raw": "FLOAT", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "float", + "raw": "FLOAT", + }, + ], }, ], "errors": Array [], @@ -808,11 +846,13 @@ Program { "name": "foo", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "float", - "raw": "float", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "float", + "raw": "float", + }, + ], }, ], "errors": Array [], @@ -833,11 +873,13 @@ Program { "name": "arg", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "int", - "raw": "INT", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "INT", + }, + ], "value": null, "variadic": false, }, @@ -874,11 +916,13 @@ Program { "name": "arg", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "int", - "raw": "int", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + ], "value": null, "variadic": false, }, @@ -931,11 +975,13 @@ Program { "name": "foo", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "int", - "raw": "INT", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "INT", + }, + ], }, ], "errors": Array [], @@ -972,11 +1018,13 @@ Program { "name": "foo", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "int", - "raw": "int", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + ], }, ], "errors": Array [], @@ -997,11 +1045,13 @@ Program { "name": "arg", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "iterable", - "raw": "ITERABLE", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "iterable", + "raw": "ITERABLE", + }, + ], "value": null, "variadic": false, }, @@ -1038,11 +1088,13 @@ Program { "name": "arg", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "iterable", - "raw": "iterable", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "iterable", + "raw": "iterable", + }, + ], "value": null, "variadic": false, }, @@ -1095,11 +1147,13 @@ Program { "name": "foo", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "iterable", - "raw": "ITERABLE", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "iterable", + "raw": "ITERABLE", + }, + ], }, ], "errors": Array [], @@ -1136,11 +1190,13 @@ Program { "name": "foo", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "iterable", - "raw": "iterable", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "iterable", + "raw": "iterable", + }, + ], }, ], "errors": Array [], @@ -1161,11 +1217,13 @@ Program { "name": "arg", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "object", - "raw": "OBJECT", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "object", + "raw": "OBJECT", + }, + ], "value": null, "variadic": false, }, @@ -1202,11 +1260,13 @@ Program { "name": "arg", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "object", - "raw": "object", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "object", + "raw": "object", + }, + ], "value": null, "variadic": false, }, @@ -1259,11 +1319,13 @@ Program { "name": "foo", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "object", - "raw": "OBJECT", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "object", + "raw": "OBJECT", + }, + ], }, ], "errors": Array [], @@ -1300,11 +1362,13 @@ Program { "name": "foo", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "object", - "raw": "object", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "object", + "raw": "object", + }, + ], }, ], "errors": Array [], @@ -1325,11 +1389,13 @@ Program { "name": "arg", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "string", - "raw": "STRING", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "string", + "raw": "STRING", + }, + ], "value": null, "variadic": false, }, @@ -1366,11 +1432,13 @@ Program { "name": "arg", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "string", - "raw": "string", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + ], "value": null, "variadic": false, }, @@ -1423,11 +1491,13 @@ Program { "name": "foo", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "string", - "raw": "STRING", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "string", + "raw": "STRING", + }, + ], }, ], "errors": Array [], @@ -1464,11 +1534,13 @@ Program { "name": "foo", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "string", - "raw": "string", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + ], }, ], "errors": Array [], @@ -1489,11 +1561,13 @@ Program { "name": "arg", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "void", - "raw": "VOID", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "void", + "raw": "VOID", + }, + ], "value": null, "variadic": false, }, @@ -1530,11 +1604,13 @@ Program { "name": "arg", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "void", - "raw": "void", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "void", + "raw": "void", + }, + ], "value": null, "variadic": false, }, @@ -1587,11 +1663,13 @@ Program { "name": "foo", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "void", - "raw": "VOID", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "void", + "raw": "VOID", + }, + ], }, ], "errors": Array [], @@ -1628,11 +1706,13 @@ Program { "name": "foo", }, "nullable": false, - "type": TypeReference { - "kind": "typereference", - "name": "void", - "raw": "void", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "void", + "raw": "void", + }, + ], }, ], "errors": Array [], diff --git a/test/snapshot/function.test.js b/test/snapshot/function.test.js index 2fa18a1a3..a2fc5ed94 100644 --- a/test/snapshot/function.test.js +++ b/test/snapshot/function.test.js @@ -14,6 +14,24 @@ describe("Function tests", function () { expect(ast).toMatchSnapshot(); }); + it("test function union types", function () { + const ast = parser.parseEval( + ` + function foo(int|float $a = 1, Foo|Bar $b) : string|int {} + ` + ); + expect(ast).toMatchSnapshot(); + }); + + it("test short function union types", function () { + const ast = parser.parseEval( + ` + fn (int|float $a = 1, Foo|Bar $b) : string|int => ""; + ` + ); + expect(ast).toMatchSnapshot(); + }); + it("implement #113 : typehint nodes", function () { expect( parser.parseEval( From 5aed303166871abcc69bc6c0dc2a5ec19f63c351 Mon Sep 17 00:00:00 2001 From: Chris Seufert Date: Mon, 22 Mar 2021 22:13:22 +1100 Subject: [PATCH 2/2] Addes support for union types as part of classes --- src/parser/class.js | 2 +- .../snapshot/__snapshots__/class.test.js.snap | 124 +++++++++++++++++- .../__snapshots__/graceful.test.js.snap | 24 ++-- test/snapshot/class.test.js | 11 ++ 4 files changed, 145 insertions(+), 16 deletions(-) diff --git a/src/parser/class.js b/src/parser/class.js index 6019433d1..57c5380e3 100644 --- a/src/parser/class.js +++ b/src/parser/class.js @@ -309,7 +309,7 @@ module.exports = { nullable = true; this.next(); } - let type = this.read_type(); + let type = this.read_types(); if (nullable && !type) { this.raiseError( "Expecting a type definition combined with nullable operator" diff --git a/test/snapshot/__snapshots__/class.test.js.snap b/test/snapshot/__snapshots__/class.test.js.snap index 4614c43a9..e2652d1d5 100644 --- a/test/snapshot/__snapshots__/class.test.js.snap +++ b/test/snapshot/__snapshots__/class.test.js.snap @@ -445,11 +445,13 @@ Program { "name": "prop", }, "nullable": true, - "type": TypeReference { - "kind": "typereference", - "name": "int", - "raw": "int", - }, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + ], "value": NullKeyword { "kind": "nullkeyword", "raw": "null", @@ -504,6 +506,118 @@ Program { } `; +exports[`Test classes Test class union properties 1`] = ` +Program { + "children": Array [ + Class { + "body": Array [ + PropertyStatement { + "isStatic": true, + "kind": "propertystatement", + "properties": Array [ + Property { + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": Array [ + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + TypeReference { + "kind": "typereference", + "name": "float", + "raw": "float", + }, + ], + "value": null, + }, + ], + "visibility": "", + }, + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": Array [ + Property { + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "bar", + }, + "nullable": true, + "type": Array [ + Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "Bar", + "resolution": "uqn", + }, + ], + "value": null, + }, + ], + "visibility": "private", + }, + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": Array [ + Property { + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "a", + }, + "nullable": false, + "type": Array [ + Name { + "kind": "name", + "name": "Repo", + "resolution": "uqn", + }, + TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + Name { + "kind": "name", + "name": "null", + "resolution": "uqn", + }, + ], + "value": null, + }, + ], + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Test", + }, + }, + ], + "errors": Array [], + "kind": "program", +} +`; + exports[`Test classes Test js properties 1`] = ` Program { "children": Array [ diff --git a/test/snapshot/__snapshots__/graceful.test.js.snap b/test/snapshot/__snapshots__/graceful.test.js.snap index d07d9e6e9..c04ecb35d 100644 --- a/test/snapshot/__snapshots__/graceful.test.js.snap +++ b/test/snapshot/__snapshots__/graceful.test.js.snap @@ -303,11 +303,13 @@ Program { "name": "onst", }, "nullable": false, - "type": Name { - "kind": "name", - "name": "foo", - "resolution": "uqn", - }, + "type": Array [ + Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + ], "value": null, }, ], @@ -834,11 +836,13 @@ Program { "name": "mplement", }, "nullable": false, - "type": Name { - "kind": "name", - "name": "bar", - "resolution": "uqn", - }, + "type": Array [ + Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + ], "value": null, }, ], diff --git a/test/snapshot/class.test.js b/test/snapshot/class.test.js index 138a9e897..a26a1975d 100644 --- a/test/snapshot/class.test.js +++ b/test/snapshot/class.test.js @@ -129,6 +129,17 @@ describe("Test classes", function () { ).toMatchSnapshot(); }); + it("Test class union properties", function () { + expect( + parser.parseEval(` + class Test { + static int|float $foo; + private ?Foo|Bar $bar; + public Repo|string|null $a; + }`) + ).toMatchSnapshot(); + }); + it("empty", function () { expect(parser.parseEval("class Foo {}")).toMatchSnapshot(); });