diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 57994f9c..25318c07 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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 @@ -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 diff --git a/ci/phpstan/baselines/lexer-constants.neon b/ci/phpstan/baselines/lexer-variations.neon similarity index 58% rename from ci/phpstan/baselines/lexer-constants.neon rename to ci/phpstan/baselines/lexer-variations.neon index 943744fd..de961a18 100644 --- a/ci/phpstan/baselines/lexer-constants.neon +++ b/ci/phpstan/baselines/lexer-variations.neon @@ -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::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::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.#' diff --git a/ci/phpstan/config.neon b/ci/phpstan/config.neon index 22d0a60e..1c0d0f1f 100644 --- a/ci/phpstan/config.neon +++ b/ci/phpstan/config.neon @@ -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 diff --git a/ci/rector/config.php b/ci/rector/config.php index f29b9a46..bec08cfc 100644 --- a/ci/rector/config.php +++ b/ci/rector/config.php @@ -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; @@ -40,6 +41,9 @@ $rectorConfig->skip([ RenamePropertyToMatchTypeRector::class, + FlipTypeControlToUseExclusiveTypeRector::class => [ + $basePath.'src/MartinGeorgiev/Utils/DoctrineLexer.php', + ], ]); $rectorConfig->importShortClasses(false); diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php index df2a08ba..8a08b319 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php @@ -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; /** @@ -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); diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Cast.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Cast.php index 2b2f7d62..c1fab78a 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Cast.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Cast.php @@ -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; /** @@ -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(); diff --git a/src/MartinGeorgiev/Utils/DoctrineLexer.php b/src/MartinGeorgiev/Utils/DoctrineLexer.php new file mode 100644 index 00000000..1abc5499 --- /dev/null +++ b/src/MartinGeorgiev/Utils/DoctrineLexer.php @@ -0,0 +1,58 @@ +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; + } +}