Aggiornato Composer

This commit is contained in:
Paolo A
2024-05-17 12:24:19 +00:00
parent 4ac62108b5
commit ec201d75b2
2238 changed files with 38684 additions and 59785 deletions

View File

@@ -5,20 +5,24 @@ namespace 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;

View File

@@ -8,16 +8,17 @@ namespace 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++) {

View File

@@ -15,47 +15,57 @@ use PhpParser\Node\Expr;
*
* @internal
*/
class PrintableNewAnonClassNode extends Expr
{
class PrintableNewAnonClassNode extends Expr {
/** @var Node\AttributeGroup[] PHP attribute groups */
public $attrGroups;
/** @var Node\Arg[] Arguments */
public $args;
public array $attrGroups;
/** @var int Modifiers */
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, 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);
$this->attrGroups = $attrGroups;
$this->flags = $flags;
$this->args = $args;
$this->extends = $extends;
$this->implements = $implements;
$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
// to anonymous classes for their own purposes. We simplify ignore the name here.
return new self(
$class->attrGroups, $newNode->args, $class->extends, $class->implements,
$class->attrGroups, $class->flags, $newNode->args, $class->extends, $class->implements,
$class->stmts, $newNode->getAttributes()
);
}
public function getType() : string {
public function getType(): string {
return 'Expr_PrintableNewAnonClass';
}
public function getSubNodeNames() : array {
return ['attrGroups', 'args', 'extends', 'implements', 'stmts'];
public function getSubNodeNames(): array {
return ['attrGroups', 'flags', 'args', 'extends', 'implements', 'stmts'];
}
}

View File

@@ -2,22 +2,23 @@
namespace PhpParser\Internal;
use 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,20 +185,19 @@ 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);
}
/**
@@ -213,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;
@@ -258,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);
}
}
}