Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 28 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,26 @@ permissions:

jobs:
tests:
name: "PHP ${{ matrix.php }} + Doctrine ORM ${{ matrix.doctrine-orm }}"
name: "PHP ${{ matrix.php }} + Doctrine ORM ${{ matrix.doctrine-orm }} + Doctrine Lexer ${{ matrix.doctrine-lexer }}"
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
php: ['8.1', '8.2', '8.3', '8.4']
doctrine-orm: ['2.14', '3.0', 'latest']
doctrine-lexer: ['2.1', '3.0', 'latest']
doctrine-orm: ['2.14', '2.18', '3.0', 'latest']
include:
- php: '8.1'
doctrine-orm: '2.14'
doctrine-lexer: '1.2'
- php: '8.4'
calculate-code-coverage: true
exclude:
- doctrine-orm: '2.14'
doctrine-lexer: '3.0'
- doctrine-orm: '3.0'
doctrine-lexer: '2.1'

steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
Expand All @@ -46,12 +55,26 @@ jobs:
restore-keys: |
${{ runner.os }}-php-

- name: Install composer dependencies
- name: Install Doctrine Lexer dependency
run: |
if [ "${{ matrix.doctrine-lexer }}" == "1.2" ]; then
composer require doctrine/lexer "~1.2" --dev --prefer-dist --no-interaction --no-progress
elif [ "${{ matrix.doctrine-lexer }}" == "2.1" ]; then
composer require doctrine/lexer "~2.1" --dev --prefer-dist --no-interaction --no-progress
elif [ "${{ matrix.doctrine-lexer }}" == "3.0" ]; then
composer require doctrine/lexer "~3.0" --dev --prefer-dist --no-interaction --no-progress
else
composer update --prefer-dist --no-interaction --no-progress
fi

- name: Install Doctrine ORM dependency
run: |
if [ "${{ matrix.doctrine-orm }}" == "2.14" ]; then
composer require doctrine/orm "~2.14" --prefer-dist --no-interaction --no-progress
composer require doctrine/orm "~2.14" --prefer-dist --no-interaction --no-progress --with-all-dependencies
elif [ "${{ matrix.doctrine-orm }}" == "2.18" ]; then
composer require doctrine/orm "~2.18" --prefer-dist --no-interaction --no-progress --with-all-dependencies
elif [ "${{ matrix.doctrine-orm }}" == "3.0" ]; then
composer require doctrine/orm "~3.0" --prefer-dist --no-interaction --no-progress
composer require doctrine/orm "~3.0" --prefer-dist --no-interaction --no-progress --with-all-dependencies
else
composer update --prefer-dist --no-interaction --no-progress
fi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@ parameters:
- '#Fetching deprecated class constant T_DISTINCT of class Doctrine\\ORM\\Query\\Lexer#'
- '#Parameter \#1 \$token of method Doctrine\\ORM\\Query\\Parser::match\(\) expects Doctrine\\ORM\\Query\\TokenType, mixed given.#'
- '#Parameter \#1 \$type of method Doctrine\\Common\\Lexer\\AbstractLexer<Doctrine\\ORM\\Query\\TokenType,string>::isNextToken\(\) expects Doctrine\\ORM\\Query\\TokenType, mixed given.#'
- '#Parameter \#1 \$token of method Doctrine\\ORM\\Query\\Parser::match\(\) expects int\|string, mixed given.#'
- '#Parameter \#1 \$type of method Doctrine\\Common\\Lexer\\AbstractLexer<int\|string,string>::isNextToken\(\) expects int\|string, mixed given.#'
- '#Parameter \#1 \$token of method Doctrine\\ORM\\Query\\Parser::match\(\) expects 1\|2\|3\|4\|5\|6\|7\|8\|9\|10\|11\|12\|13\|14\|15\|16\|17\|18\|19\|100\|101\|102\|200\|201\|202\|203\|204\|205\|206\|207\|208\|209\|210\|211\|212\|213\|214\|215\|216\|217\|218\|219\|220\|221\|222\|223\|224\|225\|226\|227\|228\|229\|230\|231\|232\|233\|234\|235\|236\|237\|238\|239\|240\|241\|242\|243\|244\|245\|246\|247\|248\|249\|250\|251\|252\|253\|254\|255\|256, mixed given.#'
- '#Parameter \#1 \$type of method Doctrine\\Common\\Lexer\\AbstractLexer::isNextToken\(\) expects int\|string, mixed given.#'
2 changes: 1 addition & 1 deletion ci/phpstan/config.neon
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ includes:
- ../../vendor/phpstan/phpstan-doctrine/extension.neon
- ../../vendor/phpstan/phpstan-phpunit/extension.neon
- ./baselines/deprecated-methods.neon
- ./baselines/lexer-constants.neon
- ./baselines/lexer-variations.neon
- ./baselines/phpstan-identifiers.neon
- ./baselines/type-mismatches.neon

Expand Down
4 changes: 4 additions & 0 deletions ci/rector/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

