php-parser
Advanced tools
Comparing version 3.0.3 to 3.1.0-beta.0
{ | ||
"name": "php-parser", | ||
"version": "3.0.3", | ||
"version": "3.1.0-beta.0", | ||
"description": "Parse PHP code from JS and returns its AST", | ||
@@ -63,20 +63,20 @@ "main": "src/index.js", | ||
"devDependencies": { | ||
"@babel/core": "^7.3.4", | ||
"@babel/preset-env": "^7.3.4", | ||
"@babel/core": "^7.16.12", | ||
"@babel/preset-env": "^7.16.11", | ||
"babel-loader": "^8.0.5", | ||
"coveralls": "^3.0.3", | ||
"eslint": "^5.15.0", | ||
"eslint-plugin-jest": "^24.0.0", | ||
"eslint-plugin-prettier": "^3.0.1", | ||
"husky": "^6.0.0", | ||
"jest": "^26.4.2", | ||
"jest-runner-eslint": "^0.9.0", | ||
"jsdoc": "^3.5.5", | ||
"eslint": "^7.32.0", | ||
"eslint-plugin-jest": "^26.0.0", | ||
"eslint-plugin-prettier": "^4.0.0", | ||
"husky": "^7.0.4", | ||
"jest": "^27.4.7", | ||
"jest-runner-eslint": "^1.0.0", | ||
"jsdoc": "^3.6.10", | ||
"jsdoc-template": "^1.2.0", | ||
"lodash.template": ">=4.5.0", | ||
"prettier": "^2.0.2", | ||
"prettier": "^2.5.1", | ||
"tsd-jsdoc": "^2.5.0", | ||
"webpack": "^5.30.0", | ||
"webpack-cli": "^4.6.0" | ||
"webpack": "^5.68.0", | ||
"webpack-cli": "^4.9.2" | ||
} | ||
} |
<h1 align="center">php-parser</h1> | ||
<p align="center"> | ||
<a href="https://travis-ci.org/glayzzle/php-parser"><img src="https://api.travis-ci.org/glayzzle/php-parser.svg?branch=2.2.0"></a> | ||
<a href="https://circleci.com/gh/glayzzle/php-parser/tree/master"><img src="https://circleci.com/gh/glayzzle/php-parser/tree/master.svg?style=svg"></a> | ||
<a href="https://coveralls.io/github/glayzzle/php-parser?branch=master"><img src="https://coveralls.io/repos/github/glayzzle/php-parser/badge.svg?branch=master&v=20170115" alt="Coverage Status" /></a> | ||
@@ -5,0 +5,0 @@ <a title="npm version" href="https://www.npmjs.com/package/php-parser"><img src="https://badge.fury.io/js/php-parser.svg"></a> |
@@ -132,19 +132,2 @@ /** | ||
/** | ||
* Create a position node from specified parser | ||
* including it's lexer current state | ||
* @private | ||
* @function AST#position | ||
* @memberOf module:php-parser | ||
* @param {Parser} parser | ||
* @return {Position} | ||
*/ | ||
AST.prototype.position = function (parser) { | ||
return new Position( | ||
parser.lexer.yylloc.first_line, | ||
parser.lexer.yylloc.first_column, | ||
parser.lexer.yylloc.first_offset | ||
); | ||
}; | ||
// operators in ascending order of precedence | ||
@@ -222,2 +205,3 @@ AST.precedence = {}; | ||
} | ||
/* istanbul ignore next */ | ||
if (target.loc.end.offset < last.loc.end.offset) { | ||
@@ -312,3 +296,3 @@ target.loc.end = last.loc.end; | ||
if (result.what && !result.what.parenthesizedExpression) { | ||
// unary precedence is allways lower | ||
// unary precedence is always lower | ||
if (result.what.kind === "bin") { | ||
@@ -381,3 +365,3 @@ buffer = result.what; | ||
if (this.withPositions || this.withSource) { | ||
start = this.position(parser); | ||
start = parser.position(); | ||
} | ||
@@ -401,3 +385,3 @@ const self = this; | ||
); | ||
// last argument is allways the location | ||
// last argument is always the location | ||
args.push(location); | ||
@@ -417,2 +401,3 @@ } | ||
result.instance = astNode; | ||
/* istanbul ignore next */ | ||
if (result.trailingComments) { | ||
@@ -484,3 +469,3 @@ // buffer of trailingComments | ||
for (const k in AST.stack) { | ||
if (AST.stack.hasOwnProperty(k)) { | ||
if (Object.prototype.hasOwnProperty.call(AST.stack, k)) { | ||
errors.push(AST.stack[k]); | ||
@@ -499,2 +484,4 @@ } | ||
require("./ast/assignref"), | ||
require("./ast/attribute"), | ||
require("./ast/attrgroup"), | ||
require("./ast/bin"), | ||
@@ -550,5 +537,8 @@ require("./ast/block"), | ||
require("./ast/magic"), | ||
require("./ast/match"), | ||
require("./ast/matcharm"), | ||
require("./ast/method"), | ||
require("./ast/name"), | ||
require("./ast/namespace"), | ||
require("./ast/namedargument"), | ||
require("./ast/new"), | ||
@@ -559,2 +549,3 @@ require("./ast/node"), | ||
require("./ast/nullkeyword"), | ||
require("./ast/nullsafepropertylookup"), | ||
require("./ast/number"), | ||
@@ -592,2 +583,3 @@ require("./ast/offsetlookup"), | ||
require("./ast/unary"), | ||
require("./ast/uniontype"), | ||
require("./ast/unset"), | ||
@@ -594,0 +586,0 @@ require("./ast/usegroup"), |
@@ -17,3 +17,3 @@ /** | ||
* @property {Identifier[]} what | ||
* @property {Variable} variable | ||
* @property {Variable|null} variable | ||
* @property {Statement} body | ||
@@ -20,0 +20,0 @@ * @see http://php.net/manual/en/language.exceptions.php |
@@ -19,2 +19,3 @@ /** | ||
* @property {Declaration[]} body | ||
* @property {AttrGroup[]} attrGroups | ||
* @property {boolean} isAnonymous | ||
@@ -32,4 +33,5 @@ * @property {boolean} isAbstract | ||
this.body = body; | ||
this.attrGroups = []; | ||
this.parseFlags(flags); | ||
} | ||
); |
@@ -22,8 +22,10 @@ /** | ||
* @property {string} visibility | ||
* @property {AttrGroup[]} attrGroups | ||
*/ | ||
const ClassConstant = ConstantStatement.extends( | ||
KIND, | ||
function ClassConstant(kind, constants, flags, docs, location) { | ||
function ClassConstant(kind, constants, flags, attrGroups, docs, location) { | ||
ConstantStatement.apply(this, [kind || KIND, constants, docs, location]); | ||
this.parseFlags(flags); | ||
this.attrGroups = attrGroups; | ||
} | ||
@@ -44,2 +46,3 @@ ); | ||
} else if (flags[0] === null) { | ||
/* istanbul ignore next */ | ||
this.visibility = null; | ||
@@ -46,0 +49,0 @@ } else if (flags[0] === 0) { |
@@ -23,2 +23,3 @@ /** | ||
* @property {boolean} isStatic | ||
* @property {AttrGroup[]} attrGroups | ||
*/ | ||
@@ -45,3 +46,4 @@ module.exports = Expression.extends( | ||
this.body = null; | ||
this.attrGroups = []; | ||
} | ||
); |
@@ -46,2 +46,3 @@ /** | ||
} else if (flags[0] === null) { | ||
/* istanbul ignore next */ | ||
this.visibility = null; | ||
@@ -48,0 +49,0 @@ } else if (flags[0] === 0) { |
@@ -21,2 +21,3 @@ /** | ||
* @property {Block|null} body | ||
* @property {AttrGroups[]} attrGroups | ||
*/ | ||
@@ -32,3 +33,4 @@ module.exports = Declaration.extends( | ||
this.body = null; | ||
this.attrGroups = []; | ||
} | ||
); |
@@ -18,10 +18,12 @@ /** | ||
* @property {Declaration[]} body | ||
* @property {AttrGroup[]} attrGroups | ||
*/ | ||
module.exports = Declaration.extends( | ||
KIND, | ||
function Interface(name, ext, body, docs, location) { | ||
function Interface(name, ext, body, attrGroups, docs, location) { | ||
Declaration.apply(this, [KIND, name, docs, location]); | ||
this.extends = ext; | ||
this.body = body; | ||
this.attrGroups = attrGroups; | ||
} | ||
); |
@@ -44,2 +44,3 @@ /** | ||
if (!node) { | ||
/* istanbul ignore next */ | ||
throw new Error( | ||
@@ -46,0 +47,0 @@ "Node already initialized, you must swap with another node" |
@@ -11,2 +11,9 @@ /** | ||
// eslint-disable-next-line no-unused-vars | ||
const MODIFIER_PUBLIC = 1; | ||
// eslint-disable-next-line no-unused-vars | ||
const MODIFIER_PROTECTED = 2; | ||
// eslint-disable-next-line no-unused-vars | ||
const MODIFIER_PRIVATE = 4; | ||
/** | ||
@@ -22,2 +29,4 @@ * Defines a function parameter | ||
* @property {boolean} nullable | ||
* @property {AttrGroups[]} attrGroups | ||
* @property {MODIFIER_PUBLIC|MODIFIER_PROTECTED|MODIFIER_PRIVATE} flags | ||
*/ | ||
@@ -33,2 +42,3 @@ module.exports = Declaration.extends( | ||
nullable, | ||
flags, | ||
docs, | ||
@@ -43,3 +53,5 @@ location | ||
this.nullable = nullable; | ||
this.flags = flags || 0; | ||
this.attrGroups = []; | ||
} | ||
); |
@@ -20,6 +20,7 @@ /** | ||
* @property {Identifier|Array<Identifier>|null} type | ||
* @property {AttrGroup[]} attrGroups | ||
*/ | ||
module.exports = Statement.extends( | ||
KIND, | ||
function Property(name, value, nullable, type, docs, location) { | ||
function Property(name, value, nullable, type, attrGroups, docs, location) { | ||
Statement.apply(this, [KIND, docs, location]); | ||
@@ -30,3 +31,4 @@ this.name = name; | ||
this.type = type; | ||
this.attrGroups = attrGroups; | ||
} | ||
); |
@@ -18,3 +18,3 @@ /** | ||
* @property {Catch[]} catches | ||
* @property {Block} allways | ||
* @property {Block} always | ||
*/ | ||
@@ -21,0 +21,0 @@ module.exports = Statement.extends( |
@@ -37,4 +37,5 @@ /** | ||
"void", | ||
"static", | ||
]; | ||
module.exports = TypeReference; |
@@ -96,4 +96,4 @@ /** | ||
} | ||
if (options.parser.version < 500 || options.parser.version > 704) { | ||
throw new Error("Can only handle versions between 5.x to 7.x"); | ||
if (options.parser.version < 500 || options.parser.version > 900) { | ||
throw new Error("Can only handle versions between 5.x to 8.x"); | ||
} | ||
@@ -203,4 +203,4 @@ } | ||
* > Note that the output tokens are *STRICLY* similar to PHP function `token_get_all` | ||
* @param {String} buffer | ||
* @return {String[]} - Each item can be a string or an array with following informations [token_name, text, line_number] | ||
* @param {string} buffer | ||
* @return {Array<string|string[]>} - Each item can be a string or an array with following informations [token_name, text, line_number] | ||
*/ | ||
@@ -218,3 +218,3 @@ Engine.prototype.tokenGetAll = function (buffer) { | ||
let entry = this.lexer.yytext; | ||
if (names.hasOwnProperty(token)) { | ||
if (Object.prototype.hasOwnProperty.call(names, token)) { | ||
entry = [names[token], entry, this.lexer.yylloc.first_line]; | ||
@@ -221,0 +221,0 @@ } |
@@ -33,3 +33,3 @@ /** | ||
this.short_tags = false; | ||
this.version = 704; | ||
this.version = 800; | ||
this.yyprevcol = 0; | ||
@@ -111,2 +111,3 @@ this.keywords = { | ||
xor: this.tok.T_LOGICAL_XOR, | ||
match: this.tok.T_MATCH, | ||
}; | ||
@@ -181,2 +182,3 @@ this.castKeywords = { | ||
// for backward compatible | ||
/* istanbul ignore next */ | ||
toString: function () { | ||
@@ -455,2 +457,3 @@ this.label; | ||
this.stateCb = this["match" + condition]; | ||
/* istanbul ignore next */ | ||
if (typeof this.stateCb !== "function") { | ||
@@ -473,2 +476,3 @@ throw new Error('Undefined condition state "' + condition + '"'); | ||
this.stateCb = this["match" + this.curCondition]; | ||
/* istanbul ignore next */ | ||
if (typeof this.stateCb !== "function") { | ||
@@ -515,2 +519,3 @@ throw new Error('Undefined condition state "' + this.curCondition + '"'); | ||
} | ||
/* istanbul ignore next */ | ||
if (this.debug) { | ||
@@ -545,2 +550,3 @@ let tName = token; | ||
[ | ||
require("./lexer/attribute.js"), | ||
require("./lexer/comments.js"), | ||
@@ -547,0 +553,0 @@ require("./lexer/initial.js"), |
@@ -69,2 +69,3 @@ /** | ||
} else { | ||
/* istanbul ignore next */ | ||
throw new Error("Unexpected terminal"); | ||
@@ -92,2 +93,3 @@ } | ||
} else { | ||
/* istanbul ignore next */ | ||
throw new Error("Unexpected terminal"); | ||
@@ -94,0 +96,0 @@ } |
@@ -19,2 +19,7 @@ /** | ||
case "#": | ||
if (this.version >= 800 && this._input[this.offset] === "[") { | ||
this.input(); | ||
this.begin("ST_ATTRIBUTE"); | ||
return this.tok.T_ATTRIBUTE; | ||
} | ||
return this.T_COMMENT(); | ||
@@ -21,0 +26,0 @@ case "/": |
@@ -165,2 +165,10 @@ /** | ||
} | ||
if ( | ||
this.version >= 800 && | ||
this._input[this.offset] === "-" && | ||
this._input[this.offset + 1] === ">" | ||
) { | ||
this.consume(2); | ||
return this.tok.T_NULLSAFE_OBJECT_OPERATOR; | ||
} | ||
return "?"; | ||
@@ -167,0 +175,0 @@ }, |
@@ -8,2 +8,4 @@ /** | ||
const Position = require("./ast/position"); | ||
/** | ||
@@ -38,3 +40,3 @@ * @private | ||
this.debug = false; | ||
this.version = 704; | ||
this.version = 800; | ||
this.extractDoc = false; | ||
@@ -102,2 +104,3 @@ this.extractTokens = false; | ||
this.tok.T_LOGICAL_XOR, | ||
this.tok.T_MATCH, | ||
this.tok.T_METHOD_C, | ||
@@ -199,2 +202,3 @@ this.tok.T_NAMESPACE, | ||
this.tok.T_EMPTY, | ||
this.tok.T_MATCH, | ||
this.tok.T_INCLUDE, | ||
@@ -313,2 +317,3 @@ this.tok.T_INCLUDE_ONCE, | ||
const errors = this.ast.checkNodes(); | ||
/* istanbul ignore next */ | ||
if (errors.length > 0) { | ||
@@ -376,2 +381,3 @@ errors.forEach(function (error) { | ||
let symbol = this.text(); | ||
/* istanbul ignore next */ | ||
if (symbol.length > 10) { | ||
@@ -394,2 +400,15 @@ symbol = symbol.substring(0, 7) + "..."; | ||
/** | ||
* Create a position node from the lexers position | ||
* | ||
* @return {Position} | ||
*/ | ||
Parser.prototype.position = function () { | ||
return new Position( | ||
this.lexer.yylloc.first_line, | ||
this.lexer.yylloc.first_column, | ||
this.lexer.yylloc.first_offset | ||
); | ||
}; | ||
/** | ||
* Creates a new AST node | ||
@@ -405,2 +424,3 @@ * @function Parser#node | ||
this._docIndex = this._docs.length; | ||
/* istanbul ignore next */ | ||
if (this.debug) { | ||
@@ -508,2 +528,3 @@ // eslint-disable-next-line no-console | ||
for (let i = 0; i < ignoreStack.length; i++) { | ||
/* istanbul ignore next */ | ||
if (line.substring(3, 3 + ignoreStack[i].length) === ignoreStack[i]) { | ||
@@ -514,2 +535,3 @@ found = true; | ||
} | ||
/* istanbul ignore next */ | ||
if (!found) { | ||
@@ -625,6 +647,11 @@ break; | ||
// the token | ||
this.token = this.lexer.lex() || this.EOF; | ||
this.token = this.lexer.lex() || /* istanbul ignore next */ this.EOF; | ||
if (this.token === this.EOF) return this; | ||
let entry = this.lexer.yytext; | ||
if (this.lexer.engine.tokens.values.hasOwnProperty(this.token)) { | ||
if ( | ||
Object.prototype.hasOwnProperty.call( | ||
this.lexer.engine.tokens.values, | ||
this.token | ||
) | ||
) { | ||
entry = [ | ||
@@ -664,3 +691,3 @@ this.lexer.engine.tokens.values[this.token], | ||
} else { | ||
this.token = this.lexer.lex() || this.EOF; | ||
this.token = this.lexer.lex() || /* istanbul ignore next */ this.EOF; | ||
} | ||
@@ -701,3 +728,4 @@ return this; | ||
for (const k in ext) { | ||
if (Parser.prototype.hasOwnProperty(k)) { | ||
/* istanbul ignore next */ | ||
if (Object.prototype.hasOwnProperty.call(Parser.prototype, k)) { | ||
// @see https://github.com/glayzzle/php-parser/issues/234 | ||
@@ -704,0 +732,0 @@ throw new Error("Function " + k + " is already defined - collision"); |
@@ -15,3 +15,3 @@ /** | ||
*/ | ||
read_class_declaration_statement: function () { | ||
read_class_declaration_statement: function (attrs) { | ||
const result = this.node("class"); | ||
@@ -34,3 +34,5 @@ const flag = this.read_class_modifiers(); | ||
const body = this.next().read_class_body(); | ||
return result(propName, propExtends, propImplements, body, flag); | ||
const node = result(propName, propExtends, propImplements, body, flag); | ||
if (attrs) node.attrGroups = attrs; | ||
return node; | ||
}, | ||
@@ -64,3 +66,3 @@ | ||
let result = []; | ||
let attrs = []; | ||
while (this.token !== this.EOF && this.token !== "}") { | ||
@@ -83,2 +85,8 @@ if (this.token === this.tok.T_COMMENT) { | ||
if (this.token === this.tok.T_ATTRIBUTE) { | ||
attrs = this.read_attr_list(); | ||
} | ||
const locStart = this.position(); | ||
// read member flags | ||
@@ -89,3 +97,3 @@ const flags = this.read_member_flags(false); | ||
if (this.token === this.tok.T_CONST) { | ||
const constants = this.read_constant_list(flags); | ||
const constants = this.read_constant_list(flags, attrs); | ||
if (this.expect(";")) { | ||
@@ -107,3 +115,4 @@ this.next(); | ||
// reads a function | ||
result.push(this.read_function(false, flags)); | ||
result.push(this.read_function(false, flags, attrs, locStart)); | ||
attrs = []; | ||
} else if ( | ||
@@ -121,3 +130,4 @@ this.token === this.tok.T_VARIABLE || | ||
// reads a variable | ||
const variables = this.read_variable_list(flags); | ||
const variables = this.read_variable_list(flags, attrs); | ||
attrs = []; | ||
this.expect(";"); | ||
@@ -147,3 +157,3 @@ this.next(); | ||
*/ | ||
read_variable_list: function (flags) { | ||
read_variable_list: function (flags, attrs) { | ||
const result = this.node("propertystatement"); | ||
@@ -168,9 +178,15 @@ | ||
if (this.token === ";" || this.token === ",") { | ||
return result(propName, null, nullable, type); | ||
return result(propName, null, nullable, type, attrs || []); | ||
} else if (this.token === "=") { | ||
// https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L815 | ||
return result(propName, this.next().read_expr(), nullable, type); | ||
return result( | ||
propName, | ||
this.next().read_expr(), | ||
nullable, | ||
type, | ||
attrs || [] | ||
); | ||
} else { | ||
this.expect([",", ";", "="]); | ||
return result(propName, null, nullable, type); | ||
return result(propName, null, nullable, type, attrs || []); | ||
} | ||
@@ -189,3 +205,3 @@ }, | ||
*/ | ||
read_constant_list: function (flags) { | ||
read_constant_list: function (flags, attrs) { | ||
if (this.expect(this.tok.T_CONST)) { | ||
@@ -227,3 +243,3 @@ this.next(); | ||
return result(null, items, flags); | ||
return result(null, items, flags, attrs || []); | ||
}, | ||
@@ -323,3 +339,3 @@ /* | ||
} | ||
let type = this.read_type(); | ||
let type = this.read_types(); | ||
if (nullable && !type) { | ||
@@ -354,3 +370,3 @@ this.raiseError( | ||
*/ | ||
read_interface_declaration_statement: function () { | ||
read_interface_declaration_statement: function (attrs) { | ||
const result = this.node("interface"); | ||
@@ -370,3 +386,3 @@ if (this.token !== this.tok.T_INTERFACE) { | ||
const body = this.next().read_interface_body(); | ||
return result(propName, propExtends, body); | ||
return result(propName, propExtends, body, attrs || []); | ||
}, | ||
@@ -380,3 +396,4 @@ /* | ||
read_interface_body: function () { | ||
let result = []; | ||
let result = [], | ||
attrs = []; | ||
@@ -394,2 +411,5 @@ while (this.token !== this.EOF && this.token !== "}") { | ||
const locStart = this.position(); | ||
attrs = this.read_attr_list(); | ||
// read member flags | ||
@@ -400,3 +420,3 @@ const flags = this.read_member_flags(true); | ||
if (this.token == this.tok.T_CONST) { | ||
const constants = this.read_constant_list(flags); | ||
const constants = this.read_constant_list(flags, attrs); | ||
if (this.expect(";")) { | ||
@@ -406,5 +426,11 @@ this.next(); | ||
result = result.concat(constants); | ||
attrs = []; | ||
} else if (this.token === this.tok.T_FUNCTION) { | ||
// reads a function | ||
const method = this.read_function_declaration(2, flags); | ||
const method = this.read_function_declaration( | ||
2, | ||
flags, | ||
attrs, | ||
locStart | ||
); | ||
method.parseFlags(flags); | ||
@@ -415,2 +441,3 @@ result.push(method); | ||
} | ||
attrs = []; | ||
} else { | ||
@@ -417,0 +444,0 @@ // raise an error |
@@ -228,3 +228,5 @@ /** | ||
read_expr_item: function () { | ||
let result, expr; | ||
let result, | ||
expr, | ||
attrs = []; | ||
if (this.token === "+") | ||
@@ -279,2 +281,3 @@ return this.node("unary")("+", this.next().read_expr()); | ||
if (!hasItem) { | ||
/* istanbul ignore next */ | ||
this.raiseError( | ||
@@ -297,2 +300,3 @@ "Fatal Error : Cannot use empty list on line " + | ||
// error fallback : list($a, $b); | ||
/* istanbul ignore next */ | ||
return result(assignList, false); | ||
@@ -305,2 +309,6 @@ } | ||
if (this.token === this.tok.T_ATTRIBUTE) { | ||
attrs = this.read_attr_list(); | ||
} | ||
if (this.token === this.tok.T_CLONE) | ||
@@ -327,2 +335,5 @@ return this.node("clone")(this.next().read_expr()); | ||
return this.read_internal_functions_in_yacc(); | ||
case this.tok.T_MATCH: | ||
return this.read_match_expression(); | ||
case this.tok.T_INT_CAST: | ||
@@ -351,2 +362,10 @@ return this.read_expr_cast("int"); | ||
case this.tok.T_THROW: { | ||
if (this.version < 800) { | ||
this.raiseError("PHP 8+ is required to use throw as an expression"); | ||
} | ||
const result = this.node("throw"); | ||
const expr = this.next().read_expr(); | ||
return result(expr); | ||
} | ||
case this.tok.T_EXIT: { | ||
@@ -388,3 +407,3 @@ const useDie = this.lexer.yytext.toLowerCase() === "die"; | ||
case this.tok.T_FUNCTION: | ||
return this.read_inline_function(); | ||
return this.read_inline_function(undefined, attrs); | ||
@@ -399,3 +418,3 @@ case this.tok.T_STATIC: { | ||
// handles static function | ||
return this.read_inline_function([0, 1, 0]); | ||
return this.read_inline_function([0, 1, 0], attrs); | ||
} else { | ||
@@ -574,5 +593,7 @@ // rollback | ||
*/ | ||
read_inline_function: function (flags) { | ||
read_inline_function: function (flags, attrs) { | ||
if (this.token === this.tok.T_FUNCTION) { | ||
return this.read_function(true, flags); | ||
const result = this.read_function(true, flags, attrs); | ||
result.attrGroups = attrs; | ||
return result; | ||
} | ||
@@ -600,7 +621,7 @@ // introduced in PHP 7.4 | ||
} | ||
returnType = this.read_type(); | ||
returnType = this.read_types(); | ||
} | ||
if (this.expect(this.tok.T_DOUBLE_ARROW)) this.next(); | ||
const body = this.read_expr(); | ||
return node( | ||
const result = node( | ||
params, | ||
@@ -613,4 +634,84 @@ isRef, | ||
); | ||
result.attrGroups = attrs; | ||
return result; | ||
}, | ||
read_match_expression: function () { | ||
const node = this.node("match"); | ||
this.expect(this.tok.T_MATCH) && this.next(); | ||
if (this.version < 800) { | ||
this.raiseError("Match statements are not allowed before PHP 8"); | ||
} | ||
let cond = null; | ||
let arms = []; | ||
if (this.expect("(")) this.next(); | ||
cond = this.read_expr(); | ||
if (this.expect(")")) this.next(); | ||
if (this.expect("{")) this.next(); | ||
arms = this.read_match_arms(); | ||
if (this.expect("}")) this.next(); | ||
return node(cond, arms); | ||
}, | ||
read_match_arms: function () { | ||
return this.read_list(() => this.read_match_arm(), ",", true); | ||
}, | ||
read_match_arm: function () { | ||
if (this.token === "}") { | ||
return; | ||
} | ||
return this.node("matcharm")(this.read_match_arm_conds(), this.read_expr()); | ||
}, | ||
read_match_arm_conds: function () { | ||
let conds = []; | ||
if (this.token === this.tok.T_DEFAULT) { | ||
conds = null; | ||
this.next(); | ||
} else { | ||
conds.push(this.read_expr()); | ||
while (this.token === ",") { | ||
this.next(); | ||
if (this.token === this.tok.T_DOUBLE_ARROW) { | ||
this.next(); | ||
return conds; | ||
} | ||
conds.push(this.read_expr()); | ||
} | ||
} | ||
if (this.expect(this.tok.T_DOUBLE_ARROW)) { | ||
this.next(); | ||
} | ||
return conds; | ||
}, | ||
read_attribute() { | ||
const name = this.text(); | ||
let args = []; | ||
this.next(); | ||
if (this.token === "(") { | ||
args = this.read_argument_list(); | ||
} | ||
return this.node("attribute")(name, args); | ||
}, | ||
read_attr_list() { | ||
const list = []; | ||
if (this.token === this.tok.T_ATTRIBUTE) { | ||
do { | ||
const attrGr = this.node("attrgroup")([]); | ||
this.next(); | ||
attrGr.attrs.push(this.read_attribute()); | ||
while (this.token === ",") { | ||
this.next(); | ||
if (this.token !== "]") attrGr.attrs.push(this.read_attribute()); | ||
} | ||
list.push(attrGr); | ||
this.expect("]"); | ||
this.next(); | ||
} while (this.token === this.tok.T_ATTRIBUTE); | ||
} | ||
return list; | ||
}, | ||
/* | ||
@@ -626,2 +727,3 @@ * ```ebnf | ||
let args = []; | ||
const attrs = this.read_attr_list(); | ||
if (this.token === this.tok.T_CLASS) { | ||
@@ -639,6 +741,5 @@ const what = this.node("class"); | ||
} | ||
return result( | ||
what(null, propExtends, propImplements, body, [0, 0, 0]), | ||
args | ||
); | ||
const whatNode = what(null, propExtends, propImplements, body, [0, 0, 0]); | ||
whatNode.attrGroups = attrs; | ||
return result(whatNode, args); | ||
} | ||
@@ -645,0 +746,0 @@ // Already existing class |
@@ -35,6 +35,8 @@ /** | ||
*/ | ||
read_function: function (closure, flag) { | ||
read_function: function (closure, flag, attrs, locStart) { | ||
const result = this.read_function_declaration( | ||
closure ? 1 : flag ? 2 : 0, | ||
flag && flag[1] === 1 | ||
flag && flag[1] === 1, | ||
attrs || [], | ||
locStart | ||
); | ||
@@ -66,3 +68,3 @@ if (flag && flag[2] == 1) { | ||
*/ | ||
read_function_declaration: function (type, isStatic) { | ||
read_function_declaration: function (type, isStatic, attrs, locStart) { | ||
let nodeName = "function"; | ||
@@ -133,9 +135,28 @@ if (type === 1) { | ||
} | ||
returnType = this.read_type(); | ||
returnType = this.read_types(); | ||
} | ||
const apply_attrgroup_location = (node) => { | ||
node.attrGroups = attrs || []; | ||
if (locStart && node.loc) { | ||
node.loc.start = locStart; | ||
if (node.loc.source) { | ||
node.loc.source = this.lexer._input.substr( | ||
node.loc.start.offset, | ||
node.loc.end.offset - node.loc.start.offset | ||
); | ||
} | ||
} | ||
return node; | ||
}; | ||
if (type === 1) { | ||
// closure | ||
return result(params, isRef, use, returnType, nullable, isStatic); | ||
return apply_attrgroup_location( | ||
result(params, isRef, use, returnType, nullable, isStatic) | ||
); | ||
} | ||
return result(name, params, isRef, returnType, nullable); | ||
return apply_attrgroup_location( | ||
result(name, params, isRef, returnType, nullable) | ||
); | ||
}, | ||
@@ -156,4 +177,24 @@ | ||
read_list_with_dangling_comma: function (item) { | ||
const result = []; | ||
while (this.token != this.EOF) { | ||
result.push(item()); | ||
if (this.token == ",") { | ||
this.next(); | ||
if (this.version >= 800 && this.token === ")") { | ||
return result; | ||
} | ||
} else if (this.token == ")") { | ||
break; | ||
} else { | ||
this.error([",", ")"]); | ||
break; | ||
} | ||
} | ||
return result; | ||
}, | ||
read_lexical_var_list: function () { | ||
return this.read_list(this.read_lexical_var, ","); | ||
return this.read_list_with_dangling_comma(this.read_lexical_var.bind(this)); | ||
}, | ||
@@ -183,17 +224,6 @@ | ||
read_parameter_list: function () { | ||
const result = []; | ||
if (this.token != ")") { | ||
while (this.token != this.EOF) { | ||
result.push(this.read_parameter()); | ||
if (this.token == ",") { | ||
this.next(); | ||
} else if (this.token == ")") { | ||
break; | ||
} else { | ||
this.error([",", ")"]); | ||
break; | ||
} | ||
} | ||
return this.read_list_with_dangling_comma(this.read_parameter.bind(this)); | ||
} | ||
return result; | ||
return []; | ||
}, | ||
@@ -210,4 +240,7 @@ /* | ||
let value = null; | ||
let type = null; | ||
let types = null; | ||
let nullable = false; | ||
let attrs = []; | ||
if (this.token === this.tok.T_ATTRIBUTE) attrs = this.read_attr_list(); | ||
const flags = this.read_promoted(); | ||
if (this.token === "?") { | ||
@@ -217,4 +250,4 @@ this.next(); | ||
} | ||
type = this.read_type(); | ||
if (nullable && !type) { | ||
types = this.read_types(); | ||
if (nullable && !types) { | ||
this.raiseError( | ||
@@ -235,4 +268,47 @@ "Expecting a type definition combined with nullable operator" | ||
} | ||
return node(parameterName, type, value, isRef, isVariadic, nullable); | ||
const result = node( | ||
parameterName, | ||
types, | ||
value, | ||
isRef, | ||
isVariadic, | ||
nullable, | ||
flags | ||
); | ||
if (attrs) result.attrGroups = attrs; | ||
return result; | ||
}, | ||
read_types() { | ||
const types = []; | ||
const unionType = this.node("uniontype"); | ||
let type = this.read_type(); | ||
if (!type) return null; | ||
types.push(type); | ||
while (this.token === "|") { | ||
this.next(); | ||
type = this.read_type(); | ||
types.push(type); | ||
} | ||
if (types.length === 1) { | ||
return types[0]; | ||
} else { | ||
return unionType(types); | ||
} | ||
}, | ||
read_promoted() { | ||
const MODIFIER_PUBLIC = 1; | ||
const MODIFIER_PROTECTED = 2; | ||
const MODIFIER_PRIVATE = 4; | ||
if (this.token === this.tok.T_PUBLIC) { | ||
this.next(); | ||
return MODIFIER_PUBLIC; | ||
} else if (this.token === this.tok.T_PROTECTED) { | ||
this.next(); | ||
return MODIFIER_PROTECTED; | ||
} else if (this.token === this.tok.T_PRIVATE) { | ||
this.next(); | ||
return MODIFIER_PRIVATE; | ||
} | ||
return 0; | ||
}, | ||
/* | ||
@@ -277,3 +353,3 @@ * Reads a list of arguments | ||
* ```ebnf | ||
* argument_list ::= T_ELLIPSIS? expr | ||
* argument_list ::= T_STRING ':' expr | T_ELLIPSIS? expr | ||
* ``` | ||
@@ -285,2 +361,19 @@ */ | ||
} | ||
if ( | ||
this.token === this.tok.T_STRING || | ||
Object.values(this.lexer.keywords).includes(this.token) | ||
) { | ||
const lexerState = this.lexer.getState(); | ||
const nextToken = this.lexer.lex(); | ||
this.lexer.setState(lexerState); | ||
if (nextToken === ":") { | ||
if (this.version < 800) { | ||
this.raiseError("PHP 8+ is required to use named arguments"); | ||
} | ||
return this.node("namedargument")( | ||
this.text(), | ||
this.next().next().read_expr() | ||
); | ||
} | ||
} | ||
return this.read_expr(); | ||
@@ -300,3 +393,6 @@ }, | ||
return result("typereference", type.toLowerCase(), type); | ||
} else if (this.token === this.tok.T_STRING) { | ||
} else if ( | ||
this.token === this.tok.T_STRING || | ||
this.token === this.tok.T_STATIC | ||
) { | ||
const type = this.text(); | ||
@@ -303,0 +399,0 @@ const backup = [this.token, this.lexer.getState()]; |
@@ -40,5 +40,9 @@ /** | ||
read_top_statement: function () { | ||
let attrs = []; | ||
if (this.token === this.tok.T_ATTRIBUTE) { | ||
attrs = this.read_attr_list(); | ||
} | ||
switch (this.token) { | ||
case this.tok.T_FUNCTION: | ||
return this.read_function(false, false); | ||
return this.read_function(false, false, attrs); | ||
// optional flags | ||
@@ -48,5 +52,5 @@ case this.tok.T_ABSTRACT: | ||
case this.tok.T_CLASS: | ||
return this.read_class_declaration_statement(); | ||
return this.read_class_declaration_statement(attrs); | ||
case this.tok.T_INTERFACE: | ||
return this.read_interface_declaration_statement(); | ||
return this.read_interface_declaration_statement(attrs); | ||
case this.tok.T_TRAIT: | ||
@@ -155,5 +159,12 @@ return this.read_trait_declaration_statement(); | ||
read_inner_statement: function () { | ||
let attrs = []; | ||
if (this.token === this.tok.T_ATTRIBUTE) { | ||
attrs = this.read_attr_list(); | ||
} | ||
switch (this.token) { | ||
case this.tok.T_FUNCTION: | ||
return this.read_function(false, false); | ||
case this.tok.T_FUNCTION: { | ||
const result = this.read_function(false, false); | ||
result.attrGroups = attrs; | ||
return result; | ||
} | ||
// optional flags | ||
@@ -160,0 +171,0 @@ case this.tok.T_ABSTRACT: |
@@ -13,3 +13,3 @@ /** | ||
* ( | ||
* T_CATCH '(' namespace_name variable ')' '{' inner_statement* '}' | ||
* T_CATCH '(' namespace_name (variable)? ')' '{' inner_statement* '}' | ||
* )* | ||
@@ -32,3 +32,6 @@ * (T_FINALLY '{' inner_statement* '}')? | ||
const what = this.read_list(this.read_namespace_name, "|", false); | ||
const variable = this.read_variable(true, false); | ||
let variable = null; | ||
if (this.version < 800 || this.token === this.tok.T_VARIABLE) { | ||
variable = this.read_variable(true, false); | ||
} | ||
this.expect(")"); | ||
@@ -35,0 +38,0 @@ catches.push(item(this.next().read_statement(), what, variable)); |
@@ -17,2 +17,3 @@ /** | ||
const items = []; | ||
/* istanbul ignore next */ | ||
if (this.expect(":")) this.next(); | ||
@@ -29,2 +30,3 @@ while (this.token != this.EOF && this.token !== token) { | ||
} | ||
/* istanbul ignore next */ | ||
if (this.expect(token)) this.next(); | ||
@@ -155,2 +157,3 @@ this.expectEndOfStatement(); | ||
// plain variable name | ||
/* istanbul ignore else */ | ||
if (this.expect(this.tok.T_VARIABLE)) { | ||
@@ -157,0 +160,0 @@ const name = this.text().substring(1); |
@@ -231,2 +231,7 @@ /** | ||
} | ||
case this.tok.T_NULLSAFE_OBJECT_OPERATOR: { | ||
node = this.node("nullsafepropertylookup"); | ||
result = node(result, this.read_what()); | ||
break; | ||
} | ||
default: | ||
@@ -233,0 +238,0 @@ break recursive_scan_loop; |
@@ -9,145 +9,2 @@ /** | ||
/** | ||
* @memberOf module:php-parser | ||
* @readonly | ||
* @enum | ||
*/ | ||
const TokenNames = { | ||
T_HALT_COMPILER: 101, | ||
T_USE: 102, | ||
T_ENCAPSED_AND_WHITESPACE: 103, | ||
T_OBJECT_OPERATOR: 104, | ||
T_STRING: 105, | ||
T_DOLLAR_OPEN_CURLY_BRACES: 106, | ||
T_STRING_VARNAME: 107, | ||
T_CURLY_OPEN: 108, | ||
T_NUM_STRING: 109, | ||
T_ISSET: 110, | ||
T_EMPTY: 111, | ||
T_INCLUDE: 112, | ||
T_INCLUDE_ONCE: 113, | ||
T_EVAL: 114, | ||
T_REQUIRE: 115, | ||
T_REQUIRE_ONCE: 116, | ||
T_NAMESPACE: 117, | ||
T_NS_SEPARATOR: 118, | ||
T_AS: 119, | ||
T_IF: 120, | ||
T_ENDIF: 121, | ||
T_WHILE: 122, | ||
T_DO: 123, | ||
T_FOR: 124, | ||
T_SWITCH: 125, | ||
T_BREAK: 126, | ||
T_CONTINUE: 127, | ||
T_RETURN: 128, | ||
T_GLOBAL: 129, | ||
T_STATIC: 130, | ||
T_ECHO: 131, | ||
T_INLINE_HTML: 132, | ||
T_UNSET: 133, | ||
T_FOREACH: 134, | ||
T_DECLARE: 135, | ||
T_TRY: 136, | ||
T_THROW: 137, | ||
T_GOTO: 138, | ||
T_FINALLY: 139, | ||
T_CATCH: 140, | ||
T_ENDDECLARE: 141, | ||
T_LIST: 142, | ||
T_CLONE: 143, | ||
T_PLUS_EQUAL: 144, | ||
T_MINUS_EQUAL: 145, | ||
T_MUL_EQUAL: 146, | ||
T_DIV_EQUAL: 147, | ||
T_CONCAT_EQUAL: 148, | ||
T_MOD_EQUAL: 149, | ||
T_AND_EQUAL: 150, | ||
T_OR_EQUAL: 151, | ||
T_XOR_EQUAL: 152, | ||
T_SL_EQUAL: 153, | ||
T_SR_EQUAL: 154, | ||
T_INC: 155, | ||
T_DEC: 156, | ||
T_BOOLEAN_OR: 157, | ||
T_BOOLEAN_AND: 158, | ||
T_LOGICAL_OR: 159, | ||
T_LOGICAL_AND: 160, | ||
T_LOGICAL_XOR: 161, | ||
T_SL: 162, | ||
T_SR: 163, | ||
T_IS_IDENTICAL: 164, | ||
T_IS_NOT_IDENTICAL: 165, | ||
T_IS_EQUAL: 166, | ||
T_IS_NOT_EQUAL: 167, | ||
T_IS_SMALLER_OR_EQUAL: 168, | ||
T_IS_GREATER_OR_EQUAL: 169, | ||
T_INSTANCEOF: 170, | ||
T_INT_CAST: 171, | ||
T_DOUBLE_CAST: 172, | ||
T_STRING_CAST: 173, | ||
T_ARRAY_CAST: 174, | ||
T_OBJECT_CAST: 175, | ||
T_BOOL_CAST: 176, | ||
T_UNSET_CAST: 177, | ||
T_EXIT: 178, | ||
T_PRINT: 179, | ||
T_YIELD: 180, | ||
T_YIELD_FROM: 181, | ||
T_FUNCTION: 182, | ||
T_DOUBLE_ARROW: 183, | ||
T_DOUBLE_COLON: 184, | ||
T_ARRAY: 185, | ||
T_CALLABLE: 186, | ||
T_CLASS: 187, | ||
T_ABSTRACT: 188, | ||
T_TRAIT: 189, | ||
T_FINAL: 190, | ||
T_EXTENDS: 191, | ||
T_INTERFACE: 192, | ||
T_IMPLEMENTS: 193, | ||
T_VAR: 194, | ||
T_PUBLIC: 195, | ||
T_PROTECTED: 196, | ||
T_PRIVATE: 197, | ||
T_CONST: 198, | ||
T_NEW: 199, | ||
T_INSTEADOF: 200, | ||
T_ELSEIF: 201, | ||
T_ELSE: 202, | ||
T_ENDSWITCH: 203, | ||
T_CASE: 204, | ||
T_DEFAULT: 205, | ||
T_ENDFOR: 206, | ||
T_ENDFOREACH: 207, | ||
T_ENDWHILE: 208, | ||
T_CONSTANT_ENCAPSED_STRING: 209, | ||
T_LNUMBER: 210, | ||
T_DNUMBER: 211, | ||
T_LINE: 212, | ||
T_FILE: 213, | ||
T_DIR: 214, | ||
T_TRAIT_C: 215, | ||
T_METHOD_C: 216, | ||
T_FUNC_C: 217, | ||
T_NS_C: 218, | ||
T_START_HEREDOC: 219, | ||
T_END_HEREDOC: 220, | ||
T_CLASS_C: 221, | ||
T_VARIABLE: 222, | ||
T_OPEN_TAG: 223, | ||
T_OPEN_TAG_WITH_ECHO: 224, | ||
T_CLOSE_TAG: 225, | ||
T_WHITESPACE: 226, | ||
T_COMMENT: 227, | ||
T_DOC_COMMENT: 228, | ||
T_ELLIPSIS: 229, | ||
T_COALESCE: 230, | ||
T_POW: 231, | ||
T_POW_EQUAL: 232, | ||
T_SPACESHIP: 233, | ||
T_COALESCE_EQUAL: 234, | ||
T_FN: 235, | ||
}; | ||
/** | ||
* PHP AST Tokens | ||
@@ -298,6 +155,148 @@ * @readonly | ||
235: "T_FN", | ||
236: "T_NULLSAFE_OBJECT_OPERATOR", | ||
237: "T_MATCH", | ||
238: "T_ATTRIBUTE", | ||
}, | ||
names: TokenNames, | ||
names: { | ||
T_HALT_COMPILER: 101, | ||
T_USE: 102, | ||
T_ENCAPSED_AND_WHITESPACE: 103, | ||
T_OBJECT_OPERATOR: 104, | ||
T_STRING: 105, | ||
T_DOLLAR_OPEN_CURLY_BRACES: 106, | ||
T_STRING_VARNAME: 107, | ||
T_CURLY_OPEN: 108, | ||
T_NUM_STRING: 109, | ||
T_ISSET: 110, | ||
T_EMPTY: 111, | ||
T_INCLUDE: 112, | ||
T_INCLUDE_ONCE: 113, | ||
T_EVAL: 114, | ||
T_REQUIRE: 115, | ||
T_REQUIRE_ONCE: 116, | ||
T_NAMESPACE: 117, | ||
T_NS_SEPARATOR: 118, | ||
T_AS: 119, | ||
T_IF: 120, | ||
T_ENDIF: 121, | ||
T_WHILE: 122, | ||
T_DO: 123, | ||
T_FOR: 124, | ||
T_SWITCH: 125, | ||
T_BREAK: 126, | ||
T_CONTINUE: 127, | ||
T_RETURN: 128, | ||
T_GLOBAL: 129, | ||
T_STATIC: 130, | ||
T_ECHO: 131, | ||
T_INLINE_HTML: 132, | ||
T_UNSET: 133, | ||
T_FOREACH: 134, | ||
T_DECLARE: 135, | ||
T_TRY: 136, | ||
T_THROW: 137, | ||
T_GOTO: 138, | ||
T_FINALLY: 139, | ||
T_CATCH: 140, | ||
T_ENDDECLARE: 141, | ||
T_LIST: 142, | ||
T_CLONE: 143, | ||
T_PLUS_EQUAL: 144, | ||
T_MINUS_EQUAL: 145, | ||
T_MUL_EQUAL: 146, | ||
T_DIV_EQUAL: 147, | ||
T_CONCAT_EQUAL: 148, | ||
T_MOD_EQUAL: 149, | ||
T_AND_EQUAL: 150, | ||
T_OR_EQUAL: 151, | ||
T_XOR_EQUAL: 152, | ||
T_SL_EQUAL: 153, | ||
T_SR_EQUAL: 154, | ||
T_INC: 155, | ||
T_DEC: 156, | ||
T_BOOLEAN_OR: 157, | ||
T_BOOLEAN_AND: 158, | ||
T_LOGICAL_OR: 159, | ||
T_LOGICAL_AND: 160, | ||
T_LOGICAL_XOR: 161, | ||
T_SL: 162, | ||
T_SR: 163, | ||
T_IS_IDENTICAL: 164, | ||
T_IS_NOT_IDENTICAL: 165, | ||
T_IS_EQUAL: 166, | ||
T_IS_NOT_EQUAL: 167, | ||
T_IS_SMALLER_OR_EQUAL: 168, | ||
T_IS_GREATER_OR_EQUAL: 169, | ||
T_INSTANCEOF: 170, | ||
T_INT_CAST: 171, | ||
T_DOUBLE_CAST: 172, | ||
T_STRING_CAST: 173, | ||
T_ARRAY_CAST: 174, | ||
T_OBJECT_CAST: 175, | ||
T_BOOL_CAST: 176, | ||
T_UNSET_CAST: 177, | ||
T_EXIT: 178, | ||
T_PRINT: 179, | ||
T_YIELD: 180, | ||
T_YIELD_FROM: 181, | ||
T_FUNCTION: 182, | ||
T_DOUBLE_ARROW: 183, | ||
T_DOUBLE_COLON: 184, | ||
T_ARRAY: 185, | ||
T_CALLABLE: 186, | ||
T_CLASS: 187, | ||
T_ABSTRACT: 188, | ||
T_TRAIT: 189, | ||
T_FINAL: 190, | ||
T_EXTENDS: 191, | ||
T_INTERFACE: 192, | ||
T_IMPLEMENTS: 193, | ||
T_VAR: 194, | ||
T_PUBLIC: 195, | ||
T_PROTECTED: 196, | ||
T_PRIVATE: 197, | ||
T_CONST: 198, | ||
T_NEW: 199, | ||
T_INSTEADOF: 200, | ||
T_ELSEIF: 201, | ||
T_ELSE: 202, | ||
T_ENDSWITCH: 203, | ||
T_CASE: 204, | ||
T_DEFAULT: 205, | ||
T_ENDFOR: 206, | ||
T_ENDFOREACH: 207, | ||
T_ENDWHILE: 208, | ||
T_CONSTANT_ENCAPSED_STRING: 209, | ||
T_LNUMBER: 210, | ||
T_DNUMBER: 211, | ||
T_LINE: 212, | ||
T_FILE: 213, | ||
T_DIR: 214, | ||
T_TRAIT_C: 215, | ||
T_METHOD_C: 216, | ||
T_FUNC_C: 217, | ||
T_NS_C: 218, | ||
T_START_HEREDOC: 219, | ||
T_END_HEREDOC: 220, | ||
T_CLASS_C: 221, | ||
T_VARIABLE: 222, | ||
T_OPEN_TAG: 223, | ||
T_OPEN_TAG_WITH_ECHO: 224, | ||
T_CLOSE_TAG: 225, | ||
T_WHITESPACE: 226, | ||
T_COMMENT: 227, | ||
T_DOC_COMMENT: 228, | ||
T_ELLIPSIS: 229, | ||
T_COALESCE: 230, | ||
T_POW: 231, | ||
T_POW_EQUAL: 232, | ||
T_SPACESHIP: 233, | ||
T_COALESCE_EQUAL: 234, | ||
T_FN: 235, | ||
T_NULLSAFE_OBJECT_OPERATOR: 236, | ||
T_MATCH: 237, | ||
T_ATTRIBUTE: 238, | ||
}, | ||
}; | ||
module.exports = Object.freeze(tokens); |
@@ -132,3 +132,3 @@ declare module "php-parser" { | ||
extends: Identifier | null; | ||
implements: Identifier[]; | ||
implements: Identifier[] | null; | ||
body: Declaration[]; | ||
@@ -264,3 +264,3 @@ isAnonymous: boolean; | ||
test: Expression; | ||
body: Statement; | ||
body: Statement | null; | ||
} | ||
@@ -402,3 +402,3 @@ /** | ||
increment: Expression[]; | ||
body: Statement; | ||
body: Statement | null; | ||
shortForm: boolean; | ||
@@ -413,3 +413,3 @@ } | ||
value: Expression; | ||
body: Statement; | ||
body: Statement | null; | ||
shortForm: boolean; | ||
@@ -707,2 +707,4 @@ } | ||
properties: Property[]; | ||
visibility: string|null; | ||
isStatic: boolean; | ||
} | ||
@@ -824,3 +826,3 @@ /** | ||
catches: Catch[]; | ||
allways: Block; | ||
always: Block; | ||
} | ||
@@ -913,3 +915,3 @@ /** | ||
test: Expression; | ||
body: Statement; | ||
body: Statement | null; | ||
shortForm: boolean; | ||
@@ -1000,3 +1002,3 @@ } | ||
*/ | ||
tokenGetAll(buffer: string): String[]; | ||
tokenGetAll(buffer: string): (string | string[])[]; | ||
lexer: Lexer; | ||
@@ -1003,0 +1005,0 @@ parser: Parser; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
797250
151
21121
1
4