From c482cc5415d58b9b68af07083214d707b66d767a Mon Sep 17 00:00:00 2001 From: Chris Seufert Date: Thu, 11 Mar 2021 00:26:35 +1100 Subject: [PATCH 1/3] implement promoted parameters --- src/ast.js | 1 + src/ast/promotedparameter.js | 40 +++++++++ src/parser/function.js | 22 +++++ .../snapshot/__snapshots__/class.test.js.snap | 90 +++++++++++++++++++ test/snapshot/class.test.js | 16 ++++ 5 files changed, 169 insertions(+) create mode 100644 src/ast/promotedparameter.js diff --git a/src/ast.js b/src/ast.js index 67f9644d5..199e7cd7e 100644 --- a/src/ast.js +++ b/src/ast.js @@ -527,6 +527,7 @@ AST.prototype.checkNodes = function () { require("./ast/offsetlookup"), require("./ast/operation"), require("./ast/parameter"), + require("./ast/promotedparameter"), require("./ast/parentreference"), require("./ast/post"), require("./ast/pre"), diff --git a/src/ast/promotedparameter.js b/src/ast/promotedparameter.js new file mode 100644 index 000000000..40ac6b990 --- /dev/null +++ b/src/ast/promotedparameter.js @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Declaration = require("./declaration"); +const KIND = "promotedparameter"; + +/** + * Defines a function parameter + * @constructor Parameter + * @extends {Declaration} + * @property {Identifier|null} type + * @property {Node|null} value + * @property {boolean} byref + * @property {boolean} variadic + * @property {boolean} nullable + * @property {'public'|'private'|'protected'} promote + */ +module.exports = Declaration.extends(KIND, function Parameter( + name, + type, + value, + isRef, + isVariadic, + nullable, + promote, + docs, + location +) { + Declaration.apply(this, [KIND, name, docs, location]); + this.value = value; + this.type = type; + this.byref = isRef; + this.variadic = isVariadic; + this.nullable = nullable; + this.promote = promote; +}); diff --git a/src/parser/function.js b/src/parser/function.js index a9f79b75e..d605beb77 100644 --- a/src/parser/function.js +++ b/src/parser/function.js @@ -204,6 +204,17 @@ module.exports = { let value = null; let type = null; let nullable = false; + let promote = null; + if (this.token === this.tok.T_PUBLIC) { + promote = "public"; + } else if (this.token === this.tok.T_PRIVATE) { + promote = "private"; + } else if (this.token === this.tok.T_PROTECTED) { + promote = "protected"; + } + if (promote !== null) { + this.next(); + } if (this.token === "?") { this.next(); nullable = true; @@ -225,6 +236,17 @@ module.exports = { if (this.token == "=") { value = this.next().read_expr(); } + if (promote !== null) { + return this.node("promotedparameter")( + parameterName, + type, + value, + isRef, + isVariadic, + nullable, + promote + ); + } return node(parameterName, type, value, isRef, isVariadic, nullable); }, /** diff --git a/test/snapshot/__snapshots__/class.test.js.snap b/test/snapshot/__snapshots__/class.test.js.snap index e64d302eb..fc26f460c 100644 --- a/test/snapshot/__snapshots__/class.test.js.snap +++ b/test/snapshot/__snapshots__/class.test.js.snap @@ -738,6 +738,96 @@ Program { } `; +exports[`Test classes Test promoted class properties php 8 1`] = ` +Program { + "children": Array [ + Class { + "body": Array [ + Method { + "arguments": Array [ + Parameter { + "byref": false, + "kind": "promotedparameter", + "name": Identifier { + "kind": "identifier", + "name": "id", + }, + "nullable": false, + "promote": "public", + "type": TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + "value": null, + "variadic": false, + }, + Parameter { + "byref": false, + "kind": "promotedparameter", + "name": Identifier { + "kind": "identifier", + "name": "name", + }, + "nullable": false, + "promote": "private", + "type": null, + "value": null, + "variadic": false, + }, + Parameter { + "byref": false, + "kind": "promotedparameter", + "name": Identifier { + "kind": "identifier", + "name": "req", + }, + "nullable": false, + "promote": "protected", + "type": Name { + "kind": "name", + "name": "ServerRequestInterface", + "resolution": "uqn", + }, + "value": null, + "variadic": false, + }, + ], + "body": Block { + "children": Array [], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "constructor", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "__proto__", + }, + }, + ], + "errors": Array [], + "kind": "program", +} +`; + exports[`Test classes Validate usual declarations 1`] = ` Program { "children": Array [ diff --git a/test/snapshot/class.test.js b/test/snapshot/class.test.js index 138a9e897..2b4f04914 100644 --- a/test/snapshot/class.test.js +++ b/test/snapshot/class.test.js @@ -129,6 +129,22 @@ describe("Test classes", function () { ).toMatchSnapshot(); }); + it("Test promoted class properties php 8", function () { + const ast = parser.parseEval( + ` + class __proto__ { + public function constructor(public int $id, private $name, protected ServerRequestInterface $req) {} + }`, + { + parser: { + version: "8.0", + suppressErrors: true, + }, + } + ); + expect(ast).toMatchSnapshot(); + }); + it("empty", function () { expect(parser.parseEval("class Foo {}")).toMatchSnapshot(); }); From 0d070672f1dca11164f194765f4c05f34f5c00e0 Mon Sep 17 00:00:00 2001 From: Chris Seufert Date: Wed, 24 Mar 2021 21:36:13 +1100 Subject: [PATCH 2/3] Update JSDoc and constructor name --- src/ast/promotedparameter.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ast/promotedparameter.js b/src/ast/promotedparameter.js index 40ac6b990..e1a2ce1b9 100644 --- a/src/ast/promotedparameter.js +++ b/src/ast/promotedparameter.js @@ -9,8 +9,8 @@ const Declaration = require("./declaration"); const KIND = "promotedparameter"; /** - * Defines a function parameter - * @constructor Parameter + * Defines a promoted function parameter (for class constructor) + * @constructor PromotedParameter * @extends {Declaration} * @property {Identifier|null} type * @property {Node|null} value @@ -19,7 +19,7 @@ const KIND = "promotedparameter"; * @property {boolean} nullable * @property {'public'|'private'|'protected'} promote */ -module.exports = Declaration.extends(KIND, function Parameter( +module.exports = Declaration.extends(KIND, function PromotedParameter( name, type, value, From 75b030ce07c41dce98e6268450a270c2550eecd2 Mon Sep 17 00:00:00 2001 From: Chris Seufert Date: Wed, 24 Mar 2021 21:37:18 +1100 Subject: [PATCH 3/3] Fix constructor name --- test/snapshot/__snapshots__/class.test.js.snap | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/snapshot/__snapshots__/class.test.js.snap b/test/snapshot/__snapshots__/class.test.js.snap index fc26f460c..615df10ba 100644 --- a/test/snapshot/__snapshots__/class.test.js.snap +++ b/test/snapshot/__snapshots__/class.test.js.snap @@ -745,7 +745,7 @@ Program { "body": Array [ Method { "arguments": Array [ - Parameter { + PromotedParameter { "byref": false, "kind": "promotedparameter", "name": Identifier { @@ -762,7 +762,7 @@ Program { "value": null, "variadic": false, }, - Parameter { + PromotedParameter { "byref": false, "kind": "promotedparameter", "name": Identifier { @@ -775,7 +775,7 @@ Program { "value": null, "variadic": false, }, - Parameter { + PromotedParameter { "byref": false, "kind": "promotedparameter", "name": Identifier {