diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
index 41b615f..17e894e 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration.yml
@@ -26,4 +26,4 @@ jobs:
name: "PHPUnit"
uses: "doctrine/.github/.github/workflows/continuous-integration.yml@3.0.0"
with:
- php-versions: '["7.1", "7.2", "7.3", "7.4", "8.0", "8.1", "8.2"]'
+ php-versions: '["8.1", "8.2"]'
diff --git a/UPGRADE.md b/UPGRADE.md
index 79d5bc8..1933fcb 100644
--- a/UPGRADE.md
+++ b/UPGRADE.md
@@ -9,6 +9,10 @@ awareness about deprecated code.
# Upgrade to 3.0.0
`Doctrine\Common\Lexer\Token` no longer implements `ArrayAccess`.
+Parameter type declarations have been added to
+`Doctrine\Common\Lexer\AbstractLexer` and `Doctrine\Common\Lexer\Token`.
+You should add both parameter type declarations and return type declarations to
+your lexers, based on the `@return` phpdoc.
# Upgrade to 2.0.0
diff --git a/composer.json b/composer.json
index 78bf961..8a61afe 100644
--- a/composer.json
+++ b/composer.json
@@ -26,14 +26,14 @@
],
"homepage": "https://www.doctrine-project.org/projects/lexer.html",
"require": {
- "php": "^7.1 || ^8.0"
+ "php": "^8.1"
},
"require-dev": {
- "doctrine/coding-standard": "^9 || ^10",
- "phpstan/phpstan": "^1.3",
- "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
+ "doctrine/coding-standard": "^10",
+ "phpstan/phpstan": "^1.9",
+ "phpunit/phpunit": "^9.5",
"psalm/plugin-phpunit": "^0.18.3",
- "vimeo/psalm": "^4.11 || ^5.0"
+ "vimeo/psalm": "^5.0"
},
"autoload": {
"psr-4": {
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index 54a9e54..b7b6083 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -6,7 +6,7 @@
-
+
@@ -15,21 +15,10 @@
tests
-
-
-
-
-
-
-
-
-
- tests/*
-
diff --git a/psalm.xml b/psalm.xml
index dfb8bc6..fa14053 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -37,6 +37,7 @@
+
@@ -44,6 +45,7 @@
+
diff --git a/src/AbstractLexer.php b/src/AbstractLexer.php
index eed4c51..7c31935 100644
--- a/src/AbstractLexer.php
+++ b/src/AbstractLexer.php
@@ -7,7 +7,6 @@
use ReflectionClass;
use UnitEnum;
-use function get_class;
use function implode;
use function preg_split;
use function sprintf;
@@ -27,31 +26,25 @@ abstract class AbstractLexer
{
/**
* Lexer original input string.
- *
- * @var string
*/
- private $input;
+ private string $input;
/**
* Array of scanned tokens.
*
* @var list>
*/
- private $tokens = [];
+ private array $tokens = [];
/**
* Current lexer position in input string.
- *
- * @var int
*/
- private $position = 0;
+ private int $position = 0;
/**
* Current peek of current lexer position.
- *
- * @var int
*/
- private $peek = 0;
+ private int $peek = 0;
/**
* The next token in the input.
@@ -59,7 +52,7 @@ abstract class AbstractLexer
* @var mixed[]|null
* @psalm-var Token|null
*/
- public $lookahead;
+ public Token|null $lookahead;
/**
* The last matched/seen token.
@@ -67,14 +60,12 @@ abstract class AbstractLexer
* @var mixed[]|null
* @psalm-var Token|null
*/
- public $token;
+ public Token|null $token;
/**
* Composed regex for input parsing.
- *
- * @var string|null
*/
- private $regex;
+ private string|null $regex = null;
/**
* Sets the input data to be tokenized.
@@ -86,7 +77,7 @@ abstract class AbstractLexer
*
* @return void
*/
- public function setInput($input)
+ public function setInput(string $input)
{
$this->input = $input;
$this->tokens = [];
@@ -125,7 +116,7 @@ public function resetPeek()
*
* @return void
*/
- public function resetPosition($position = 0)
+ public function resetPosition(int $position = 0)
{
$this->position = $position;
}
@@ -133,11 +124,9 @@ public function resetPosition($position = 0)
/**
* Retrieve the original lexer's input until a given position.
*
- * @param int $position
- *
* @return string
*/
- public function getInputUntilPosition($position)
+ public function getInputUntilPosition(int $position)
{
return substr($this->input, 0, $position);
}
@@ -151,7 +140,7 @@ public function getInputUntilPosition($position)
*
* @psalm-assert-if-true !=null $this->lookahead
*/
- public function isNextToken($type)
+ public function isNextToken(int|string|UnitEnum $type)
{
return $this->lookahead !== null && $this->lookahead->isA($type);
}
@@ -194,7 +183,7 @@ public function moveNext()
*
* @return void
*/
- public function skipUntil($type)
+ public function skipUntil(int|string|UnitEnum $type)
{
while ($this->lookahead !== null && ! $this->lookahead->isA($type)) {
$this->moveNext();
@@ -204,12 +193,9 @@ public function skipUntil($type)
/**
* Checks if given value is identical to the given token.
*
- * @param string $value
- * @param int|string $token
- *
* @return bool
*/
- public function isA($value, $token)
+ public function isA(string $value, int|string|UnitEnum $token)
{
return $this->getType($value) === $token;
}
@@ -250,14 +236,14 @@ public function glimpse()
*
* @return void
*/
- protected function scan($input)
+ protected function scan(string $input)
{
if (! isset($this->regex)) {
$this->regex = sprintf(
'/(%s)|%s/%s',
implode(')|(', $this->getCatchablePatterns()),
implode('|', $this->getNonCatchablePatterns()),
- $this->getModifiers()
+ $this->getModifiers(),
);
}
@@ -277,7 +263,7 @@ protected function scan($input)
$this->tokens[] = new Token(
$firstMatch,
$type,
- $match[1]
+ $match[1],
);
}
}
@@ -289,10 +275,10 @@ protected function scan($input)
*
* @return int|string
*/
- public function getLiteral($token)
+ public function getLiteral(int|string|UnitEnum $token)
{
if ($token instanceof UnitEnum) {
- return get_class($token) . '::' . $token->name;
+ return $token::class . '::' . $token->name;
}
$className = static::class;
@@ -336,11 +322,9 @@ abstract protected function getNonCatchablePatterns();
/**
* Retrieve token type. Also processes the token value if necessary.
*
- * @param string $value
- *
* @return T|null
*
* @param-out V $value
*/
- abstract protected function getType(&$value);
+ abstract protected function getType(string &$value);
}
diff --git a/src/Token.php b/src/Token.php
index 68a9fa8..b6df694 100644
--- a/src/Token.php
+++ b/src/Token.php
@@ -20,7 +20,7 @@ final class Token
* @readonly
* @var V
*/
- public $value;
+ public string|int $value;
/**
* The type of the token (identifier, numeric, string, input parameter, none)
@@ -34,15 +34,14 @@ final class Token
* The position of the token in the input string
*
* @readonly
- * @var int
*/
- public $position;
+ public int $position;
/**
* @param V $value
* @param T|null $type
*/
- public function __construct($value, $type, int $position)
+ public function __construct(string|int $value, $type, int $position)
{
$this->value = $value;
$this->type = $type;
diff --git a/tests/AbstractLexerTest.php b/tests/AbstractLexerTest.php
index 7050914..4a74a9d 100644
--- a/tests/AbstractLexerTest.php
+++ b/tests/AbstractLexerTest.php
@@ -16,8 +16,7 @@
class AbstractLexerTest extends TestCase
{
- /** @var ConcreteLexer */
- private $concreteLexer;
+ private ConcreteLexer $concreteLexer;
public function setUp(): void
{
@@ -29,9 +28,7 @@ public function tearDown(): void
setlocale(LC_ALL, null);
}
- /**
- * @psalm-return list>}>
- */
+ /** @psalm-return list>}> */
public function dataProvider(): array
{
return [
@@ -113,7 +110,7 @@ public function testSkipUntil(): void
$this->assertEquals(
new Token('=', 'operator', 5),
- $this->concreteLexer->lookahead
+ $this->concreteLexer->lookahead,
);
}
@@ -125,7 +122,7 @@ public function testUtf8Mismatch(): void
$this->assertEquals(
new Token("\xE9=10", 'string', 0),
- $this->concreteLexer->lookahead
+ $this->concreteLexer->lookahead,
);
}
@@ -172,9 +169,7 @@ public function testGlimpse(string $input, array $expectedTokens): void
$this->assertNull($this->concreteLexer->peek());
}
- /**
- * @psalm-return list
- */
+ /** @psalm-return list */
public function inputUntilPositionDataProvider(): array
{
return [
@@ -182,13 +177,11 @@ public function inputUntilPositionDataProvider(): array
];
}
- /**
- * @dataProvider inputUntilPositionDataProvider
- */
+ /** @dataProvider inputUntilPositionDataProvider */
public function testGetInputUntilPosition(
string $input,
int $position,
- string $expectedInput
+ string $expectedInput,
): void {
$this->concreteLexer->setInput($input);
@@ -242,15 +235,12 @@ public function testGetLiteral(): void
$this->assertSame('fake_token', $this->concreteLexer->getLiteral('fake_token'));
}
- /**
- * @requires PHP 8.1
- */
public function testGetLiteralWithEnumLexer(): void
{
$enumLexer = new EnumLexer();
$this->assertSame(
'Doctrine\Tests\Common\Lexer\TokenType::OPERATOR',
- $enumLexer->getLiteral(TokenType::OPERATOR)
+ $enumLexer->getLiteral(TokenType::OPERATOR),
);
}
diff --git a/tests/ConcreteLexer.php b/tests/ConcreteLexer.php
index 62fc2db..989bae3 100644
--- a/tests/ConcreteLexer.php
+++ b/tests/ConcreteLexer.php
@@ -12,7 +12,7 @@
/** @extends AbstractLexer */
class ConcreteLexer extends AbstractLexer
{
- public const INT = 'int';
+ final public const INT = 'int';
/**
* {@inheritDoc}
@@ -37,10 +37,7 @@ protected function getNonCatchablePatterns(): array
];
}
- /**
- * {@inheritDoc}
- */
- protected function getType(&$value): string
+ protected function getType(string|int|float &$value): string
{
if (is_numeric($value)) {
$value = (int) $value;
diff --git a/tests/EnumLexer.php b/tests/EnumLexer.php
index 083d0a2..1aebbe1 100644
--- a/tests/EnumLexer.php
+++ b/tests/EnumLexer.php
@@ -35,10 +35,7 @@ protected function getNonCatchablePatterns(): array
];
}
- /**
- * {@inheritDoc}
- */
- protected function getType(&$value): TokenType
+ protected function getType(string &$value): TokenType
{
if (is_numeric($value)) {
$value = (int) $value;
diff --git a/tests/MutableLexer.php b/tests/MutableLexer.php
index 5530b29..b8b706d 100644
--- a/tests/MutableLexer.php
+++ b/tests/MutableLexer.php
@@ -10,7 +10,7 @@
class MutableLexer extends AbstractLexer
{
/** @var string[] */
- private $catchablePatterns = [];
+ private array $catchablePatterns = [];
public function addCatchablePattern(string $pattern): void
{
@@ -33,10 +33,7 @@ protected function getNonCatchablePatterns(): array
return ['[\s,]+'];
}
- /**
- * {@inheritDoc}
- */
- protected function getType(&$value): int
+ protected function getType(string &$value): int
{
return 1;
}