declare(strict_types=1);

use Rector\CodeQuality\Rector\Identical\FlipTypeControlToUseExclusiveTypeRector;
use Rector\Config\RectorConfig;
use Rector\Doctrine\Set\DoctrineSetList;
use Rector\Naming\Rector\Class_\RenamePropertyToMatchTypeRector;
Expand Down Expand Up @@ -40,6 +41,9 @@

$rectorConfig->skip([
RenamePropertyToMatchTypeRector::class,
FlipTypeControlToUseExclusiveTypeRector::class => [
$basePath.'src/MartinGeorgiev/Utils/DoctrineLexer.php',
],
]);

$rectorConfig->importShortClasses(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Doctrine\ORM\Query\TokenType;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\ParserException;
use MartinGeorgiev\Utils\DoctrineLexer;
use MartinGeorgiev\Utils\DoctrineOrm;

/**
Expand All @@ -30,24 +31,24 @@ protected function feedParserWithNodes(Parser $parser): void
try {
// @phpstan-ignore-next-line
$this->nodes[] = $parser->{$this->commonNodeMapping}();
if ($lexer->lookahead?->type === null) {
$lookaheadType = DoctrineLexer::getLookaheadType($lexer);
if ($lookaheadType === null) {
throw ParserException::missingLookaheadType();
}
} catch (\Throwable $throwable) {
throw ParserException::withThrowable($throwable);
}

$aheadType = $lexer->lookahead->type;
$shouldUseLexer = DoctrineOrm::isPre219();

while (($shouldUseLexer ? Lexer::T_CLOSE_PARENTHESIS : TokenType::T_CLOSE_PARENTHESIS) !== $aheadType) {
if (($shouldUseLexer ? Lexer::T_COMMA : TokenType::T_COMMA) === $aheadType) {
while (($shouldUseLexer ? Lexer::T_CLOSE_PARENTHESIS : TokenType::T_CLOSE_PARENTHESIS) !== $lookaheadType) {
if (($shouldUseLexer ? Lexer::T_COMMA : TokenType::T_COMMA) === $lookaheadType) {
$parser->match($shouldUseLexer ? Lexer::T_COMMA : TokenType::T_COMMA);
// @phpstan-ignore-next-line
$this->nodes[] = $parser->{$this->commonNodeMapping}();
}

$aheadType = $lexer->lookahead->type;
$lookaheadType = DoctrineLexer::getLookaheadType($lexer);
}

$this->validateArguments($this->nodes);
Expand Down
11 changes: 3 additions & 8 deletions src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Cast.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;

use Doctrine\Common\Lexer\Token;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\AST\Node;
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\SqlWalker;
use Doctrine\ORM\Query\TokenType;
use MartinGeorgiev\Utils\DoctrineLexer;
use MartinGeorgiev\Utils\DoctrineOrm;

/**
Expand Down Expand Up @@ -40,16 +40,11 @@ public function parse(Parser $parser): void
$parser->match($shouldUseLexer ? Lexer::T_IDENTIFIER : TokenType::T_IDENTIFIER);

$lexer = $parser->getLexer();
$token = $lexer->token;
if (!$token instanceof Token) {
$type = DoctrineLexer::getTokenValue($lexer);
if (!\is_string($type)) {
return;
}

if (!\is_string($token->value)) {
return;
}

$type = $token->value;
if ($lexer->isNextToken($shouldUseLexer ? Lexer::T_OPEN_PARENTHESIS : TokenType::T_OPEN_PARENTHESIS)) {
$parser->match($shouldUseLexer ? Lexer::T_OPEN_PARENTHESIS : TokenType::T_OPEN_PARENTHESIS);
$parameter = $parser->Literal();
Expand Down
58 changes: 58 additions & 0 deletions src/MartinGeorgiev/Utils/DoctrineLexer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace MartinGeorgiev\Utils;

use Doctrine\ORM\Query\Lexer;

/**
* @internal
*/
final class DoctrineLexer
{
/**
* Checks if the Lexer is prior to version 2.0.0.
*
* In Lexer versions prior to 2.0.0, the lookahead property is an array,
* while in 2.0.0+ it's an object.
*/
public static function isPre200(Lexer $lexer): bool
{
// @phpstan-ignore-next-line
return \is_array($lexer->lookahead);
}

/**
* @return mixed|null
*/
public static function getLookaheadType(Lexer $lexer)
{
if (self::isPre200($lexer)) {
// @phpstan-ignore-next-line
return $lexer->lookahead['type'];
}

// @phpstan-ignore-next-line
return $lexer->lookahead?->type;
}

/**
* @return mixed|null
*/
public static function getTokenValue(Lexer $lexer)
{
if (self::isPre200($lexer)) {
// @phpstan-ignore-next-line
if ($lexer->token === null) {
return null;
}

// @phpstan-ignore-next-line
return $lexer->token['value'];
}

// @phpstan-ignore-next-line
return $lexer->token?->value;
}
}
Loading