Aggiornato Composer
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user