Updated nikic/PhpParser to version 5.2.0
This commit is contained in:
parent
a1404490bb
commit
923117999b
277 changed files with 12140 additions and 10393 deletions
|
@ -73,6 +73,7 @@ This update introduces a refactored code-base, code quality improvements, and be
|
|||
- Updated Symfony/polyfill-ctype to version 1.31.0
|
||||
- Updated Symfony/polyfill-mbstring to version 1.31.0
|
||||
- Updated Symfony/polyfill-uuid to version 1.31.0
|
||||
- Updated nikic/PhpParser to version 5.2.0
|
||||
|
||||
### Fixed
|
||||
- Fixed Division by zero in PackageManager
|
||||
|
|
|
@ -2,12 +2,11 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser;
|
||||
|
||||
interface Builder
|
||||
{
|
||||
interface Builder {
|
||||
/**
|
||||
* Returns the built node.
|
||||
*
|
||||
* @return Node The built node
|
||||
*/
|
||||
public function getNode() : Node;
|
||||
public function getNode(): Node;
|
||||
}
|
||||
|
|
|
@ -6,27 +6,29 @@ namespace ncc\ThirdParty\nikic\PhpParser\Builder;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser;
|
||||
use PhpParser\BuilderHelpers;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Const_;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Stmt;
|
||||
use PhpParser\Modifiers;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Const_;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Identifier;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Stmt;
|
||||
|
||||
class ClassConst implements PhpParser\Builder
|
||||
{
|
||||
protected $flags = 0;
|
||||
protected $attributes = [];
|
||||
protected $constants = [];
|
||||
class ClassConst implements PhpParser\Builder {
|
||||
protected int $flags = 0;
|
||||
/** @var array<string, mixed> */
|
||||
protected array $attributes = [];
|
||||
/** @var list<Const_> */
|
||||
protected array $constants = [];
|
||||
|
||||
/** @var Node\AttributeGroup[] */
|
||||
protected $attributeGroups = [];
|
||||
/** @var Identifier|Node\Name|Node\ComplexType */
|
||||
protected $type;
|
||||
/** @var list<Node\AttributeGroup> */
|
||||
protected array $attributeGroups = [];
|
||||
/** @var Identifier|Node\Name|Node\ComplexType|null */
|
||||
protected ?Node $type = null;
|
||||
|
||||
/**
|
||||
* Creates a class constant builder
|
||||
*
|
||||
* @param string|Identifier $name Name
|
||||
* @param Node\Expr|bool|null|int|float|string|array $value Value
|
||||
* @param string|Identifier $name Name
|
||||
* @param Node\Expr|bool|null|int|float|string|array|\UnitEnum $value Value
|
||||
*/
|
||||
public function __construct($name, $value) {
|
||||
$this->constants = [new Const_($name, BuilderHelpers::normalizeValue($value))];
|
||||
|
@ -35,8 +37,8 @@ class ClassConst implements PhpParser\Builder
|
|||
/**
|
||||
* Add another constant to const group
|
||||
*
|
||||
* @param string|Identifier $name Name
|
||||
* @param Node\Expr|bool|null|int|float|string|array $value Value
|
||||
* @param string|Identifier $name Name
|
||||
* @param Node\Expr|bool|null|int|float|string|array|\UnitEnum $value Value
|
||||
*
|
||||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
|
@ -52,7 +54,7 @@ class ClassConst implements PhpParser\Builder
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makePublic() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PUBLIC);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -63,7 +65,7 @@ class ClassConst implements PhpParser\Builder
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeProtected() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PROTECTED);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -74,7 +76,7 @@ class ClassConst implements PhpParser\Builder
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makePrivate() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PRIVATE);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -85,7 +87,7 @@ class ClassConst implements PhpParser\Builder
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeFinal() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_FINAL);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::FINAL);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
|
@ -4,25 +4,27 @@ namespace ncc\ThirdParty\nikic\PhpParser\Builder;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser;
|
||||
use PhpParser\BuilderHelpers;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Stmt;
|
||||
use PhpParser\Modifiers;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Name;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Stmt;
|
||||
|
||||
class Class_ extends Declaration
|
||||
{
|
||||
protected $name;
|
||||
|
||||
protected $extends = null;
|
||||
protected $implements = [];
|
||||
protected $flags = 0;
|
||||
|
||||
protected $uses = [];
|
||||
protected $constants = [];
|
||||
protected $properties = [];
|
||||
protected $methods = [];
|
||||
|
||||
/** @var Node\AttributeGroup[] */
|
||||
protected $attributeGroups = [];
|
||||
class Class_ extends Declaration {
|
||||
protected string $name;
|
||||
protected ?Name $extends = null;
|
||||
/** @var list<Name> */
|
||||
protected array $implements = [];
|
||||
protected int $flags = 0;
|
||||
/** @var list<Stmt\TraitUse> */
|
||||
protected array $uses = [];
|
||||
/** @var list<Stmt\ClassConst> */
|
||||
protected array $constants = [];
|
||||
/** @var list<Stmt\Property> */
|
||||
protected array $properties = [];
|
||||
/** @var list<Stmt\ClassMethod> */
|
||||
protected array $methods = [];
|
||||
/** @var list<Node\AttributeGroup> */
|
||||
protected array $attributeGroups = [];
|
||||
|
||||
/**
|
||||
* Creates a class builder.
|
||||
|
@ -67,7 +69,7 @@ class Class_ extends Declaration
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeAbstract() {
|
||||
$this->flags = BuilderHelpers::addClassModifier($this->flags, Stmt\Class_::MODIFIER_ABSTRACT);
|
||||
$this->flags = BuilderHelpers::addClassModifier($this->flags, Modifiers::ABSTRACT);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -78,13 +80,18 @@ class Class_ extends Declaration
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeFinal() {
|
||||
$this->flags = BuilderHelpers::addClassModifier($this->flags, Stmt\Class_::MODIFIER_FINAL);
|
||||
$this->flags = BuilderHelpers::addClassModifier($this->flags, Modifiers::FINAL);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the class readonly.
|
||||
*
|
||||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeReadonly() {
|
||||
$this->flags = BuilderHelpers::addClassModifier($this->flags, Stmt\Class_::MODIFIER_READONLY);
|
||||
$this->flags = BuilderHelpers::addClassModifier($this->flags, Modifiers::READONLY);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -99,20 +106,18 @@ class Class_ extends Declaration
|
|||
public function addStmt($stmt) {
|
||||
$stmt = BuilderHelpers::normalizeNode($stmt);
|
||||
|
||||
$targets = [
|
||||
Stmt\TraitUse::class => &$this->uses,
|
||||
Stmt\ClassConst::class => &$this->constants,
|
||||
Stmt\Property::class => &$this->properties,
|
||||
Stmt\ClassMethod::class => &$this->methods,
|
||||
];
|
||||
|
||||
$class = \get_class($stmt);
|
||||
if (!isset($targets[$class])) {
|
||||
if ($stmt instanceof Stmt\Property) {
|
||||
$this->properties[] = $stmt;
|
||||
} elseif ($stmt instanceof Stmt\ClassMethod) {
|
||||
$this->methods[] = $stmt;
|
||||
} elseif ($stmt instanceof Stmt\TraitUse) {
|
||||
$this->uses[] = $stmt;
|
||||
} elseif ($stmt instanceof Stmt\ClassConst) {
|
||||
$this->constants[] = $stmt;
|
||||
} else {
|
||||
throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType()));
|
||||
}
|
||||
|
||||
$targets[$class][] = $stmt;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -134,7 +139,7 @@ class Class_ extends Declaration
|
|||
*
|
||||
* @return Stmt\Class_ The built class node
|
||||
*/
|
||||
public function getNode() : PhpParser\Node {
|
||||
public function getNode(): PhpParser\Node {
|
||||
return new Stmt\Class_($this->name, [
|
||||
'flags' => $this->flags,
|
||||
'extends' => $this->extends,
|
||||
|
|
|
@ -5,16 +5,23 @@ namespace ncc\ThirdParty\nikic\PhpParser\Builder;
|
|||
use ncc\ThirdParty\nikic\PhpParser;
|
||||
use PhpParser\BuilderHelpers;
|
||||
|
||||
abstract class Declaration implements PhpParser\Builder
|
||||
{
|
||||
protected $attributes = [];
|
||||
abstract class Declaration implements PhpParser\Builder {
|
||||
/** @var array<string, mixed> */
|
||||
protected array $attributes = [];
|
||||
|
||||
/**
|
||||
* Adds a statement.
|
||||
*
|
||||
* @param \ncc\ThirdParty\nikic\PhpParser\Node\Stmt|PhpParser\Builder $stmt The statement to add
|
||||
*
|
||||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
abstract public function addStmt($stmt);
|
||||
|
||||
/**
|
||||
* Adds multiple statements.
|
||||
*
|
||||
* @param array $stmts The statements to add
|
||||
* @param (\ncc\ThirdParty\nikic\PhpParser\Node\Stmt|PhpParser\Builder)[] $stmts The statements to add
|
||||
*
|
||||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
|
|
|
@ -6,23 +6,24 @@ namespace ncc\ThirdParty\nikic\PhpParser\Builder;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser;
|
||||
use PhpParser\BuilderHelpers;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Stmt;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Identifier;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Stmt;
|
||||
|
||||
class EnumCase implements PhpParser\Builder
|
||||
{
|
||||
class EnumCase implements PhpParser\Builder {
|
||||
/** @var Identifier|string */
|
||||
protected $name;
|
||||
protected $value = null;
|
||||
protected $attributes = [];
|
||||
protected ?Node\Expr $value = null;
|
||||
/** @var array<string, mixed> */
|
||||
protected array $attributes = [];
|
||||
|
||||
/** @var Node\AttributeGroup[] */
|
||||
protected $attributeGroups = [];
|
||||
/** @var list<Node\AttributeGroup> */
|
||||
protected array $attributeGroups = [];
|
||||
|
||||
/**
|
||||
* Creates an enum case builder.
|
||||
*
|
||||
* @param string|Identifier $name Name
|
||||
* @param string|Identifier $name Name
|
||||
*/
|
||||
public function __construct($name) {
|
||||
$this->name = $name;
|
||||
|
|
|
@ -4,25 +4,26 @@ namespace ncc\ThirdParty\nikic\PhpParser\Builder;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser;
|
||||
use PhpParser\BuilderHelpers;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Stmt;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Identifier;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Name;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Stmt;
|
||||
|
||||
class Enum_ extends Declaration
|
||||
{
|
||||
protected $name;
|
||||
protected $scalarType = null;
|
||||
|
||||
protected $implements = [];
|
||||
|
||||
protected $uses = [];
|
||||
protected $enumCases = [];
|
||||
protected $constants = [];
|
||||
protected $methods = [];
|
||||
|
||||
/** @var Node\AttributeGroup[] */
|
||||
protected $attributeGroups = [];
|
||||
class Enum_ extends Declaration {
|
||||
protected string $name;
|
||||
protected ?Identifier $scalarType = null;
|
||||
/** @var list<Name> */
|
||||
protected array $implements = [];
|
||||
/** @var list<Stmt\TraitUse> */
|
||||
protected array $uses = [];
|
||||
/** @var list<Stmt\EnumCase> */
|
||||
protected array $enumCases = [];
|
||||
/** @var list<Stmt\ClassConst> */
|
||||
protected array $constants = [];
|
||||
/** @var list<Stmt\ClassMethod> */
|
||||
protected array $methods = [];
|
||||
/** @var list<Node\AttributeGroup> */
|
||||
protected array $attributeGroups = [];
|
||||
|
||||
/**
|
||||
* Creates an enum builder.
|
||||
|
@ -36,7 +37,7 @@ class Enum_ extends Declaration
|
|||
/**
|
||||
* Sets the scalar type.
|
||||
*
|
||||
* @param string|Identifier $type
|
||||
* @param string|Identifier $scalarType
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
|
@ -71,20 +72,18 @@ class Enum_ extends Declaration
|
|||
public function addStmt($stmt) {
|
||||
$stmt = BuilderHelpers::normalizeNode($stmt);
|
||||
|
||||
$targets = [
|
||||
Stmt\TraitUse::class => &$this->uses,
|
||||
Stmt\EnumCase::class => &$this->enumCases,
|
||||
Stmt\ClassConst::class => &$this->constants,
|
||||
Stmt\ClassMethod::class => &$this->methods,
|
||||
];
|
||||
|
||||
$class = \get_class($stmt);
|
||||
if (!isset($targets[$class])) {
|
||||
if ($stmt instanceof Stmt\EnumCase) {
|
||||
$this->enumCases[] = $stmt;
|
||||
} elseif ($stmt instanceof Stmt\ClassMethod) {
|
||||
$this->methods[] = $stmt;
|
||||
} elseif ($stmt instanceof Stmt\TraitUse) {
|
||||
$this->uses[] = $stmt;
|
||||
} elseif ($stmt instanceof Stmt\ClassConst) {
|
||||
$this->constants[] = $stmt;
|
||||
} else {
|
||||
throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType()));
|
||||
}
|
||||
|
||||
$targets[$class][] = $stmt;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -106,7 +105,7 @@ class Enum_ extends Declaration
|
|||
*
|
||||
* @return Stmt\Enum_ The built enum node
|
||||
*/
|
||||
public function getNode() : PhpParser\Node {
|
||||
public function getNode(): PhpParser\Node {
|
||||
return new Stmt\Enum_($this->name, [
|
||||
'scalarType' => $this->scalarType,
|
||||
'implements' => $this->implements,
|
||||
|
|
|
@ -5,13 +5,13 @@ namespace ncc\ThirdParty\nikic\PhpParser\Builder;
|
|||
use ncc\ThirdParty\nikic\PhpParser\BuilderHelpers;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
|
||||
abstract class FunctionLike extends Declaration
|
||||
{
|
||||
protected $returnByRef = false;
|
||||
protected $params = [];
|
||||
abstract class FunctionLike extends Declaration {
|
||||
protected bool $returnByRef = false;
|
||||
/** @var Node\Param[] */
|
||||
protected array $params = [];
|
||||
|
||||
/** @var string|Node\Name|Node\NullableType|null */
|
||||
protected $returnType = null;
|
||||
/** @var Node\Identifier|Node\Name|Node\ComplexType|null */
|
||||
protected ?Node $returnType = null;
|
||||
|
||||
/**
|
||||
* Make the function return by reference.
|
||||
|
@ -46,7 +46,7 @@ abstract class FunctionLike extends Declaration
|
|||
/**
|
||||
* Adds multiple parameters.
|
||||
*
|
||||
* @param array $params The parameters to add
|
||||
* @param (Node\Param|Param)[] $params The parameters to add
|
||||
*
|
||||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
|
|
|
@ -4,16 +4,16 @@ namespace ncc\ThirdParty\nikic\PhpParser\Builder;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser;
|
||||
use PhpParser\BuilderHelpers;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Stmt;
|
||||
|
||||
class Function_ extends FunctionLike
|
||||
{
|
||||
protected $name;
|
||||
protected $stmts = [];
|
||||
class Function_ extends FunctionLike {
|
||||
protected string $name;
|
||||
/** @var list<Stmt> */
|
||||
protected array $stmts = [];
|
||||
|
||||
/** @var Node\AttributeGroup[] */
|
||||
protected $attributeGroups = [];
|
||||
/** @var list<Node\AttributeGroup> */
|
||||
protected array $attributeGroups = [];
|
||||
|
||||
/**
|
||||
* Creates a function builder.
|
||||
|
@ -55,7 +55,7 @@ class Function_ extends FunctionLike
|
|||
*
|
||||
* @return Stmt\Function_ The built function node
|
||||
*/
|
||||
public function getNode() : Node {
|
||||
public function getNode(): Node {
|
||||
return new Stmt\Function_($this->name, [
|
||||
'byRef' => $this->returnByRef,
|
||||
'params' => $this->params,
|
||||
|
|
|
@ -4,19 +4,20 @@ namespace ncc\ThirdParty\nikic\PhpParser\Builder;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser;
|
||||
use PhpParser\BuilderHelpers;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Stmt;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Name;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Stmt;
|
||||
|
||||
class Interface_ extends Declaration
|
||||
{
|
||||
protected $name;
|
||||
protected $extends = [];
|
||||
protected $constants = [];
|
||||
protected $methods = [];
|
||||
|
||||
/** @var Node\AttributeGroup[] */
|
||||
protected $attributeGroups = [];
|
||||
class Interface_ extends Declaration {
|
||||
protected string $name;
|
||||
/** @var list<Name> */
|
||||
protected array $extends = [];
|
||||
/** @var list<Stmt\ClassConst> */
|
||||
protected array $constants = [];
|
||||
/** @var list<Stmt\ClassMethod> */
|
||||
protected array $methods = [];
|
||||
/** @var list<Node\AttributeGroup> */
|
||||
protected array $attributeGroups = [];
|
||||
|
||||
/**
|
||||
* Creates an interface builder.
|
||||
|
@ -83,7 +84,7 @@ class Interface_ extends Declaration
|
|||
*
|
||||
* @return Stmt\Interface_ The built interface node
|
||||
*/
|
||||
public function getNode() : PhpParser\Node {
|
||||
public function getNode(): PhpParser\Node {
|
||||
return new Stmt\Interface_($this->name, [
|
||||
'extends' => $this->extends,
|
||||
'stmts' => array_merge($this->constants, $this->methods),
|
||||
|
|
|
@ -4,19 +4,20 @@ namespace ncc\ThirdParty\nikic\PhpParser\Builder;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser;
|
||||
use PhpParser\BuilderHelpers;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt;
|
||||
use PhpParser\Modifiers;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Stmt;
|
||||
|
||||
class Method extends FunctionLike
|
||||
{
|
||||
protected $name;
|
||||
protected $flags = 0;
|
||||
class Method extends FunctionLike {
|
||||
protected string $name;
|
||||
|
||||
/** @var array|null */
|
||||
protected $stmts = [];
|
||||
protected int $flags = 0;
|
||||
|
||||
/** @var Node\AttributeGroup[] */
|
||||
protected $attributeGroups = [];
|
||||
/** @var list<Stmt>|null */
|
||||
protected ?array $stmts = [];
|
||||
|
||||
/** @var list<Node\AttributeGroup> */
|
||||
protected array $attributeGroups = [];
|
||||
|
||||
/**
|
||||
* Creates a method builder.
|
||||
|
@ -33,7 +34,7 @@ class Method extends FunctionLike
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makePublic() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PUBLIC);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -44,7 +45,7 @@ class Method extends FunctionLike
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeProtected() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PROTECTED);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -55,7 +56,7 @@ class Method extends FunctionLike
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makePrivate() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PRIVATE);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -66,7 +67,7 @@ class Method extends FunctionLike
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeStatic() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_STATIC);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::STATIC);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -81,7 +82,7 @@ class Method extends FunctionLike
|
|||
throw new \LogicException('Cannot make method with statements abstract');
|
||||
}
|
||||
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_ABSTRACT);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::ABSTRACT);
|
||||
$this->stmts = null; // abstract methods don't have statements
|
||||
|
||||
return $this;
|
||||
|
@ -93,7 +94,7 @@ class Method extends FunctionLike
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeFinal() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_FINAL);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::FINAL);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -133,7 +134,7 @@ class Method extends FunctionLike
|
|||
*
|
||||
* @return Stmt\ClassMethod The built method node
|
||||
*/
|
||||
public function getNode() : Node {
|
||||
public function getNode(): Node {
|
||||
return new Stmt\ClassMethod($this->name, [
|
||||
'flags' => $this->flags,
|
||||
'byRef' => $this->returnByRef,
|
||||
|
|
|
@ -4,13 +4,13 @@ namespace ncc\ThirdParty\nikic\PhpParser\Builder;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser;
|
||||
use PhpParser\BuilderHelpers;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Stmt;
|
||||
|
||||
class Namespace_ extends Declaration
|
||||
{
|
||||
private $name;
|
||||
private $stmts = [];
|
||||
class Namespace_ extends Declaration {
|
||||
private ?Node\Name $name;
|
||||
/** @var Stmt[] */
|
||||
private array $stmts = [];
|
||||
|
||||
/**
|
||||
* Creates a namespace builder.
|
||||
|
@ -39,7 +39,7 @@ class Namespace_ extends Declaration
|
|||
*
|
||||
* @return Stmt\Namespace_ The built node
|
||||
*/
|
||||
public function getNode() : Node {
|
||||
public function getNode(): Node {
|
||||
return new Stmt\Namespace_($this->name, $this->stmts, $this->attributes);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,25 +4,19 @@ namespace ncc\ThirdParty\nikic\PhpParser\Builder;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser;
|
||||
use PhpParser\BuilderHelpers;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Modifiers;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
|
||||
class Param implements PhpParser\Builder
|
||||
{
|
||||
protected $name;
|
||||
|
||||
protected $default = null;
|
||||
|
||||
/** @var Node\Identifier|Node\Name|Node\NullableType|null */
|
||||
protected $type = null;
|
||||
|
||||
protected $byRef = false;
|
||||
|
||||
protected $variadic = false;
|
||||
|
||||
protected $flags = 0;
|
||||
|
||||
/** @var Node\AttributeGroup[] */
|
||||
protected $attributeGroups = [];
|
||||
class Param implements PhpParser\Builder {
|
||||
protected string $name;
|
||||
protected ?Node\Expr $default = null;
|
||||
/** @var Node\Identifier|Node\Name|Node\ComplexType|null */
|
||||
protected ?Node $type = null;
|
||||
protected bool $byRef = false;
|
||||
protected int $flags = 0;
|
||||
protected bool $variadic = false;
|
||||
/** @var list<Node\AttributeGroup> */
|
||||
protected array $attributeGroups = [];
|
||||
|
||||
/**
|
||||
* Creates a parameter builder.
|
||||
|
@ -62,19 +56,6 @@ class Param implements PhpParser\Builder
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets type for the parameter.
|
||||
*
|
||||
* @param string|Node\Name|Node\Identifier|Node\ComplexType $type Parameter type
|
||||
*
|
||||
* @return $this The builder instance (for fluid interface)
|
||||
*
|
||||
* @deprecated Use setType() instead
|
||||
*/
|
||||
public function setTypeHint($type) {
|
||||
return $this->setType($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the parameter accept the value by reference.
|
||||
*
|
||||
|
@ -103,7 +84,7 @@ class Param implements PhpParser\Builder
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makePublic() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Node\Stmt\Class_::MODIFIER_PUBLIC);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PUBLIC);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -114,7 +95,7 @@ class Param implements PhpParser\Builder
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeProtected() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Node\Stmt\Class_::MODIFIER_PROTECTED);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PROTECTED);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -125,7 +106,7 @@ class Param implements PhpParser\Builder
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makePrivate() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Node\Stmt\Class_::MODIFIER_PRIVATE);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PRIVATE);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -136,7 +117,29 @@ class Param implements PhpParser\Builder
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeReadonly() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Node\Stmt\Class_::MODIFIER_READONLY);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::READONLY);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the promoted property private(set) visibility.
|
||||
*
|
||||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makePrivateSet() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PRIVATE_SET);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the promoted property protected(set) visibility.
|
||||
*
|
||||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeProtectedSet() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PROTECTED_SET);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -159,7 +162,7 @@ class Param implements PhpParser\Builder
|
|||
*
|
||||
* @return Node\Param The built parameter node
|
||||
*/
|
||||
public function getNode() : Node {
|
||||
public function getNode(): Node {
|
||||
return new Node\Param(
|
||||
new Node\Expr\Variable($this->name),
|
||||
$this->default, $this->type, $this->byRef, $this->variadic, [], $this->flags, $this->attributeGroups
|
||||
|
|
|
@ -4,25 +4,27 @@ namespace ncc\ThirdParty\nikic\PhpParser\Builder;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser;
|
||||
use PhpParser\BuilderHelpers;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Stmt;
|
||||
use PhpParser\Node\ComplexType;
|
||||
use PhpParser\Modifiers;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Identifier;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Name;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Stmt;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\ComplexType;
|
||||
|
||||
class Property implements PhpParser\Builder
|
||||
{
|
||||
protected $name;
|
||||
class Property implements PhpParser\Builder {
|
||||
protected string $name;
|
||||
|
||||
protected $flags = 0;
|
||||
protected $default = null;
|
||||
protected $attributes = [];
|
||||
protected int $flags = 0;
|
||||
|
||||
/** @var null|Identifier|Name|NullableType */
|
||||
protected $type;
|
||||
|
||||
/** @var Node\AttributeGroup[] */
|
||||
protected $attributeGroups = [];
|
||||
protected ?Node\Expr $default = null;
|
||||
/** @var array<string, mixed> */
|
||||
protected array $attributes = [];
|
||||
/** @var null|Identifier|Name|ComplexType */
|
||||
protected ?Node $type = null;
|
||||
/** @var list<Node\AttributeGroup> */
|
||||
protected array $attributeGroups = [];
|
||||
/** @var list<Node\PropertyHook> */
|
||||
protected array $hooks = [];
|
||||
|
||||
/**
|
||||
* Creates a property builder.
|
||||
|
@ -39,7 +41,7 @@ class Property implements PhpParser\Builder
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makePublic() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PUBLIC);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -50,7 +52,7 @@ class Property implements PhpParser\Builder
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeProtected() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PROTECTED);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -61,7 +63,7 @@ class Property implements PhpParser\Builder
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makePrivate() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PRIVATE);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -72,7 +74,7 @@ class Property implements PhpParser\Builder
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeStatic() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_STATIC);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::STATIC);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -83,7 +85,51 @@ class Property implements PhpParser\Builder
|
|||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeReadonly() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_READONLY);
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::READONLY);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the property abstract. Requires at least one property hook to be specified as well.
|
||||
*
|
||||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeAbstract() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::ABSTRACT);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the property final.
|
||||
*
|
||||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeFinal() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::FINAL);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the property private(set) visibility.
|
||||
*
|
||||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makePrivateSet() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PRIVATE_SET);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the property protected(set) visibility.
|
||||
*
|
||||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeProtectedSet() {
|
||||
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PROTECTED_SET);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -142,20 +188,36 @@ class Property implements PhpParser\Builder
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a property hook.
|
||||
*
|
||||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function addHook(Node\PropertyHook $hook) {
|
||||
$this->hooks[] = $hook;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the built class node.
|
||||
*
|
||||
* @return Stmt\Property The built property node
|
||||
*/
|
||||
public function getNode() : PhpParser\Node {
|
||||
public function getNode(): PhpParser\Node {
|
||||
if ($this->flags & Modifiers::ABSTRACT && !$this->hooks) {
|
||||
throw new PhpParser\Error('Only hooked properties may be declared abstract');
|
||||
}
|
||||
|
||||
return new Stmt\Property(
|
||||
$this->flags !== 0 ? $this->flags : Stmt\Class_::MODIFIER_PUBLIC,
|
||||
$this->flags !== 0 ? $this->flags : Modifiers::PUBLIC,
|
||||
[
|
||||
new Stmt\PropertyProperty($this->name, $this->default)
|
||||
new Node\PropertyItem($this->name, $this->default)
|
||||
],
|
||||
$this->attributes,
|
||||
$this->type,
|
||||
$this->attributeGroups
|
||||
$this->attributeGroups,
|
||||
$this->hooks
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,11 @@ use ncc\ThirdParty\nikic\PhpParser\BuilderHelpers;
|
|||
use ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Stmt;
|
||||
|
||||
class TraitUse implements Builder
|
||||
{
|
||||
protected $traits = [];
|
||||
protected $adaptations = [];
|
||||
class TraitUse implements Builder {
|
||||
/** @var Node\Name[] */
|
||||
protected array $traits = [];
|
||||
/** @var Stmt\TraitUseAdaptation[] */
|
||||
protected array $adaptations = [];
|
||||
|
||||
/**
|
||||
* Creates a trait use builder.
|
||||
|
@ -58,7 +59,7 @@ class TraitUse implements Builder
|
|||
*
|
||||
* @return Node The built node
|
||||
*/
|
||||
public function getNode() : Node {
|
||||
public function getNode(): Node {
|
||||
return new Stmt\TraitUse($this->traits, $this->adaptations);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,43 +4,40 @@ namespace ncc\ThirdParty\nikic\PhpParser\Builder;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Builder;
|
||||
use ncc\ThirdParty\nikic\PhpParser\BuilderHelpers;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Modifiers;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Stmt;
|
||||
|
||||
class TraitUseAdaptation implements Builder
|
||||
{
|
||||
const TYPE_UNDEFINED = 0;
|
||||
const TYPE_ALIAS = 1;
|
||||
const TYPE_PRECEDENCE = 2;
|
||||
class TraitUseAdaptation implements Builder {
|
||||
private const TYPE_UNDEFINED = 0;
|
||||
private const TYPE_ALIAS = 1;
|
||||
private const TYPE_PRECEDENCE = 2;
|
||||
|
||||
/** @var int Type of building adaptation */
|
||||
protected $type;
|
||||
|
||||
protected $trait;
|
||||
protected $method;
|
||||
|
||||
protected $modifier = null;
|
||||
protected $alias = null;
|
||||
|
||||
protected $insteadof = [];
|
||||
protected int $type;
|
||||
protected ?Node\Name $trait;
|
||||
protected Node\Identifier $method;
|
||||
protected ?int $modifier = null;
|
||||
protected ?Node\Identifier $alias = null;
|
||||
/** @var Node\Name[] */
|
||||
protected array $insteadof = [];
|
||||
|
||||
/**
|
||||
* Creates a trait use adaptation builder.
|
||||
*
|
||||
* @param Node\Name|string|null $trait Name of adaptated trait
|
||||
* @param Node\Identifier|string $method Name of adaptated method
|
||||
* @param Node\Name|string|null $trait Name of adapted trait
|
||||
* @param Node\Identifier|string $method Name of adapted method
|
||||
*/
|
||||
public function __construct($trait, $method) {
|
||||
$this->type = self::TYPE_UNDEFINED;
|
||||
|
||||
$this->trait = is_null($trait)? null: BuilderHelpers::normalizeName($trait);
|
||||
$this->trait = is_null($trait) ? null : BuilderHelpers::normalizeName($trait);
|
||||
$this->method = BuilderHelpers::normalizeIdentifier($method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets alias of method.
|
||||
*
|
||||
* @param Node\Identifier|string $alias Alias for adaptated method
|
||||
* @param Node\Identifier|string $alias Alias for adapted method
|
||||
*
|
||||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
|
@ -53,37 +50,37 @@ class TraitUseAdaptation implements Builder
|
|||
throw new \LogicException('Cannot set alias for not alias adaptation buider');
|
||||
}
|
||||
|
||||
$this->alias = $alias;
|
||||
$this->alias = BuilderHelpers::normalizeIdentifier($alias);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets adaptated method public.
|
||||
* Sets adapted method public.
|
||||
*
|
||||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makePublic() {
|
||||
$this->setModifier(Stmt\Class_::MODIFIER_PUBLIC);
|
||||
$this->setModifier(Modifiers::PUBLIC);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets adaptated method protected.
|
||||
* Sets adapted method protected.
|
||||
*
|
||||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeProtected() {
|
||||
$this->setModifier(Stmt\Class_::MODIFIER_PROTECTED);
|
||||
$this->setModifier(Modifiers::PROTECTED);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets adaptated method private.
|
||||
* Sets adapted method private.
|
||||
*
|
||||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makePrivate() {
|
||||
$this->setModifier(Stmt\Class_::MODIFIER_PRIVATE);
|
||||
$this->setModifier(Modifiers::PRIVATE);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -114,7 +111,7 @@ class TraitUseAdaptation implements Builder
|
|||
return $this;
|
||||
}
|
||||
|
||||
protected function setModifier(int $modifier) {
|
||||
protected function setModifier(int $modifier): void {
|
||||
if ($this->type === self::TYPE_UNDEFINED) {
|
||||
$this->type = self::TYPE_ALIAS;
|
||||
}
|
||||
|
@ -135,12 +132,12 @@ class TraitUseAdaptation implements Builder
|
|||
*
|
||||
* @return Node The built node
|
||||
*/
|
||||
public function getNode() : Node {
|
||||
public function getNode(): Node {
|
||||
switch ($this->type) {
|
||||
case self::TYPE_ALIAS:
|
||||
return new Stmt\TraitUseAdaptation\Alias($this->trait, $this->method, $this->modifier, $this->alias);
|
||||
return new \ncc\ThirdParty\nikic\PhpParser\Node\Stmt\TraitUseAdaptation\Alias($this->trait, $this->method, $this->modifier, $this->alias);
|
||||
case self::TYPE_PRECEDENCE:
|
||||
return new Stmt\TraitUseAdaptation\Precedence($this->trait, $this->method, $this->insteadof);
|
||||
return new \ncc\ThirdParty\nikic\PhpParser\Node\Stmt\TraitUseAdaptation\Precedence($this->trait, $this->method, $this->insteadof);
|
||||
default:
|
||||
throw new \LogicException('Type of adaptation is not defined');
|
||||
}
|
||||
|
|
|
@ -4,18 +4,21 @@ namespace ncc\ThirdParty\nikic\PhpParser\Builder;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser;
|
||||
use PhpParser\BuilderHelpers;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Stmt;
|
||||
|
||||
class Trait_ extends Declaration
|
||||
{
|
||||
protected $name;
|
||||
protected $uses = [];
|
||||
protected $properties = [];
|
||||
protected $methods = [];
|
||||
|
||||
/** @var Node\AttributeGroup[] */
|
||||
protected $attributeGroups = [];
|
||||
class Trait_ extends Declaration {
|
||||
protected string $name;
|
||||
/** @var list<Stmt\TraitUse> */
|
||||
protected array $uses = [];
|
||||
/** @var list<Stmt\ClassConst> */
|
||||
protected array $constants = [];
|
||||
/** @var list<Stmt\Property> */
|
||||
protected array $properties = [];
|
||||
/** @var list<Stmt\ClassMethod> */
|
||||
protected array $methods = [];
|
||||
/** @var list<Node\AttributeGroup> */
|
||||
protected array $attributeGroups = [];
|
||||
|
||||
/**
|
||||
* Creates an interface builder.
|
||||
|
@ -42,6 +45,8 @@ class Trait_ extends Declaration
|
|||
$this->methods[] = $stmt;
|
||||
} elseif ($stmt instanceof Stmt\TraitUse) {
|
||||
$this->uses[] = $stmt;
|
||||
} elseif ($stmt instanceof Stmt\ClassConst) {
|
||||
$this->constants[] = $stmt;
|
||||
} else {
|
||||
throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType()));
|
||||
}
|
||||
|
@ -67,10 +72,10 @@ class Trait_ extends Declaration
|
|||
*
|
||||
* @return Stmt\Trait_ The built interface node
|
||||
*/
|
||||
public function getNode() : PhpParser\Node {
|
||||
public function getNode(): PhpParser\Node {
|
||||
return new Stmt\Trait_(
|
||||
$this->name, [
|
||||
'stmts' => array_merge($this->uses, $this->properties, $this->methods),
|
||||
'stmts' => array_merge($this->uses, $this->constants, $this->properties, $this->methods),
|
||||
'attrGroups' => $this->attributeGroups,
|
||||
], $this->attributes
|
||||
);
|
||||
|
|
|
@ -7,17 +7,17 @@ use ncc\ThirdParty\nikic\PhpParser\BuilderHelpers;
|
|||
use ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Stmt;
|
||||
|
||||
class Use_ implements Builder
|
||||
{
|
||||
protected $name;
|
||||
protected $type;
|
||||
protected $alias = null;
|
||||
class Use_ implements Builder {
|
||||
protected Node\Name $name;
|
||||
/** @var Stmt\Use_::TYPE_* */
|
||||
protected int $type;
|
||||
protected ?string $alias = null;
|
||||
|
||||
/**
|
||||
* Creates a name use (alias) builder.
|
||||
*
|
||||
* @param Node\Name|string $name Name of the entity (namespace, class, function, constant) to alias
|
||||
* @param int $type One of the Stmt\Use_::TYPE_* constants
|
||||
* @param Stmt\Use_::TYPE_* $type One of the Stmt\Use_::TYPE_* constants
|
||||
*/
|
||||
public function __construct($name, int $type) {
|
||||
$this->name = BuilderHelpers::normalizeName($name);
|
||||
|
@ -41,9 +41,9 @@ class Use_ implements Builder
|
|||
*
|
||||
* @return Stmt\Use_ The built node
|
||||
*/
|
||||
public function getNode() : Node {
|
||||
public function getNode(): Node {
|
||||
return new Stmt\Use_([
|
||||
new Stmt\UseUse($this->name, $this->alias)
|
||||
new Node\UseItem($this->name, $this->alias)
|
||||
], $this->type);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,18 +10,15 @@ use ncc\ThirdParty\nikic\PhpParser\Node\Name;
|
|||
use ncc\ThirdParty\nikic\PhpParser\Node\Scalar\String_;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Stmt\Use_;
|
||||
|
||||
class BuilderFactory
|
||||
{
|
||||
class BuilderFactory {
|
||||
/**
|
||||
* Creates an attribute node.
|
||||
*
|
||||
* @param string|Name $name Name of the attribute
|
||||
* @param array $args Attribute named arguments
|
||||
*
|
||||
* @return Node\Attribute
|
||||
* @param array $args Attribute named arguments
|
||||
*/
|
||||
public function attribute($name, array $args = []) : Node\Attribute {
|
||||
return new Node\Attribute(
|
||||
public function attribute($name, array $args = []): ncc\ThirdParty\nikic\PhpParser\Node\Attribute {
|
||||
return new ncc\ThirdParty\nikic\PhpParser\Node\Attribute(
|
||||
BuilderHelpers::normalizeName($name),
|
||||
$this->args($args)
|
||||
);
|
||||
|
@ -30,12 +27,12 @@ class BuilderFactory
|
|||
/**
|
||||
* Creates a namespace builder.
|
||||
*
|
||||
* @param null|string|Node\Name $name Name of the namespace
|
||||
* @param null|string|ncc\ThirdParty\nikic\PhpParser\Node\Name $name Name of the namespace
|
||||
*
|
||||
* @return Builder\Namespace_ The created namespace builder
|
||||
* @return ncc\ThirdParty\nikic\PhpParser\Builder\Namespace_ The created namespace builder
|
||||
*/
|
||||
public function namespace($name) : Builder\Namespace_ {
|
||||
return new Builder\Namespace_($name);
|
||||
public function namespace($name): ncc\ThirdParty\nikic\PhpParser\Builder\Namespace_ {
|
||||
return new ncc\ThirdParty\nikic\PhpParser\Builder\Namespace_($name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,10 +40,10 @@ class BuilderFactory
|
|||
*
|
||||
* @param string $name Name of the class
|
||||
*
|
||||
* @return Builder\Class_ The created class builder
|
||||
* @return ncc\ThirdParty\nikic\PhpParser\Builder\Class_ The created class builder
|
||||
*/
|
||||
public function class(string $name) : Builder\Class_ {
|
||||
return new Builder\Class_($name);
|
||||
public function class(string $name): ncc\ThirdParty\nikic\PhpParser\Builder\Class_ {
|
||||
return new ncc\ThirdParty\nikic\PhpParser\Builder\Class_($name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -54,10 +51,10 @@ class BuilderFactory
|
|||
*
|
||||
* @param string $name Name of the interface
|
||||
*
|
||||
* @return Builder\Interface_ The created interface builder
|
||||
* @return ncc\ThirdParty\nikic\PhpParser\Builder\Interface_ The created interface builder
|
||||
*/
|
||||
public function interface(string $name) : Builder\Interface_ {
|
||||
return new Builder\Interface_($name);
|
||||
public function interface(string $name): ncc\ThirdParty\nikic\PhpParser\Builder\Interface_ {
|
||||
return new ncc\ThirdParty\nikic\PhpParser\Builder\Interface_($name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,10 +62,10 @@ class BuilderFactory
|
|||
*
|
||||
* @param string $name Name of the trait
|
||||
*
|
||||
* @return Builder\Trait_ The created trait builder
|
||||
* @return ncc\ThirdParty\nikic\PhpParser\Builder\Trait_ The created trait builder
|
||||
*/
|
||||
public function trait(string $name) : Builder\Trait_ {
|
||||
return new Builder\Trait_($name);
|
||||
public function trait(string $name): ncc\ThirdParty\nikic\PhpParser\Builder\Trait_ {
|
||||
return new ncc\ThirdParty\nikic\PhpParser\Builder\Trait_($name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -76,38 +73,38 @@ class BuilderFactory
|
|||
*
|
||||
* @param string $name Name of the enum
|
||||
*
|
||||
* @return Builder\Enum_ The created enum builder
|
||||
* @return ncc\ThirdParty\nikic\PhpParser\Builder\Enum_ The created enum builder
|
||||
*/
|
||||
public function enum(string $name) : Builder\Enum_ {
|
||||
return new Builder\Enum_($name);
|
||||
public function enum(string $name): ncc\ThirdParty\nikic\PhpParser\Builder\Enum_ {
|
||||
return new ncc\ThirdParty\nikic\PhpParser\Builder\Enum_($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a trait use builder.
|
||||
*
|
||||
* @param Node\Name|string ...$traits Trait names
|
||||
* @param ncc\ThirdParty\nikic\PhpParser\Node\Name|string ...$traits Trait names
|
||||
*
|
||||
* @return Builder\TraitUse The create trait use builder
|
||||
* @return ncc\ThirdParty\nikic\PhpParser\Builder\TraitUse The created trait use builder
|
||||
*/
|
||||
public function useTrait(...$traits) : Builder\TraitUse {
|
||||
return new Builder\TraitUse(...$traits);
|
||||
public function useTrait(...$traits): ncc\ThirdParty\nikic\PhpParser\Builder\TraitUse {
|
||||
return new ncc\ThirdParty\nikic\PhpParser\Builder\TraitUse(...$traits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a trait use adaptation builder.
|
||||
*
|
||||
* @param Node\Name|string|null $trait Trait name
|
||||
* @param Node\Identifier|string $method Method name
|
||||
* @param ncc\ThirdParty\nikic\PhpParser\Node\Name|string|null $trait Trait name
|
||||
* @param ncc\ThirdParty\nikic\PhpParser\Node\Identifier|string $method Method name
|
||||
*
|
||||
* @return Builder\TraitUseAdaptation The create trait use adaptation builder
|
||||
* @return ncc\ThirdParty\nikic\PhpParser\Builder\TraitUseAdaptation The created trait use adaptation builder
|
||||
*/
|
||||
public function traitUseAdaptation($trait, $method = null) : Builder\TraitUseAdaptation {
|
||||
public function traitUseAdaptation($trait, $method = null): ncc\ThirdParty\nikic\PhpParser\Builder\TraitUseAdaptation {
|
||||
if ($method === null) {
|
||||
$method = $trait;
|
||||
$trait = null;
|
||||
}
|
||||
|
||||
return new Builder\TraitUseAdaptation($trait, $method);
|
||||
return new ncc\ThirdParty\nikic\PhpParser\Builder\TraitUseAdaptation($trait, $method);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -115,10 +112,10 @@ class BuilderFactory
|
|||
*
|
||||
* @param string $name Name of the method
|
||||
*
|
||||
* @return Builder\Method The created method builder
|
||||
* @return ncc\ThirdParty\nikic\PhpParser\Builder\Method The created method builder
|
||||
*/
|
||||
public function method(string $name) : Builder\Method {
|
||||
return new Builder\Method($name);
|
||||
public function method(string $name): ncc\ThirdParty\nikic\PhpParser\Builder\Method {
|
||||
return new ncc\ThirdParty\nikic\PhpParser\Builder\Method($name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -126,10 +123,10 @@ class BuilderFactory
|
|||
*
|
||||
* @param string $name Name of the parameter
|
||||
*
|
||||
* @return Builder\Param The created parameter builder
|
||||
* @return ncc\ThirdParty\nikic\PhpParser\Builder\Param The created parameter builder
|
||||
*/
|
||||
public function param(string $name) : Builder\Param {
|
||||
return new Builder\Param($name);
|
||||
public function param(string $name): ncc\ThirdParty\nikic\PhpParser\Builder\Param {
|
||||
return new ncc\ThirdParty\nikic\PhpParser\Builder\Param($name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -137,10 +134,10 @@ class BuilderFactory
|
|||
*
|
||||
* @param string $name Name of the property
|
||||
*
|
||||
* @return Builder\Property The created property builder
|
||||
* @return ncc\ThirdParty\nikic\PhpParser\Builder\Property The created property builder
|
||||
*/
|
||||
public function property(string $name) : Builder\Property {
|
||||
return new Builder\Property($name);
|
||||
public function property(string $name): ncc\ThirdParty\nikic\PhpParser\Builder\Property {
|
||||
return new ncc\ThirdParty\nikic\PhpParser\Builder\Property($name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -148,76 +145,74 @@ class BuilderFactory
|
|||
*
|
||||
* @param string $name Name of the function
|
||||
*
|
||||
* @return Builder\Function_ The created function builder
|
||||
* @return ncc\ThirdParty\nikic\PhpParser\Builder\Function_ The created function builder
|
||||
*/
|
||||
public function function(string $name) : Builder\Function_ {
|
||||
return new Builder\Function_($name);
|
||||
public function function(string $name): ncc\ThirdParty\nikic\PhpParser\Builder\Function_ {
|
||||
return new ncc\ThirdParty\nikic\PhpParser\Builder\Function_($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a namespace/class use builder.
|
||||
*
|
||||
* @param Node\Name|string $name Name of the entity (namespace or class) to alias
|
||||
* @param ncc\ThirdParty\nikic\PhpParser\Node\Name|string $name Name of the entity (namespace or class) to alias
|
||||
*
|
||||
* @return Builder\Use_ The created use builder
|
||||
* @return ncc\ThirdParty\nikic\PhpParser\Builder\Use_ The created use builder
|
||||
*/
|
||||
public function use($name) : Builder\Use_ {
|
||||
return new Builder\Use_($name, Use_::TYPE_NORMAL);
|
||||
public function use($name): ncc\ThirdParty\nikic\PhpParser\Builder\Use_ {
|
||||
return new ncc\ThirdParty\nikic\PhpParser\Builder\Use_($name, Use_::TYPE_NORMAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a function use builder.
|
||||
*
|
||||
* @param Node\Name|string $name Name of the function to alias
|
||||
* @param ncc\ThirdParty\nikic\PhpParser\Node\Name|string $name Name of the function to alias
|
||||
*
|
||||
* @return Builder\Use_ The created use function builder
|
||||
* @return ncc\ThirdParty\nikic\PhpParser\Builder\Use_ The created use function builder
|
||||
*/
|
||||
public function useFunction($name) : Builder\Use_ {
|
||||
return new Builder\Use_($name, Use_::TYPE_FUNCTION);
|
||||
public function useFunction($name): ncc\ThirdParty\nikic\PhpParser\Builder\Use_ {
|
||||
return new ncc\ThirdParty\nikic\PhpParser\Builder\Use_($name, Use_::TYPE_FUNCTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a constant use builder.
|
||||
*
|
||||
* @param Node\Name|string $name Name of the const to alias
|
||||
* @param ncc\ThirdParty\nikic\PhpParser\Node\Name|string $name Name of the const to alias
|
||||
*
|
||||
* @return Builder\Use_ The created use const builder
|
||||
* @return ncc\ThirdParty\nikic\PhpParser\Builder\Use_ The created use const builder
|
||||
*/
|
||||
public function useConst($name) : Builder\Use_ {
|
||||
return new Builder\Use_($name, Use_::TYPE_CONSTANT);
|
||||
public function useConst($name): ncc\ThirdParty\nikic\PhpParser\Builder\Use_ {
|
||||
return new ncc\ThirdParty\nikic\PhpParser\Builder\Use_($name, Use_::TYPE_CONSTANT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a class constant builder.
|
||||
*
|
||||
* @param string|Identifier $name Name
|
||||
* @param Node\Expr|bool|null|int|float|string|array $value Value
|
||||
* @param string|Identifier $name Name
|
||||
* @param ncc\ThirdParty\nikic\PhpParser\Node\Expr|bool|null|int|float|string|array $value Value
|
||||
*
|
||||
* @return Builder\ClassConst The created use const builder
|
||||
* @return ncc\ThirdParty\nikic\PhpParser\Builder\ClassConst The created use const builder
|
||||
*/
|
||||
public function classConst($name, $value) : Builder\ClassConst {
|
||||
return new Builder\ClassConst($name, $value);
|
||||
public function classConst($name, $value): ncc\ThirdParty\nikic\PhpParser\Builder\ClassConst {
|
||||
return new ncc\ThirdParty\nikic\PhpParser\Builder\ClassConst($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an enum case builder.
|
||||
*
|
||||
* @param string|Identifier $name Name
|
||||
* @param string|Identifier $name Name
|
||||
*
|
||||
* @return Builder\EnumCase The created use const builder
|
||||
* @return ncc\ThirdParty\nikic\PhpParser\Builder\EnumCase The created use const builder
|
||||
*/
|
||||
public function enumCase($name) : Builder\EnumCase {
|
||||
return new Builder\EnumCase($name);
|
||||
public function enumCase($name): ncc\ThirdParty\nikic\PhpParser\Builder\EnumCase {
|
||||
return new ncc\ThirdParty\nikic\PhpParser\Builder\EnumCase($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates node a for a literal value.
|
||||
*
|
||||
* @param Expr|bool|null|int|float|string|array $value $value
|
||||
*
|
||||
* @return Expr
|
||||
* @param Expr|bool|null|int|float|string|array|\UnitEnum $value $value
|
||||
*/
|
||||
public function val($value) : Expr {
|
||||
public function val($value): Expr {
|
||||
return BuilderHelpers::normalizeValue($value);
|
||||
}
|
||||
|
||||
|
@ -225,10 +220,8 @@ class BuilderFactory
|
|||
* Creates variable node.
|
||||
*
|
||||
* @param string|Expr $name Name
|
||||
*
|
||||
* @return Expr\Variable
|
||||
*/
|
||||
public function var($name) : Expr\Variable {
|
||||
public function var($name): Expr\Variable {
|
||||
if (!\is_string($name) && !$name instanceof Expr) {
|
||||
throw new \LogicException('Variable name must be string or Expr');
|
||||
}
|
||||
|
@ -243,9 +236,9 @@ class BuilderFactory
|
|||
*
|
||||
* @param array $args List of arguments to normalize
|
||||
*
|
||||
* @return Arg[]
|
||||
* @return list<Arg>
|
||||
*/
|
||||
public function args(array $args) : array {
|
||||
public function args(array $args): array {
|
||||
$normalizedArgs = [];
|
||||
foreach ($args as $key => $arg) {
|
||||
if (!($arg instanceof Arg)) {
|
||||
|
@ -263,11 +256,9 @@ class BuilderFactory
|
|||
* Creates a function call node.
|
||||
*
|
||||
* @param string|Name|Expr $name Function name
|
||||
* @param array $args Function arguments
|
||||
*
|
||||
* @return Expr\FuncCall
|
||||
* @param array $args Function arguments
|
||||
*/
|
||||
public function funcCall($name, array $args = []) : Expr\FuncCall {
|
||||
public function funcCall($name, array $args = []): Expr\FuncCall {
|
||||
return new Expr\FuncCall(
|
||||
BuilderHelpers::normalizeNameOrExpr($name),
|
||||
$this->args($args)
|
||||
|
@ -277,13 +268,11 @@ class BuilderFactory
|
|||
/**
|
||||
* Creates a method call node.
|
||||
*
|
||||
* @param Expr $var Variable the method is called on
|
||||
* @param Expr $var Variable the method is called on
|
||||
* @param string|Identifier|Expr $name Method name
|
||||
* @param array $args Method arguments
|
||||
*
|
||||
* @return Expr\MethodCall
|
||||
* @param array $args Method arguments
|
||||
*/
|
||||
public function methodCall(Expr $var, $name, array $args = []) : Expr\MethodCall {
|
||||
public function methodCall(Expr $var, $name, array $args = []): Expr\MethodCall {
|
||||
return new Expr\MethodCall(
|
||||
$var,
|
||||
BuilderHelpers::normalizeIdentifierOrExpr($name),
|
||||
|
@ -294,13 +283,11 @@ class BuilderFactory
|
|||
/**
|
||||
* Creates a static method call node.
|
||||
*
|
||||
* @param string|Name|Expr $class Class name
|
||||
* @param string|Identifier|Expr $name Method name
|
||||
* @param array $args Method arguments
|
||||
*
|
||||
* @return Expr\StaticCall
|
||||
* @param string|Name|Expr $class Class name
|
||||
* @param string|Identifier|Expr $name Method name
|
||||
* @param array $args Method arguments
|
||||
*/
|
||||
public function staticCall($class, $name, array $args = []) : Expr\StaticCall {
|
||||
public function staticCall($class, $name, array $args = []): Expr\StaticCall {
|
||||
return new Expr\StaticCall(
|
||||
BuilderHelpers::normalizeNameOrExpr($class),
|
||||
BuilderHelpers::normalizeIdentifierOrExpr($name),
|
||||
|
@ -312,11 +299,9 @@ class BuilderFactory
|
|||
* Creates an object creation node.
|
||||
*
|
||||
* @param string|Name|Expr $class Class name
|
||||
* @param array $args Constructor arguments
|
||||
*
|
||||
* @return Expr\New_
|
||||
* @param array $args Constructor arguments
|
||||
*/
|
||||
public function new($class, array $args = []) : Expr\New_ {
|
||||
public function new($class, array $args = []): Expr\New_ {
|
||||
return new Expr\New_(
|
||||
BuilderHelpers::normalizeNameOrExpr($class),
|
||||
$this->args($args)
|
||||
|
@ -327,22 +312,18 @@ class BuilderFactory
|
|||
* Creates a constant fetch node.
|
||||
*
|
||||
* @param string|Name $name Constant name
|
||||
*
|
||||
* @return Expr\ConstFetch
|
||||
*/
|
||||
public function constFetch($name) : Expr\ConstFetch {
|
||||
public function constFetch($name): Expr\ConstFetch {
|
||||
return new Expr\ConstFetch(BuilderHelpers::normalizeName($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a property fetch node.
|
||||
*
|
||||
* @param Expr $var Variable holding object
|
||||
* @param Expr $var Variable holding object
|
||||
* @param string|Identifier|Expr $name Property name
|
||||
*
|
||||
* @return Expr\PropertyFetch
|
||||
*/
|
||||
public function propertyFetch(Expr $var, $name) : Expr\PropertyFetch {
|
||||
public function propertyFetch(Expr $var, $name): Expr\PropertyFetch {
|
||||
return new Expr\PropertyFetch($var, BuilderHelpers::normalizeIdentifierOrExpr($name));
|
||||
}
|
||||
|
||||
|
@ -350,9 +331,7 @@ class BuilderFactory
|
|||
* Creates a class constant fetch node.
|
||||
*
|
||||
* @param string|Name|Expr $class Class name
|
||||
* @param string|Identifier|Expr $name Constant name
|
||||
*
|
||||
* @return Expr\ClassConstFetch
|
||||
* @param string|Identifier|Expr $name Constant name
|
||||
*/
|
||||
public function classConstFetch($class, $name): Expr\ClassConstFetch {
|
||||
return new Expr\ClassConstFetch(
|
||||
|
@ -365,10 +344,8 @@ class BuilderFactory
|
|||
* Creates nested Concat nodes from a list of expressions.
|
||||
*
|
||||
* @param Expr|string ...$exprs Expressions or literal strings
|
||||
*
|
||||
* @return Concat
|
||||
*/
|
||||
public function concat(...$exprs) : Concat {
|
||||
public function concat(...$exprs): Concat {
|
||||
$numExprs = count($exprs);
|
||||
if ($numExprs < 2) {
|
||||
throw new \LogicException('Expected at least two expressions');
|
||||
|
@ -383,9 +360,8 @@ class BuilderFactory
|
|||
|
||||
/**
|
||||
* @param string|Expr $expr
|
||||
* @return Expr
|
||||
*/
|
||||
private function normalizeStringExpr($expr) : Expr {
|
||||
private function normalizeStringExpr($expr): Expr {
|
||||
if ($expr instanceof Expr) {
|
||||
return $expr;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use ncc\ThirdParty\nikic\PhpParser\Node\ComplexType;
|
|||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Identifier;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Name;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Name\FullyQualified;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\NullableType;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Scalar;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Stmt;
|
||||
|
@ -15,8 +16,7 @@ use ncc\ThirdParty\nikic\PhpParser\Node\Stmt;
|
|||
*
|
||||
* @internal
|
||||
*/
|
||||
final class BuilderHelpers
|
||||
{
|
||||
final class BuilderHelpers {
|
||||
/**
|
||||
* Normalizes a node: Converts builder objects to nodes.
|
||||
*
|
||||
|
@ -24,7 +24,7 @@ final class BuilderHelpers
|
|||
*
|
||||
* @return Node The normalized node
|
||||
*/
|
||||
public static function normalizeNode($node) : Node {
|
||||
public static function normalizeNode($node): Node {
|
||||
if ($node instanceof Builder) {
|
||||
return $node->getNode();
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ final class BuilderHelpers
|
|||
*
|
||||
* @return Stmt The normalized statement node
|
||||
*/
|
||||
public static function normalizeStmt($node) : Stmt {
|
||||
public static function normalizeStmt($node): Stmt {
|
||||
$node = self::normalizeNode($node);
|
||||
if ($node instanceof Stmt) {
|
||||
return $node;
|
||||
|
@ -65,7 +65,7 @@ final class BuilderHelpers
|
|||
*
|
||||
* @return Identifier The normalized identifier
|
||||
*/
|
||||
public static function normalizeIdentifier($name) : Identifier {
|
||||
public static function normalizeIdentifier($name): Identifier {
|
||||
if ($name instanceof Identifier) {
|
||||
return $name;
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ final class BuilderHelpers
|
|||
*
|
||||
* @return Name The normalized name
|
||||
*/
|
||||
public static function normalizeName($name) : Name {
|
||||
public static function normalizeName($name): Name {
|
||||
if ($name instanceof Name) {
|
||||
return $name;
|
||||
}
|
||||
|
@ -215,12 +215,12 @@ final class BuilderHelpers
|
|||
* Normalizes a value: Converts nulls, booleans, integers,
|
||||
* floats, strings and arrays into their respective nodes
|
||||
*
|
||||
* @param Node\Expr|bool|null|int|float|string|array $value The value to normalize
|
||||
* @param ncc\ThirdParty\nikic\PhpParser\Node\Expr|bool|null|int|float|string|array|\UnitEnum $value The value to normalize
|
||||
*
|
||||
* @return Expr The normalized value
|
||||
*/
|
||||
public static function normalizeValue($value) : Expr {
|
||||
if ($value instanceof Node\Expr) {
|
||||
public static function normalizeValue($value): Expr {
|
||||
if ($value instanceof ncc\ThirdParty\nikic\PhpParser\Node\Expr) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
@ -237,11 +237,11 @@ final class BuilderHelpers
|
|||
}
|
||||
|
||||
if (is_int($value)) {
|
||||
return new Scalar\LNumber($value);
|
||||
return new Scalar\Int_($value);
|
||||
}
|
||||
|
||||
if (is_float($value)) {
|
||||
return new Scalar\DNumber($value);
|
||||
return new Scalar\Float_($value);
|
||||
}
|
||||
|
||||
if (is_string($value)) {
|
||||
|
@ -254,12 +254,12 @@ final class BuilderHelpers
|
|||
foreach ($value as $itemKey => $itemValue) {
|
||||
// for consecutive, numeric keys don't generate keys
|
||||
if (null !== $lastKey && ++$lastKey === $itemKey) {
|
||||
$items[] = new Expr\ArrayItem(
|
||||
$items[] = new ncc\ThirdParty\nikic\PhpParser\Node\ArrayItem(
|
||||
self::normalizeValue($itemValue)
|
||||
);
|
||||
} else {
|
||||
$lastKey = null;
|
||||
$items[] = new Expr\ArrayItem(
|
||||
$items[] = new ncc\ThirdParty\nikic\PhpParser\Node\ArrayItem(
|
||||
self::normalizeValue($itemValue),
|
||||
self::normalizeValue($itemKey)
|
||||
);
|
||||
|
@ -269,6 +269,10 @@ final class BuilderHelpers
|
|||
return new Expr\Array_($items);
|
||||
}
|
||||
|
||||
if ($value instanceof \UnitEnum) {
|
||||
return new Expr\ClassConstFetch(new FullyQualified(\get_class($value)), new Identifier($value->name));
|
||||
}
|
||||
|
||||
throw new \LogicException('Invalid value');
|
||||
}
|
||||
|
||||
|
@ -279,7 +283,7 @@ final class BuilderHelpers
|
|||
*
|
||||
* @return Comment\Doc The normalized doc comment
|
||||
*/
|
||||
public static function normalizeDocComment($docComment) : Comment\Doc {
|
||||
public static function normalizeDocComment($docComment): Comment\Doc {
|
||||
if ($docComment instanceof Comment\Doc) {
|
||||
return $docComment;
|
||||
}
|
||||
|
@ -294,33 +298,32 @@ final class BuilderHelpers
|
|||
/**
|
||||
* Normalizes a attribute: Converts attribute to the Attribute Group if needed.
|
||||
*
|
||||
* @param Node\Attribute|Node\AttributeGroup $attribute
|
||||
* @param ncc\ThirdParty\nikic\PhpParser\Node\Attribute|ncc\ThirdParty\nikic\PhpParser\Node\AttributeGroup $attribute
|
||||
*
|
||||
* @return Node\AttributeGroup The Attribute Group
|
||||
* @return ncc\ThirdParty\nikic\PhpParser\Node\AttributeGroup The Attribute Group
|
||||
*/
|
||||
public static function normalizeAttribute($attribute) : Node\AttributeGroup
|
||||
{
|
||||
if ($attribute instanceof Node\AttributeGroup) {
|
||||
public static function normalizeAttribute($attribute): ncc\ThirdParty\nikic\PhpParser\Node\AttributeGroup {
|
||||
if ($attribute instanceof ncc\ThirdParty\nikic\PhpParser\Node\AttributeGroup) {
|
||||
return $attribute;
|
||||
}
|
||||
|
||||
if (!($attribute instanceof Node\Attribute)) {
|
||||
if (!($attribute instanceof ncc\ThirdParty\nikic\PhpParser\Node\Attribute)) {
|
||||
throw new \LogicException('Attribute must be an instance of PhpParser\Node\Attribute or PhpParser\Node\AttributeGroup');
|
||||
}
|
||||
|
||||
return new Node\AttributeGroup([$attribute]);
|
||||
return new ncc\ThirdParty\nikic\PhpParser\Node\AttributeGroup([$attribute]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a modifier and returns new modifier bitmask.
|
||||
*
|
||||
* @param int $modifiers Existing modifiers
|
||||
* @param int $modifier Modifier to set
|
||||
* @param int $modifier Modifier to set
|
||||
*
|
||||
* @return int New modifiers
|
||||
*/
|
||||
public static function addModifier(int $modifiers, int $modifier) : int {
|
||||
Stmt\Class_::verifyModifier($modifiers, $modifier);
|
||||
public static function addModifier(int $modifiers, int $modifier): int {
|
||||
Modifiers::verifyModifier($modifiers, $modifier);
|
||||
return $modifiers | $modifier;
|
||||
}
|
||||
|
||||
|
@ -328,8 +331,8 @@ final class BuilderHelpers
|
|||
* Adds a modifier and returns new modifier bitmask.
|
||||
* @return int New modifiers
|
||||
*/
|
||||
public static function addClassModifier(int $existingModifiers, int $modifierToSet) : int {
|
||||
Stmt\Class_::verifyClassModifier($existingModifiers, $modifierToSet);
|
||||
public static function addClassModifier(int $existingModifiers, int $modifierToSet): int {
|
||||
Modifiers::verifyClassModifier($existingModifiers, $modifierToSet);
|
||||
return $existingModifiers | $modifierToSet;
|
||||
}
|
||||
}
|
||||
|
|
1219
src/ncc/ThirdParty/nikic/PhpParser/CHANGELOG.md
vendored
Normal file
1219
src/ncc/ThirdParty/nikic/PhpParser/CHANGELOG.md
vendored
Normal file
File diff suppressed because it is too large
Load diff
104
src/ncc/ThirdParty/nikic/PhpParser/Comment.php
vendored
104
src/ncc/ThirdParty/nikic/PhpParser/Comment.php
vendored
|
@ -2,23 +2,22 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser;
|
||||
|
||||
class Comment implements \JsonSerializable
|
||||
{
|
||||
protected $text;
|
||||
protected $startLine;
|
||||
protected $startFilePos;
|
||||
protected $startTokenPos;
|
||||
protected $endLine;
|
||||
protected $endFilePos;
|
||||
protected $endTokenPos;
|
||||
class Comment implements \JsonSerializable {
|
||||
protected string $text;
|
||||
protected int $startLine;
|
||||
protected int $startFilePos;
|
||||
protected int $startTokenPos;
|
||||
protected int $endLine;
|
||||
protected int $endFilePos;
|
||||
protected int $endTokenPos;
|
||||
|
||||
/**
|
||||
* Constructs a comment node.
|
||||
*
|
||||
* @param string $text Comment text (including comment delimiters like /*)
|
||||
* @param int $startLine Line number the comment started on
|
||||
* @param int $startFilePos File offset the comment started on
|
||||
* @param int $startTokenPos Token offset the comment started on
|
||||
* @param string $text Comment text (including comment delimiters like /*)
|
||||
* @param int $startLine Line number the comment started on
|
||||
* @param int $startFilePos File offset the comment started on
|
||||
* @param int $startTokenPos Token offset the comment started on
|
||||
*/
|
||||
public function __construct(
|
||||
string $text,
|
||||
|
@ -39,7 +38,7 @@ class Comment implements \JsonSerializable
|
|||
*
|
||||
* @return string The comment text (including comment delimiters like /*)
|
||||
*/
|
||||
public function getText() : string {
|
||||
public function getText(): string {
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
|
@ -47,8 +46,9 @@ class Comment implements \JsonSerializable
|
|||
* Gets the line number the comment started on.
|
||||
*
|
||||
* @return int Line number (or -1 if not available)
|
||||
* @phpstan-return -1|positive-int
|
||||
*/
|
||||
public function getStartLine() : int {
|
||||
public function getStartLine(): int {
|
||||
return $this->startLine;
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ class Comment implements \JsonSerializable
|
|||
*
|
||||
* @return int File offset (or -1 if not available)
|
||||
*/
|
||||
public function getStartFilePos() : int {
|
||||
public function getStartFilePos(): int {
|
||||
return $this->startFilePos;
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ class Comment implements \JsonSerializable
|
|||
*
|
||||
* @return int Token offset (or -1 if not available)
|
||||
*/
|
||||
public function getStartTokenPos() : int {
|
||||
public function getStartTokenPos(): int {
|
||||
return $this->startTokenPos;
|
||||
}
|
||||
|
||||
|
@ -74,8 +74,9 @@ class Comment implements \JsonSerializable
|
|||
* Gets the line number the comment ends on.
|
||||
*
|
||||
* @return int Line number (or -1 if not available)
|
||||
* @phpstan-return -1|positive-int
|
||||
*/
|
||||
public function getEndLine() : int {
|
||||
public function getEndLine(): int {
|
||||
return $this->endLine;
|
||||
}
|
||||
|
||||
|
@ -84,7 +85,7 @@ class Comment implements \JsonSerializable
|
|||
*
|
||||
* @return int File offset (or -1 if not available)
|
||||
*/
|
||||
public function getEndFilePos() : int {
|
||||
public function getEndFilePos(): int {
|
||||
return $this->endFilePos;
|
||||
}
|
||||
|
||||
|
@ -93,49 +94,16 @@ class Comment implements \JsonSerializable
|
|||
*
|
||||
* @return int Token offset (or -1 if not available)
|
||||
*/
|
||||
public function getEndTokenPos() : int {
|
||||
public function getEndTokenPos(): int {
|
||||
return $this->endTokenPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the line number the comment started on.
|
||||
*
|
||||
* @deprecated Use getStartLine() instead
|
||||
*
|
||||
* @return int Line number
|
||||
*/
|
||||
public function getLine() : int {
|
||||
return $this->startLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file offset the comment started on.
|
||||
*
|
||||
* @deprecated Use getStartFilePos() instead
|
||||
*
|
||||
* @return int File offset
|
||||
*/
|
||||
public function getFilePos() : int {
|
||||
return $this->startFilePos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the token offset the comment started on.
|
||||
*
|
||||
* @deprecated Use getStartTokenPos() instead
|
||||
*
|
||||
* @return int Token offset
|
||||
*/
|
||||
public function getTokenPos() : int {
|
||||
return $this->startTokenPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the comment text.
|
||||
*
|
||||
* @return string The comment text (including comment delimiters like /*)
|
||||
*/
|
||||
public function __toString() : string {
|
||||
public function __toString(): string {
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
|
@ -144,18 +112,19 @@ class Comment implements \JsonSerializable
|
|||
*
|
||||
* "Reformatted" here means that we try to clean up the whitespace at the
|
||||
* starts of the lines. This is necessary because we receive the comments
|
||||
* without trailing whitespace on the first line, but with trailing whitespace
|
||||
* without leading whitespace on the first line, but with leading whitespace
|
||||
* on all subsequent lines.
|
||||
*
|
||||
* @return mixed|string
|
||||
* Additionally, this normalizes CRLF newlines to LF newlines.
|
||||
*/
|
||||
public function getReformattedText() {
|
||||
$text = trim($this->text);
|
||||
public function getReformattedText(): string {
|
||||
$text = str_replace("\r\n", "\n", $this->text);
|
||||
$newlinePos = strpos($text, "\n");
|
||||
if (false === $newlinePos) {
|
||||
// Single line comments don't need further processing
|
||||
return $text;
|
||||
} elseif (preg_match('((*BSR_ANYCRLF)(*ANYCRLF)^.*(?:\R\s+\*.*)+$)', $text)) {
|
||||
}
|
||||
if (preg_match('(^.*(?:\n\s+\*.*)+$)', $text)) {
|
||||
// Multi line comment of the type
|
||||
//
|
||||
// /*
|
||||
|
@ -164,8 +133,9 @@ class Comment implements \JsonSerializable
|
|||
// */
|
||||
//
|
||||
// is handled by replacing the whitespace sequences before the * by a single space
|
||||
return preg_replace('(^\s+\*)m', ' *', $this->text);
|
||||
} elseif (preg_match('(^/\*\*?\s*[\r\n])', $text) && preg_match('(\n(\s*)\*/$)', $text, $matches)) {
|
||||
return preg_replace('(^\s+\*)m', ' *', $text);
|
||||
}
|
||||
if (preg_match('(^/\*\*?\s*\n)', $text) && preg_match('(\n(\s*)\*/$)', $text, $matches)) {
|
||||
// Multi line comment of the type
|
||||
//
|
||||
// /*
|
||||
|
@ -177,7 +147,8 @@ class Comment implements \JsonSerializable
|
|||
// */ on all lines. So if the last line is " */", then " " is removed at the
|
||||
// start of all lines.
|
||||
return preg_replace('(^' . preg_quote($matches[1]) . ')m', '', $text);
|
||||
} elseif (preg_match('(^/\*\*?\s*(?!\s))', $text, $matches)) {
|
||||
}
|
||||
if (preg_match('(^/\*\*?\s*(?!\s))', $text, $matches)) {
|
||||
// Multi line comment of the type
|
||||
//
|
||||
// /* Some text.
|
||||
|
@ -204,9 +175,9 @@ class Comment implements \JsonSerializable
|
|||
* @param string $str String to check
|
||||
* @return int Length in characters. Tabs count as single characters.
|
||||
*/
|
||||
private function getShortestWhitespacePrefixLen(string $str) : int {
|
||||
private function getShortestWhitespacePrefixLen(string $str): int {
|
||||
$lines = explode("\n", $str);
|
||||
$shortestPrefixLen = \INF;
|
||||
$shortestPrefixLen = \PHP_INT_MAX;
|
||||
foreach ($lines as $line) {
|
||||
preg_match('(^\s*)', $line, $matches);
|
||||
$prefixLen = strlen($matches[0]);
|
||||
|
@ -218,10 +189,9 @@ class Comment implements \JsonSerializable
|
|||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{nodeType:string, text:mixed, line:mixed, filePos:mixed}
|
||||
* @return array{nodeType:string, text:mixed, line:mixed, filePos:mixed}
|
||||
*/
|
||||
public function jsonSerialize() : array {
|
||||
public function jsonSerialize(): array {
|
||||
// Technically not a node, but we make it look like one anyway
|
||||
$type = $this instanceof Comment\Doc ? 'Comment_Doc' : 'Comment';
|
||||
return [
|
||||
|
|
|
@ -2,6 +2,5 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Comment;
|
||||
|
||||
class Doc extends \ncc\ThirdParty\nikic\PhpParser\Comment
|
||||
{
|
||||
class Doc extends \ncc\ThirdParty\nikic\PhpParser\Comment {
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser;
|
||||
|
||||
class ConstExprEvaluationException extends \Exception
|
||||
{}
|
||||
class ConstExprEvaluationException extends \Exception {
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
<?php
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser;
|
||||
|
||||
use function array_merge;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Scalar;
|
||||
|
||||
use function array_merge;
|
||||
|
||||
/**
|
||||
* Evaluates constant expressions.
|
||||
*
|
||||
|
@ -25,8 +26,8 @@ use ncc\ThirdParty\nikic\PhpParser\Node\Scalar;
|
|||
* point to string conversions are affected by the precision ini setting. Secondly, they are also
|
||||
* affected by the LC_NUMERIC locale.
|
||||
*/
|
||||
class ConstExprEvaluator
|
||||
{
|
||||
class ConstExprEvaluator {
|
||||
/** @var callable|null */
|
||||
private $fallbackEvaluator;
|
||||
|
||||
/**
|
||||
|
@ -37,8 +38,8 @@ class ConstExprEvaluator
|
|||
*
|
||||
* @param callable|null $fallbackEvaluator To call if subexpression cannot be evaluated
|
||||
*/
|
||||
public function __construct(callable $fallbackEvaluator = null) {
|
||||
$this->fallbackEvaluator = $fallbackEvaluator ?? function(Expr $expr) {
|
||||
public function __construct(?callable $fallbackEvaluator = null) {
|
||||
$this->fallbackEvaluator = $fallbackEvaluator ?? function (Expr $expr) {
|
||||
throw new ConstExprEvaluationException(
|
||||
"Expression of type {$expr->getType()} cannot be evaluated"
|
||||
);
|
||||
|
@ -63,7 +64,7 @@ class ConstExprEvaluator
|
|||
* @throws ConstExprEvaluationException if the expression cannot be evaluated or an error occurred
|
||||
*/
|
||||
public function evaluateSilently(Expr $expr) {
|
||||
set_error_handler(function($num, $str, $file, $line) {
|
||||
set_error_handler(function ($num, $str, $file, $line) {
|
||||
throw new \ErrorException($str, 0, $num, $file, $line);
|
||||
});
|
||||
|
||||
|
@ -101,9 +102,10 @@ class ConstExprEvaluator
|
|||
return $this->evaluate($expr);
|
||||
}
|
||||
|
||||
/** @return mixed */
|
||||
private function evaluate(Expr $expr) {
|
||||
if ($expr instanceof Scalar\LNumber
|
||||
|| $expr instanceof Scalar\DNumber
|
||||
if ($expr instanceof Scalar\Int_
|
||||
|| $expr instanceof Scalar\Float_
|
||||
|| $expr instanceof Scalar\String_
|
||||
) {
|
||||
return $expr->value;
|
||||
|
@ -146,7 +148,7 @@ class ConstExprEvaluator
|
|||
return ($this->fallbackEvaluator)($expr);
|
||||
}
|
||||
|
||||
private function evaluateArray(Expr\Array_ $expr) {
|
||||
private function evaluateArray(Expr\Array_ $expr): array {
|
||||
$array = [];
|
||||
foreach ($expr->items as $item) {
|
||||
if (null !== $item->key) {
|
||||
|
@ -160,6 +162,7 @@ class ConstExprEvaluator
|
|||
return $array;
|
||||
}
|
||||
|
||||
/** @return mixed */
|
||||
private function evaluateTernary(Expr\Ternary $expr) {
|
||||
if (null === $expr->if) {
|
||||
return $this->evaluate($expr->cond) ?: $this->evaluate($expr->else);
|
||||
|
@ -170,6 +173,7 @@ class ConstExprEvaluator
|
|||
: $this->evaluate($expr->else);
|
||||
}
|
||||
|
||||
/** @return mixed */
|
||||
private function evaluateBinaryOp(Expr\BinaryOp $expr) {
|
||||
if ($expr instanceof Expr\BinaryOp\Coalesce
|
||||
&& $expr->left instanceof Expr\ArrayDimFetch
|
||||
|
@ -216,6 +220,7 @@ class ConstExprEvaluator
|
|||
throw new \Exception('Should not happen');
|
||||
}
|
||||
|
||||
/** @return mixed */
|
||||
private function evaluateConstFetch(Expr\ConstFetch $expr) {
|
||||
$name = $expr->name->toLowerString();
|
||||
switch ($name) {
|
||||
|
|
59
src/ncc/ThirdParty/nikic/PhpParser/Error.php
vendored
59
src/ncc/ThirdParty/nikic/PhpParser/Error.php
vendored
|
@ -2,25 +2,20 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser;
|
||||
|
||||
class Error extends \RuntimeException
|
||||
{
|
||||
protected $rawMessage;
|
||||
protected $attributes;
|
||||
class Error extends \RuntimeException {
|
||||
protected string $rawMessage;
|
||||
/** @var array<string, mixed> */
|
||||
protected array $attributes;
|
||||
|
||||
/**
|
||||
* Creates an Exception signifying a parse error.
|
||||
*
|
||||
* @param string $message Error message
|
||||
* @param array|int $attributes Attributes of node/token where error occurred
|
||||
* (or start line of error -- deprecated)
|
||||
* @param string $message Error message
|
||||
* @param array<string, mixed> $attributes Attributes of node/token where error occurred
|
||||
*/
|
||||
public function __construct(string $message, $attributes = []) {
|
||||
public function __construct(string $message, array $attributes = []) {
|
||||
$this->rawMessage = $message;
|
||||
if (is_array($attributes)) {
|
||||
$this->attributes = $attributes;
|
||||
} else {
|
||||
$this->attributes = ['startLine' => $attributes];
|
||||
}
|
||||
$this->attributes = $attributes;
|
||||
$this->updateMessage();
|
||||
}
|
||||
|
||||
|
@ -29,7 +24,7 @@ class Error extends \RuntimeException
|
|||
*
|
||||
* @return string Error message
|
||||
*/
|
||||
public function getRawMessage() : string {
|
||||
public function getRawMessage(): string {
|
||||
return $this->rawMessage;
|
||||
}
|
||||
|
||||
|
@ -37,8 +32,9 @@ class Error extends \RuntimeException
|
|||
* Gets the line the error starts in.
|
||||
*
|
||||
* @return int Error start line
|
||||
* @phpstan-return -1|positive-int
|
||||
*/
|
||||
public function getStartLine() : int {
|
||||
public function getStartLine(): int {
|
||||
return $this->attributes['startLine'] ?? -1;
|
||||
}
|
||||
|
||||
|
@ -46,26 +42,27 @@ class Error extends \RuntimeException
|
|||
* Gets the line the error ends in.
|
||||
*
|
||||
* @return int Error end line
|
||||
* @phpstan-return -1|positive-int
|
||||
*/
|
||||
public function getEndLine() : int {
|
||||
public function getEndLine(): int {
|
||||
return $this->attributes['endLine'] ?? -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the attributes of the node/token the error occurred at.
|
||||
*
|
||||
* @return array
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getAttributes() : array {
|
||||
public function getAttributes(): array {
|
||||
return $this->attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attributes of the node/token the error occurred at.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array<string, mixed> $attributes
|
||||
*/
|
||||
public function setAttributes(array $attributes) {
|
||||
public function setAttributes(array $attributes): void {
|
||||
$this->attributes = $attributes;
|
||||
$this->updateMessage();
|
||||
}
|
||||
|
@ -75,7 +72,7 @@ class Error extends \RuntimeException
|
|||
*
|
||||
* @param string $message Error message
|
||||
*/
|
||||
public function setRawMessage(string $message) {
|
||||
public function setRawMessage(string $message): void {
|
||||
$this->rawMessage = $message;
|
||||
$this->updateMessage();
|
||||
}
|
||||
|
@ -85,7 +82,7 @@ class Error extends \RuntimeException
|
|||
*
|
||||
* @param int $line Error start line
|
||||
*/
|
||||
public function setStartLine(int $line) {
|
||||
public function setStartLine(int $line): void {
|
||||
$this->attributes['startLine'] = $line;
|
||||
$this->updateMessage();
|
||||
}
|
||||
|
@ -94,10 +91,8 @@ class Error extends \RuntimeException
|
|||
* Returns whether the error has start and end column information.
|
||||
*
|
||||
* For column information enable the startFilePos and endFilePos in the lexer options.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasColumnInfo() : bool {
|
||||
public function hasColumnInfo(): bool {
|
||||
return isset($this->attributes['startFilePos'], $this->attributes['endFilePos']);
|
||||
}
|
||||
|
||||
|
@ -105,9 +100,8 @@ class Error extends \RuntimeException
|
|||
* Gets the start column (1-based) into the line where the error started.
|
||||
*
|
||||
* @param string $code Source code of the file
|
||||
* @return int
|
||||
*/
|
||||
public function getStartColumn(string $code) : int {
|
||||
public function getStartColumn(string $code): int {
|
||||
if (!$this->hasColumnInfo()) {
|
||||
throw new \RuntimeException('Error does not have column information');
|
||||
}
|
||||
|
@ -119,9 +113,8 @@ class Error extends \RuntimeException
|
|||
* Gets the end column (1-based) into the line where the error ended.
|
||||
*
|
||||
* @param string $code Source code of the file
|
||||
* @return int
|
||||
*/
|
||||
public function getEndColumn(string $code) : int {
|
||||
public function getEndColumn(string $code): int {
|
||||
if (!$this->hasColumnInfo()) {
|
||||
throw new \RuntimeException('Error does not have column information');
|
||||
}
|
||||
|
@ -136,7 +129,7 @@ class Error extends \RuntimeException
|
|||
*
|
||||
* @return string Formatted message
|
||||
*/
|
||||
public function getMessageWithColumnInfo(string $code) : string {
|
||||
public function getMessageWithColumnInfo(string $code): string {
|
||||
return sprintf(
|
||||
'%s from %d:%d to %d:%d', $this->getRawMessage(),
|
||||
$this->getStartLine(), $this->getStartColumn($code),
|
||||
|
@ -148,11 +141,11 @@ class Error extends \RuntimeException
|
|||
* Converts a file offset into a column.
|
||||
*
|
||||
* @param string $code Source code that $pos indexes into
|
||||
* @param int $pos 0-based position in $code
|
||||
* @param int $pos 0-based position in $code
|
||||
*
|
||||
* @return int 1-based column (relative to start of line)
|
||||
*/
|
||||
private function toColumn(string $code, int $pos) : int {
|
||||
private function toColumn(string $code, int $pos): int {
|
||||
if ($pos > strlen($code)) {
|
||||
throw new \RuntimeException('Invalid position information');
|
||||
}
|
||||
|
@ -168,7 +161,7 @@ class Error extends \RuntimeException
|
|||
/**
|
||||
* Updates the exception message after a change to rawMessage or rawLine.
|
||||
*/
|
||||
protected function updateMessage() {
|
||||
protected function updateMessage(): void {
|
||||
$this->message = $this->rawMessage;
|
||||
|
||||
if (-1 === $this->getStartLine()) {
|
||||
|
|
|
@ -2,12 +2,11 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser;
|
||||
|
||||
interface ErrorHandler
|
||||
{
|
||||
interface ErrorHandler {
|
||||
/**
|
||||
* Handle an error generated during lexing, parsing or some other operation.
|
||||
*
|
||||
* @param Error $error The error that needs to be handled
|
||||
*/
|
||||
public function handleError(Error $error);
|
||||
public function handleError(Error $error): void;
|
||||
}
|
||||
|
|
|
@ -10,12 +10,11 @@ use ncc\ThirdParty\nikic\PhpParser\ErrorHandler;
|
|||
*
|
||||
* This allows graceful handling of errors.
|
||||
*/
|
||||
class Collecting implements ErrorHandler
|
||||
{
|
||||
class Collecting implements ErrorHandler {
|
||||
/** @var Error[] Collected errors */
|
||||
private $errors = [];
|
||||
private array $errors = [];
|
||||
|
||||
public function handleError(Error $error) {
|
||||
public function handleError(Error $error): void {
|
||||
$this->errors[] = $error;
|
||||
}
|
||||
|
||||
|
@ -24,23 +23,21 @@ class Collecting implements ErrorHandler
|
|||
*
|
||||
* @return Error[]
|
||||
*/
|
||||
public function getErrors() : array {
|
||||
public function getErrors(): array {
|
||||
return $this->errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether there are any errors.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasErrors() : bool {
|
||||
public function hasErrors(): bool {
|
||||
return !empty($this->errors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset/clear collected errors.
|
||||
*/
|
||||
public function clearErrors() {
|
||||
public function clearErrors(): void {
|
||||
$this->errors = [];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,8 @@ use ncc\ThirdParty\nikic\PhpParser\ErrorHandler;
|
|||
*
|
||||
* This is the default strategy used by all components.
|
||||
*/
|
||||
class Throwing implements ErrorHandler
|
||||
{
|
||||
public function handleError(Error $error) {
|
||||
class Throwing implements ErrorHandler {
|
||||
public function handleError(Error $error): void {
|
||||
throw $error;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,20 +5,24 @@ namespace ncc\ThirdParty\nikic\PhpParser\Internal;
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
class DiffElem
|
||||
{
|
||||
const TYPE_KEEP = 0;
|
||||
const TYPE_REMOVE = 1;
|
||||
const TYPE_ADD = 2;
|
||||
const TYPE_REPLACE = 3;
|
||||
class DiffElem {
|
||||
public const TYPE_KEEP = 0;
|
||||
public const TYPE_REMOVE = 1;
|
||||
public const TYPE_ADD = 2;
|
||||
public const TYPE_REPLACE = 3;
|
||||
|
||||
/** @var int One of the TYPE_* constants */
|
||||
public $type;
|
||||
public int $type;
|
||||
/** @var mixed Is null for add operations */
|
||||
public $old;
|
||||
/** @var mixed Is null for remove operations */
|
||||
public $new;
|
||||
|
||||
/**
|
||||
* @param int $type One of the TYPE_* constants
|
||||
* @param mixed $old Is null for add operations
|
||||
* @param mixed $new Is null for remove operations
|
||||
*/
|
||||
public function __construct(int $type, $old, $new) {
|
||||
$this->type = $type;
|
||||
$this->old = $old;
|
||||
|
|
|
@ -8,16 +8,17 @@ namespace ncc\ThirdParty\nikic\PhpParser\Internal;
|
|||
* Myers, Eugene W. "An O (ND) difference algorithm and its variations."
|
||||
* Algorithmica 1.1 (1986): 251-266.
|
||||
*
|
||||
* @template T
|
||||
* @internal
|
||||
*/
|
||||
class Differ
|
||||
{
|
||||
class Differ {
|
||||
/** @var callable(T, T): bool */
|
||||
private $isEqual;
|
||||
|
||||
/**
|
||||
* Create differ over the given equality relation.
|
||||
*
|
||||
* @param callable $isEqual Equality relation with signature function($a, $b) : bool
|
||||
* @param callable(T, T): bool $isEqual Equality relation
|
||||
*/
|
||||
public function __construct(callable $isEqual) {
|
||||
$this->isEqual = $isEqual;
|
||||
|
@ -26,12 +27,14 @@ class Differ
|
|||
/**
|
||||
* Calculate diff (edit script) from $old to $new.
|
||||
*
|
||||
* @param array $old Original array
|
||||
* @param array $new New array
|
||||
* @param T[] $old Original array
|
||||
* @param T[] $new New array
|
||||
*
|
||||
* @return DiffElem[] Diff (edit script)
|
||||
*/
|
||||
public function diff(array $old, array $new) {
|
||||
public function diff(array $old, array $new): array {
|
||||
$old = \array_values($old);
|
||||
$new = \array_values($new);
|
||||
list($trace, $x, $y) = $this->calculateTrace($old, $new);
|
||||
return $this->extractDiff($trace, $x, $y, $old, $new);
|
||||
}
|
||||
|
@ -42,32 +45,37 @@ class Differ
|
|||
* If a sequence of remove operations is followed by the same number of add operations, these
|
||||
* will be coalesced into replace operations.
|
||||
*
|
||||
* @param array $old Original array
|
||||
* @param array $new New array
|
||||
* @param T[] $old Original array
|
||||
* @param T[] $new New array
|
||||
*
|
||||
* @return DiffElem[] Diff (edit script), including replace operations
|
||||
*/
|
||||
public function diffWithReplacements(array $old, array $new) {
|
||||
public function diffWithReplacements(array $old, array $new): array {
|
||||
return $this->coalesceReplacements($this->diff($old, $new));
|
||||
}
|
||||
|
||||
private function calculateTrace(array $a, array $b) {
|
||||
$n = \count($a);
|
||||
$m = \count($b);
|
||||
/**
|
||||
* @param T[] $old
|
||||
* @param T[] $new
|
||||
* @return array{array<int, array<int, int>>, int, int}
|
||||
*/
|
||||
private function calculateTrace(array $old, array $new): array {
|
||||
$n = \count($old);
|
||||
$m = \count($new);
|
||||
$max = $n + $m;
|
||||
$v = [1 => 0];
|
||||
$trace = [];
|
||||
for ($d = 0; $d <= $max; $d++) {
|
||||
$trace[] = $v;
|
||||
for ($k = -$d; $k <= $d; $k += 2) {
|
||||
if ($k === -$d || ($k !== $d && $v[$k-1] < $v[$k+1])) {
|
||||
$x = $v[$k+1];
|
||||
if ($k === -$d || ($k !== $d && $v[$k - 1] < $v[$k + 1])) {
|
||||
$x = $v[$k + 1];
|
||||
} else {
|
||||
$x = $v[$k-1] + 1;
|
||||
$x = $v[$k - 1] + 1;
|
||||
}
|
||||
|
||||
$y = $x - $k;
|
||||
while ($x < $n && $y < $m && ($this->isEqual)($a[$x], $b[$y])) {
|
||||
while ($x < $n && $y < $m && ($this->isEqual)($old[$x], $new[$y])) {
|
||||
$x++;
|
||||
$y++;
|
||||
}
|
||||
|
@ -81,13 +89,19 @@ class Differ
|
|||
throw new \Exception('Should not happen');
|
||||
}
|
||||
|
||||
private function extractDiff(array $trace, int $x, int $y, array $a, array $b) {
|
||||
/**
|
||||
* @param array<int, array<int, int>> $trace
|
||||
* @param T[] $old
|
||||
* @param T[] $new
|
||||
* @return DiffElem[]
|
||||
*/
|
||||
private function extractDiff(array $trace, int $x, int $y, array $old, array $new): array {
|
||||
$result = [];
|
||||
for ($d = \count($trace) - 1; $d >= 0; $d--) {
|
||||
$v = $trace[$d];
|
||||
$k = $x - $y;
|
||||
|
||||
if ($k === -$d || ($k !== $d && $v[$k-1] < $v[$k+1])) {
|
||||
if ($k === -$d || ($k !== $d && $v[$k - 1] < $v[$k + 1])) {
|
||||
$prevK = $k + 1;
|
||||
} else {
|
||||
$prevK = $k - 1;
|
||||
|
@ -97,7 +111,7 @@ class Differ
|
|||
$prevY = $prevX - $prevK;
|
||||
|
||||
while ($x > $prevX && $y > $prevY) {
|
||||
$result[] = new DiffElem(DiffElem::TYPE_KEEP, $a[$x-1], $b[$y-1]);
|
||||
$result[] = new DiffElem(DiffElem::TYPE_KEEP, $old[$x - 1], $new[$y - 1]);
|
||||
$x--;
|
||||
$y--;
|
||||
}
|
||||
|
@ -107,12 +121,12 @@ class Differ
|
|||
}
|
||||
|
||||
while ($x > $prevX) {
|
||||
$result[] = new DiffElem(DiffElem::TYPE_REMOVE, $a[$x-1], null);
|
||||
$result[] = new DiffElem(DiffElem::TYPE_REMOVE, $old[$x - 1], null);
|
||||
$x--;
|
||||
}
|
||||
|
||||
while ($y > $prevY) {
|
||||
$result[] = new DiffElem(DiffElem::TYPE_ADD, null, $b[$y-1]);
|
||||
$result[] = new DiffElem(DiffElem::TYPE_ADD, null, $new[$y - 1]);
|
||||
$y--;
|
||||
}
|
||||
}
|
||||
|
@ -125,7 +139,7 @@ class Differ
|
|||
* @param DiffElem[] $diff
|
||||
* @return DiffElem[]
|
||||
*/
|
||||
private function coalesceReplacements(array $diff) {
|
||||
private function coalesceReplacements(array $diff): array {
|
||||
$newDiff = [];
|
||||
$c = \count($diff);
|
||||
for ($i = 0; $i < $c; $i++) {
|
||||
|
|
|
@ -15,23 +15,30 @@ use ncc\ThirdParty\nikic\PhpParser\Node\Expr;
|
|||
*
|
||||
* @internal
|
||||
*/
|
||||
class PrintableNewAnonClassNode extends Expr
|
||||
{
|
||||
class PrintableNewAnonClassNode extends Expr {
|
||||
/** @var Node\AttributeGroup[] PHP attribute groups */
|
||||
public $attrGroups;
|
||||
public array $attrGroups;
|
||||
/** @var int Modifiers */
|
||||
public $flags;
|
||||
/** @var Node\Arg[] Arguments */
|
||||
public $args;
|
||||
public int $flags;
|
||||
/** @var (Node\Arg|Node\VariadicPlaceholder)[] Arguments */
|
||||
public array $args;
|
||||
/** @var null|Node\Name Name of extended class */
|
||||
public $extends;
|
||||
public ?Node\Name $extends;
|
||||
/** @var Node\Name[] Names of implemented interfaces */
|
||||
public $implements;
|
||||
public array $implements;
|
||||
/** @var Node\Stmt[] Statements */
|
||||
public $stmts;
|
||||
public array $stmts;
|
||||
|
||||
/**
|
||||
* @param Node\AttributeGroup[] $attrGroups PHP attribute groups
|
||||
* @param (Node\Arg|Node\VariadicPlaceholder)[] $args Arguments
|
||||
* @param Node\Name|null $extends Name of extended class
|
||||
* @param Node\Name[] $implements Names of implemented interfaces
|
||||
* @param Node\Stmt[] $stmts Statements
|
||||
* @param array<string, mixed> $attributes Attributes
|
||||
*/
|
||||
public function __construct(
|
||||
array $attrGroups, int $flags, array $args, Node\Name $extends = null, array $implements,
|
||||
array $attrGroups, int $flags, array $args, ?Node\Name $extends, array $implements,
|
||||
array $stmts, array $attributes
|
||||
) {
|
||||
parent::__construct($attributes);
|
||||
|
@ -43,7 +50,7 @@ class PrintableNewAnonClassNode extends Expr
|
|||
$this->stmts = $stmts;
|
||||
}
|
||||
|
||||
public static function fromNewNode(Expr\New_ $newNode) {
|
||||
public static function fromNewNode(Expr\New_ $newNode): self {
|
||||
$class = $newNode->class;
|
||||
assert($class instanceof Node\Stmt\Class_);
|
||||
// We don't assert that $class->name is null here, to allow consumers to assign unique names
|
||||
|
@ -54,11 +61,11 @@ class PrintableNewAnonClassNode extends Expr
|
|||
);
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
public function getType(): string {
|
||||
return 'Expr_PrintableNewAnonClass';
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
public function getSubNodeNames(): array {
|
||||
return ['attrGroups', 'flags', 'args', 'extends', 'implements', 'stmts'];
|
||||
}
|
||||
}
|
||||
|
|
237
src/ncc/ThirdParty/nikic/PhpParser/Internal/TokenPolyfill.php
vendored
Normal file
237
src/ncc/ThirdParty/nikic/PhpParser/Internal/TokenPolyfill.php
vendored
Normal file
|
@ -0,0 +1,237 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Internal;
|
||||
|
||||
if (\PHP_VERSION_ID >= 80000) {
|
||||
class TokenPolyfill extends \PhpToken {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a polyfill for the PhpToken class introduced in PHP 8.0. We do not actually polyfill
|
||||
* PhpToken, because composer might end up picking a different polyfill implementation, which does
|
||||
* not meet our requirements.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class TokenPolyfill {
|
||||
/** @var int The ID of the token. Either a T_* constant of a character code < 256. */
|
||||
public int $id;
|
||||
/** @var string The textual content of the token. */
|
||||
public string $text;
|
||||
/** @var int The 1-based starting line of the token (or -1 if unknown). */
|
||||
public int $line;
|
||||
/** @var int The 0-based starting position of the token (or -1 if unknown). */
|
||||
public int $pos;
|
||||
|
||||
/** @var array<int, bool> Tokens ignored by the PHP parser. */
|
||||
private const IGNORABLE_TOKENS = [
|
||||
\T_WHITESPACE => true,
|
||||
\T_COMMENT => true,
|
||||
\T_DOC_COMMENT => true,
|
||||
\T_OPEN_TAG => true,
|
||||
];
|
||||
|
||||
/** @var array<int, bool> Tokens that may be part of a T_NAME_* identifier. */
|
||||
private static array $identifierTokens;
|
||||
|
||||
/**
|
||||
* Create a Token with the given ID and text, as well optional line and position information.
|
||||
*/
|
||||
final public function __construct(int $id, string $text, int $line = -1, int $pos = -1) {
|
||||
$this->id = $id;
|
||||
$this->text = $text;
|
||||
$this->line = $line;
|
||||
$this->pos = $pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the token. For single-char tokens this will be the token character.
|
||||
* Otherwise it will be a T_* style name, or null if the token ID is unknown.
|
||||
*/
|
||||
public function getTokenName(): ?string {
|
||||
if ($this->id < 256) {
|
||||
return \chr($this->id);
|
||||
}
|
||||
|
||||
$name = token_name($this->id);
|
||||
return $name === 'UNKNOWN' ? null : $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the token is of the given kind. The kind may be either an integer that matches
|
||||
* the token ID, a string that matches the token text, or an array of integers/strings. In the
|
||||
* latter case, the function returns true if any of the kinds in the array match.
|
||||
*
|
||||
* @param int|string|(int|string)[] $kind
|
||||
*/
|
||||
public function is($kind): bool {
|
||||
if (\is_int($kind)) {
|
||||
return $this->id === $kind;
|
||||
}
|
||||
if (\is_string($kind)) {
|
||||
return $this->text === $kind;
|
||||
}
|
||||
if (\is_array($kind)) {
|
||||
foreach ($kind as $entry) {
|
||||
if (\is_int($entry)) {
|
||||
if ($this->id === $entry) {
|
||||
return true;
|
||||
}
|
||||
} elseif (\is_string($entry)) {
|
||||
if ($this->text === $entry) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
throw new \TypeError(
|
||||
'Argument #1 ($kind) must only have elements of type string|int, ' .
|
||||
gettype($entry) . ' given');
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
throw new \TypeError(
|
||||
'Argument #1 ($kind) must be of type string|int|array, ' .gettype($kind) . ' given');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this token would be ignored by the PHP parser. Returns true for T_WHITESPACE,
|
||||
* T_COMMENT, T_DOC_COMMENT and T_OPEN_TAG, and false for everything else.
|
||||
*/
|
||||
public function isIgnorable(): bool {
|
||||
return isset(self::IGNORABLE_TOKENS[$this->id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the textual content of the token.
|
||||
*/
|
||||
public function __toString(): string {
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tokenize the given source code and return an array of tokens.
|
||||
*
|
||||
* This performs certain canonicalizations to match the PHP 8.0 token format:
|
||||
* * Bad characters are represented using T_BAD_CHARACTER rather than omitted.
|
||||
* * T_COMMENT does not include trailing newlines, instead the newline is part of a following
|
||||
* T_WHITESPACE token.
|
||||
* * Namespaced names are represented using T_NAME_* tokens.
|
||||
*
|
||||
* @return static[]
|
||||
*/
|
||||
public static function tokenize(string $code, int $flags = 0): array {
|
||||
self::init();
|
||||
|
||||
$tokens = [];
|
||||
$line = 1;
|
||||
$pos = 0;
|
||||
$origTokens = \token_get_all($code, $flags);
|
||||
|
||||
$numTokens = \count($origTokens);
|
||||
for ($i = 0; $i < $numTokens; $i++) {
|
||||
$token = $origTokens[$i];
|
||||
if (\is_string($token)) {
|
||||
if (\strlen($token) === 2) {
|
||||
// b" and B" are tokenized as single-char tokens, even though they aren't.
|
||||
$tokens[] = new static(\ord('"'), $token, $line, $pos);
|
||||
$pos += 2;
|
||||
} else {
|
||||
$tokens[] = new static(\ord($token), $token, $line, $pos);
|
||||
$pos++;
|
||||
}
|
||||
} else {
|
||||
$id = $token[0];
|
||||
$text = $token[1];
|
||||
|
||||
// Emulate PHP 8.0 comment format, which does not include trailing whitespace anymore.
|
||||
if ($id === \T_COMMENT && \substr($text, 0, 2) !== '/*' &&
|
||||
\preg_match('/(\r\n|\n|\r)$/D', $text, $matches)
|
||||
) {
|
||||
$trailingNewline = $matches[0];
|
||||
$text = \substr($text, 0, -\strlen($trailingNewline));
|
||||
$tokens[] = new static($id, $text, $line, $pos);
|
||||
$pos += \strlen($text);
|
||||
|
||||
if ($i + 1 < $numTokens && $origTokens[$i + 1][0] === \T_WHITESPACE) {
|
||||
// Move trailing newline into following T_WHITESPACE token, if it already exists.
|
||||
$origTokens[$i + 1][1] = $trailingNewline . $origTokens[$i + 1][1];
|
||||
$origTokens[$i + 1][2]--;
|
||||
} else {
|
||||
// Otherwise, we need to create a new T_WHITESPACE token.
|
||||
$tokens[] = new static(\T_WHITESPACE, $trailingNewline, $line, $pos);
|
||||
$line++;
|
||||
$pos += \strlen($trailingNewline);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Emulate PHP 8.0 T_NAME_* tokens, by combining sequences of T_NS_SEPARATOR and
|
||||
// T_STRING into a single token.
|
||||
if (($id === \T_NS_SEPARATOR || isset(self::$identifierTokens[$id]))) {
|
||||
$newText = $text;
|
||||
$lastWasSeparator = $id === \T_NS_SEPARATOR;
|
||||
for ($j = $i + 1; $j < $numTokens; $j++) {
|
||||
if ($lastWasSeparator) {
|
||||
if (!isset(self::$identifierTokens[$origTokens[$j][0]])) {
|
||||
break;
|
||||
}
|
||||
$lastWasSeparator = false;
|
||||
} else {
|
||||
if ($origTokens[$j][0] !== \T_NS_SEPARATOR) {
|
||||
break;
|
||||
}
|
||||
$lastWasSeparator = true;
|
||||
}
|
||||
$newText .= $origTokens[$j][1];
|
||||
}
|
||||
if ($lastWasSeparator) {
|
||||
// Trailing separator is not part of the name.
|
||||
$j--;
|
||||
$newText = \substr($newText, 0, -1);
|
||||
}
|
||||
if ($j > $i + 1) {
|
||||
if ($id === \T_NS_SEPARATOR) {
|
||||
$id = \T_NAME_FULLY_QUALIFIED;
|
||||
} elseif ($id === \T_NAMESPACE) {
|
||||
$id = \T_NAME_RELATIVE;
|
||||
} else {
|
||||
$id = \T_NAME_QUALIFIED;
|
||||
}
|
||||
$tokens[] = new static($id, $newText, $line, $pos);
|
||||
$pos += \strlen($newText);
|
||||
$i = $j - 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$tokens[] = new static($id, $text, $line, $pos);
|
||||
$line += \substr_count($text, "\n");
|
||||
$pos += \strlen($text);
|
||||
}
|
||||
}
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
/** Initialize private static state needed by tokenize(). */
|
||||
private static function init(): void {
|
||||
if (isset(self::$identifierTokens)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Based on semi_reserved production.
|
||||
self::$identifierTokens = \array_fill_keys([
|
||||
\T_STRING,
|
||||
\T_STATIC, \T_ABSTRACT, \T_FINAL, \T_PRIVATE, \T_PROTECTED, \T_PUBLIC, \T_READONLY,
|
||||
\T_INCLUDE, \T_INCLUDE_ONCE, \T_EVAL, \T_REQUIRE, \T_REQUIRE_ONCE, \T_LOGICAL_OR, \T_LOGICAL_XOR, \T_LOGICAL_AND,
|
||||
\T_INSTANCEOF, \T_NEW, \T_CLONE, \T_EXIT, \T_IF, \T_ELSEIF, \T_ELSE, \T_ENDIF, \T_ECHO, \T_DO, \T_WHILE,
|
||||
\T_ENDWHILE, \T_FOR, \T_ENDFOR, \T_FOREACH, \T_ENDFOREACH, \T_DECLARE, \T_ENDDECLARE, \T_AS, \T_TRY, \T_CATCH,
|
||||
\T_FINALLY, \T_THROW, \T_USE, \T_INSTEADOF, \T_GLOBAL, \T_VAR, \T_UNSET, \T_ISSET, \T_EMPTY, \T_CONTINUE, \T_GOTO,
|
||||
\T_FUNCTION, \T_CONST, \T_RETURN, \T_PRINT, \T_YIELD, \T_LIST, \T_SWITCH, \T_ENDSWITCH, \T_CASE, \T_DEFAULT,
|
||||
\T_BREAK, \T_ARRAY, \T_CALLABLE, \T_EXTENDS, \T_IMPLEMENTS, \T_NAMESPACE, \T_TRAIT, \T_INTERFACE, \T_CLASS,
|
||||
\T_CLASS_C, \T_TRAIT_C, \T_FUNC_C, \T_METHOD_C, \T_LINE, \T_FILE, \T_DIR, \T_NS_C, \T_HALT_COMPILER, \T_FN,
|
||||
\T_MATCH,
|
||||
], true);
|
||||
}
|
||||
}
|
|
@ -2,22 +2,23 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Internal;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Token;
|
||||
|
||||
/**
|
||||
* Provides operations on token streams, for use by pretty printer.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class TokenStream
|
||||
{
|
||||
/** @var array Tokens (in token_get_all format) */
|
||||
private $tokens;
|
||||
class TokenStream {
|
||||
/** @var Token[] Tokens (in PhpToken::tokenize() format) */
|
||||
private array $tokens;
|
||||
/** @var int[] Map from position to indentation */
|
||||
private $indentMap;
|
||||
private array $indentMap;
|
||||
|
||||
/**
|
||||
* Create token stream instance.
|
||||
*
|
||||
* @param array $tokens Tokens in token_get_all() format
|
||||
* @param Token[] $tokens Tokens in PhpToken::tokenize() format
|
||||
*/
|
||||
public function __construct(array $tokens) {
|
||||
$this->tokens = $tokens;
|
||||
|
@ -28,11 +29,9 @@ class TokenStream
|
|||
* Whether the given position is immediately surrounded by parenthesis.
|
||||
*
|
||||
* @param int $startPos Start position
|
||||
* @param int $endPos End position
|
||||
*
|
||||
* @return bool
|
||||
* @param int $endPos End position
|
||||
*/
|
||||
public function haveParens(int $startPos, int $endPos) : bool {
|
||||
public function haveParens(int $startPos, int $endPos): bool {
|
||||
return $this->haveTokenImmediatelyBefore($startPos, '(')
|
||||
&& $this->haveTokenImmediatelyAfter($endPos, ')');
|
||||
}
|
||||
|
@ -41,11 +40,9 @@ class TokenStream
|
|||
* Whether the given position is immediately surrounded by braces.
|
||||
*
|
||||
* @param int $startPos Start position
|
||||
* @param int $endPos End position
|
||||
*
|
||||
* @return bool
|
||||
* @param int $endPos End position
|
||||
*/
|
||||
public function haveBraces(int $startPos, int $endPos) : bool {
|
||||
public function haveBraces(int $startPos, int $endPos): bool {
|
||||
return ($this->haveTokenImmediatelyBefore($startPos, '{')
|
||||
|| $this->haveTokenImmediatelyBefore($startPos, T_CURLY_OPEN))
|
||||
&& $this->haveTokenImmediatelyAfter($endPos, '}');
|
||||
|
@ -56,21 +53,20 @@ class TokenStream
|
|||
*
|
||||
* During this check whitespace and comments are skipped.
|
||||
*
|
||||
* @param int $pos Position before which the token should occur
|
||||
* @param int $pos Position before which the token should occur
|
||||
* @param int|string $expectedTokenType Token to check for
|
||||
*
|
||||
* @return bool Whether the expected token was found
|
||||
*/
|
||||
public function haveTokenImmediatelyBefore(int $pos, $expectedTokenType) : bool {
|
||||
public function haveTokenImmediatelyBefore(int $pos, $expectedTokenType): bool {
|
||||
$tokens = $this->tokens;
|
||||
$pos--;
|
||||
for (; $pos >= 0; $pos--) {
|
||||
$tokenType = $tokens[$pos][0];
|
||||
if ($tokenType === $expectedTokenType) {
|
||||
$token = $tokens[$pos];
|
||||
if ($token->is($expectedTokenType)) {
|
||||
return true;
|
||||
}
|
||||
if ($tokenType !== \T_WHITESPACE
|
||||
&& $tokenType !== \T_COMMENT && $tokenType !== \T_DOC_COMMENT) {
|
||||
if (!$token->isIgnorable()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -82,28 +78,28 @@ class TokenStream
|
|||
*
|
||||
* During this check whitespace and comments are skipped.
|
||||
*
|
||||
* @param int $pos Position after which the token should occur
|
||||
* @param int $pos Position after which the token should occur
|
||||
* @param int|string $expectedTokenType Token to check for
|
||||
*
|
||||
* @return bool Whether the expected token was found
|
||||
*/
|
||||
public function haveTokenImmediatelyAfter(int $pos, $expectedTokenType) : bool {
|
||||
public function haveTokenImmediatelyAfter(int $pos, $expectedTokenType): bool {
|
||||
$tokens = $this->tokens;
|
||||
$pos++;
|
||||
for (; $pos < \count($tokens); $pos++) {
|
||||
$tokenType = $tokens[$pos][0];
|
||||
if ($tokenType === $expectedTokenType) {
|
||||
for ($c = \count($tokens); $pos < $c; $pos++) {
|
||||
$token = $tokens[$pos];
|
||||
if ($token->is($expectedTokenType)) {
|
||||
return true;
|
||||
}
|
||||
if ($tokenType !== \T_WHITESPACE
|
||||
&& $tokenType !== \T_COMMENT && $tokenType !== \T_DOC_COMMENT) {
|
||||
if (!$token->isIgnorable()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function skipLeft(int $pos, $skipTokenType) {
|
||||
/** @param int|string|(int|string)[] $skipTokenType */
|
||||
public function skipLeft(int $pos, $skipTokenType): int {
|
||||
$tokens = $this->tokens;
|
||||
|
||||
$pos = $this->skipLeftWhitespace($pos);
|
||||
|
@ -111,7 +107,7 @@ class TokenStream
|
|||
return $pos;
|
||||
}
|
||||
|
||||
if ($tokens[$pos][0] !== $skipTokenType) {
|
||||
if (!$tokens[$pos]->is($skipTokenType)) {
|
||||
// Shouldn't happen. The skip token MUST be there
|
||||
throw new \Exception('Encountered unexpected token');
|
||||
}
|
||||
|
@ -120,7 +116,8 @@ class TokenStream
|
|||
return $this->skipLeftWhitespace($pos);
|
||||
}
|
||||
|
||||
public function skipRight(int $pos, $skipTokenType) {
|
||||
/** @param int|string|(int|string)[] $skipTokenType */
|
||||
public function skipRight(int $pos, $skipTokenType): int {
|
||||
$tokens = $this->tokens;
|
||||
|
||||
$pos = $this->skipRightWhitespace($pos);
|
||||
|
@ -128,7 +125,7 @@ class TokenStream
|
|||
return $pos;
|
||||
}
|
||||
|
||||
if ($tokens[$pos][0] !== $skipTokenType) {
|
||||
if (!$tokens[$pos]->is($skipTokenType)) {
|
||||
// Shouldn't happen. The skip token MUST be there
|
||||
throw new \Exception('Encountered unexpected token');
|
||||
}
|
||||
|
@ -143,11 +140,10 @@ class TokenStream
|
|||
* @param int $pos Token position
|
||||
* @return int Non-whitespace token position
|
||||
*/
|
||||
public function skipLeftWhitespace(int $pos) {
|
||||
public function skipLeftWhitespace(int $pos): int {
|
||||
$tokens = $this->tokens;
|
||||
for (; $pos >= 0; $pos--) {
|
||||
$type = $tokens[$pos][0];
|
||||
if ($type !== \T_WHITESPACE && $type !== \T_COMMENT && $type !== \T_DOC_COMMENT) {
|
||||
if (!$tokens[$pos]->isIgnorable()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -160,22 +156,21 @@ class TokenStream
|
|||
* @param int $pos Token position
|
||||
* @return int Non-whitespace token position
|
||||
*/
|
||||
public function skipRightWhitespace(int $pos) {
|
||||
public function skipRightWhitespace(int $pos): int {
|
||||
$tokens = $this->tokens;
|
||||
for ($count = \count($tokens); $pos < $count; $pos++) {
|
||||
$type = $tokens[$pos][0];
|
||||
if ($type !== \T_WHITESPACE && $type !== \T_COMMENT && $type !== \T_DOC_COMMENT) {
|
||||
if (!$tokens[$pos]->isIgnorable()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $pos;
|
||||
}
|
||||
|
||||
public function findRight(int $pos, $findTokenType) {
|
||||
/** @param int|string|(int|string)[] $findTokenType */
|
||||
public function findRight(int $pos, $findTokenType): int {
|
||||
$tokens = $this->tokens;
|
||||
for ($count = \count($tokens); $pos < $count; $pos++) {
|
||||
$type = $tokens[$pos][0];
|
||||
if ($type === $findTokenType) {
|
||||
if ($tokens[$pos]->is($findTokenType)) {
|
||||
return $pos;
|
||||
}
|
||||
}
|
||||
|
@ -190,22 +185,16 @@ class TokenStream
|
|||
* @param int|string $tokenType Token type to look for
|
||||
* @return bool Whether the token occurs in the given range
|
||||
*/
|
||||
public function haveTokenInRange(int $startPos, int $endPos, $tokenType) {
|
||||
public function haveTokenInRange(int $startPos, int $endPos, $tokenType): bool {
|
||||
$tokens = $this->tokens;
|
||||
for ($pos = $startPos; $pos < $endPos; $pos++) {
|
||||
if ($tokens[$pos][0] === $tokenType) {
|
||||
if ($tokens[$pos]->is($tokenType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function haveBracesInRange(int $startPos, int $endPos) {
|
||||
return $this->haveTokenInRange($startPos, $endPos, '{')
|
||||
|| $this->haveTokenInRange($startPos, $endPos, T_CURLY_OPEN)
|
||||
|| $this->haveTokenInRange($startPos, $endPos, '}');
|
||||
}
|
||||
|
||||
public function haveTagInRange(int $startPos, int $endPos): bool {
|
||||
return $this->haveTokenInRange($startPos, $endPos, \T_OPEN_TAG)
|
||||
|| $this->haveTokenInRange($startPos, $endPos, \T_CLOSE_TAG);
|
||||
|
@ -218,41 +207,37 @@ class TokenStream
|
|||
*
|
||||
* @return int Indentation depth (in spaces)
|
||||
*/
|
||||
public function getIndentationBefore(int $pos) : int {
|
||||
public function getIndentationBefore(int $pos): int {
|
||||
return $this->indentMap[$pos];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the code corresponding to a token offset range, optionally adjusted for indentation.
|
||||
*
|
||||
* @param int $from Token start position (inclusive)
|
||||
* @param int $to Token end position (exclusive)
|
||||
* @param int $from Token start position (inclusive)
|
||||
* @param int $to Token end position (exclusive)
|
||||
* @param int $indent By how much the code should be indented (can be negative as well)
|
||||
*
|
||||
* @return string Code corresponding to token range, adjusted for indentation
|
||||
*/
|
||||
public function getTokenCode(int $from, int $to, int $indent) : string {
|
||||
public function getTokenCode(int $from, int $to, int $indent): string {
|
||||
$tokens = $this->tokens;
|
||||
$result = '';
|
||||
for ($pos = $from; $pos < $to; $pos++) {
|
||||
$token = $tokens[$pos];
|
||||
if (\is_array($token)) {
|
||||
$type = $token[0];
|
||||
$content = $token[1];
|
||||
if ($type === \T_CONSTANT_ENCAPSED_STRING || $type === \T_ENCAPSED_AND_WHITESPACE) {
|
||||
$result .= $content;
|
||||
} else {
|
||||
// TODO Handle non-space indentation
|
||||
if ($indent < 0) {
|
||||
$result .= str_replace("\n" . str_repeat(" ", -$indent), "\n", $content);
|
||||
} elseif ($indent > 0) {
|
||||
$result .= str_replace("\n", "\n" . str_repeat(" ", $indent), $content);
|
||||
} else {
|
||||
$result .= $content;
|
||||
}
|
||||
}
|
||||
$id = $token->id;
|
||||
$text = $token->text;
|
||||
if ($id === \T_CONSTANT_ENCAPSED_STRING || $id === \T_ENCAPSED_AND_WHITESPACE) {
|
||||
$result .= $text;
|
||||
} else {
|
||||
$result .= $token;
|
||||
// TODO Handle non-space indentation
|
||||
if ($indent < 0) {
|
||||
$result .= str_replace("\n" . str_repeat(" ", -$indent), "\n", $text);
|
||||
} elseif ($indent > 0) {
|
||||
$result .= str_replace("\n", "\n" . str_repeat(" ", $indent), $text);
|
||||
} else {
|
||||
$result .= $text;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
|
@ -263,17 +248,21 @@ class TokenStream
|
|||
*
|
||||
* @return int[] Token position to indentation map
|
||||
*/
|
||||
private function calcIndentMap() {
|
||||
private function calcIndentMap(): array {
|
||||
$indentMap = [];
|
||||
$indent = 0;
|
||||
foreach ($this->tokens as $token) {
|
||||
foreach ($this->tokens as $i => $token) {
|
||||
$indentMap[] = $indent;
|
||||
|
||||
if ($token[0] === \T_WHITESPACE) {
|
||||
$content = $token[1];
|
||||
if ($token->id === \T_WHITESPACE) {
|
||||
$content = $token->text;
|
||||
$newlinePos = \strrpos($content, "\n");
|
||||
if (false !== $newlinePos) {
|
||||
$indent = \strlen($content) - $newlinePos - 1;
|
||||
} elseif ($i === 1 && $this->tokens[0]->id === \T_OPEN_TAG &&
|
||||
$this->tokens[0]->text[\strlen($this->tokens[0]->text) - 1] === "\n") {
|
||||
// Special case: Newline at the end of opening tag followed by whitespace.
|
||||
$indent = \strlen($content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser;
|
||||
|
||||
class JsonDecoder
|
||||
{
|
||||
/** @var \ReflectionClass[] Node type to reflection class map */
|
||||
private $reflectionClassCache;
|
||||
class JsonDecoder {
|
||||
/** @var \ReflectionClass<Node>[] Node type to reflection class map */
|
||||
private array $reflectionClassCache;
|
||||
|
||||
/** @return mixed */
|
||||
public function decode(string $json) {
|
||||
$value = json_decode($json, true);
|
||||
if (json_last_error()) {
|
||||
|
@ -16,6 +16,10 @@ class JsonDecoder
|
|||
return $this->decodeRecursive($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
private function decodeRecursive($value) {
|
||||
if (\is_array($value)) {
|
||||
if (isset($value['nodeType'])) {
|
||||
|
@ -29,7 +33,7 @@ class JsonDecoder
|
|||
return $value;
|
||||
}
|
||||
|
||||
private function decodeArray(array $array) : array {
|
||||
private function decodeArray(array $array): array {
|
||||
$decodedArray = [];
|
||||
foreach ($array as $key => $value) {
|
||||
$decodedArray[$key] = $this->decodeRecursive($value);
|
||||
|
@ -37,14 +41,13 @@ class JsonDecoder
|
|||
return $decodedArray;
|
||||
}
|
||||
|
||||
private function decodeNode(array $value) : Node {
|
||||
private function decodeNode(array $value): Node {
|
||||
$nodeType = $value['nodeType'];
|
||||
if (!\is_string($nodeType)) {
|
||||
throw new \RuntimeException('Node type must be a string');
|
||||
}
|
||||
|
||||
$reflectionClass = $this->reflectionClassFromNodeType($nodeType);
|
||||
/** @var Node $node */
|
||||
$node = $reflectionClass->newInstanceWithoutConstructor();
|
||||
|
||||
if (isset($value['attributes'])) {
|
||||
|
@ -66,7 +69,7 @@ class JsonDecoder
|
|||
return $node;
|
||||
}
|
||||
|
||||
private function decodeComment(array $value) : Comment {
|
||||
private function decodeComment(array $value): Comment {
|
||||
$className = $value['nodeType'] === 'Comment' ? Comment::class : Comment\Doc::class;
|
||||
if (!isset($value['text'])) {
|
||||
throw new \RuntimeException('Comment must have text');
|
||||
|
@ -79,7 +82,8 @@ class JsonDecoder
|
|||
);
|
||||
}
|
||||
|
||||
private function reflectionClassFromNodeType(string $nodeType) : \ReflectionClass {
|
||||
/** @return \ReflectionClass<Node> */
|
||||
private function reflectionClassFromNodeType(string $nodeType): \ReflectionClass {
|
||||
if (!isset($this->reflectionClassCache[$nodeType])) {
|
||||
$className = $this->classNameFromNodeType($nodeType);
|
||||
$this->reflectionClassCache[$nodeType] = new \ReflectionClass($className);
|
||||
|
@ -87,7 +91,8 @@ class JsonDecoder
|
|||
return $this->reflectionClassCache[$nodeType];
|
||||
}
|
||||
|
||||
private function classNameFromNodeType(string $nodeType) : string {
|
||||
/** @return class-string<Node> */
|
||||
private function classNameFromNodeType(string $nodeType): string {
|
||||
$className = 'PhpParser\\Node\\' . strtr($nodeType, '_', '\\');
|
||||
if (class_exists($className)) {
|
||||
return $className;
|
||||
|
|
590
src/ncc/ThirdParty/nikic/PhpParser/Lexer.php
vendored
590
src/ncc/ThirdParty/nikic/PhpParser/Lexer.php
vendored
|
@ -2,559 +2,115 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Parser\Tokens;
|
||||
|
||||
class Lexer
|
||||
{
|
||||
protected $code;
|
||||
protected $tokens;
|
||||
protected $pos;
|
||||
protected $line;
|
||||
protected $filePos;
|
||||
protected $prevCloseTagHasNewline;
|
||||
|
||||
protected $tokenMap;
|
||||
protected $dropTokens;
|
||||
protected $identifierTokens;
|
||||
|
||||
private $attributeStartLineUsed;
|
||||
private $attributeEndLineUsed;
|
||||
private $attributeStartTokenPosUsed;
|
||||
private $attributeEndTokenPosUsed;
|
||||
private $attributeStartFilePosUsed;
|
||||
private $attributeEndFilePosUsed;
|
||||
private $attributeCommentsUsed;
|
||||
require __DIR__ . '/compatibility_tokens.php';
|
||||
|
||||
class Lexer {
|
||||
/**
|
||||
* Creates a Lexer.
|
||||
* Tokenize the provided source code.
|
||||
*
|
||||
* @param array $options Options array. Currently only the 'usedAttributes' option is supported,
|
||||
* which is an array of attributes to add to the AST nodes. Possible
|
||||
* attributes are: 'comments', 'startLine', 'endLine', 'startTokenPos',
|
||||
* 'endTokenPos', 'startFilePos', 'endFilePos'. The option defaults to the
|
||||
* first three. For more info see getNextToken() docs.
|
||||
*/
|
||||
public function __construct(array $options = []) {
|
||||
// Create Map from internal tokens to PhpParser tokens.
|
||||
$this->defineCompatibilityTokens();
|
||||
$this->tokenMap = $this->createTokenMap();
|
||||
$this->identifierTokens = $this->createIdentifierTokenMap();
|
||||
|
||||
// map of tokens to drop while lexing (the map is only used for isset lookup,
|
||||
// that's why the value is simply set to 1; the value is never actually used.)
|
||||
$this->dropTokens = array_fill_keys(
|
||||
[\T_WHITESPACE, \T_OPEN_TAG, \T_COMMENT, \T_DOC_COMMENT, \T_BAD_CHARACTER], 1
|
||||
);
|
||||
|
||||
$defaultAttributes = ['comments', 'startLine', 'endLine'];
|
||||
$usedAttributes = array_fill_keys($options['usedAttributes'] ?? $defaultAttributes, true);
|
||||
|
||||
// Create individual boolean properties to make these checks faster.
|
||||
$this->attributeStartLineUsed = isset($usedAttributes['startLine']);
|
||||
$this->attributeEndLineUsed = isset($usedAttributes['endLine']);
|
||||
$this->attributeStartTokenPosUsed = isset($usedAttributes['startTokenPos']);
|
||||
$this->attributeEndTokenPosUsed = isset($usedAttributes['endTokenPos']);
|
||||
$this->attributeStartFilePosUsed = isset($usedAttributes['startFilePos']);
|
||||
$this->attributeEndFilePosUsed = isset($usedAttributes['endFilePos']);
|
||||
$this->attributeCommentsUsed = isset($usedAttributes['comments']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the lexer for lexing the provided source code.
|
||||
* The token array is in the same format as provided by the PhpToken::tokenize() method in
|
||||
* PHP 8.0. The tokens are instances of PhpParser\Token, to abstract over a polyfill
|
||||
* implementation in earlier PHP version.
|
||||
*
|
||||
* This function does not throw if lexing errors occur. Instead, errors may be retrieved using
|
||||
* the getErrors() method.
|
||||
* The token array is terminated by a sentinel token with token ID 0.
|
||||
* The token array does not discard any tokens (i.e. whitespace and comments are included).
|
||||
* The token position attributes are against this token array.
|
||||
*
|
||||
* @param string $code The source code to lex
|
||||
* @param string $code The source code to tokenize.
|
||||
* @param ErrorHandler|null $errorHandler Error handler to use for lexing errors. Defaults to
|
||||
* ErrorHandler\Throwing
|
||||
* ErrorHandler\Throwing.
|
||||
* @return Token[] Tokens
|
||||
*/
|
||||
public function startLexing(string $code, ErrorHandler $errorHandler = null) {
|
||||
public function tokenize(string $code, ?ErrorHandler $errorHandler = null): array {
|
||||
if (null === $errorHandler) {
|
||||
$errorHandler = new ErrorHandler\Throwing();
|
||||
}
|
||||
|
||||
$this->code = $code; // keep the code around for __halt_compiler() handling
|
||||
$this->pos = -1;
|
||||
$this->line = 1;
|
||||
$this->filePos = 0;
|
||||
|
||||
// If inline HTML occurs without preceding code, treat it as if it had a leading newline.
|
||||
// This ensures proper composability, because having a newline is the "safe" assumption.
|
||||
$this->prevCloseTagHasNewline = true;
|
||||
|
||||
$scream = ini_set('xdebug.scream', '0');
|
||||
|
||||
$this->tokens = @token_get_all($code);
|
||||
$this->postprocessTokens($errorHandler);
|
||||
$tokens = @Token::tokenize($code);
|
||||
$this->postprocessTokens($tokens, $errorHandler);
|
||||
|
||||
if (false !== $scream) {
|
||||
ini_set('xdebug.scream', $scream);
|
||||
}
|
||||
}
|
||||
|
||||
private function handleInvalidCharacterRange($start, $end, $line, ErrorHandler $errorHandler) {
|
||||
$tokens = [];
|
||||
for ($i = $start; $i < $end; $i++) {
|
||||
$chr = $this->code[$i];
|
||||
if ($chr === "\0") {
|
||||
// PHP cuts error message after null byte, so need special case
|
||||
$errorMsg = 'Unexpected null byte';
|
||||
} else {
|
||||
$errorMsg = sprintf(
|
||||
'Unexpected character "%s" (ASCII %d)', $chr, ord($chr)
|
||||
);
|
||||
}
|
||||
|
||||
$tokens[] = [\T_BAD_CHARACTER, $chr, $line];
|
||||
$errorHandler->handleError(new Error($errorMsg, [
|
||||
'startLine' => $line,
|
||||
'endLine' => $line,
|
||||
'startFilePos' => $i,
|
||||
'endFilePos' => $i,
|
||||
]));
|
||||
}
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether comment token is unterminated.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isUnterminatedComment($token) : bool {
|
||||
return ($token[0] === \T_COMMENT || $token[0] === \T_DOC_COMMENT)
|
||||
&& substr($token[1], 0, 2) === '/*'
|
||||
&& substr($token[1], -2) !== '*/';
|
||||
private function handleInvalidCharacter(Token $token, ErrorHandler $errorHandler): void {
|
||||
$chr = $token->text;
|
||||
if ($chr === "\0") {
|
||||
// PHP cuts error message after null byte, so need special case
|
||||
$errorMsg = 'Unexpected null byte';
|
||||
} else {
|
||||
$errorMsg = sprintf(
|
||||
'Unexpected character "%s" (ASCII %d)', $chr, ord($chr)
|
||||
);
|
||||
}
|
||||
|
||||
$errorHandler->handleError(new Error($errorMsg, [
|
||||
'startLine' => $token->line,
|
||||
'endLine' => $token->line,
|
||||
'startFilePos' => $token->pos,
|
||||
'endFilePos' => $token->pos,
|
||||
]));
|
||||
}
|
||||
|
||||
protected function postprocessTokens(ErrorHandler $errorHandler) {
|
||||
// PHP's error handling for token_get_all() is rather bad, so if we want detailed
|
||||
// error information we need to compute it ourselves. Invalid character errors are
|
||||
// detected by finding "gaps" in the token array. Unterminated comments are detected
|
||||
// by checking if a trailing comment has a "*/" at the end.
|
||||
//
|
||||
// Additionally, we perform a number of canonicalizations here:
|
||||
// * Use the PHP 8.0 comment format, which does not include trailing whitespace anymore.
|
||||
// * Use PHP 8.0 T_NAME_* tokens.
|
||||
private function isUnterminatedComment(Token $token): bool {
|
||||
return $token->is([\T_COMMENT, \T_DOC_COMMENT])
|
||||
&& substr($token->text, 0, 2) === '/*'
|
||||
&& substr($token->text, -2) !== '*/';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<Token> $tokens
|
||||
*/
|
||||
protected function postprocessTokens(array &$tokens, ErrorHandler $errorHandler): void {
|
||||
// This function reports errors (bad characters and unterminated comments) in the token
|
||||
// array, and performs certain canonicalizations:
|
||||
// * Use PHP 8.1 T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG and
|
||||
// T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG tokens used to disambiguate intersection types.
|
||||
// * Add a sentinel token with ID 0.
|
||||
|
||||
$numTokens = \count($tokens);
|
||||
if ($numTokens === 0) {
|
||||
// Empty input edge case: Just add the sentinel token.
|
||||
$tokens[] = new Token(0, "\0", 1, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
$filePos = 0;
|
||||
$line = 1;
|
||||
$numTokens = \count($this->tokens);
|
||||
for ($i = 0; $i < $numTokens; $i++) {
|
||||
$token = $this->tokens[$i];
|
||||
|
||||
// Since PHP 7.4 invalid characters are represented by a T_BAD_CHARACTER token.
|
||||
// In this case we only need to emit an error.
|
||||
if ($token[0] === \T_BAD_CHARACTER) {
|
||||
$this->handleInvalidCharacterRange($filePos, $filePos + 1, $line, $errorHandler);
|
||||
$token = $tokens[$i];
|
||||
if ($token->id === \T_BAD_CHARACTER) {
|
||||
$this->handleInvalidCharacter($token, $errorHandler);
|
||||
}
|
||||
|
||||
if ($token[0] === \T_COMMENT && substr($token[1], 0, 2) !== '/*'
|
||||
&& preg_match('/(\r\n|\n|\r)$/D', $token[1], $matches)) {
|
||||
$trailingNewline = $matches[0];
|
||||
$token[1] = substr($token[1], 0, -strlen($trailingNewline));
|
||||
$this->tokens[$i] = $token;
|
||||
if (isset($this->tokens[$i + 1]) && $this->tokens[$i + 1][0] === \T_WHITESPACE) {
|
||||
// Move trailing newline into following T_WHITESPACE token, if it already exists.
|
||||
$this->tokens[$i + 1][1] = $trailingNewline . $this->tokens[$i + 1][1];
|
||||
$this->tokens[$i + 1][2]--;
|
||||
} else {
|
||||
// Otherwise, we need to create a new T_WHITESPACE token.
|
||||
array_splice($this->tokens, $i + 1, 0, [
|
||||
[\T_WHITESPACE, $trailingNewline, $line],
|
||||
]);
|
||||
$numTokens++;
|
||||
}
|
||||
}
|
||||
|
||||
// Emulate PHP 8 T_NAME_* tokens, by combining sequences of T_NS_SEPARATOR and T_STRING
|
||||
// into a single token.
|
||||
if (\is_array($token)
|
||||
&& ($token[0] === \T_NS_SEPARATOR || isset($this->identifierTokens[$token[0]]))) {
|
||||
$lastWasSeparator = $token[0] === \T_NS_SEPARATOR;
|
||||
$text = $token[1];
|
||||
for ($j = $i + 1; isset($this->tokens[$j]); $j++) {
|
||||
if ($lastWasSeparator) {
|
||||
if (!isset($this->identifierTokens[$this->tokens[$j][0]])) {
|
||||
break;
|
||||
}
|
||||
$lastWasSeparator = false;
|
||||
} else {
|
||||
if ($this->tokens[$j][0] !== \T_NS_SEPARATOR) {
|
||||
break;
|
||||
}
|
||||
$lastWasSeparator = true;
|
||||
}
|
||||
$text .= $this->tokens[$j][1];
|
||||
}
|
||||
if ($lastWasSeparator) {
|
||||
// Trailing separator is not part of the name.
|
||||
$j--;
|
||||
$text = substr($text, 0, -1);
|
||||
}
|
||||
if ($j > $i + 1) {
|
||||
if ($token[0] === \T_NS_SEPARATOR) {
|
||||
$type = \T_NAME_FULLY_QUALIFIED;
|
||||
} else if ($token[0] === \T_NAMESPACE) {
|
||||
$type = \T_NAME_RELATIVE;
|
||||
} else {
|
||||
$type = \T_NAME_QUALIFIED;
|
||||
}
|
||||
$token = [$type, $text, $line];
|
||||
array_splice($this->tokens, $i, $j - $i, [$token]);
|
||||
$numTokens -= $j - $i - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($token === '&') {
|
||||
if ($token->id === \ord('&')) {
|
||||
$next = $i + 1;
|
||||
while (isset($this->tokens[$next]) && $this->tokens[$next][0] === \T_WHITESPACE) {
|
||||
while (isset($tokens[$next]) && $tokens[$next]->id === \T_WHITESPACE) {
|
||||
$next++;
|
||||
}
|
||||
$followedByVarOrVarArg = isset($this->tokens[$next]) &&
|
||||
($this->tokens[$next][0] === \T_VARIABLE || $this->tokens[$next][0] === \T_ELLIPSIS);
|
||||
$this->tokens[$i] = $token = [
|
||||
$followedByVarOrVarArg
|
||||
? \T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG
|
||||
: \T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG,
|
||||
'&',
|
||||
$line,
|
||||
];
|
||||
}
|
||||
|
||||
$tokenValue = \is_string($token) ? $token : $token[1];
|
||||
$tokenLen = \strlen($tokenValue);
|
||||
|
||||
if (substr($this->code, $filePos, $tokenLen) !== $tokenValue) {
|
||||
// Something is missing, must be an invalid character
|
||||
$nextFilePos = strpos($this->code, $tokenValue, $filePos);
|
||||
$badCharTokens = $this->handleInvalidCharacterRange(
|
||||
$filePos, $nextFilePos, $line, $errorHandler);
|
||||
$filePos = (int) $nextFilePos;
|
||||
|
||||
array_splice($this->tokens, $i, 0, $badCharTokens);
|
||||
$numTokens += \count($badCharTokens);
|
||||
$i += \count($badCharTokens);
|
||||
}
|
||||
|
||||
$filePos += $tokenLen;
|
||||
$line += substr_count($tokenValue, "\n");
|
||||
}
|
||||
|
||||
if ($filePos !== \strlen($this->code)) {
|
||||
if (substr($this->code, $filePos, 2) === '/*') {
|
||||
// Unlike PHP, HHVM will drop unterminated comments entirely
|
||||
$comment = substr($this->code, $filePos);
|
||||
$errorHandler->handleError(new Error('Unterminated comment', [
|
||||
'startLine' => $line,
|
||||
'endLine' => $line + substr_count($comment, "\n"),
|
||||
'startFilePos' => $filePos,
|
||||
'endFilePos' => $filePos + \strlen($comment),
|
||||
]));
|
||||
|
||||
// Emulate the PHP behavior
|
||||
$isDocComment = isset($comment[3]) && $comment[3] === '*';
|
||||
$this->tokens[] = [$isDocComment ? \T_DOC_COMMENT : \T_COMMENT, $comment, $line];
|
||||
} else {
|
||||
// Invalid characters at the end of the input
|
||||
$badCharTokens = $this->handleInvalidCharacterRange(
|
||||
$filePos, \strlen($this->code), $line, $errorHandler);
|
||||
$this->tokens = array_merge($this->tokens, $badCharTokens);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (count($this->tokens) > 0) {
|
||||
// Check for unterminated comment
|
||||
$lastToken = $this->tokens[count($this->tokens) - 1];
|
||||
if ($this->isUnterminatedComment($lastToken)) {
|
||||
$errorHandler->handleError(new Error('Unterminated comment', [
|
||||
'startLine' => $line - substr_count($lastToken[1], "\n"),
|
||||
'endLine' => $line,
|
||||
'startFilePos' => $filePos - \strlen($lastToken[1]),
|
||||
'endFilePos' => $filePos,
|
||||
]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the next token.
|
||||
*
|
||||
* The available attributes are determined by the 'usedAttributes' option, which can
|
||||
* be specified in the constructor. The following attributes are supported:
|
||||
*
|
||||
* * 'comments' => Array of PhpParser\Comment or PhpParser\Comment\Doc instances,
|
||||
* representing all comments that occurred between the previous
|
||||
* non-discarded token and the current one.
|
||||
* * 'startLine' => Line in which the node starts.
|
||||
* * 'endLine' => Line in which the node ends.
|
||||
* * 'startTokenPos' => Offset into the token array of the first token in the node.
|
||||
* * 'endTokenPos' => Offset into the token array of the last token in the node.
|
||||
* * 'startFilePos' => Offset into the code string of the first character that is part of the node.
|
||||
* * 'endFilePos' => Offset into the code string of the last character that is part of the node.
|
||||
*
|
||||
* @param mixed $value Variable to store token content in
|
||||
* @param mixed $startAttributes Variable to store start attributes in
|
||||
* @param mixed $endAttributes Variable to store end attributes in
|
||||
*
|
||||
* @return int Token id
|
||||
*/
|
||||
public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) : int {
|
||||
$startAttributes = [];
|
||||
$endAttributes = [];
|
||||
|
||||
while (1) {
|
||||
if (isset($this->tokens[++$this->pos])) {
|
||||
$token = $this->tokens[$this->pos];
|
||||
} else {
|
||||
// EOF token with ID 0
|
||||
$token = "\0";
|
||||
}
|
||||
|
||||
if ($this->attributeStartLineUsed) {
|
||||
$startAttributes['startLine'] = $this->line;
|
||||
}
|
||||
if ($this->attributeStartTokenPosUsed) {
|
||||
$startAttributes['startTokenPos'] = $this->pos;
|
||||
}
|
||||
if ($this->attributeStartFilePosUsed) {
|
||||
$startAttributes['startFilePos'] = $this->filePos;
|
||||
}
|
||||
|
||||
if (\is_string($token)) {
|
||||
$value = $token;
|
||||
if (isset($token[1])) {
|
||||
// bug in token_get_all
|
||||
$this->filePos += 2;
|
||||
$id = ord('"');
|
||||
} else {
|
||||
$this->filePos += 1;
|
||||
$id = ord($token);
|
||||
}
|
||||
} elseif (!isset($this->dropTokens[$token[0]])) {
|
||||
$value = $token[1];
|
||||
$id = $this->tokenMap[$token[0]];
|
||||
if (\T_CLOSE_TAG === $token[0]) {
|
||||
$this->prevCloseTagHasNewline = false !== strpos($token[1], "\n")
|
||||
|| false !== strpos($token[1], "\r");
|
||||
} elseif (\T_INLINE_HTML === $token[0]) {
|
||||
$startAttributes['hasLeadingNewline'] = $this->prevCloseTagHasNewline;
|
||||
}
|
||||
|
||||
$this->line += substr_count($value, "\n");
|
||||
$this->filePos += \strlen($value);
|
||||
} else {
|
||||
$origLine = $this->line;
|
||||
$origFilePos = $this->filePos;
|
||||
$this->line += substr_count($token[1], "\n");
|
||||
$this->filePos += \strlen($token[1]);
|
||||
|
||||
if (\T_COMMENT === $token[0] || \T_DOC_COMMENT === $token[0]) {
|
||||
if ($this->attributeCommentsUsed) {
|
||||
$comment = \T_DOC_COMMENT === $token[0]
|
||||
? new Comment\Doc($token[1],
|
||||
$origLine, $origFilePos, $this->pos,
|
||||
$this->line, $this->filePos - 1, $this->pos)
|
||||
: new Comment($token[1],
|
||||
$origLine, $origFilePos, $this->pos,
|
||||
$this->line, $this->filePos - 1, $this->pos);
|
||||
$startAttributes['comments'][] = $comment;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->attributeEndLineUsed) {
|
||||
$endAttributes['endLine'] = $this->line;
|
||||
}
|
||||
if ($this->attributeEndTokenPosUsed) {
|
||||
$endAttributes['endTokenPos'] = $this->pos;
|
||||
}
|
||||
if ($this->attributeEndFilePosUsed) {
|
||||
$endAttributes['endFilePos'] = $this->filePos - 1;
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
throw new \RuntimeException('Reached end of lexer loop');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the token array for current code.
|
||||
*
|
||||
* The token array is in the same format as provided by the
|
||||
* token_get_all() function and does not discard tokens (i.e.
|
||||
* whitespace and comments are included). The token position
|
||||
* attributes are against this token array.
|
||||
*
|
||||
* @return array Array of tokens in token_get_all() format
|
||||
*/
|
||||
public function getTokens() : array {
|
||||
return $this->tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles __halt_compiler() by returning the text after it.
|
||||
*
|
||||
* @return string Remaining text
|
||||
*/
|
||||
public function handleHaltCompiler() : string {
|
||||
// text after T_HALT_COMPILER, still including ();
|
||||
$textAfter = substr($this->code, $this->filePos);
|
||||
|
||||
// ensure that it is followed by ();
|
||||
// this simplifies the situation, by not allowing any comments
|
||||
// in between of the tokens.
|
||||
if (!preg_match('~^\s*\(\s*\)\s*(?:;|\?>\r?\n?)~', $textAfter, $matches)) {
|
||||
throw new Error('__HALT_COMPILER must be followed by "();"');
|
||||
}
|
||||
|
||||
// prevent the lexer from returning any further tokens
|
||||
$this->pos = count($this->tokens);
|
||||
|
||||
// return with (); removed
|
||||
return substr($textAfter, strlen($matches[0]));
|
||||
}
|
||||
|
||||
private function defineCompatibilityTokens() {
|
||||
static $compatTokensDefined = false;
|
||||
if ($compatTokensDefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
$compatTokens = [
|
||||
// PHP 7.4
|
||||
'T_BAD_CHARACTER',
|
||||
'T_FN',
|
||||
'T_COALESCE_EQUAL',
|
||||
// PHP 8.0
|
||||
'T_NAME_QUALIFIED',
|
||||
'T_NAME_FULLY_QUALIFIED',
|
||||
'T_NAME_RELATIVE',
|
||||
'T_MATCH',
|
||||
'T_NULLSAFE_OBJECT_OPERATOR',
|
||||
'T_ATTRIBUTE',
|
||||
// PHP 8.1
|
||||
'T_ENUM',
|
||||
'T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG',
|
||||
'T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG',
|
||||
'T_READONLY',
|
||||
];
|
||||
|
||||
// PHP-Parser might be used together with another library that also emulates some or all
|
||||
// of these tokens. Perform a sanity-check that all already defined tokens have been
|
||||
// assigned a unique ID.
|
||||
$usedTokenIds = [];
|
||||
foreach ($compatTokens as $token) {
|
||||
if (\defined($token)) {
|
||||
$tokenId = \constant($token);
|
||||
$clashingToken = $usedTokenIds[$tokenId] ?? null;
|
||||
if ($clashingToken !== null) {
|
||||
throw new \Error(sprintf(
|
||||
'Token %s has same ID as token %s, ' .
|
||||
'you may be using a library with broken token emulation',
|
||||
$token, $clashingToken
|
||||
));
|
||||
}
|
||||
$usedTokenIds[$tokenId] = $token;
|
||||
$followedByVarOrVarArg = isset($tokens[$next]) &&
|
||||
$tokens[$next]->is([\T_VARIABLE, \T_ELLIPSIS]);
|
||||
$token->id = $followedByVarOrVarArg
|
||||
? \T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG
|
||||
: \T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG;
|
||||
}
|
||||
}
|
||||
|
||||
// Now define any tokens that have not yet been emulated. Try to assign IDs from -1
|
||||
// downwards, but skip any IDs that may already be in use.
|
||||
$newTokenId = -1;
|
||||
foreach ($compatTokens as $token) {
|
||||
if (!\defined($token)) {
|
||||
while (isset($usedTokenIds[$newTokenId])) {
|
||||
$newTokenId--;
|
||||
}
|
||||
\define($token, $newTokenId);
|
||||
$newTokenId--;
|
||||
}
|
||||
// Check for unterminated comment
|
||||
$lastToken = $tokens[$numTokens - 1];
|
||||
if ($this->isUnterminatedComment($lastToken)) {
|
||||
$errorHandler->handleError(new Error('Unterminated comment', [
|
||||
'startLine' => $lastToken->line,
|
||||
'endLine' => $lastToken->getEndLine(),
|
||||
'startFilePos' => $lastToken->pos,
|
||||
'endFilePos' => $lastToken->getEndPos(),
|
||||
]));
|
||||
}
|
||||
|
||||
$compatTokensDefined = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the token map.
|
||||
*
|
||||
* The token map maps the PHP internal token identifiers
|
||||
* to the identifiers used by the Parser. Additionally it
|
||||
* maps T_OPEN_TAG_WITH_ECHO to T_ECHO and T_CLOSE_TAG to ';'.
|
||||
*
|
||||
* @return array The token map
|
||||
*/
|
||||
protected function createTokenMap() : array {
|
||||
$tokenMap = [];
|
||||
|
||||
// 256 is the minimum possible token number, as everything below
|
||||
// it is an ASCII value
|
||||
for ($i = 256; $i < 1000; ++$i) {
|
||||
if (\T_DOUBLE_COLON === $i) {
|
||||
// T_DOUBLE_COLON is equivalent to T_PAAMAYIM_NEKUDOTAYIM
|
||||
$tokenMap[$i] = Tokens::T_PAAMAYIM_NEKUDOTAYIM;
|
||||
} elseif(\T_OPEN_TAG_WITH_ECHO === $i) {
|
||||
// T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO
|
||||
$tokenMap[$i] = Tokens::T_ECHO;
|
||||
} elseif(\T_CLOSE_TAG === $i) {
|
||||
// T_CLOSE_TAG is equivalent to ';'
|
||||
$tokenMap[$i] = ord(';');
|
||||
} elseif ('UNKNOWN' !== $name = token_name($i)) {
|
||||
if ('T_HASHBANG' === $name) {
|
||||
// HHVM uses a special token for #! hashbang lines
|
||||
$tokenMap[$i] = Tokens::T_INLINE_HTML;
|
||||
} elseif (defined($name = Tokens::class . '::' . $name)) {
|
||||
// Other tokens can be mapped directly
|
||||
$tokenMap[$i] = constant($name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HHVM uses a special token for numbers that overflow to double
|
||||
if (defined('T_ONUMBER')) {
|
||||
$tokenMap[\T_ONUMBER] = Tokens::T_DNUMBER;
|
||||
}
|
||||
// HHVM also has a separate token for the __COMPILER_HALT_OFFSET__ constant
|
||||
if (defined('T_COMPILER_HALT_OFFSET')) {
|
||||
$tokenMap[\T_COMPILER_HALT_OFFSET] = Tokens::T_STRING;
|
||||
}
|
||||
|
||||
// Assign tokens for which we define compatibility constants, as token_name() does not know them.
|
||||
$tokenMap[\T_FN] = Tokens::T_FN;
|
||||
$tokenMap[\T_COALESCE_EQUAL] = Tokens::T_COALESCE_EQUAL;
|
||||
$tokenMap[\T_NAME_QUALIFIED] = Tokens::T_NAME_QUALIFIED;
|
||||
$tokenMap[\T_NAME_FULLY_QUALIFIED] = Tokens::T_NAME_FULLY_QUALIFIED;
|
||||
$tokenMap[\T_NAME_RELATIVE] = Tokens::T_NAME_RELATIVE;
|
||||
$tokenMap[\T_MATCH] = Tokens::T_MATCH;
|
||||
$tokenMap[\T_NULLSAFE_OBJECT_OPERATOR] = Tokens::T_NULLSAFE_OBJECT_OPERATOR;
|
||||
$tokenMap[\T_ATTRIBUTE] = Tokens::T_ATTRIBUTE;
|
||||
$tokenMap[\T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG] = Tokens::T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG;
|
||||
$tokenMap[\T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG] = Tokens::T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG;
|
||||
$tokenMap[\T_ENUM] = Tokens::T_ENUM;
|
||||
$tokenMap[\T_READONLY] = Tokens::T_READONLY;
|
||||
|
||||
return $tokenMap;
|
||||
}
|
||||
|
||||
private function createIdentifierTokenMap(): array {
|
||||
// Based on semi_reserved production.
|
||||
return array_fill_keys([
|
||||
\T_STRING,
|
||||
\T_STATIC, \T_ABSTRACT, \T_FINAL, \T_PRIVATE, \T_PROTECTED, \T_PUBLIC, \T_READONLY,
|
||||
\T_INCLUDE, \T_INCLUDE_ONCE, \T_EVAL, \T_REQUIRE, \T_REQUIRE_ONCE, \T_LOGICAL_OR, \T_LOGICAL_XOR, \T_LOGICAL_AND,
|
||||
\T_INSTANCEOF, \T_NEW, \T_CLONE, \T_EXIT, \T_IF, \T_ELSEIF, \T_ELSE, \T_ENDIF, \T_ECHO, \T_DO, \T_WHILE,
|
||||
\T_ENDWHILE, \T_FOR, \T_ENDFOR, \T_FOREACH, \T_ENDFOREACH, \T_DECLARE, \T_ENDDECLARE, \T_AS, \T_TRY, \T_CATCH,
|
||||
\T_FINALLY, \T_THROW, \T_USE, \T_INSTEADOF, \T_GLOBAL, \T_VAR, \T_UNSET, \T_ISSET, \T_EMPTY, \T_CONTINUE, \T_GOTO,
|
||||
\T_FUNCTION, \T_CONST, \T_RETURN, \T_PRINT, \T_YIELD, \T_LIST, \T_SWITCH, \T_ENDSWITCH, \T_CASE, \T_DEFAULT,
|
||||
\T_BREAK, \T_ARRAY, \T_CALLABLE, \T_EXTENDS, \T_IMPLEMENTS, \T_NAMESPACE, \T_TRAIT, \T_INTERFACE, \T_CLASS,
|
||||
\T_CLASS_C, \T_TRAIT_C, \T_FUNC_C, \T_METHOD_C, \T_LINE, \T_FILE, \T_DIR, \T_NS_C, \T_HALT_COMPILER, \T_FN,
|
||||
\T_MATCH,
|
||||
], true);
|
||||
// Add sentinel token.
|
||||
$tokens[] = new Token(0, "\0", $lastToken->getEndLine(), $lastToken->getEndPos());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,61 +5,48 @@ namespace ncc\ThirdParty\nikic\PhpParser\Lexer;
|
|||
use ncc\ThirdParty\nikic\PhpParser\Error;
|
||||
use ncc\ThirdParty\nikic\PhpParser\ErrorHandler;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator\AsymmetricVisibilityTokenEmulator;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator\AttributeEmulator;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator\EnumTokenEmulator;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator\CoaleseEqualTokenEmulator;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator\ExplicitOctalEmulator;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator\FlexibleDocStringEmulator;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator\FnTokenEmulator;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator\MatchTokenEmulator;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator\NullsafeTokenEmulator;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator\NumericLiteralSeparatorEmulator;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator\PropertyTokenEmulator;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator\ReadonlyFunctionTokenEmulator;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator\ReadonlyTokenEmulator;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator\ReverseEmulator;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator\TokenEmulator;
|
||||
use ncc\ThirdParty\nikic\PhpParser\PhpVersion;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Token;
|
||||
|
||||
class Emulative extends Lexer
|
||||
{
|
||||
const PHP_7_3 = '7.3dev';
|
||||
const PHP_7_4 = '7.4dev';
|
||||
const PHP_8_0 = '8.0dev';
|
||||
const PHP_8_1 = '8.1dev';
|
||||
const PHP_8_2 = '8.2dev';
|
||||
class Emulative extends Lexer {
|
||||
/** @var array{int, string, string}[] Patches used to reverse changes introduced in the code */
|
||||
private array $patches = [];
|
||||
|
||||
/** @var mixed[] Patches used to reverse changes introduced in the code */
|
||||
private $patches = [];
|
||||
/** @var list<TokenEmulator> */
|
||||
private array $emulators = [];
|
||||
|
||||
/** @var TokenEmulator[] */
|
||||
private $emulators = [];
|
||||
private PhpVersion $targetPhpVersion;
|
||||
|
||||
/** @var string */
|
||||
private $targetPhpVersion;
|
||||
private PhpVersion $hostPhpVersion;
|
||||
|
||||
/**
|
||||
* @param mixed[] $options Lexer options. In addition to the usual options,
|
||||
* accepts a 'phpVersion' string that specifies the
|
||||
* version to emulate. Defaults to newest supported.
|
||||
* @param PhpVersion|null $phpVersion PHP version to emulate. Defaults to newest supported.
|
||||
*/
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
$this->targetPhpVersion = $options['phpVersion'] ?? Emulative::PHP_8_2;
|
||||
unset($options['phpVersion']);
|
||||
|
||||
parent::__construct($options);
|
||||
public function __construct(?PhpVersion $phpVersion = null) {
|
||||
$this->targetPhpVersion = $phpVersion ?? PhpVersion::getNewestSupported();
|
||||
$this->hostPhpVersion = PhpVersion::getHostVersion();
|
||||
|
||||
$emulators = [
|
||||
new FlexibleDocStringEmulator(),
|
||||
new FnTokenEmulator(),
|
||||
new MatchTokenEmulator(),
|
||||
new CoaleseEqualTokenEmulator(),
|
||||
new NumericLiteralSeparatorEmulator(),
|
||||
new NullsafeTokenEmulator(),
|
||||
new AttributeEmulator(),
|
||||
new EnumTokenEmulator(),
|
||||
new ReadonlyTokenEmulator(),
|
||||
new ExplicitOctalEmulator(),
|
||||
new ReadonlyFunctionTokenEmulator(),
|
||||
new PropertyTokenEmulator(),
|
||||
new AsymmetricVisibilityTokenEmulator(),
|
||||
];
|
||||
|
||||
// Collect emulators that are relevant for the PHP version we're running
|
||||
|
@ -68,21 +55,24 @@ class Emulative extends Lexer
|
|||
$emulatorPhpVersion = $emulator->getPhpVersion();
|
||||
if ($this->isForwardEmulationNeeded($emulatorPhpVersion)) {
|
||||
$this->emulators[] = $emulator;
|
||||
} else if ($this->isReverseEmulationNeeded($emulatorPhpVersion)) {
|
||||
} elseif ($this->isReverseEmulationNeeded($emulatorPhpVersion)) {
|
||||
$this->emulators[] = new ReverseEmulator($emulator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function startLexing(string $code, ErrorHandler $errorHandler = null) {
|
||||
$emulators = array_filter($this->emulators, function($emulator) use($code) {
|
||||
public function tokenize(string $code, ?ErrorHandler $errorHandler = null): array {
|
||||
$emulators = array_filter($this->emulators, function ($emulator) use ($code) {
|
||||
return $emulator->isEmulationNeeded($code);
|
||||
});
|
||||
|
||||
if (empty($emulators)) {
|
||||
// Nothing to emulate, yay
|
||||
parent::startLexing($code, $errorHandler);
|
||||
return;
|
||||
return parent::tokenize($code, $errorHandler);
|
||||
}
|
||||
|
||||
if ($errorHandler === null) {
|
||||
$errorHandler = new ErrorHandler\Throwing();
|
||||
}
|
||||
|
||||
$this->patches = [];
|
||||
|
@ -91,9 +81,9 @@ class Emulative extends Lexer
|
|||
}
|
||||
|
||||
$collector = new ErrorHandler\Collecting();
|
||||
parent::startLexing($code, $collector);
|
||||
$tokens = parent::tokenize($code, $collector);
|
||||
$this->sortPatches();
|
||||
$this->fixupTokens();
|
||||
$tokens = $this->fixupTokens($tokens);
|
||||
|
||||
$errors = $collector->getErrors();
|
||||
if (!empty($errors)) {
|
||||
|
@ -104,90 +94,80 @@ class Emulative extends Lexer
|
|||
}
|
||||
|
||||
foreach ($emulators as $emulator) {
|
||||
$this->tokens = $emulator->emulate($code, $this->tokens);
|
||||
$tokens = $emulator->emulate($code, $tokens);
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
private function isForwardEmulationNeeded(string $emulatorPhpVersion): bool {
|
||||
return version_compare(\PHP_VERSION, $emulatorPhpVersion, '<')
|
||||
&& version_compare($this->targetPhpVersion, $emulatorPhpVersion, '>=');
|
||||
private function isForwardEmulationNeeded(PhpVersion $emulatorPhpVersion): bool {
|
||||
return $this->hostPhpVersion->older($emulatorPhpVersion)
|
||||
&& $this->targetPhpVersion->newerOrEqual($emulatorPhpVersion);
|
||||
}
|
||||
|
||||
private function isReverseEmulationNeeded(string $emulatorPhpVersion): bool {
|
||||
return version_compare(\PHP_VERSION, $emulatorPhpVersion, '>=')
|
||||
&& version_compare($this->targetPhpVersion, $emulatorPhpVersion, '<');
|
||||
private function isReverseEmulationNeeded(PhpVersion $emulatorPhpVersion): bool {
|
||||
return $this->hostPhpVersion->newerOrEqual($emulatorPhpVersion)
|
||||
&& $this->targetPhpVersion->older($emulatorPhpVersion);
|
||||
}
|
||||
|
||||
private function sortPatches()
|
||||
{
|
||||
private function sortPatches(): void {
|
||||
// Patches may be contributed by different emulators.
|
||||
// Make sure they are sorted by increasing patch position.
|
||||
usort($this->patches, function($p1, $p2) {
|
||||
usort($this->patches, function ($p1, $p2) {
|
||||
return $p1[0] <=> $p2[0];
|
||||
});
|
||||
}
|
||||
|
||||
private function fixupTokens()
|
||||
{
|
||||
/**
|
||||
* @param list<Token> $tokens
|
||||
* @return list<Token>
|
||||
*/
|
||||
private function fixupTokens(array $tokens): array {
|
||||
if (\count($this->patches) === 0) {
|
||||
return;
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
// Load first patch
|
||||
$patchIdx = 0;
|
||||
|
||||
list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx];
|
||||
|
||||
// We use a manual loop over the tokens, because we modify the array on the fly
|
||||
$pos = 0;
|
||||
for ($i = 0, $c = \count($this->tokens); $i < $c; $i++) {
|
||||
$token = $this->tokens[$i];
|
||||
if (\is_string($token)) {
|
||||
if ($patchPos === $pos) {
|
||||
// Only support replacement for string tokens.
|
||||
assert($patchType === 'replace');
|
||||
$this->tokens[$i] = $patchText;
|
||||
|
||||
// Fetch the next patch
|
||||
$patchIdx++;
|
||||
if ($patchIdx >= \count($this->patches)) {
|
||||
// No more patches, we're done
|
||||
return;
|
||||
}
|
||||
list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx];
|
||||
}
|
||||
|
||||
$pos += \strlen($token);
|
||||
continue;
|
||||
}
|
||||
|
||||
$len = \strlen($token[1]);
|
||||
$posDelta = 0;
|
||||
$posDelta = 0;
|
||||
$lineDelta = 0;
|
||||
for ($i = 0, $c = \count($tokens); $i < $c; $i++) {
|
||||
$token = $tokens[$i];
|
||||
$pos = $token->pos;
|
||||
$token->pos += $posDelta;
|
||||
$token->line += $lineDelta;
|
||||
$localPosDelta = 0;
|
||||
$len = \strlen($token->text);
|
||||
while ($patchPos >= $pos && $patchPos < $pos + $len) {
|
||||
$patchTextLen = \strlen($patchText);
|
||||
if ($patchType === 'remove') {
|
||||
if ($patchPos === $pos && $patchTextLen === $len) {
|
||||
// Remove token entirely
|
||||
array_splice($this->tokens, $i, 1, []);
|
||||
array_splice($tokens, $i, 1, []);
|
||||
$i--;
|
||||
$c--;
|
||||
} else {
|
||||
// Remove from token string
|
||||
$this->tokens[$i][1] = substr_replace(
|
||||
$token[1], '', $patchPos - $pos + $posDelta, $patchTextLen
|
||||
$token->text = substr_replace(
|
||||
$token->text, '', $patchPos - $pos + $localPosDelta, $patchTextLen
|
||||
);
|
||||
$posDelta -= $patchTextLen;
|
||||
$localPosDelta -= $patchTextLen;
|
||||
}
|
||||
$lineDelta -= \substr_count($patchText, "\n");
|
||||
} elseif ($patchType === 'add') {
|
||||
// Insert into the token string
|
||||
$this->tokens[$i][1] = substr_replace(
|
||||
$token[1], $patchText, $patchPos - $pos + $posDelta, 0
|
||||
$token->text = substr_replace(
|
||||
$token->text, $patchText, $patchPos - $pos + $localPosDelta, 0
|
||||
);
|
||||
$posDelta += $patchTextLen;
|
||||
} else if ($patchType === 'replace') {
|
||||
$localPosDelta += $patchTextLen;
|
||||
$lineDelta += \substr_count($patchText, "\n");
|
||||
} elseif ($patchType === 'replace') {
|
||||
// Replace inside the token string
|
||||
$this->tokens[$i][1] = substr_replace(
|
||||
$token[1], $patchText, $patchPos - $pos + $posDelta, $patchTextLen
|
||||
$token->text = substr_replace(
|
||||
$token->text, $patchText, $patchPos - $pos + $localPosDelta, $patchTextLen
|
||||
);
|
||||
} else {
|
||||
assert(false);
|
||||
|
@ -196,22 +176,17 @@ class Emulative extends Lexer
|
|||
// Fetch the next patch
|
||||
$patchIdx++;
|
||||
if ($patchIdx >= \count($this->patches)) {
|
||||
// No more patches, we're done
|
||||
return;
|
||||
// No more patches. However, we still need to adjust position.
|
||||
$patchPos = \PHP_INT_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx];
|
||||
|
||||
// Multiple patches may apply to the same token. Reload the current one to check
|
||||
// If the new patch applies
|
||||
$token = $this->tokens[$i];
|
||||
}
|
||||
|
||||
$pos += $len;
|
||||
$posDelta += $localPosDelta;
|
||||
}
|
||||
|
||||
// A patch did not apply
|
||||
assert(false);
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -219,7 +194,7 @@ class Emulative extends Lexer
|
|||
*
|
||||
* @param Error[] $errors
|
||||
*/
|
||||
private function fixupErrors(array $errors) {
|
||||
private function fixupErrors(array $errors): void {
|
||||
foreach ($errors as $error) {
|
||||
$attrs = $error->getAttributes();
|
||||
|
||||
|
@ -235,7 +210,7 @@ class Emulative extends Lexer
|
|||
if ($patchType === 'add') {
|
||||
$posDelta += strlen($patchText);
|
||||
$lineDelta += substr_count($patchText, "\n");
|
||||
} else if ($patchType === 'remove') {
|
||||
} elseif ($patchType === 'remove') {
|
||||
$posDelta -= strlen($patchText);
|
||||
$lineDelta -= substr_count($patchText, "\n");
|
||||
}
|
||||
|
|
93
src/ncc/ThirdParty/nikic/PhpParser/Lexer/TokenEmulator/AsymmetricVisibilityTokenEmulator.php
vendored
Normal file
93
src/ncc/ThirdParty/nikic/PhpParser/Lexer/TokenEmulator/AsymmetricVisibilityTokenEmulator.php
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\PhpVersion;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Token;
|
||||
|
||||
final class AsymmetricVisibilityTokenEmulator extends TokenEmulator {
|
||||
public function getPhpVersion(): PhpVersion {
|
||||
return PhpVersion::fromComponents(8, 4);
|
||||
}
|
||||
public function isEmulationNeeded(string $code): bool {
|
||||
$code = strtolower($code);
|
||||
return strpos($code, 'public(set)') !== false ||
|
||||
strpos($code, 'protected(set)') !== false ||
|
||||
strpos($code, 'private(set)') !== false;
|
||||
}
|
||||
|
||||
public function emulate(string $code, array $tokens): array {
|
||||
$map = [
|
||||
\T_PUBLIC => \T_PUBLIC_SET,
|
||||
\T_PROTECTED => \T_PROTECTED_SET,
|
||||
\T_PRIVATE => \T_PRIVATE_SET,
|
||||
];
|
||||
for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
|
||||
$token = $tokens[$i];
|
||||
if (isset($map[$token->id]) && $i + 3 < $c && $tokens[$i + 1]->text === '(' &&
|
||||
$tokens[$i + 2]->id === \T_STRING && \strtolower($tokens[$i + 2]->text) === 'set' &&
|
||||
$tokens[$i + 3]->text === ')' &&
|
||||
$this->isKeywordContext($tokens, $i)
|
||||
) {
|
||||
array_splice($tokens, $i, 4, [
|
||||
new Token(
|
||||
$map[$token->id], $token->text . '(' . $tokens[$i + 2]->text . ')',
|
||||
$token->line, $token->pos),
|
||||
]);
|
||||
$c -= 3;
|
||||
}
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
public function reverseEmulate(string $code, array $tokens): array {
|
||||
$reverseMap = [
|
||||
\T_PUBLIC_SET => \T_PUBLIC,
|
||||
\T_PROTECTED_SET => \T_PROTECTED,
|
||||
\T_PRIVATE_SET => \T_PRIVATE,
|
||||
];
|
||||
for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
|
||||
$token = $tokens[$i];
|
||||
if (isset($reverseMap[$token->id]) &&
|
||||
\preg_match('/(public|protected|private)\((set)\)/i', $token->text, $matches)
|
||||
) {
|
||||
[, $modifier, $set] = $matches;
|
||||
$modifierLen = \strlen($modifier);
|
||||
array_splice($tokens, $i, 1, [
|
||||
new Token($reverseMap[$token->id], $modifier, $token->line, $token->pos),
|
||||
new Token(\ord('('), '(', $token->line, $token->pos + $modifierLen),
|
||||
new Token(\T_STRING, $set, $token->line, $token->pos + $modifierLen + 1),
|
||||
new Token(\ord(')'), ')', $token->line, $token->pos + $modifierLen + 4),
|
||||
]);
|
||||
$i += 3;
|
||||
$c += 3;
|
||||
}
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
/** @param Token[] $tokens */
|
||||
protected function isKeywordContext(array $tokens, int $pos): bool {
|
||||
$prevToken = $this->getPreviousNonSpaceToken($tokens, $pos);
|
||||
if ($prevToken === null) {
|
||||
return false;
|
||||
}
|
||||
return $prevToken->id !== \T_OBJECT_OPERATOR
|
||||
&& $prevToken->id !== \T_NULLSAFE_OBJECT_OPERATOR;
|
||||
}
|
||||
|
||||
/** @param Token[] $tokens */
|
||||
private function getPreviousNonSpaceToken(array $tokens, int $start): ?Token {
|
||||
for ($i = $start - 1; $i >= 0; --$i) {
|
||||
if ($tokens[$i]->id === T_WHITESPACE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $tokens[$i];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -2,43 +2,36 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\Emulative;
|
||||
use ncc\ThirdParty\nikic\PhpParser\PhpVersion;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Token;
|
||||
|
||||
final class AttributeEmulator extends TokenEmulator
|
||||
{
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
return Emulative::PHP_8_0;
|
||||
final class AttributeEmulator extends TokenEmulator {
|
||||
public function getPhpVersion(): PhpVersion {
|
||||
return PhpVersion::fromComponents(8, 0);
|
||||
}
|
||||
|
||||
public function isEmulationNeeded(string $code) : bool
|
||||
{
|
||||
public function isEmulationNeeded(string $code): bool {
|
||||
return strpos($code, '#[') !== false;
|
||||
}
|
||||
|
||||
public function emulate(string $code, array $tokens): array
|
||||
{
|
||||
public function emulate(string $code, array $tokens): array {
|
||||
// We need to manually iterate and manage a count because we'll change
|
||||
// the tokens array on the way.
|
||||
$line = 1;
|
||||
for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
|
||||
if ($tokens[$i] === '#' && isset($tokens[$i + 1]) && $tokens[$i + 1] === '[') {
|
||||
$token = $tokens[$i];
|
||||
if ($token->text === '#' && isset($tokens[$i + 1]) && $tokens[$i + 1]->text === '[') {
|
||||
array_splice($tokens, $i, 2, [
|
||||
[\T_ATTRIBUTE, '#[', $line]
|
||||
new Token(\T_ATTRIBUTE, '#[', $token->line, $token->pos),
|
||||
]);
|
||||
$c--;
|
||||
continue;
|
||||
}
|
||||
if (\is_array($tokens[$i])) {
|
||||
$line += substr_count($tokens[$i][1], "\n");
|
||||
}
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
public function reverseEmulate(string $code, array $tokens): array
|
||||
{
|
||||
public function reverseEmulate(string $code, array $tokens): array {
|
||||
// TODO
|
||||
return $tokens;
|
||||
}
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\Emulative;
|
||||
|
||||
final class CoaleseEqualTokenEmulator extends TokenEmulator
|
||||
{
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
return Emulative::PHP_7_4;
|
||||
}
|
||||
|
||||
public function isEmulationNeeded(string $code): bool
|
||||
{
|
||||
return strpos($code, '??=') !== false;
|
||||
}
|
||||
|
||||
public function emulate(string $code, array $tokens): array
|
||||
{
|
||||
// We need to manually iterate and manage a count because we'll change
|
||||
// the tokens array on the way
|
||||
$line = 1;
|
||||
for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
|
||||
if (isset($tokens[$i + 1])) {
|
||||
if ($tokens[$i][0] === T_COALESCE && $tokens[$i + 1] === '=') {
|
||||
array_splice($tokens, $i, 2, [
|
||||
[\T_COALESCE_EQUAL, '??=', $line]
|
||||
]);
|
||||
$c--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (\is_array($tokens[$i])) {
|
||||
$line += substr_count($tokens[$i][1], "\n");
|
||||
}
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
public function reverseEmulate(string $code, array $tokens): array
|
||||
{
|
||||
// ??= was not valid code previously, don't bother.
|
||||
return $tokens;
|
||||
}
|
||||
}
|
|
@ -2,30 +2,25 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\Emulative;
|
||||
use ncc\ThirdParty\nikic\PhpParser\PhpVersion;
|
||||
|
||||
final class EnumTokenEmulator extends KeywordEmulator
|
||||
{
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
return Emulative::PHP_8_1;
|
||||
final class EnumTokenEmulator extends KeywordEmulator {
|
||||
public function getPhpVersion(): PhpVersion {
|
||||
return PhpVersion::fromComponents(8, 1);
|
||||
}
|
||||
|
||||
public function getKeywordString(): string
|
||||
{
|
||||
public function getKeywordString(): string {
|
||||
return 'enum';
|
||||
}
|
||||
|
||||
public function getKeywordToken(): int
|
||||
{
|
||||
public function getKeywordToken(): int {
|
||||
return \T_ENUM;
|
||||
}
|
||||
|
||||
protected function isKeywordContext(array $tokens, int $pos): bool
|
||||
{
|
||||
protected function isKeywordContext(array $tokens, int $pos): bool {
|
||||
return parent::isKeywordContext($tokens, $pos)
|
||||
&& isset($tokens[$pos + 2])
|
||||
&& $tokens[$pos + 1][0] === \T_WHITESPACE
|
||||
&& $tokens[$pos + 2][0] === \T_STRING;
|
||||
&& $tokens[$pos + 1]->id === \T_WHITESPACE
|
||||
&& $tokens[$pos + 2]->id === \T_STRING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\Emulative;
|
||||
use ncc\ThirdParty\nikic\PhpParser\PhpVersion;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Token;
|
||||
|
||||
class ExplicitOctalEmulator extends TokenEmulator {
|
||||
public function getPhpVersion(): string {
|
||||
return Emulative::PHP_8_1;
|
||||
public function getPhpVersion(): PhpVersion {
|
||||
return PhpVersion::fromComponents(8, 1);
|
||||
}
|
||||
|
||||
public function isEmulationNeeded(string $code): bool {
|
||||
|
@ -15,13 +16,14 @@ class ExplicitOctalEmulator extends TokenEmulator {
|
|||
|
||||
public function emulate(string $code, array $tokens): array {
|
||||
for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
|
||||
if ($tokens[$i][0] == \T_LNUMBER && $tokens[$i][1] === '0' &&
|
||||
isset($tokens[$i + 1]) && $tokens[$i + 1][0] == \T_STRING &&
|
||||
preg_match('/[oO][0-7]+(?:_[0-7]+)*/', $tokens[$i + 1][1])
|
||||
$token = $tokens[$i];
|
||||
if ($token->id == \T_LNUMBER && $token->text === '0' &&
|
||||
isset($tokens[$i + 1]) && $tokens[$i + 1]->id == \T_STRING &&
|
||||
preg_match('/[oO][0-7]+(?:_[0-7]+)*/', $tokens[$i + 1]->text)
|
||||
) {
|
||||
$tokenKind = $this->resolveIntegerOrFloatToken($tokens[$i + 1][1]);
|
||||
$tokenKind = $this->resolveIntegerOrFloatToken($tokens[$i + 1]->text);
|
||||
array_splice($tokens, $i, 2, [
|
||||
[$tokenKind, '0' . $tokens[$i + 1][1], $tokens[$i][2]],
|
||||
new Token($tokenKind, '0' . $tokens[$i + 1]->text, $token->line, $token->pos),
|
||||
]);
|
||||
$c--;
|
||||
}
|
||||
|
@ -29,8 +31,7 @@ class ExplicitOctalEmulator extends TokenEmulator {
|
|||
return $tokens;
|
||||
}
|
||||
|
||||
private function resolveIntegerOrFloatToken(string $str): int
|
||||
{
|
||||
private function resolveIntegerOrFloatToken(string $str): int {
|
||||
$str = substr($str, 1);
|
||||
$str = str_replace('_', '', $str);
|
||||
$num = octdec($str);
|
||||
|
@ -41,4 +42,4 @@ class ExplicitOctalEmulator extends TokenEmulator {
|
|||
// Explicit octals were not legal code previously, don't bother.
|
||||
return $tokens;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\Emulative;
|
||||
|
||||
final class FlexibleDocStringEmulator extends TokenEmulator
|
||||
{
|
||||
const FLEXIBLE_DOC_STRING_REGEX = <<<'REGEX'
|
||||
/<<<[ \t]*(['"]?)([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)\1\r?\n
|
||||
(?:.*\r?\n)*?
|
||||
(?<indentation>\h*)\2(?![a-zA-Z0-9_\x80-\xff])(?<separator>(?:;?[\r\n])?)/x
|
||||
REGEX;
|
||||
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
return Emulative::PHP_7_3;
|
||||
}
|
||||
|
||||
public function isEmulationNeeded(string $code) : bool
|
||||
{
|
||||
return strpos($code, '<<<') !== false;
|
||||
}
|
||||
|
||||
public function emulate(string $code, array $tokens): array
|
||||
{
|
||||
// Handled by preprocessing + fixup.
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
public function reverseEmulate(string $code, array $tokens): array
|
||||
{
|
||||
// Not supported.
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
public function preprocessCode(string $code, array &$patches): string {
|
||||
if (!preg_match_all(self::FLEXIBLE_DOC_STRING_REGEX, $code, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE)) {
|
||||
// No heredoc/nowdoc found
|
||||
return $code;
|
||||
}
|
||||
|
||||
// Keep track of how much we need to adjust string offsets due to the modifications we
|
||||
// already made
|
||||
$posDelta = 0;
|
||||
foreach ($matches as $match) {
|
||||
$indentation = $match['indentation'][0];
|
||||
$indentationStart = $match['indentation'][1];
|
||||
|
||||
$separator = $match['separator'][0];
|
||||
$separatorStart = $match['separator'][1];
|
||||
|
||||
if ($indentation === '' && $separator !== '') {
|
||||
// Ordinary heredoc/nowdoc
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($indentation !== '') {
|
||||
// Remove indentation
|
||||
$indentationLen = strlen($indentation);
|
||||
$code = substr_replace($code, '', $indentationStart + $posDelta, $indentationLen);
|
||||
$patches[] = [$indentationStart + $posDelta, 'add', $indentation];
|
||||
$posDelta -= $indentationLen;
|
||||
}
|
||||
|
||||
if ($separator === '') {
|
||||
// Insert newline as separator
|
||||
$code = substr_replace($code, "\n", $separatorStart + $posDelta, 0);
|
||||
$patches[] = [$separatorStart + $posDelta, 'remove', "\n"];
|
||||
$posDelta += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return $code;
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\Emulative;
|
||||
|
||||
final class FnTokenEmulator extends KeywordEmulator
|
||||
{
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
return Emulative::PHP_7_4;
|
||||
}
|
||||
|
||||
public function getKeywordString(): string
|
||||
{
|
||||
return 'fn';
|
||||
}
|
||||
|
||||
public function getKeywordToken(): int
|
||||
{
|
||||
return \T_FN;
|
||||
}
|
||||
}
|
|
@ -2,43 +2,42 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
abstract class KeywordEmulator extends TokenEmulator
|
||||
{
|
||||
abstract function getKeywordString(): string;
|
||||
abstract function getKeywordToken(): int;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Token;
|
||||
|
||||
public function isEmulationNeeded(string $code): bool
|
||||
{
|
||||
abstract class KeywordEmulator extends TokenEmulator {
|
||||
abstract public function getKeywordString(): string;
|
||||
abstract public function getKeywordToken(): int;
|
||||
|
||||
public function isEmulationNeeded(string $code): bool {
|
||||
return strpos(strtolower($code), $this->getKeywordString()) !== false;
|
||||
}
|
||||
|
||||
protected function isKeywordContext(array $tokens, int $pos): bool
|
||||
{
|
||||
$previousNonSpaceToken = $this->getPreviousNonSpaceToken($tokens, $pos);
|
||||
return $previousNonSpaceToken === null || $previousNonSpaceToken[0] !== \T_OBJECT_OPERATOR;
|
||||
/** @param Token[] $tokens */
|
||||
protected function isKeywordContext(array $tokens, int $pos): bool {
|
||||
$prevToken = $this->getPreviousNonSpaceToken($tokens, $pos);
|
||||
if ($prevToken === null) {
|
||||
return false;
|
||||
}
|
||||
return $prevToken->id !== \T_OBJECT_OPERATOR
|
||||
&& $prevToken->id !== \T_NULLSAFE_OBJECT_OPERATOR;
|
||||
}
|
||||
|
||||
public function emulate(string $code, array $tokens): array
|
||||
{
|
||||
public function emulate(string $code, array $tokens): array {
|
||||
$keywordString = $this->getKeywordString();
|
||||
foreach ($tokens as $i => $token) {
|
||||
if ($token[0] === T_STRING && strtolower($token[1]) === $keywordString
|
||||
if ($token->id === T_STRING && strtolower($token->text) === $keywordString
|
||||
&& $this->isKeywordContext($tokens, $i)) {
|
||||
$tokens[$i][0] = $this->getKeywordToken();
|
||||
$token->id = $this->getKeywordToken();
|
||||
}
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $tokens
|
||||
* @return array|string|null
|
||||
*/
|
||||
private function getPreviousNonSpaceToken(array $tokens, int $start)
|
||||
{
|
||||
/** @param Token[] $tokens */
|
||||
private function getPreviousNonSpaceToken(array $tokens, int $start): ?Token {
|
||||
for ($i = $start - 1; $i >= 0; --$i) {
|
||||
if ($tokens[$i][0] === T_WHITESPACE) {
|
||||
if ($tokens[$i]->id === T_WHITESPACE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -48,12 +47,11 @@ abstract class KeywordEmulator extends TokenEmulator
|
|||
return null;
|
||||
}
|
||||
|
||||
public function reverseEmulate(string $code, array $tokens): array
|
||||
{
|
||||
public function reverseEmulate(string $code, array $tokens): array {
|
||||
$keywordToken = $this->getKeywordToken();
|
||||
foreach ($tokens as $i => $token) {
|
||||
if ($token[0] === $keywordToken) {
|
||||
$tokens[$i][0] = \T_STRING;
|
||||
foreach ($tokens as $token) {
|
||||
if ($token->id === $keywordToken) {
|
||||
$token->id = \T_STRING;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,22 +2,18 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\Emulative;
|
||||
use ncc\ThirdParty\nikic\PhpParser\PhpVersion;
|
||||
|
||||
final class MatchTokenEmulator extends KeywordEmulator
|
||||
{
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
return Emulative::PHP_8_0;
|
||||
final class MatchTokenEmulator extends KeywordEmulator {
|
||||
public function getPhpVersion(): PhpVersion {
|
||||
return PhpVersion::fromComponents(8, 0);
|
||||
}
|
||||
|
||||
public function getKeywordString(): string
|
||||
{
|
||||
public function getKeywordString(): string {
|
||||
return 'match';
|
||||
}
|
||||
|
||||
public function getKeywordToken(): int
|
||||
{
|
||||
public function getKeywordToken(): int {
|
||||
return \T_MATCH;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,65 +2,58 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\Emulative;
|
||||
use ncc\ThirdParty\nikic\PhpParser\PhpVersion;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Token;
|
||||
|
||||
final class NullsafeTokenEmulator extends TokenEmulator
|
||||
{
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
return Emulative::PHP_8_0;
|
||||
final class NullsafeTokenEmulator extends TokenEmulator {
|
||||
public function getPhpVersion(): PhpVersion {
|
||||
return PhpVersion::fromComponents(8, 0);
|
||||
}
|
||||
|
||||
public function isEmulationNeeded(string $code): bool
|
||||
{
|
||||
public function isEmulationNeeded(string $code): bool {
|
||||
return strpos($code, '?->') !== false;
|
||||
}
|
||||
|
||||
public function emulate(string $code, array $tokens): array
|
||||
{
|
||||
public function emulate(string $code, array $tokens): array {
|
||||
// We need to manually iterate and manage a count because we'll change
|
||||
// the tokens array on the way
|
||||
$line = 1;
|
||||
for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
|
||||
if ($tokens[$i] === '?' && isset($tokens[$i + 1]) && $tokens[$i + 1][0] === \T_OBJECT_OPERATOR) {
|
||||
$token = $tokens[$i];
|
||||
if ($token->text === '?' && isset($tokens[$i + 1]) && $tokens[$i + 1]->id === \T_OBJECT_OPERATOR) {
|
||||
array_splice($tokens, $i, 2, [
|
||||
[\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line]
|
||||
new Token(\T_NULLSAFE_OBJECT_OPERATOR, '?->', $token->line, $token->pos),
|
||||
]);
|
||||
$c--;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle ?-> inside encapsed string.
|
||||
if ($tokens[$i][0] === \T_ENCAPSED_AND_WHITESPACE && isset($tokens[$i - 1])
|
||||
&& $tokens[$i - 1][0] === \T_VARIABLE
|
||||
&& preg_match('/^\?->([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)/', $tokens[$i][1], $matches)
|
||||
if ($token->id === \T_ENCAPSED_AND_WHITESPACE && isset($tokens[$i - 1])
|
||||
&& $tokens[$i - 1]->id === \T_VARIABLE
|
||||
&& preg_match('/^\?->([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)/', $token->text, $matches)
|
||||
) {
|
||||
$replacement = [
|
||||
[\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line],
|
||||
[\T_STRING, $matches[1], $line],
|
||||
new Token(\T_NULLSAFE_OBJECT_OPERATOR, '?->', $token->line, $token->pos),
|
||||
new Token(\T_STRING, $matches[1], $token->line, $token->pos + 3),
|
||||
];
|
||||
if (\strlen($matches[0]) !== \strlen($tokens[$i][1])) {
|
||||
$replacement[] = [
|
||||
$matchLen = \strlen($matches[0]);
|
||||
if ($matchLen !== \strlen($token->text)) {
|
||||
$replacement[] = new Token(
|
||||
\T_ENCAPSED_AND_WHITESPACE,
|
||||
\substr($tokens[$i][1], \strlen($matches[0])),
|
||||
$line
|
||||
];
|
||||
\substr($token->text, $matchLen),
|
||||
$token->line, $token->pos + $matchLen
|
||||
);
|
||||
}
|
||||
array_splice($tokens, $i, 1, $replacement);
|
||||
$c += \count($replacement) - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (\is_array($tokens[$i])) {
|
||||
$line += substr_count($tokens[$i][1], "\n");
|
||||
}
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
public function reverseEmulate(string $code, array $tokens): array
|
||||
{
|
||||
public function reverseEmulate(string $code, array $tokens): array {
|
||||
// ?-> was not valid code previously, don't bother.
|
||||
return $tokens;
|
||||
}
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\Emulative;
|
||||
|
||||
final class NumericLiteralSeparatorEmulator extends TokenEmulator
|
||||
{
|
||||
const BIN = '(?:0b[01]+(?:_[01]+)*)';
|
||||
const HEX = '(?:0x[0-9a-f]+(?:_[0-9a-f]+)*)';
|
||||
const DEC = '(?:[0-9]+(?:_[0-9]+)*)';
|
||||
const SIMPLE_FLOAT = '(?:' . self::DEC . '\.' . self::DEC . '?|\.' . self::DEC . ')';
|
||||
const EXP = '(?:e[+-]?' . self::DEC . ')';
|
||||
const FLOAT = '(?:' . self::SIMPLE_FLOAT . self::EXP . '?|' . self::DEC . self::EXP . ')';
|
||||
const NUMBER = '~' . self::FLOAT . '|' . self::BIN . '|' . self::HEX . '|' . self::DEC . '~iA';
|
||||
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
return Emulative::PHP_7_4;
|
||||
}
|
||||
|
||||
public function isEmulationNeeded(string $code) : bool
|
||||
{
|
||||
return preg_match('~[0-9]_[0-9]~', $code)
|
||||
|| preg_match('~0x[0-9a-f]+_[0-9a-f]~i', $code);
|
||||
}
|
||||
|
||||
public function emulate(string $code, array $tokens): array
|
||||
{
|
||||
// We need to manually iterate and manage a count because we'll change
|
||||
// the tokens array on the way
|
||||
$codeOffset = 0;
|
||||
for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
|
||||
$token = $tokens[$i];
|
||||
$tokenLen = \strlen(\is_array($token) ? $token[1] : $token);
|
||||
|
||||
if ($token[0] !== T_LNUMBER && $token[0] !== T_DNUMBER) {
|
||||
$codeOffset += $tokenLen;
|
||||
continue;
|
||||
}
|
||||
|
||||
$res = preg_match(self::NUMBER, $code, $matches, 0, $codeOffset);
|
||||
assert($res, "No number at number token position");
|
||||
|
||||
$match = $matches[0];
|
||||
$matchLen = \strlen($match);
|
||||
if ($matchLen === $tokenLen) {
|
||||
// Original token already holds the full number.
|
||||
$codeOffset += $tokenLen;
|
||||
continue;
|
||||
}
|
||||
|
||||
$tokenKind = $this->resolveIntegerOrFloatToken($match);
|
||||
$newTokens = [[$tokenKind, $match, $token[2]]];
|
||||
|
||||
$numTokens = 1;
|
||||
$len = $tokenLen;
|
||||
while ($matchLen > $len) {
|
||||
$nextToken = $tokens[$i + $numTokens];
|
||||
$nextTokenText = \is_array($nextToken) ? $nextToken[1] : $nextToken;
|
||||
$nextTokenLen = \strlen($nextTokenText);
|
||||
|
||||
$numTokens++;
|
||||
if ($matchLen < $len + $nextTokenLen) {
|
||||
// Split trailing characters into a partial token.
|
||||
assert(is_array($nextToken), "Partial token should be an array token");
|
||||
$partialText = substr($nextTokenText, $matchLen - $len);
|
||||
$newTokens[] = [$nextToken[0], $partialText, $nextToken[2]];
|
||||
break;
|
||||
}
|
||||
|
||||
$len += $nextTokenLen;
|
||||
}
|
||||
|
||||
array_splice($tokens, $i, $numTokens, $newTokens);
|
||||
$c -= $numTokens - \count($newTokens);
|
||||
$codeOffset += $matchLen;
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
private function resolveIntegerOrFloatToken(string $str): int
|
||||
{
|
||||
$str = str_replace('_', '', $str);
|
||||
|
||||
if (stripos($str, '0b') === 0) {
|
||||
$num = bindec($str);
|
||||
} elseif (stripos($str, '0x') === 0) {
|
||||
$num = hexdec($str);
|
||||
} elseif (stripos($str, '0') === 0 && ctype_digit($str)) {
|
||||
$num = octdec($str);
|
||||
} else {
|
||||
$num = +$str;
|
||||
}
|
||||
|
||||
return is_float($num) ? T_DNUMBER : T_LNUMBER;
|
||||
}
|
||||
|
||||
public function reverseEmulate(string $code, array $tokens): array
|
||||
{
|
||||
// Numeric separators were not legal code previously, don't bother.
|
||||
return $tokens;
|
||||
}
|
||||
}
|
19
src/ncc/ThirdParty/nikic/PhpParser/Lexer/TokenEmulator/PropertyTokenEmulator.php
vendored
Normal file
19
src/ncc/ThirdParty/nikic/PhpParser/Lexer/TokenEmulator/PropertyTokenEmulator.php
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\PhpVersion;
|
||||
|
||||
final class PropertyTokenEmulator extends KeywordEmulator {
|
||||
public function getPhpVersion(): PhpVersion {
|
||||
return PhpVersion::fromComponents(8, 4);
|
||||
}
|
||||
|
||||
public function getKeywordString(): string {
|
||||
return '__property__';
|
||||
}
|
||||
|
||||
public function getKeywordToken(): int {
|
||||
return \T_PROPERTY_C;
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\Emulative;
|
||||
use ncc\ThirdParty\nikic\PhpParser\PhpVersion;
|
||||
|
||||
/*
|
||||
* In PHP 8.1, "readonly(" was special cased in the lexer in order to support functions with
|
||||
|
@ -20,8 +20,8 @@ class ReadonlyFunctionTokenEmulator extends KeywordEmulator {
|
|||
return \T_READONLY;
|
||||
}
|
||||
|
||||
public function getPhpVersion(): string {
|
||||
return Emulative::PHP_8_2;
|
||||
public function getPhpVersion(): PhpVersion {
|
||||
return PhpVersion::fromComponents(8, 2);
|
||||
}
|
||||
|
||||
public function reverseEmulate(string $code, array $tokens): array {
|
||||
|
|
|
@ -2,35 +2,30 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Lexer\Emulative;
|
||||
use ncc\ThirdParty\nikic\PhpParser\PhpVersion;
|
||||
|
||||
final class ReadonlyTokenEmulator extends KeywordEmulator
|
||||
{
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
return Emulative::PHP_8_1;
|
||||
final class ReadonlyTokenEmulator extends KeywordEmulator {
|
||||
public function getPhpVersion(): PhpVersion {
|
||||
return PhpVersion::fromComponents(8, 1);
|
||||
}
|
||||
|
||||
public function getKeywordString(): string
|
||||
{
|
||||
public function getKeywordString(): string {
|
||||
return 'readonly';
|
||||
}
|
||||
|
||||
public function getKeywordToken(): int
|
||||
{
|
||||
public function getKeywordToken(): int {
|
||||
return \T_READONLY;
|
||||
}
|
||||
|
||||
protected function isKeywordContext(array $tokens, int $pos): bool
|
||||
{
|
||||
protected function isKeywordContext(array $tokens, int $pos): bool {
|
||||
if (!parent::isKeywordContext($tokens, $pos)) {
|
||||
return false;
|
||||
}
|
||||
// Support "function readonly("
|
||||
return !(isset($tokens[$pos + 1]) &&
|
||||
($tokens[$pos + 1][0] === '(' ||
|
||||
($tokens[$pos + 1][0] === \T_WHITESPACE &&
|
||||
($tokens[$pos + 1]->text === '(' ||
|
||||
($tokens[$pos + 1]->id === \T_WHITESPACE &&
|
||||
isset($tokens[$pos + 2]) &&
|
||||
$tokens[$pos + 2][0] === '(')));
|
||||
$tokens[$pos + 2]->text === '(')));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,19 +2,20 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\PhpVersion;
|
||||
|
||||
/**
|
||||
* Reverses emulation direction of the inner emulator.
|
||||
*/
|
||||
final class ReverseEmulator extends TokenEmulator
|
||||
{
|
||||
final class ReverseEmulator extends TokenEmulator {
|
||||
/** @var TokenEmulator Inner emulator */
|
||||
private $emulator;
|
||||
private TokenEmulator $emulator;
|
||||
|
||||
public function __construct(TokenEmulator $emulator) {
|
||||
$this->emulator = $emulator;
|
||||
}
|
||||
|
||||
public function getPhpVersion(): string {
|
||||
public function getPhpVersion(): PhpVersion {
|
||||
return $this->emulator->getPhpVersion();
|
||||
}
|
||||
|
||||
|
@ -33,4 +34,4 @@ final class ReverseEmulator extends TokenEmulator
|
|||
public function preprocessCode(string $code, array &$patches): string {
|
||||
return $code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,23 +2,28 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\PhpVersion;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Token;
|
||||
|
||||
/** @internal */
|
||||
abstract class TokenEmulator
|
||||
{
|
||||
abstract public function getPhpVersion(): string;
|
||||
abstract class TokenEmulator {
|
||||
abstract public function getPhpVersion(): PhpVersion;
|
||||
|
||||
abstract public function isEmulationNeeded(string $code): bool;
|
||||
|
||||
/**
|
||||
* @return array Modified Tokens
|
||||
* @param Token[] $tokens Original tokens
|
||||
* @return Token[] Modified Tokens
|
||||
*/
|
||||
abstract public function emulate(string $code, array $tokens): array;
|
||||
|
||||
/**
|
||||
* @return array Modified Tokens
|
||||
* @param Token[] $tokens Original tokens
|
||||
* @return Token[] Modified Tokens
|
||||
*/
|
||||
abstract public function reverseEmulate(string $code, array $tokens): array;
|
||||
|
||||
/** @param array{int, string, string}[] $patches */
|
||||
public function preprocessCode(string $code, array &$patches): string {
|
||||
return $code;
|
||||
}
|
||||
|
|
85
src/ncc/ThirdParty/nikic/PhpParser/Modifiers.php
vendored
Normal file
85
src/ncc/ThirdParty/nikic/PhpParser/Modifiers.php
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser;
|
||||
|
||||
/**
|
||||
* Modifiers used (as a bit mask) by various flags subnodes, for example on classes, functions,
|
||||
* properties and constants.
|
||||
*/
|
||||
final class Modifiers {
|
||||
public const PUBLIC = 1;
|
||||
public const PROTECTED = 2;
|
||||
public const PRIVATE = 4;
|
||||
public const STATIC = 8;
|
||||
public const ABSTRACT = 16;
|
||||
public const FINAL = 32;
|
||||
public const READONLY = 64;
|
||||
public const PUBLIC_SET = 128;
|
||||
public const PROTECTED_SET = 256;
|
||||
public const PRIVATE_SET = 512;
|
||||
|
||||
public const VISIBILITY_MASK = self::PUBLIC | self::PROTECTED | self::PRIVATE;
|
||||
|
||||
public const VISIBILITY_SET_MASK = self::PUBLIC_SET | self::PROTECTED_SET | self::PRIVATE_SET;
|
||||
|
||||
private const TO_STRING_MAP = [
|
||||
self::PUBLIC => 'public',
|
||||
self::PROTECTED => 'protected',
|
||||
self::PRIVATE => 'private',
|
||||
self::STATIC => 'static',
|
||||
self::ABSTRACT => 'abstract',
|
||||
self::FINAL => 'final',
|
||||
self::READONLY => 'readonly',
|
||||
self::PUBLIC_SET => 'public(set)',
|
||||
self::PROTECTED_SET => 'protected(set)',
|
||||
self::PRIVATE_SET => 'private(set)',
|
||||
];
|
||||
|
||||
public static function toString(int $modifier): string {
|
||||
if (!isset(self::TO_STRING_MAP[$modifier])) {
|
||||
throw new \InvalidArgumentException("Unknown modifier $modifier");
|
||||
}
|
||||
return self::TO_STRING_MAP[$modifier];
|
||||
}
|
||||
|
||||
private static function isValidModifier(int $modifier): bool {
|
||||
$isPow2 = ($modifier & ($modifier - 1)) == 0 && $modifier != 0;
|
||||
return $isPow2 && $modifier <= self::PRIVATE_SET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public static function verifyClassModifier(int $a, int $b): void {
|
||||
assert(self::isValidModifier($b));
|
||||
if (($a & $b) != 0) {
|
||||
throw new Error(
|
||||
'Multiple ' . self::toString($b) . ' modifiers are not allowed');
|
||||
}
|
||||
|
||||
if ($a & 48 && $b & 48) {
|
||||
throw new Error('Cannot use the final modifier on an abstract class');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public static function verifyModifier(int $a, int $b): void {
|
||||
assert(self::isValidModifier($b));
|
||||
if (($a & Modifiers::VISIBILITY_MASK && $b & Modifiers::VISIBILITY_MASK) ||
|
||||
($a & Modifiers::VISIBILITY_SET_MASK && $b & Modifiers::VISIBILITY_SET_MASK)
|
||||
) {
|
||||
throw new Error('Multiple access type modifiers are not allowed');
|
||||
}
|
||||
|
||||
if (($a & $b) != 0) {
|
||||
throw new Error(
|
||||
'Multiple ' . self::toString($b) . ' modifiers are not allowed');
|
||||
}
|
||||
|
||||
if ($a & 48 && $b & 48) {
|
||||
throw new Error('Cannot use the final modifier on an abstract class member');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,19 +6,18 @@ use ncc\ThirdParty\nikic\PhpParser\Node\Name;
|
|||
use ncc\ThirdParty\nikic\PhpParser\Node\Name\FullyQualified;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Stmt;
|
||||
|
||||
class NameContext
|
||||
{
|
||||
class NameContext {
|
||||
/** @var null|Name Current namespace */
|
||||
protected $namespace;
|
||||
protected ?Name $namespace;
|
||||
|
||||
/** @var Name[][] Map of format [aliasType => [aliasName => originalName]] */
|
||||
protected $aliases = [];
|
||||
protected array $aliases = [];
|
||||
|
||||
/** @var Name[][] Same as $aliases but preserving original case */
|
||||
protected $origAliases = [];
|
||||
protected array $origAliases = [];
|
||||
|
||||
/** @var ErrorHandler Error handler */
|
||||
protected $errorHandler;
|
||||
protected ErrorHandler $errorHandler;
|
||||
|
||||
/**
|
||||
* Create a name context.
|
||||
|
@ -36,7 +35,7 @@ class NameContext
|
|||
*
|
||||
* @param Name|null $namespace Null is the global namespace
|
||||
*/
|
||||
public function startNamespace(Name $namespace = null) {
|
||||
public function startNamespace(?Name $namespace = null): void {
|
||||
$this->namespace = $namespace;
|
||||
$this->origAliases = $this->aliases = [
|
||||
Stmt\Use_::TYPE_NORMAL => [],
|
||||
|
@ -48,12 +47,12 @@ class NameContext
|
|||
/**
|
||||
* Add an alias / import.
|
||||
*
|
||||
* @param Name $name Original name
|
||||
* @param string $aliasName Aliased name
|
||||
* @param int $type One of Stmt\Use_::TYPE_*
|
||||
* @param array $errorAttrs Attributes to use to report an error
|
||||
* @param Name $name Original name
|
||||
* @param string $aliasName Aliased name
|
||||
* @param Stmt\Use_::TYPE_* $type One of Stmt\Use_::TYPE_*
|
||||
* @param array<string, mixed> $errorAttrs Attributes to use to report an error
|
||||
*/
|
||||
public function addAlias(Name $name, string $aliasName, int $type, array $errorAttrs = []) {
|
||||
public function addAlias(Name $name, string $aliasName, int $type, array $errorAttrs = []): void {
|
||||
// Constant names are case sensitive, everything else case insensitive
|
||||
if ($type === Stmt\Use_::TYPE_CONSTANT) {
|
||||
$aliasLookupName = $aliasName;
|
||||
|
@ -87,7 +86,7 @@ class NameContext
|
|||
*
|
||||
* @return null|Name Namespace (or null if global namespace)
|
||||
*/
|
||||
public function getNamespace() {
|
||||
public function getNamespace(): ?Name {
|
||||
return $this->namespace;
|
||||
}
|
||||
|
||||
|
@ -95,11 +94,11 @@ class NameContext
|
|||
* Get resolved name.
|
||||
*
|
||||
* @param Name $name Name to resolve
|
||||
* @param int $type One of Stmt\Use_::TYPE_{FUNCTION|CONSTANT}
|
||||
* @param Stmt\Use_::TYPE_* $type One of Stmt\Use_::TYPE_{FUNCTION|CONSTANT}
|
||||
*
|
||||
* @return null|Name Resolved name, or null if static resolution is not possible
|
||||
*/
|
||||
public function getResolvedName(Name $name, int $type) {
|
||||
public function getResolvedName(Name $name, int $type): ?Name {
|
||||
// don't resolve special class names
|
||||
if ($type === Stmt\Use_::TYPE_NORMAL && $name->isSpecialClassName()) {
|
||||
if (!$name->isUnqualified()) {
|
||||
|
@ -142,7 +141,7 @@ class NameContext
|
|||
*
|
||||
* @return Name Resolved name
|
||||
*/
|
||||
public function getResolvedClassName(Name $name) : Name {
|
||||
public function getResolvedClassName(Name $name): Name {
|
||||
return $this->getResolvedName($name, Stmt\Use_::TYPE_NORMAL);
|
||||
}
|
||||
|
||||
|
@ -150,11 +149,11 @@ class NameContext
|
|||
* Get possible ways of writing a fully qualified name (e.g., by making use of aliases).
|
||||
*
|
||||
* @param string $name Fully-qualified name (without leading namespace separator)
|
||||
* @param int $type One of Stmt\Use_::TYPE_*
|
||||
* @param Stmt\Use_::TYPE_* $type One of Stmt\Use_::TYPE_*
|
||||
*
|
||||
* @return Name[] Possible representations of the name
|
||||
*/
|
||||
public function getPossibleNames(string $name, int $type) : array {
|
||||
public function getPossibleNames(string $name, int $type): array {
|
||||
$lcName = strtolower($name);
|
||||
|
||||
if ($type === Stmt\Use_::TYPE_NORMAL) {
|
||||
|
@ -186,7 +185,7 @@ class NameContext
|
|||
// Check for relevant type-specific use statements
|
||||
foreach ($this->origAliases[$type] as $alias => $orig) {
|
||||
if ($type === Stmt\Use_::TYPE_CONSTANT) {
|
||||
// Constants are are complicated-sensitive
|
||||
// Constants are complicated-sensitive
|
||||
$normalizedOrig = $this->normalizeConstName($orig->toString());
|
||||
if ($normalizedOrig === $this->normalizeConstName($name)) {
|
||||
$possibleNames[] = new Name($alias);
|
||||
|
@ -206,11 +205,11 @@ class NameContext
|
|||
* Get shortest representation of this fully-qualified name.
|
||||
*
|
||||
* @param string $name Fully-qualified name (without leading namespace separator)
|
||||
* @param int $type One of Stmt\Use_::TYPE_*
|
||||
* @param Stmt\Use_::TYPE_* $type One of Stmt\Use_::TYPE_*
|
||||
*
|
||||
* @return Name Shortest representation
|
||||
*/
|
||||
public function getShortName(string $name, int $type) : Name {
|
||||
public function getShortName(string $name, int $type): Name {
|
||||
$possibleNames = $this->getPossibleNames($name, $type);
|
||||
|
||||
// Find shortest name
|
||||
|
@ -224,10 +223,10 @@ class NameContext
|
|||
}
|
||||
}
|
||||
|
||||
return $shortestName;
|
||||
return $shortestName;
|
||||
}
|
||||
|
||||
private function resolveAlias(Name $name, $type) {
|
||||
private function resolveAlias(Name $name, int $type): ?FullyQualified {
|
||||
$firstPart = $name->getFirst();
|
||||
|
||||
if ($name->isQualified()) {
|
||||
|
@ -250,7 +249,7 @@ class NameContext
|
|||
return null;
|
||||
}
|
||||
|
||||
private function getNamespaceRelativeName(string $name, string $lcName, int $type) {
|
||||
private function getNamespaceRelativeName(string $name, string $lcName, int $type): ?Name {
|
||||
if (null === $this->namespace) {
|
||||
return new Name($name);
|
||||
}
|
||||
|
@ -271,7 +270,7 @@ class NameContext
|
|||
return null;
|
||||
}
|
||||
|
||||
private function normalizeConstName(string $name) {
|
||||
private function normalizeConstName(string $name): string {
|
||||
$nsSep = strrpos($name, '\\');
|
||||
if (false === $nsSep) {
|
||||
return $name;
|
||||
|
|
57
src/ncc/ThirdParty/nikic/PhpParser/Node.php
vendored
57
src/ncc/ThirdParty/nikic/PhpParser/Node.php
vendored
|
@ -2,28 +2,31 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser;
|
||||
|
||||
interface Node
|
||||
{
|
||||
interface Node {
|
||||
/**
|
||||
* Gets the type of the node.
|
||||
*
|
||||
* @psalm-return non-empty-string
|
||||
* @return string Type of the node
|
||||
*/
|
||||
public function getType() : string;
|
||||
public function getType(): string;
|
||||
|
||||
/**
|
||||
* Gets the names of the sub nodes.
|
||||
*
|
||||
* @return array Names of sub nodes
|
||||
* @return string[] Names of sub nodes
|
||||
*/
|
||||
public function getSubNodeNames() : array;
|
||||
public function getSubNodeNames(): array;
|
||||
|
||||
/**
|
||||
* Gets line the node started in (alias of getStartLine).
|
||||
*
|
||||
* @return int Start line (or -1 if not available)
|
||||
* @phpstan-return -1|positive-int
|
||||
*
|
||||
* @deprecated Use getStartLine() instead
|
||||
*/
|
||||
public function getLine() : int;
|
||||
public function getLine(): int;
|
||||
|
||||
/**
|
||||
* Gets line the node started in.
|
||||
|
@ -31,8 +34,9 @@ interface Node
|
|||
* Requires the 'startLine' attribute to be enabled in the lexer (enabled by default).
|
||||
*
|
||||
* @return int Start line (or -1 if not available)
|
||||
* @phpstan-return -1|positive-int
|
||||
*/
|
||||
public function getStartLine() : int;
|
||||
public function getStartLine(): int;
|
||||
|
||||
/**
|
||||
* Gets the line the node ended in.
|
||||
|
@ -40,8 +44,9 @@ interface Node
|
|||
* Requires the 'endLine' attribute to be enabled in the lexer (enabled by default).
|
||||
*
|
||||
* @return int End line (or -1 if not available)
|
||||
* @phpstan-return -1|positive-int
|
||||
*/
|
||||
public function getEndLine() : int;
|
||||
public function getEndLine(): int;
|
||||
|
||||
/**
|
||||
* Gets the token offset of the first token that is part of this node.
|
||||
|
@ -52,7 +57,7 @@ interface Node
|
|||
*
|
||||
* @return int Token start position (or -1 if not available)
|
||||
*/
|
||||
public function getStartTokenPos() : int;
|
||||
public function getStartTokenPos(): int;
|
||||
|
||||
/**
|
||||
* Gets the token offset of the last token that is part of this node.
|
||||
|
@ -63,7 +68,7 @@ interface Node
|
|||
*
|
||||
* @return int Token end position (or -1 if not available)
|
||||
*/
|
||||
public function getEndTokenPos() : int;
|
||||
public function getEndTokenPos(): int;
|
||||
|
||||
/**
|
||||
* Gets the file offset of the first character that is part of this node.
|
||||
|
@ -72,7 +77,7 @@ interface Node
|
|||
*
|
||||
* @return int File start position (or -1 if not available)
|
||||
*/
|
||||
public function getStartFilePos() : int;
|
||||
public function getStartFilePos(): int;
|
||||
|
||||
/**
|
||||
* Gets the file offset of the last character that is part of this node.
|
||||
|
@ -81,7 +86,7 @@ interface Node
|
|||
*
|
||||
* @return int File end position (or -1 if not available)
|
||||
*/
|
||||
public function getEndFilePos() : int;
|
||||
public function getEndFilePos(): int;
|
||||
|
||||
/**
|
||||
* Gets all comments directly preceding this node.
|
||||
|
@ -90,14 +95,14 @@ interface Node
|
|||
*
|
||||
* @return Comment[]
|
||||
*/
|
||||
public function getComments() : array;
|
||||
public function getComments(): array;
|
||||
|
||||
/**
|
||||
* Gets the doc comment of the node.
|
||||
*
|
||||
* @return null|Comment\Doc Doc comment object or null
|
||||
*/
|
||||
public function getDocComment();
|
||||
public function getDocComment(): ?Comment\Doc;
|
||||
|
||||
/**
|
||||
* Sets the doc comment of the node.
|
||||
|
@ -106,30 +111,24 @@ interface Node
|
|||
*
|
||||
* @param Comment\Doc $docComment Doc comment to set
|
||||
*/
|
||||
public function setDocComment(Comment\Doc $docComment);
|
||||
public function setDocComment(Comment\Doc $docComment): void;
|
||||
|
||||
/**
|
||||
* Sets an attribute on a node.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function setAttribute(string $key, $value);
|
||||
public function setAttribute(string $key, $value): void;
|
||||
|
||||
/**
|
||||
* Returns whether an attribute exists.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAttribute(string $key) : bool;
|
||||
public function hasAttribute(string $key): bool;
|
||||
|
||||
/**
|
||||
* Returns the value of an attribute.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
|
@ -138,14 +137,14 @@ interface Node
|
|||
/**
|
||||
* Returns all the attributes of this node.
|
||||
*
|
||||
* @return array
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getAttributes() : array;
|
||||
public function getAttributes(): array;
|
||||
|
||||
/**
|
||||
* Replaces all the attributes of this node.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array<string, mixed> $attributes
|
||||
*/
|
||||
public function setAttributes(array $attributes);
|
||||
public function setAttributes(array $attributes): void;
|
||||
}
|
||||
|
|
28
src/ncc/ThirdParty/nikic/PhpParser/Node/Arg.php
vendored
28
src/ncc/ThirdParty/nikic/PhpParser/Node/Arg.php
vendored
|
@ -2,32 +2,30 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\VariadicPlaceholder;
|
||||
use ncc\ThirdParty\nikic\PhpParser\NodeAbstract;
|
||||
|
||||
class Arg extends NodeAbstract
|
||||
{
|
||||
class Arg extends NodeAbstract {
|
||||
/** @var Identifier|null Parameter name (for named parameters) */
|
||||
public $name;
|
||||
public ?Identifier $name;
|
||||
/** @var Expr Value to pass */
|
||||
public $value;
|
||||
public Expr $value;
|
||||
/** @var bool Whether to pass by ref */
|
||||
public $byRef;
|
||||
public bool $byRef;
|
||||
/** @var bool Whether to unpack the argument */
|
||||
public $unpack;
|
||||
public bool $unpack;
|
||||
|
||||
/**
|
||||
* Constructs a function call argument node.
|
||||
*
|
||||
* @param Expr $value Value to pass
|
||||
* @param bool $byRef Whether to pass by ref
|
||||
* @param bool $unpack Whether to unpack the argument
|
||||
* @param array $attributes Additional attributes
|
||||
* @param Expr $value Value to pass
|
||||
* @param bool $byRef Whether to pass by ref
|
||||
* @param bool $unpack Whether to unpack the argument
|
||||
* @param array<string, mixed> $attributes Additional attributes
|
||||
* @param Identifier|null $name Parameter name (for named parameters)
|
||||
*/
|
||||
public function __construct(
|
||||
Expr $value, bool $byRef = false, bool $unpack = false, array $attributes = [],
|
||||
Identifier $name = null
|
||||
?Identifier $name = null
|
||||
) {
|
||||
$this->attributes = $attributes;
|
||||
$this->name = $name;
|
||||
|
@ -36,11 +34,11 @@ class Arg extends NodeAbstract
|
|||
$this->unpack = $unpack;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
public function getSubNodeNames(): array {
|
||||
return ['name', 'value', 'byRef', 'unpack'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Arg';
|
||||
}
|
||||
}
|
||||
|
|
43
src/ncc/ThirdParty/nikic/PhpParser/Node/ArrayItem.php
vendored
Normal file
43
src/ncc/ThirdParty/nikic/PhpParser/Node/ArrayItem.php
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\NodeAbstract;
|
||||
|
||||
class ArrayItem extends NodeAbstract {
|
||||
/** @var null|Expr Key */
|
||||
public ?Expr $key;
|
||||
/** @var Expr Value */
|
||||
public Expr $value;
|
||||
/** @var bool Whether to assign by reference */
|
||||
public bool $byRef;
|
||||
/** @var bool Whether to unpack the argument */
|
||||
public bool $unpack;
|
||||
|
||||
/**
|
||||
* Constructs an array item node.
|
||||
*
|
||||
* @param Expr $value Value
|
||||
* @param null|Expr $key Key
|
||||
* @param bool $byRef Whether to assign by reference
|
||||
* @param array<string, mixed> $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $value, ?Expr $key = null, bool $byRef = false, array $attributes = [], bool $unpack = false) {
|
||||
$this->attributes = $attributes;
|
||||
$this->key = $key;
|
||||
$this->value = $value;
|
||||
$this->byRef = $byRef;
|
||||
$this->unpack = $unpack;
|
||||
}
|
||||
|
||||
public function getSubNodeNames(): array {
|
||||
return ['key', 'value', 'byRef', 'unpack'];
|
||||
}
|
||||
|
||||
public function getType(): string {
|
||||
return 'ArrayItem';
|
||||
}
|
||||
}
|
||||
|
||||
// @deprecated compatibility alias
|
||||
class_alias(ArrayItem::class, Expr\ArrayItem::class);
|
|
@ -5,18 +5,17 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node;
|
|||
use ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
use ncc\ThirdParty\nikic\PhpParser\NodeAbstract;
|
||||
|
||||
class Attribute extends NodeAbstract
|
||||
{
|
||||
class Attribute extends NodeAbstract {
|
||||
/** @var Name Attribute name */
|
||||
public $name;
|
||||
public Name $name;
|
||||
|
||||
/** @var Arg[] Attribute arguments */
|
||||
public $args;
|
||||
/** @var list<Arg> Attribute arguments */
|
||||
public array $args;
|
||||
|
||||
/**
|
||||
* @param Node\Name $name Attribute name
|
||||
* @param Arg[] $args Attribute arguments
|
||||
* @param array $attributes Additional node attributes
|
||||
* @param Node\Name $name Attribute name
|
||||
* @param list<Arg> $args Attribute arguments
|
||||
* @param array<string, mixed> $attributes Additional node attributes
|
||||
*/
|
||||
public function __construct(Name $name, array $args = [], array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
|
@ -24,11 +23,11 @@ class Attribute extends NodeAbstract
|
|||
$this->args = $args;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
public function getSubNodeNames(): array {
|
||||
return ['name', 'args'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
public function getType(): string {
|
||||
return 'Attribute';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,28 +2,26 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
use ncc\ThirdParty\nikic\PhpParser\NodeAbstract;
|
||||
|
||||
class AttributeGroup extends NodeAbstract
|
||||
{
|
||||
class AttributeGroup extends NodeAbstract {
|
||||
/** @var Attribute[] Attributes */
|
||||
public $attrs;
|
||||
public array $attrs;
|
||||
|
||||
/**
|
||||
* @param Attribute[] $attrs PHP attributes
|
||||
* @param array $attributes Additional node attributes
|
||||
* @param array<string, mixed> $attributes Additional node attributes
|
||||
*/
|
||||
public function __construct(array $attrs, array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
$this->attrs = $attrs;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
public function getSubNodeNames(): array {
|
||||
return ['attrs'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
public function getType(): string {
|
||||
return 'AttributeGroup';
|
||||
}
|
||||
}
|
||||
|
|
36
src/ncc/ThirdParty/nikic/PhpParser/Node/ClosureUse.php
vendored
Normal file
36
src/ncc/ThirdParty/nikic/PhpParser/Node/ClosureUse.php
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\NodeAbstract;
|
||||
|
||||
class ClosureUse extends NodeAbstract {
|
||||
/** @var Expr\Variable Variable to use */
|
||||
public Expr\Variable $var;
|
||||
/** @var bool Whether to use by reference */
|
||||
public bool $byRef;
|
||||
|
||||
/**
|
||||
* Constructs a closure use node.
|
||||
*
|
||||
* @param Expr\Variable $var Variable to use
|
||||
* @param bool $byRef Whether to use by reference
|
||||
* @param array<string, mixed> $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr\Variable $var, bool $byRef = false, array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
$this->var = $var;
|
||||
$this->byRef = $byRef;
|
||||
}
|
||||
|
||||
public function getSubNodeNames(): array {
|
||||
return ['var', 'byRef'];
|
||||
}
|
||||
|
||||
public function getType(): string {
|
||||
return 'ClosureUse';
|
||||
}
|
||||
}
|
||||
|
||||
// @deprecated compatibility alias
|
||||
class_alias(ClosureUse::class, Expr\ClosureUse::class);
|
|
@ -9,6 +9,5 @@ use ncc\ThirdParty\nikic\PhpParser\NodeAbstract;
|
|||
*
|
||||
* It does not provide any shared behavior and exists only for type-checking purposes.
|
||||
*/
|
||||
abstract class ComplexType extends NodeAbstract
|
||||
{
|
||||
abstract class ComplexType extends NodeAbstract {
|
||||
}
|
||||
|
|
|
@ -4,22 +4,21 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\NodeAbstract;
|
||||
|
||||
class Const_ extends NodeAbstract
|
||||
{
|
||||
class Const_ extends NodeAbstract {
|
||||
/** @var Identifier Name */
|
||||
public $name;
|
||||
public Identifier $name;
|
||||
/** @var Expr Value */
|
||||
public $value;
|
||||
public Expr $value;
|
||||
|
||||
/** @var Name|null Namespaced name (if using NameResolver) */
|
||||
public $namespacedName;
|
||||
public ?Name $namespacedName;
|
||||
|
||||
/**
|
||||
* Constructs a const node for use in class const and const statements.
|
||||
*
|
||||
* @param string|Identifier $name Name
|
||||
* @param Expr $value Value
|
||||
* @param array $attributes Additional attributes
|
||||
* @param string|Identifier $name Name
|
||||
* @param Expr $value Value
|
||||
* @param array<string, mixed> $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($name, Expr $value, array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
|
@ -27,11 +26,11 @@ class Const_ extends NodeAbstract
|
|||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
public function getSubNodeNames(): array {
|
||||
return ['name', 'value'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
public function getType(): string {
|
||||
return 'Const';
|
||||
}
|
||||
}
|
||||
|
|
37
src/ncc/ThirdParty/nikic/PhpParser/Node/DeclareItem.php
vendored
Normal file
37
src/ncc/ThirdParty/nikic/PhpParser/Node/DeclareItem.php
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node;
|
||||
use ncc\ThirdParty\nikic\PhpParser\NodeAbstract;
|
||||
|
||||
class DeclareItem extends NodeAbstract {
|
||||
/** @var Node\Identifier Key */
|
||||
public Identifier $key;
|
||||
/** @var Node\Expr Value */
|
||||
public Expr $value;
|
||||
|
||||
/**
|
||||
* Constructs a declare key=>value pair node.
|
||||
*
|
||||
* @param string|Node\Identifier $key Key
|
||||
* @param Node\Expr $value Value
|
||||
* @param array<string, mixed> $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($key, Node\Expr $value, array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
$this->key = \is_string($key) ? new Node\Identifier($key) : $key;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function getSubNodeNames(): array {
|
||||
return ['key', 'value'];
|
||||
}
|
||||
|
||||
public function getType(): string {
|
||||
return 'DeclareItem';
|
||||
}
|
||||
}
|
||||
|
||||
// @deprecated compatibility alias
|
||||
class_alias(DeclareItem::class, Stmt\DeclareDeclare::class);
|
|
@ -4,6 +4,5 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\NodeAbstract;
|
||||
|
||||
abstract class Expr extends NodeAbstract
|
||||
{
|
||||
abstract class Expr extends NodeAbstract {
|
||||
}
|
||||
|
|
|
@ -4,31 +4,30 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr;
|
||||
|
||||
class ArrayDimFetch extends Expr
|
||||
{
|
||||
class ArrayDimFetch extends Expr {
|
||||
/** @var Expr Variable */
|
||||
public $var;
|
||||
public Expr $var;
|
||||
/** @var null|Expr Array index / dim */
|
||||
public $dim;
|
||||
public ?Expr $dim;
|
||||
|
||||
/**
|
||||
* Constructs an array index fetch node.
|
||||
*
|
||||
* @param Expr $var Variable
|
||||
* @param null|Expr $dim Array index / dim
|
||||
* @param array $attributes Additional attributes
|
||||
* @param Expr $var Variable
|
||||
* @param null|Expr $dim Array index / dim
|
||||
* @param array<string, mixed> $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $var, Expr $dim = null, array $attributes = []) {
|
||||
public function __construct(Expr $var, ?Expr $dim = null, array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
$this->var = $var;
|
||||
$this->dim = $dim;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
public function getSubNodeNames(): array {
|
||||
return ['var', 'dim'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_ArrayDimFetch';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,41 +1,3 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr;
|
||||
|
||||
class ArrayItem extends Expr
|
||||
{
|
||||
/** @var null|Expr Key */
|
||||
public $key;
|
||||
/** @var Expr Value */
|
||||
public $value;
|
||||
/** @var bool Whether to assign by reference */
|
||||
public $byRef;
|
||||
/** @var bool Whether to unpack the argument */
|
||||
public $unpack;
|
||||
|
||||
/**
|
||||
* Constructs an array item node.
|
||||
*
|
||||
* @param Expr $value Value
|
||||
* @param null|Expr $key Key
|
||||
* @param bool $byRef Whether to assign by reference
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $value, Expr $key = null, bool $byRef = false, array $attributes = [], bool $unpack = false) {
|
||||
$this->attributes = $attributes;
|
||||
$this->key = $key;
|
||||
$this->value = $value;
|
||||
$this->byRef = $byRef;
|
||||
$this->unpack = $unpack;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['key', 'value', 'byRef', 'unpack'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
return 'Expr_ArrayItem';
|
||||
}
|
||||
}
|
||||
require __DIR__ . '/../ArrayItem.php';
|
||||
|
|
|
@ -2,33 +2,33 @@
|
|||
|
||||
namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr;
|
||||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\ArrayItem;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr;
|
||||
|
||||
class Array_ extends Expr
|
||||
{
|
||||
class Array_ extends Expr {
|
||||
// For use in "kind" attribute
|
||||
const KIND_LONG = 1; // array() syntax
|
||||
const KIND_SHORT = 2; // [] syntax
|
||||
public const KIND_LONG = 1; // array() syntax
|
||||
public const KIND_SHORT = 2; // [] syntax
|
||||
|
||||
/** @var (ArrayItem|null)[] Items */
|
||||
public $items;
|
||||
/** @var ArrayItem[] Items */
|
||||
public array $items;
|
||||
|
||||
/**
|
||||
* Constructs an array node.
|
||||
*
|
||||
* @param (ArrayItem|null)[] $items Items of the array
|
||||
* @param array $attributes Additional attributes
|
||||
* @param ArrayItem[] $items Items of the array
|
||||
* @param array<string, mixed> $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $items = [], array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
$this->items = $items;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
public function getSubNodeNames(): array {
|
||||
return ['items'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_Array';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,55 +6,60 @@ use ncc\ThirdParty\nikic\PhpParser\Node;
|
|||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr;
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\FunctionLike;
|
||||
|
||||
class ArrowFunction extends Expr implements FunctionLike
|
||||
{
|
||||
/** @var bool */
|
||||
public $static;
|
||||
class ArrowFunction extends Expr implements FunctionLike {
|
||||
/** @var bool Whether the closure is static */
|
||||
public bool $static;
|
||||
|
||||
/** @var bool */
|
||||
public $byRef;
|
||||
/** @var bool Whether to return by reference */
|
||||
public bool $byRef;
|
||||
|
||||
/** @var Node\Param[] */
|
||||
public $params = [];
|
||||
public array $params = [];
|
||||
|
||||
/** @var null|Node\Identifier|Node\Name|Node\ComplexType */
|
||||
public $returnType;
|
||||
public ?Node $returnType;
|
||||
|
||||
/** @var Expr */
|
||||
public $expr;
|
||||
/** @var Expr Expression body */
|
||||
public Expr $expr;
|
||||
/** @var Node\AttributeGroup[] */
|
||||
public $attrGroups;
|
||||
public array $attrGroups;
|
||||
|
||||
/**
|
||||
* @param array $subNodes Array of the following optional subnodes:
|
||||
* 'static' => false : Whether the closure is static
|
||||
* 'byRef' => false : Whether to return by reference
|
||||
* 'params' => array() : Parameters
|
||||
* 'returnType' => null : Return type
|
||||
* 'expr' => Expr : Expression body
|
||||
* 'attrGroups' => array() : PHP attribute groups
|
||||
* @param array $attributes Additional attributes
|
||||
* @param array{
|
||||
* expr: Expr,
|
||||
* static?: bool,
|
||||
* byRef?: bool,
|
||||
* params?: Node\Param[],
|
||||
* returnType?: null|Node\Identifier|Node\Name|Node\ComplexType,
|
||||
* attrGroups?: Node\AttributeGroup[]
|
||||
* } $subNodes Array of the following subnodes:
|
||||
* 'expr' : Expression body
|
||||
* 'static' => false : Whether the closure is static
|
||||
* 'byRef' => false : Whether to return by reference
|
||||
* 'params' => array() : Parameters
|
||||
* 'returnType' => null : Return type
|
||||
* 'attrGroups' => array() : PHP attribute groups
|
||||
* @param array<string, mixed> $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $subNodes = [], array $attributes = []) {
|
||||
public function __construct(array $subNodes, array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
$this->static = $subNodes['static'] ?? false;
|
||||
$this->byRef = $subNodes['byRef'] ?? false;
|
||||
$this->params = $subNodes['params'] ?? [];
|
||||
$returnType = $subNodes['returnType'] ?? null;
|
||||
$this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType;
|
||||
$this->returnType = $subNodes['returnType'] ?? null;
|
||||
$this->expr = $subNodes['expr'];
|
||||
$this->attrGroups = $subNodes['attrGroups'] ?? [];
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
public function getSubNodeNames(): array {
|
||||
return ['attrGroups', 'static', 'byRef', 'params', 'returnType', 'expr'];
|
||||
}
|
||||
|
||||
public function returnsByRef() : bool {
|
||||
public function returnsByRef(): bool {
|
||||
return $this->byRef;
|
||||
}
|
||||
|
||||
public function getParams() : array {
|
||||
public function getParams(): array {
|
||||
return $this->params;
|
||||
}
|
||||
|
||||
|
@ -62,18 +67,18 @@ class ArrowFunction extends Expr implements FunctionLike
|
|||
return $this->returnType;
|
||||
}
|
||||
|
||||
public function getAttrGroups() : array {
|
||||
public function getAttrGroups(): array {
|
||||
return $this->attrGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Node\Stmt\Return_[]
|
||||
*/
|
||||
public function getStmts() : array {
|
||||
public function getStmts(): array {
|
||||
return [new Node\Stmt\Return_($this->expr)];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
public function getType(): string {
|
||||
return 'Expr_ArrowFunction';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,19 +4,18 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr;
|
||||
|
||||
class Assign extends Expr
|
||||
{
|
||||
class Assign extends Expr {
|
||||
/** @var Expr Variable */
|
||||
public $var;
|
||||
public Expr $var;
|
||||
/** @var Expr Expression */
|
||||
public $expr;
|
||||
public Expr $expr;
|
||||
|
||||
/**
|
||||
* Constructs an assignment node.
|
||||
*
|
||||
* @param Expr $var Variable
|
||||
* @param Expr $expr Expression
|
||||
* @param array $attributes Additional attributes
|
||||
* @param Expr $var Variable
|
||||
* @param Expr $expr Expression
|
||||
* @param array<string, mixed> $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $var, Expr $expr, array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
|
@ -24,11 +23,11 @@ class Assign extends Expr
|
|||
$this->expr = $expr;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
public function getSubNodeNames(): array {
|
||||
return ['var', 'expr'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_Assign';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,19 +4,18 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr;
|
||||
|
||||
abstract class AssignOp extends Expr
|
||||
{
|
||||
abstract class AssignOp extends Expr {
|
||||
/** @var Expr Variable */
|
||||
public $var;
|
||||
public Expr $var;
|
||||
/** @var Expr Expression */
|
||||
public $expr;
|
||||
public Expr $expr;
|
||||
|
||||
/**
|
||||
* Constructs a compound assignment operation node.
|
||||
*
|
||||
* @param Expr $var Variable
|
||||
* @param Expr $expr Expression
|
||||
* @param array $attributes Additional attributes
|
||||
* @param Expr $var Variable
|
||||
* @param Expr $expr Expression
|
||||
* @param array<string, mixed> $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $var, Expr $expr, array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
|
@ -24,7 +23,7 @@ abstract class AssignOp extends Expr
|
|||
$this->expr = $expr;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
public function getSubNodeNames(): array {
|
||||
return ['var', 'expr'];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
||||
|
||||
class BitwiseAnd extends AssignOp
|
||||
{
|
||||
public function getType() : string {
|
||||
class BitwiseAnd extends AssignOp {
|
||||
public function getType(): string {
|
||||
return 'Expr_AssignOp_BitwiseAnd';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
||||
|
||||
class BitwiseOr extends AssignOp
|
||||
{
|
||||
public function getType() : string {
|
||||
class BitwiseOr extends AssignOp {
|
||||
public function getType(): string {
|
||||
return 'Expr_AssignOp_BitwiseOr';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
||||
|
||||
class BitwiseXor extends AssignOp
|
||||
{
|
||||
public function getType() : string {
|
||||
class BitwiseXor extends AssignOp {
|
||||
public function getType(): string {
|
||||
return 'Expr_AssignOp_BitwiseXor';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
||||
|
||||
class Coalesce extends AssignOp
|
||||
{
|
||||
public function getType() : string {
|
||||
class Coalesce extends AssignOp {
|
||||
public function getType(): string {
|
||||
return 'Expr_AssignOp_Coalesce';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
||||
|
||||
class Concat extends AssignOp
|
||||
{
|
||||
public function getType() : string {
|
||||
class Concat extends AssignOp {
|
||||
public function getType(): string {
|
||||
return 'Expr_AssignOp_Concat';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
||||
|
||||
class Div extends AssignOp
|
||||
{
|
||||
public function getType() : string {
|
||||
class Div extends AssignOp {
|
||||
public function getType(): string {
|
||||
return 'Expr_AssignOp_Div';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
||||
|
||||
class Minus extends AssignOp
|
||||
{
|
||||
public function getType() : string {
|
||||
class Minus extends AssignOp {
|
||||
public function getType(): string {
|
||||
return 'Expr_AssignOp_Minus';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
||||
|
||||
class Mod extends AssignOp
|
||||
{
|
||||
public function getType() : string {
|
||||
class Mod extends AssignOp {
|
||||
public function getType(): string {
|
||||
return 'Expr_AssignOp_Mod';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
||||
|
||||
class Mul extends AssignOp
|
||||
{
|
||||
public function getType() : string {
|
||||
class Mul extends AssignOp {
|
||||
public function getType(): string {
|
||||
return 'Expr_AssignOp_Mul';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
||||
|
||||
class Plus extends AssignOp
|
||||
{
|
||||
public function getType() : string {
|
||||
class Plus extends AssignOp {
|
||||
public function getType(): string {
|
||||
return 'Expr_AssignOp_Plus';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
||||
|
||||
class Pow extends AssignOp
|
||||
{
|
||||
public function getType() : string {
|
||||
class Pow extends AssignOp {
|
||||
public function getType(): string {
|
||||
return 'Expr_AssignOp_Pow';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
||||
|
||||
class ShiftLeft extends AssignOp
|
||||
{
|
||||
public function getType() : string {
|
||||
class ShiftLeft extends AssignOp {
|
||||
public function getType(): string {
|
||||
return 'Expr_AssignOp_ShiftLeft';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\AssignOp;
|
||||
|
||||
class ShiftRight extends AssignOp
|
||||
{
|
||||
public function getType() : string {
|
||||
class ShiftRight extends AssignOp {
|
||||
public function getType(): string {
|
||||
return 'Expr_AssignOp_ShiftRight';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,19 +4,18 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr;
|
||||
|
||||
class AssignRef extends Expr
|
||||
{
|
||||
class AssignRef extends Expr {
|
||||
/** @var Expr Variable reference is assigned to */
|
||||
public $var;
|
||||
public Expr $var;
|
||||
/** @var Expr Variable which is referenced */
|
||||
public $expr;
|
||||
public Expr $expr;
|
||||
|
||||
/**
|
||||
* Constructs an assignment node.
|
||||
*
|
||||
* @param Expr $var Variable
|
||||
* @param Expr $expr Expression
|
||||
* @param array $attributes Additional attributes
|
||||
* @param Expr $var Variable
|
||||
* @param Expr $expr Expression
|
||||
* @param array<string, mixed> $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $var, Expr $expr, array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
|
@ -24,11 +23,11 @@ class AssignRef extends Expr
|
|||
$this->expr = $expr;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
public function getSubNodeNames(): array {
|
||||
return ['var', 'expr'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_AssignRef';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,19 +4,18 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr;
|
||||
|
||||
abstract class BinaryOp extends Expr
|
||||
{
|
||||
abstract class BinaryOp extends Expr {
|
||||
/** @var Expr The left hand side expression */
|
||||
public $left;
|
||||
public Expr $left;
|
||||
/** @var Expr The right hand side expression */
|
||||
public $right;
|
||||
public Expr $right;
|
||||
|
||||
/**
|
||||
* Constructs a binary operator node.
|
||||
*
|
||||
* @param Expr $left The left hand side expression
|
||||
* @param Expr $right The right hand side expression
|
||||
* @param array $attributes Additional attributes
|
||||
* @param Expr $left The left hand side expression
|
||||
* @param Expr $right The right hand side expression
|
||||
* @param array<string, mixed> $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $left, Expr $right, array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
|
@ -24,7 +23,7 @@ abstract class BinaryOp extends Expr
|
|||
$this->right = $right;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
public function getSubNodeNames(): array {
|
||||
return ['left', 'right'];
|
||||
}
|
||||
|
||||
|
@ -33,8 +32,6 @@ abstract class BinaryOp extends Expr
|
|||
*
|
||||
* In the case there are multiple possible sigils for an operator, this method does not
|
||||
* necessarily return the one used in the parsed code.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getOperatorSigil() : string;
|
||||
abstract public function getOperatorSigil(): string;
|
||||
}
|
||||
|
|
|
@ -4,13 +4,12 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
||||
|
||||
class BitwiseAnd extends BinaryOp
|
||||
{
|
||||
public function getOperatorSigil() : string {
|
||||
class BitwiseAnd extends BinaryOp {
|
||||
public function getOperatorSigil(): string {
|
||||
return '&';
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_BinaryOp_BitwiseAnd';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,12 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
||||
|
||||
class BitwiseOr extends BinaryOp
|
||||
{
|
||||
public function getOperatorSigil() : string {
|
||||
class BitwiseOr extends BinaryOp {
|
||||
public function getOperatorSigil(): string {
|
||||
return '|';
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_BinaryOp_BitwiseOr';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,12 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
||||
|
||||
class BitwiseXor extends BinaryOp
|
||||
{
|
||||
public function getOperatorSigil() : string {
|
||||
class BitwiseXor extends BinaryOp {
|
||||
public function getOperatorSigil(): string {
|
||||
return '^';
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_BinaryOp_BitwiseXor';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,12 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
||||
|
||||
class BooleanAnd extends BinaryOp
|
||||
{
|
||||
public function getOperatorSigil() : string {
|
||||
class BooleanAnd extends BinaryOp {
|
||||
public function getOperatorSigil(): string {
|
||||
return '&&';
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_BinaryOp_BooleanAnd';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,12 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
||||
|
||||
class BooleanOr extends BinaryOp
|
||||
{
|
||||
public function getOperatorSigil() : string {
|
||||
class BooleanOr extends BinaryOp {
|
||||
public function getOperatorSigil(): string {
|
||||
return '||';
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_BinaryOp_BooleanOr';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,12 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
||||
|
||||
class Coalesce extends BinaryOp
|
||||
{
|
||||
public function getOperatorSigil() : string {
|
||||
class Coalesce extends BinaryOp {
|
||||
public function getOperatorSigil(): string {
|
||||
return '??';
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_BinaryOp_Coalesce';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,12 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
||||
|
||||
class Concat extends BinaryOp
|
||||
{
|
||||
public function getOperatorSigil() : string {
|
||||
class Concat extends BinaryOp {
|
||||
public function getOperatorSigil(): string {
|
||||
return '.';
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_BinaryOp_Concat';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,12 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
||||
|
||||
class Div extends BinaryOp
|
||||
{
|
||||
public function getOperatorSigil() : string {
|
||||
class Div extends BinaryOp {
|
||||
public function getOperatorSigil(): string {
|
||||
return '/';
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_BinaryOp_Div';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,12 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
||||
|
||||
class Equal extends BinaryOp
|
||||
{
|
||||
public function getOperatorSigil() : string {
|
||||
class Equal extends BinaryOp {
|
||||
public function getOperatorSigil(): string {
|
||||
return '==';
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_BinaryOp_Equal';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,12 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
||||
|
||||
class Greater extends BinaryOp
|
||||
{
|
||||
public function getOperatorSigil() : string {
|
||||
class Greater extends BinaryOp {
|
||||
public function getOperatorSigil(): string {
|
||||
return '>';
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_BinaryOp_Greater';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,12 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
||||
|
||||
class GreaterOrEqual extends BinaryOp
|
||||
{
|
||||
public function getOperatorSigil() : string {
|
||||
class GreaterOrEqual extends BinaryOp {
|
||||
public function getOperatorSigil(): string {
|
||||
return '>=';
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_BinaryOp_GreaterOrEqual';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,12 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
||||
|
||||
class Identical extends BinaryOp
|
||||
{
|
||||
public function getOperatorSigil() : string {
|
||||
class Identical extends BinaryOp {
|
||||
public function getOperatorSigil(): string {
|
||||
return '===';
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_BinaryOp_Identical';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,12 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
||||
|
||||
class LogicalAnd extends BinaryOp
|
||||
{
|
||||
public function getOperatorSigil() : string {
|
||||
class LogicalAnd extends BinaryOp {
|
||||
public function getOperatorSigil(): string {
|
||||
return 'and';
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_BinaryOp_LogicalAnd';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,12 @@ namespace ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
|||
|
||||
use ncc\ThirdParty\nikic\PhpParser\Node\Expr\BinaryOp;
|
||||
|
||||
class LogicalOr extends BinaryOp
|
||||
{
|
||||
public function getOperatorSigil() : string {
|
||||
class LogicalOr extends BinaryOp {
|
||||
public function getOperatorSigil(): string {
|
||||
return 'or';
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_BinaryOp_LogicalOr';
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue