diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 6202f32..575b25e 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -10,7 +10,6 @@ jobs: fail-fast: false matrix: php: - - "8.1" - "8.2" - "8.3" dependencies: @@ -43,8 +42,8 @@ jobs: fail-fast: false matrix: php: - - "8.1" - "8.2" + - "8.3" dependencies: - "" - "--prefer-lowest" @@ -74,7 +73,6 @@ jobs: fail-fast: false matrix: php: - - "8.1" - "8.2" - "8.3" dependencies: @@ -106,7 +104,6 @@ jobs: fail-fast: false matrix: php: - - "8.1" - "8.2" - "8.3" dependencies: @@ -140,7 +137,6 @@ jobs: fail-fast: false matrix: php: - - "8.1" - "8.2" - "8.3" dependencies: @@ -171,9 +167,9 @@ jobs: --coverage-clover=build/coverage/clover.xml - name: Upload coverage - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: coverage-${{ matrix.php }} + name: coverage-${{ matrix.php }}-${{ matrix.dependencies }} path: build/coverage/ infection: @@ -185,7 +181,6 @@ jobs: fail-fast: false matrix: php: - - "8.1" - "8.2" - "8.3" dependencies: @@ -211,9 +206,9 @@ jobs: run: composer update --no-progress --no-interaction ${{ matrix.dependencies }} - name: Download coverage - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: - name: coverage-${{ matrix.php }} + name: coverage-${{ matrix.php }}-${{ matrix.dependencies }} path: build/coverage/ - name: Infection coverage of changed lines @@ -231,10 +226,10 @@ jobs: -jmax - name: Save Infection result - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: always() with: - name: infection-log-${{ matrix.php }}.txt + name: infection-log-${{ matrix.php }}-${{ matrix.dependencies }}.txt path: infection-log.txt bc-breaks: diff --git a/composer.json b/composer.json index a1260fa..3c94de1 100644 --- a/composer.json +++ b/composer.json @@ -4,21 +4,22 @@ "license": "MIT", "type": "library", "require": { - "php": ">=8.1", + "php": ">=8.2", "ext-ctype": "*" }, "require-dev": { - "eventjet/coding-standard": "^3.12", + "eventjet/coding-standard": "^3.18", + "friendsofphp/php-cs-fixer": "^3.75", "infection/infection": "^0.27.0", "maglnet/composer-require-checker": "^4.6", "phpstan/extension-installer": "^1.3", - "phpstan/phpstan": "^1.10.34", - "phpstan/phpstan-phpunit": "^1.3", - "phpstan/phpstan-strict-rules": "^1.5", + "phpstan/phpstan": "^1.12.25", + "phpstan/phpstan-phpunit": "^1.4.2", + "phpstan/phpstan-strict-rules": "^1.6.2", "phpunit/phpunit": "^10.2", "psalm/plugin-phpunit": "^0.18.4", "roave/backward-compatibility-check": "^8.3", - "vimeo/psalm": "^5.16" + "vimeo/psalm": "^5.26.1" }, "minimum-stability": "stable", "autoload": { diff --git a/src/And_.php b/src/And_.php index 4a2c65e..df031c7 100644 --- a/src/And_.php +++ b/src/And_.php @@ -5,6 +5,7 @@ namespace Eventjet\Ausdruck; use Eventjet\Ausdruck\Parser\Span; +use Override; use function get_debug_type; use function is_bool; @@ -25,6 +26,7 @@ public function __toString(): string return sprintf('%s && %s', $this->left, $this->right); } + #[Override] public function evaluate(Scope $scope): bool { $left = $this->left->evaluate($scope); @@ -37,6 +39,7 @@ public function evaluate(Scope $scope): bool return $left && $right; } + #[Override] public function equals(Expression $other): bool { return $other instanceof self @@ -44,11 +47,13 @@ public function equals(Expression $other): bool && $this->right->equals($other->right); } + #[Override] public function getType(): Type { return Type::bool(); } + #[Override] public function location(): Span { return $this->left->location()->to($this->right->location()); diff --git a/src/Call.php b/src/Call.php index 83fcbbf..3b3777e 100644 --- a/src/Call.php +++ b/src/Call.php @@ -5,6 +5,7 @@ namespace Eventjet\Ausdruck; use Eventjet\Ausdruck\Parser\Span; +use Override; use Throwable; use function array_map; @@ -57,6 +58,7 @@ public function __toString(): string return sprintf('%s.%s:%s(%s)', $this->target, $this->name, $this->type, implode(', ', $this->arguments)); } + #[Override] public function evaluate(Scope $scope): mixed { $func = $scope->func($this->name); @@ -72,6 +74,7 @@ public function evaluate(Scope $scope): mixed } } + #[Override] public function equals(Expression $other): bool { return $other instanceof self @@ -81,6 +84,7 @@ public function equals(Expression $other): bool && self::compareArguments($this->arguments, $other->arguments); } + #[Override] public function getType(): Type { return $this->type; diff --git a/src/Eq.php b/src/Eq.php index 2d1eaed..dacd584 100644 --- a/src/Eq.php +++ b/src/Eq.php @@ -5,6 +5,7 @@ namespace Eventjet\Ausdruck; use Eventjet\Ausdruck\Parser\Span; +use Override; use function sprintf; @@ -23,11 +24,13 @@ public function __toString(): string return sprintf('%s === %s', $this->left, $this->right); } + #[Override] public function evaluate(Scope $scope): bool { return $this->left->evaluate($scope) === $this->right->evaluate($scope); } + #[Override] public function equals(Expression $other): bool { return $other instanceof self @@ -35,11 +38,13 @@ public function equals(Expression $other): bool && $this->right->equals($other->right); } + #[Override] public function getType(): Type { return Type::bool(); } + #[Override] public function location(): Span { return $this->left->location()->to($this->right->location()); diff --git a/src/Expression.php b/src/Expression.php index 735c3a8..d15cb3f 100644 --- a/src/Expression.php +++ b/src/Expression.php @@ -19,30 +19,22 @@ public function eq(self $other): Eq public function subtract(self $subtrahend): Subtract { - /** @var self $self */ - $self = $this; - return Expr::subtract($self, $subtrahend); + return Expr::subtract($this, $subtrahend); } public function gt(self $right): Gt { - /** @var self $self */ - $self = $this; - return Expr::gt($self, $right); + return Expr::gt($this, $right); } public function or_(self $other): Or_ { - /** @var self $self */ - $self = $this; - return Expr::or_($self, $other); + return Expr::or_($this, $other); } public function and_(self $other): self { - /** @var self $self */ - $self = $this; - return Expr::and_($self, $other); + return Expr::and_($this, $other); } /** diff --git a/src/Get.php b/src/Get.php index 72d2b16..a6e882e 100644 --- a/src/Get.php +++ b/src/Get.php @@ -6,6 +6,7 @@ use Eventjet\Ausdruck\Parser\Span; use Eventjet\Ausdruck\Parser\TypeHint; +use Override; use function get_debug_type; use function sprintf; @@ -34,6 +35,7 @@ public function __toString(): string return sprintf('%s%s', $this->name, $this->typeHint); } + #[Override] public function evaluate(Scope $scope): mixed { /** @psalm-suppress MixedAssignment */ @@ -57,6 +59,7 @@ public function evaluate(Scope $scope): mixed } } + #[Override] public function equals(Expression $other): bool { return $other instanceof self @@ -64,6 +67,7 @@ public function equals(Expression $other): bool && $this->typeHint->type->equals($other->typeHint->type); } + #[Override] public function getType(): Type { return $this->typeHint->type; diff --git a/src/Gt.php b/src/Gt.php index 93c1f52..f38de1a 100644 --- a/src/Gt.php +++ b/src/Gt.php @@ -5,6 +5,7 @@ namespace Eventjet\Ausdruck; use Eventjet\Ausdruck\Parser\Span; +use Override; use function sprintf; @@ -23,11 +24,13 @@ public function __toString(): string return sprintf('%s > %s', $this->left, $this->right); } + #[Override] public function evaluate(Scope $scope): bool { return $this->left->evaluate($scope) > $this->right->evaluate($scope); } + #[Override] public function equals(Expression $other): bool { return $other instanceof self @@ -35,11 +38,13 @@ public function equals(Expression $other): bool && $this->right->equals($other->right); } + #[Override] public function getType(): Type { return Type::bool(); } + #[Override] public function location(): Span { return $this->left->location()->to($this->right->location()); diff --git a/src/Lambda.php b/src/Lambda.php index dfd1b1a..5eb41a5 100644 --- a/src/Lambda.php +++ b/src/Lambda.php @@ -5,6 +5,7 @@ namespace Eventjet\Ausdruck; use Eventjet\Ausdruck\Parser\Span; +use Override; use function array_map; use function implode; @@ -34,6 +35,7 @@ public function __toString(): string /** * @return callable(Scope): mixed */ + #[Override] public function evaluate(Scope $scope): callable { return function (mixed ...$params) use ($scope): mixed { @@ -45,6 +47,7 @@ public function evaluate(Scope $scope): callable }; } + #[Override] public function equals(Expression $other): bool { return $other instanceof self @@ -52,6 +55,7 @@ public function equals(Expression $other): bool && $this->body->equals($other->body); } + #[Override] public function getType(): Type { return Type::func($this->body->getType(), array_map(static fn(string $_name) => Type::any(), $this->parameters)); diff --git a/src/ListLiteral.php b/src/ListLiteral.php index 5c434c9..634d962 100644 --- a/src/ListLiteral.php +++ b/src/ListLiteral.php @@ -5,6 +5,7 @@ namespace Eventjet\Ausdruck; use Eventjet\Ausdruck\Parser\Span; +use Override; use function array_map; use function implode; @@ -23,6 +24,7 @@ public function __toString() return '[' . implode(', ', $this->elements) . ']'; } + #[Override] public function location(): Span { return $this->location; @@ -31,6 +33,7 @@ public function location(): Span /** * @return list */ + #[Override] public function evaluate(Scope $scope): array { return array_map( @@ -39,6 +42,7 @@ public function evaluate(Scope $scope): array ); } + #[Override] public function equals(Expression $other): bool { if (!$other instanceof self) { @@ -53,6 +57,7 @@ public function equals(Expression $other): bool return true; } + #[Override] public function getType(): Type { $elementType = null; diff --git a/src/Literal.php b/src/Literal.php index b0cde23..ae3de93 100644 --- a/src/Literal.php +++ b/src/Literal.php @@ -5,6 +5,7 @@ namespace Eventjet\Ausdruck; use Eventjet\Ausdruck\Parser\Span; +use Override; use function array_is_list; use function array_map; @@ -65,17 +66,20 @@ public function __toString(): string return self::dumpValue($this->value); } + #[Override] public function evaluate(Scope $scope): mixed { return $this->value; } + #[Override] public function equals(Expression $other): bool { return $other instanceof self && $this->value === $other->value; } + #[Override] public function getType(): Type { return Type::fromValue($this->value); diff --git a/src/Negative.php b/src/Negative.php index 7e944d3..70f51d7 100644 --- a/src/Negative.php +++ b/src/Negative.php @@ -5,6 +5,7 @@ namespace Eventjet\Ausdruck; use Eventjet\Ausdruck\Parser\Span; +use Override; use function is_float; use function is_int; @@ -24,6 +25,7 @@ public function __toString(): string return sprintf('-%s', $this->expression); } + #[Override] public function evaluate(Scope $scope): float|int { $value = $this->expression->evaluate($scope); @@ -33,12 +35,14 @@ public function evaluate(Scope $scope): float|int return -$value; } + #[Override] public function equals(Expression $other): bool { return $other instanceof self && $this->expression->equals($other->expression); } + #[Override] public function getType(): Type { return $this->expression->getType(); diff --git a/src/Or_.php b/src/Or_.php index edfa87e..205c378 100644 --- a/src/Or_.php +++ b/src/Or_.php @@ -5,6 +5,7 @@ namespace Eventjet\Ausdruck; use Eventjet\Ausdruck\Parser\Span; +use Override; use function get_debug_type; use function is_bool; @@ -25,6 +26,7 @@ public function __toString(): string return sprintf('%s || %s', $this->left, $this->right); } + #[Override] public function evaluate(Scope $scope): bool { $left = $this->left->evaluate($scope); @@ -37,6 +39,7 @@ public function evaluate(Scope $scope): bool return $left || $right; } + #[Override] public function equals(Expression $other): bool { return $other instanceof self @@ -44,11 +47,13 @@ public function equals(Expression $other): bool && $this->right->equals($other->right); } + #[Override] public function getType(): Type { return Type::bool(); } + #[Override] public function location(): Span { return $this->left->location()->to($this->right->location()); diff --git a/src/Parser/Literal.php b/src/Parser/Literal.php index a99e520..58b8c31 100644 --- a/src/Parser/Literal.php +++ b/src/Parser/Literal.php @@ -4,6 +4,7 @@ namespace Eventjet\Ausdruck\Parser; +use Override; use Stringable; use function is_string; @@ -23,6 +24,7 @@ public function __construct(public readonly string|int|float $value) { } + #[Override] public function __toString(): string { if (is_string($this->value)) { diff --git a/src/Parser/Span.php b/src/Parser/Span.php index d2d3219..4596cf2 100644 --- a/src/Parser/Span.php +++ b/src/Parser/Span.php @@ -4,6 +4,7 @@ namespace Eventjet\Ausdruck\Parser; +use Override; use Stringable; use function sprintf; @@ -33,6 +34,7 @@ public static function char(int $line, int $column): self return new self($line, $column, $line, $column); } + #[Override] public function __toString(): string { return sprintf( diff --git a/src/Parser/TypeHint.php b/src/Parser/TypeHint.php index 4c825a7..84cea9b 100644 --- a/src/Parser/TypeHint.php +++ b/src/Parser/TypeHint.php @@ -5,6 +5,7 @@ namespace Eventjet\Ausdruck\Parser; use Eventjet\Ausdruck\Type; +use Override; use Stringable; use function sprintf; @@ -15,6 +16,7 @@ public function __construct(public readonly Type $type, public readonly bool $ex { } + #[Override] public function __toString(): string { if (!$this->explicit) { diff --git a/src/Parser/TypeNode.php b/src/Parser/TypeNode.php index c9008de..42d5f4d 100644 --- a/src/Parser/TypeNode.php +++ b/src/Parser/TypeNode.php @@ -4,6 +4,7 @@ namespace Eventjet\Ausdruck\Parser; +use Override; use Stringable; use function implode; @@ -25,6 +26,7 @@ public function __construct( ) { } + #[Override] public function __toString(): string { return $this->args === [] diff --git a/src/Subtract.php b/src/Subtract.php index 46e82f0..aed892a 100644 --- a/src/Subtract.php +++ b/src/Subtract.php @@ -5,6 +5,7 @@ namespace Eventjet\Ausdruck; use Eventjet\Ausdruck\Parser\Span; +use Override; use function get_debug_type; use function gettype; @@ -27,6 +28,7 @@ public function __toString(): string return sprintf('%s - %s', $this->minuend, $this->subtrahend); } + #[Override] public function evaluate(Scope $scope): int|float { /** @var mixed $minuend */ @@ -57,6 +59,7 @@ public function evaluate(Scope $scope): int|float ); } + #[Override] public function equals(Expression $other): bool { return $other instanceof self @@ -64,11 +67,13 @@ public function equals(Expression $other): bool && $this->subtrahend->equals($other->subtrahend); } + #[Override] public function getType(): Type { return $this->minuend->getType(); } + #[Override] public function location(): Span { return $this->minuend->location()->to($this->subtrahend->location()); diff --git a/src/Type.php b/src/Type.php index 28909e4..bd36369 100644 --- a/src/Type.php +++ b/src/Type.php @@ -5,12 +5,14 @@ namespace Eventjet\Ausdruck; use InvalidArgumentException; +use Override; use Stringable; use function array_is_list; use function array_key_first; use function array_shift; use function array_slice; +use function assert; use function gettype; use function implode; use function in_array; @@ -140,9 +142,11 @@ private static function keyAndValueTypeFromArray(array $value): array return [self::fromValue($firstKey), self::fromValue($value[$firstKey])]; } + #[Override] public function __toString(): string { if ($this->name === 'Func') { + assert($this->args !== []); $args = $this->args; $returnType = array_shift($args); return sprintf('func(%s): %s', implode(', ', $args), $returnType); diff --git a/tests/unit/Parser/ExpressionParserTest.php b/tests/unit/Parser/ExpressionParserTest.php index 732ecfc..bb2c22e 100644 --- a/tests/unit/Parser/ExpressionParserTest.php +++ b/tests/unit/Parser/ExpressionParserTest.php @@ -334,15 +334,15 @@ public static function syntaxErrorLocationCases(): iterable yield [ <<<'EXPR' - :list - EXPR, + :list + EXPR, Span::char(2, 3), ]; yield [ <<<'EXPR' - foo:string - === :string - EXPR, + foo:string + === :string + EXPR, Span::char(2, 9), ]; } diff --git a/tests/unit/Parser/TypeParserTest.php b/tests/unit/Parser/TypeParserTest.php index b29b5bb..a52588b 100644 --- a/tests/unit/Parser/TypeParserTest.php +++ b/tests/unit/Parser/TypeParserTest.php @@ -10,7 +10,6 @@ use LogicException; use PHPUnit\Framework\TestCase; -use function assert; use function explode; use function implode; use function preg_match; @@ -37,9 +36,9 @@ public static function syntaxErrorCases(): iterable ]; yield 'Empty string' => [ <<<'AUSDRUCK' - - = - AUSDRUCK, + + = + AUSDRUCK, 'Invalid type ""', ]; yield 'Whitespace-only string' => [ @@ -48,9 +47,9 @@ public static function syntaxErrorCases(): iterable ]; yield 'Arrow' => [ <<<'AUSDRUCK' - -> - == - AUSDRUCK, + -> + == + AUSDRUCK, 'Expected type, got ->', ]; } @@ -76,7 +75,7 @@ public function testSyntaxErrors(string $type, string $expectedMessage): void } $startCol = strlen($matches['indent']) + 1; $endCol = strlen($matches['indent']) + strlen($matches['marker']); - assert($endCol > 0, 'End column can\'t be lower than 1 because the marker is at least one character long'); + /** @psalm-suppress InvalidArgument Psalm doesn't analyze regular expressions */ $expectedSpan = new Span($lineNumber, $startCol, $lineNumber, $endCol); unset($lines[$lineIndex]); }