Skip to content

Commit

Permalink
Merge pull request #673 from czosel/named-arguments
Browse files Browse the repository at this point in the history
feat(php8): named arguments
  • Loading branch information
czosel committed Mar 31, 2021
2 parents da4f3f5 + 39b527c commit 0b7781f
Show file tree
Hide file tree
Showing 5 changed files with 265 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/ast.js
Expand Up @@ -519,6 +519,7 @@ AST.prototype.checkNodes = function () {
require("./ast/method"),
require("./ast/name"),
require("./ast/namespace"),
require("./ast/namedargument"),
require("./ast/new"),
require("./ast/node"),
require("./ast/noop"),
Expand Down
28 changes: 28 additions & 0 deletions src/ast/namedargument.js
@@ -0,0 +1,28 @@
/**
* Copyright (C) 2018 Glayzzle (BSD3 License)
* @authors https://github.com/glayzzle/php-parser/graphs/contributors
* @url http://glayzzle.com
*/
"use strict";

const Expression = require("./expression");
const KIND = "namedargument";

/**
* Named arguments.
* @constructor namedargument
* @extends {Expression}
* @property {String} name
* @property {Expression} value
* @see https://www.php.net/manual/en/functions.arguments.php#functions.named-arguments
*/
module.exports = Expression.extends(KIND, function namedargument(
name,
value,
docs,
location
) {
Expression.apply(this, [KIND, docs, location]);
this.name = name;
this.value = value;
});
15 changes: 14 additions & 1 deletion src/parser/function.js
Expand Up @@ -283,13 +283,26 @@ module.exports = {
},
/**
* ```ebnf
* argument_list ::= T_ELLIPSIS? expr
* argument_list ::= T_STRING ':' expr | T_ELLIPSIS? expr
* ```
*/
read_argument: function () {
if (this.token === this.tok.T_ELLIPSIS) {
return this.node("variadic")(this.next().read_expr());
}
if (
this.token === this.tok.T_STRING ||
Object.values(this.lexer.keywords).includes(this.token)
) {
const backup = [this.token, this.lexer.getState()];
const name = this.text();
this.next();
if (this.token === ":") {
return this.node("namedargument")(name, this.next().read_expr());
}
this.lexer.tokens.push(backup);
this.next();
}
return this.read_expr();
},
/**
Expand Down
182 changes: 182 additions & 0 deletions test/snapshot/__snapshots__/call.test.js.snap
Expand Up @@ -97,6 +97,84 @@ Program {
}
`;

exports[`Test call comments 1`] = `
Program {
"children": Array [
ExpressionStatement {
"expression": Call {
"arguments": Array [
Array {
"items": Array [
Entry {
"byRef": false,
"key": null,
"kind": "entry",
"leadingComments": Array [
CommentLine {
"kind": "commentline",
"offset": 10,
"value": "// comment
",
},
],
"unpack": false,
"value": Number {
"kind": "number",
"value": "100",
},
},
Entry {
"byRef": false,
"key": null,
"kind": "entry",
"unpack": false,
"value": Number {
"kind": "number",
"value": "0",
},
},
],
"kind": "array",
"leadingComments": Array [
CommentLine {
"kind": "commentline",
"offset": 10,
"value": "// comment
",
},
],
"shortForm": false,
},
],
"kind": "call",
"what": Name {
"kind": "name",
"name": "foo",
"resolution": "uqn",
},
},
"kind": "expressionstatement",
},
],
"comments": Array [
CommentLine {
"kind": "commentline",
"offset": 10,
"value": "// comment
",
},
CommentLine {
"kind": "commentline",
"offset": 10,
"value": "// comment
",
},
],
"errors": Array [],
"kind": "program",
}
`;

exports[`Test call inside offsetlookup 1`] = `
Program {
"children": Array [
Expand Down Expand Up @@ -636,6 +714,79 @@ Program {
}
`;

exports[`Test call keyword as named argument 1`] = `
Program {
"children": Array [
ExpressionStatement {
"expression": Call {
"arguments": Array [
namedargument {
"kind": "namedargument",
"name": "array",
"value": Variable {
"curly": false,
"kind": "variable",
"name": "a",
},
},
],
"kind": "call",
"what": Name {
"kind": "name",
"name": "foo",
"resolution": "uqn",
},
},
"kind": "expressionstatement",
},
],
"errors": Array [],
"kind": "program",
}
`;

exports[`Test call mix of unnamed and named arguments 1`] = `
Program {
"children": Array [
ExpressionStatement {
"expression": Call {
"arguments": Array [
Number {
"kind": "number",
"value": "50",
},
namedargument {
"kind": "namedargument",
"name": "num",
"value": Number {
"kind": "number",
"value": "100",
},
},
namedargument {
"kind": "namedargument",
"name": "start_index",
"value": Number {
"kind": "number",
"value": "0",
},
},
],
"kind": "call",
"what": Name {
"kind": "name",
"name": "foo",
"resolution": "uqn",
},
},
"kind": "expressionstatement",
},
],
"errors": Array [],
"kind": "program",
}
`;

exports[`Test call multiple (2) 1`] = `
Program {
"children": Array [
Expand Down Expand Up @@ -752,6 +903,37 @@ Program {
}
`;

exports[`Test call named arguments in php 8.0 1`] = `
Program {
"children": Array [
ExpressionStatement {
"expression": Call {
"arguments": Array [
namedargument {
"kind": "namedargument",
"name": "a",
"value": Variable {
"curly": false,
"kind": "variable",
"name": "a",
},
},
],
"kind": "call",
"what": Name {
"kind": "name",
"name": "foo",
"resolution": "uqn",
},
},
"kind": "expressionstatement",
},
],
"errors": Array [],
"kind": "program",
}
`;

exports[`Test call nested 1`] = `
Program {
"children": Array [
Expand Down
40 changes: 40 additions & 0 deletions test/snapshot/call.test.js
Expand Up @@ -244,4 +244,44 @@ describe("Test call", function () {
});
expect(ast).toMatchSnapshot();
});
it("named arguments in php 8.0", function () {
const astErr = parser.parseEval(`foo(a: $a);`, {
parser: {
version: "8.0",
debug: false,
},
});
expect(astErr).toMatchSnapshot();
});
it("keyword as named argument", function () {
const astErr = parser.parseEval(`foo(array: $a);`, {
parser: {
version: "8.0",
debug: false,
},
});
expect(astErr).toMatchSnapshot();
});
it("mix of unnamed and named arguments", function () {
const astErr = parser.parseEval(`foo(50, num: 100, start_index: 0);`, {
parser: {
version: "8.0",
debug: false,
},
});
expect(astErr).toMatchSnapshot();
});
it("comments", function () {
const astErr = parser.parseEval(
`foo(array // comment
(100, 0));`,
{
parser: {
extractDoc: true,
debug: false,
},
}
);
expect(astErr).toMatchSnapshot();
});
});

0 comments on commit 0b7781f

Please sign in to comment.